sp5100_tco.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * sp5100_tco : TCO timer driver for sp5100 chipsets
  4. *
  5. * (c) Copyright 2009 Google Inc., All Rights Reserved.
  6. *
  7. * Based on i8xx_tco.c:
  8. * (c) Copyright 2000 kernel concepts <[email protected]>, All Rights
  9. * Reserved.
  10. * https://www.kernelconcepts.de
  11. *
  12. * See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide",
  13. * AMD Publication 44413 "AMD SP5100 Register Reference Guide"
  14. * AMD Publication 45482 "AMD SB800-Series Southbridges Register
  15. * Reference Guide"
  16. * AMD Publication 48751 "BIOS and Kernel Developer’s Guide (BKDG)
  17. * for AMD Family 16h Models 00h-0Fh Processors"
  18. * AMD Publication 51192 "AMD Bolton FCH Register Reference Guide"
  19. * AMD Publication 52740 "BIOS and Kernel Developer’s Guide (BKDG)
  20. * for AMD Family 16h Models 30h-3Fh Processors"
  21. * AMD Publication 55570-B1-PUB "Processor Programming Reference (PPR)
  22. * for AMD Family 17h Model 18h, Revision B1
  23. * Processors (PUB)
  24. * AMD Publication 55772-A1-PUB "Processor Programming Reference (PPR)
  25. * for AMD Family 17h Model 20h, Revision A1
  26. * Processors (PUB)
  27. */
  28. /*
  29. * Includes, defines, variables, module parameters, ...
  30. */
  31. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  32. #include <linux/init.h>
  33. #include <linux/io.h>
  34. #include <linux/ioport.h>
  35. #include <linux/module.h>
  36. #include <linux/moduleparam.h>
  37. #include <linux/pci.h>
  38. #include <linux/platform_device.h>
  39. #include <linux/types.h>
  40. #include <linux/watchdog.h>
  41. #include "sp5100_tco.h"
  42. #define TCO_DRIVER_NAME "sp5100-tco"
  43. /* internal variables */
  44. enum tco_reg_layout {
  45. sp5100, sb800, efch, efch_mmio
  46. };
  47. struct sp5100_tco {
  48. struct watchdog_device wdd;
  49. void __iomem *tcobase;
  50. enum tco_reg_layout tco_reg_layout;
  51. };
  52. /* the watchdog platform device */
  53. static struct platform_device *sp5100_tco_platform_device;
  54. /* the associated PCI device */
  55. static struct pci_dev *sp5100_tco_pci;
  56. /* module parameters */
  57. #define WATCHDOG_ACTION 0
  58. static bool action = WATCHDOG_ACTION;
  59. module_param(action, bool, 0);
  60. MODULE_PARM_DESC(action, "Action taken when watchdog expires, 0 to reset, 1 to poweroff (default="
  61. __MODULE_STRING(WATCHDOG_ACTION) ")");
  62. #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat. */
  63. static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
  64. module_param(heartbeat, int, 0);
  65. MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
  66. __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
  67. static bool nowayout = WATCHDOG_NOWAYOUT;
  68. module_param(nowayout, bool, 0);
  69. MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started."
  70. " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  71. /*
  72. * Some TCO specific functions
  73. */
  74. static enum tco_reg_layout tco_reg_layout(struct pci_dev *dev)
  75. {
  76. if (dev->vendor == PCI_VENDOR_ID_ATI &&
  77. dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
  78. dev->revision < 0x40) {
  79. return sp5100;
  80. } else if (dev->vendor == PCI_VENDOR_ID_AMD &&
  81. sp5100_tco_pci->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
  82. sp5100_tco_pci->revision >= AMD_ZEN_SMBUS_PCI_REV) {
  83. return efch_mmio;
  84. } else if ((dev->vendor == PCI_VENDOR_ID_AMD || dev->vendor == PCI_VENDOR_ID_HYGON) &&
  85. ((dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
  86. dev->revision >= 0x41) ||
  87. (dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
  88. dev->revision >= 0x49))) {
  89. return efch;
  90. }
  91. return sb800;
  92. }
  93. static int tco_timer_start(struct watchdog_device *wdd)
  94. {
  95. struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
  96. u32 val;
  97. val = readl(SP5100_WDT_CONTROL(tco->tcobase));
  98. val |= SP5100_WDT_START_STOP_BIT;
  99. writel(val, SP5100_WDT_CONTROL(tco->tcobase));
  100. /* This must be a distinct write. */
  101. val |= SP5100_WDT_TRIGGER_BIT;
  102. writel(val, SP5100_WDT_CONTROL(tco->tcobase));
  103. return 0;
  104. }
  105. static int tco_timer_stop(struct watchdog_device *wdd)
  106. {
  107. struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
  108. u32 val;
  109. val = readl(SP5100_WDT_CONTROL(tco->tcobase));
  110. val &= ~SP5100_WDT_START_STOP_BIT;
  111. writel(val, SP5100_WDT_CONTROL(tco->tcobase));
  112. return 0;
  113. }
  114. static int tco_timer_ping(struct watchdog_device *wdd)
  115. {
  116. struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
  117. u32 val;
  118. val = readl(SP5100_WDT_CONTROL(tco->tcobase));
  119. val |= SP5100_WDT_TRIGGER_BIT;
  120. writel(val, SP5100_WDT_CONTROL(tco->tcobase));
  121. return 0;
  122. }
  123. static int tco_timer_set_timeout(struct watchdog_device *wdd,
  124. unsigned int t)
  125. {
  126. struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
  127. /* Write new heartbeat to watchdog */
  128. writel(t, SP5100_WDT_COUNT(tco->tcobase));
  129. wdd->timeout = t;
  130. return 0;
  131. }
  132. static unsigned int tco_timer_get_timeleft(struct watchdog_device *wdd)
  133. {
  134. struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
  135. return readl(SP5100_WDT_COUNT(tco->tcobase));
  136. }
  137. static u8 sp5100_tco_read_pm_reg8(u8 index)
  138. {
  139. outb(index, SP5100_IO_PM_INDEX_REG);
  140. return inb(SP5100_IO_PM_DATA_REG);
  141. }
  142. static void sp5100_tco_update_pm_reg8(u8 index, u8 reset, u8 set)
  143. {
  144. u8 val;
  145. outb(index, SP5100_IO_PM_INDEX_REG);
  146. val = inb(SP5100_IO_PM_DATA_REG);
  147. val &= reset;
  148. val |= set;
  149. outb(val, SP5100_IO_PM_DATA_REG);
  150. }
  151. static void tco_timer_enable(struct sp5100_tco *tco)
  152. {
  153. u32 val;
  154. switch (tco->tco_reg_layout) {
  155. case sb800:
  156. /* For SB800 or later */
  157. /* Set the Watchdog timer resolution to 1 sec */
  158. sp5100_tco_update_pm_reg8(SB800_PM_WATCHDOG_CONFIG,
  159. 0xff, SB800_PM_WATCHDOG_SECOND_RES);
  160. /* Enable watchdog decode bit and watchdog timer */
  161. sp5100_tco_update_pm_reg8(SB800_PM_WATCHDOG_CONTROL,
  162. ~SB800_PM_WATCHDOG_DISABLE,
  163. SB800_PCI_WATCHDOG_DECODE_EN);
  164. break;
  165. case sp5100:
  166. /* For SP5100 or SB7x0 */
  167. /* Enable watchdog decode bit */
  168. pci_read_config_dword(sp5100_tco_pci,
  169. SP5100_PCI_WATCHDOG_MISC_REG,
  170. &val);
  171. val |= SP5100_PCI_WATCHDOG_DECODE_EN;
  172. pci_write_config_dword(sp5100_tco_pci,
  173. SP5100_PCI_WATCHDOG_MISC_REG,
  174. val);
  175. /* Enable Watchdog timer and set the resolution to 1 sec */
  176. sp5100_tco_update_pm_reg8(SP5100_PM_WATCHDOG_CONTROL,
  177. ~SP5100_PM_WATCHDOG_DISABLE,
  178. SP5100_PM_WATCHDOG_SECOND_RES);
  179. break;
  180. case efch:
  181. /* Set the Watchdog timer resolution to 1 sec and enable */
  182. sp5100_tco_update_pm_reg8(EFCH_PM_DECODEEN3,
  183. ~EFCH_PM_WATCHDOG_DISABLE,
  184. EFCH_PM_DECODEEN_SECOND_RES);
  185. break;
  186. default:
  187. break;
  188. }
  189. }
  190. static u32 sp5100_tco_read_pm_reg32(u8 index)
  191. {
  192. u32 val = 0;
  193. int i;
  194. for (i = 3; i >= 0; i--)
  195. val = (val << 8) + sp5100_tco_read_pm_reg8(index + i);
  196. return val;
  197. }
  198. static u32 sp5100_tco_request_region(struct device *dev,
  199. u32 mmio_addr,
  200. const char *dev_name)
  201. {
  202. if (!devm_request_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE,
  203. dev_name)) {
  204. dev_dbg(dev, "MMIO address 0x%08x already in use\n", mmio_addr);
  205. return 0;
  206. }
  207. return mmio_addr;
  208. }
  209. static u32 sp5100_tco_prepare_base(struct sp5100_tco *tco,
  210. u32 mmio_addr,
  211. u32 alt_mmio_addr,
  212. const char *dev_name)
  213. {
  214. struct device *dev = tco->wdd.parent;
  215. dev_dbg(dev, "Got 0x%08x from SBResource_MMIO register\n", mmio_addr);
  216. if (!mmio_addr && !alt_mmio_addr)
  217. return -ENODEV;
  218. /* Check for MMIO address and alternate MMIO address conflicts */
  219. if (mmio_addr)
  220. mmio_addr = sp5100_tco_request_region(dev, mmio_addr, dev_name);
  221. if (!mmio_addr && alt_mmio_addr)
  222. mmio_addr = sp5100_tco_request_region(dev, alt_mmio_addr, dev_name);
  223. if (!mmio_addr) {
  224. dev_err(dev, "Failed to reserve MMIO or alternate MMIO region\n");
  225. return -EBUSY;
  226. }
  227. tco->tcobase = devm_ioremap(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
  228. if (!tco->tcobase) {
  229. dev_err(dev, "MMIO address 0x%08x failed mapping\n", mmio_addr);
  230. devm_release_mem_region(dev, mmio_addr, SP5100_WDT_MEM_MAP_SIZE);
  231. return -ENOMEM;
  232. }
  233. dev_info(dev, "Using 0x%08x for watchdog MMIO address\n", mmio_addr);
  234. return 0;
  235. }
  236. static int sp5100_tco_timer_init(struct sp5100_tco *tco)
  237. {
  238. struct watchdog_device *wdd = &tco->wdd;
  239. struct device *dev = wdd->parent;
  240. u32 val;
  241. val = readl(SP5100_WDT_CONTROL(tco->tcobase));
  242. if (val & SP5100_WDT_DISABLED) {
  243. dev_err(dev, "Watchdog hardware is disabled\n");
  244. return -ENODEV;
  245. }
  246. /*
  247. * Save WatchDogFired status, because WatchDogFired flag is
  248. * cleared here.
  249. */
  250. if (val & SP5100_WDT_FIRED)
  251. wdd->bootstatus = WDIOF_CARDRESET;
  252. /* Set watchdog action */
  253. if (action)
  254. val |= SP5100_WDT_ACTION_RESET;
  255. else
  256. val &= ~SP5100_WDT_ACTION_RESET;
  257. writel(val, SP5100_WDT_CONTROL(tco->tcobase));
  258. /* Set a reasonable heartbeat before we stop the timer */
  259. tco_timer_set_timeout(wdd, wdd->timeout);
  260. /*
  261. * Stop the TCO before we change anything so we don't race with
  262. * a zeroed timer.
  263. */
  264. tco_timer_stop(wdd);
  265. return 0;
  266. }
  267. static u8 efch_read_pm_reg8(void __iomem *addr, u8 index)
  268. {
  269. return readb(addr + index);
  270. }
  271. static void efch_update_pm_reg8(void __iomem *addr, u8 index, u8 reset, u8 set)
  272. {
  273. u8 val;
  274. val = readb(addr + index);
  275. val &= reset;
  276. val |= set;
  277. writeb(val, addr + index);
  278. }
  279. static void tco_timer_enable_mmio(void __iomem *addr)
  280. {
  281. efch_update_pm_reg8(addr, EFCH_PM_DECODEEN3,
  282. ~EFCH_PM_WATCHDOG_DISABLE,
  283. EFCH_PM_DECODEEN_SECOND_RES);
  284. }
  285. static int sp5100_tco_setupdevice_mmio(struct device *dev,
  286. struct watchdog_device *wdd)
  287. {
  288. struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
  289. const char *dev_name = SB800_DEVNAME;
  290. u32 mmio_addr = 0, alt_mmio_addr = 0;
  291. struct resource *res;
  292. void __iomem *addr;
  293. int ret;
  294. u32 val;
  295. res = request_mem_region_muxed(EFCH_PM_ACPI_MMIO_PM_ADDR,
  296. EFCH_PM_ACPI_MMIO_PM_SIZE,
  297. "sp5100_tco");
  298. if (!res) {
  299. dev_err(dev,
  300. "Memory region 0x%08x already in use\n",
  301. EFCH_PM_ACPI_MMIO_PM_ADDR);
  302. return -EBUSY;
  303. }
  304. addr = ioremap(EFCH_PM_ACPI_MMIO_PM_ADDR, EFCH_PM_ACPI_MMIO_PM_SIZE);
  305. if (!addr) {
  306. dev_err(dev, "Address mapping failed\n");
  307. ret = -ENOMEM;
  308. goto out;
  309. }
  310. /*
  311. * EFCH_PM_DECODEEN_WDT_TMREN is dual purpose. This bitfield
  312. * enables sp5100_tco register MMIO space decoding. The bitfield
  313. * also starts the timer operation. Enable if not already enabled.
  314. */
  315. val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN);
  316. if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
  317. efch_update_pm_reg8(addr, EFCH_PM_DECODEEN, 0xff,
  318. EFCH_PM_DECODEEN_WDT_TMREN);
  319. }
  320. /* Error if the timer could not be enabled */
  321. val = efch_read_pm_reg8(addr, EFCH_PM_DECODEEN);
  322. if (!(val & EFCH_PM_DECODEEN_WDT_TMREN)) {
  323. dev_err(dev, "Failed to enable the timer\n");
  324. ret = -EFAULT;
  325. goto out;
  326. }
  327. mmio_addr = EFCH_PM_WDT_ADDR;
  328. /* Determine alternate MMIO base address */
  329. val = efch_read_pm_reg8(addr, EFCH_PM_ISACONTROL);
  330. if (val & EFCH_PM_ISACONTROL_MMIOEN)
  331. alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
  332. EFCH_PM_ACPI_MMIO_WDT_OFFSET;
  333. ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
  334. if (!ret) {
  335. tco_timer_enable_mmio(addr);
  336. ret = sp5100_tco_timer_init(tco);
  337. }
  338. out:
  339. if (addr)
  340. iounmap(addr);
  341. release_resource(res);
  342. kfree(res);
  343. return ret;
  344. }
  345. static int sp5100_tco_setupdevice(struct device *dev,
  346. struct watchdog_device *wdd)
  347. {
  348. struct sp5100_tco *tco = watchdog_get_drvdata(wdd);
  349. const char *dev_name;
  350. u32 mmio_addr = 0, val;
  351. u32 alt_mmio_addr = 0;
  352. int ret;
  353. if (tco->tco_reg_layout == efch_mmio)
  354. return sp5100_tco_setupdevice_mmio(dev, wdd);
  355. /* Request the IO ports used by this driver */
  356. if (!request_muxed_region(SP5100_IO_PM_INDEX_REG,
  357. SP5100_PM_IOPORTS_SIZE, "sp5100_tco")) {
  358. dev_err(dev, "I/O address 0x%04x already in use\n",
  359. SP5100_IO_PM_INDEX_REG);
  360. return -EBUSY;
  361. }
  362. /*
  363. * Determine type of southbridge chipset.
  364. */
  365. switch (tco->tco_reg_layout) {
  366. case sp5100:
  367. dev_name = SP5100_DEVNAME;
  368. mmio_addr = sp5100_tco_read_pm_reg32(SP5100_PM_WATCHDOG_BASE) &
  369. 0xfffffff8;
  370. /*
  371. * Secondly, find the watchdog timer MMIO address
  372. * from SBResource_MMIO register.
  373. */
  374. /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */
  375. pci_read_config_dword(sp5100_tco_pci,
  376. SP5100_SB_RESOURCE_MMIO_BASE,
  377. &val);
  378. /* Verify MMIO is enabled and using bar0 */
  379. if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
  380. alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
  381. break;
  382. case sb800:
  383. dev_name = SB800_DEVNAME;
  384. mmio_addr = sp5100_tco_read_pm_reg32(SB800_PM_WATCHDOG_BASE) &
  385. 0xfffffff8;
  386. /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */
  387. val = sp5100_tco_read_pm_reg32(SB800_PM_ACPI_MMIO_EN);
  388. /* Verify MMIO is enabled and using bar0 */
  389. if ((val & SB800_ACPI_MMIO_MASK) == SB800_ACPI_MMIO_DECODE_EN)
  390. alt_mmio_addr = (val & ~0xfff) + SB800_PM_WDT_MMIO_OFFSET;
  391. break;
  392. case efch:
  393. dev_name = SB800_DEVNAME;
  394. val = sp5100_tco_read_pm_reg8(EFCH_PM_DECODEEN);
  395. if (val & EFCH_PM_DECODEEN_WDT_TMREN)
  396. mmio_addr = EFCH_PM_WDT_ADDR;
  397. val = sp5100_tco_read_pm_reg8(EFCH_PM_ISACONTROL);
  398. if (val & EFCH_PM_ISACONTROL_MMIOEN)
  399. alt_mmio_addr = EFCH_PM_ACPI_MMIO_ADDR +
  400. EFCH_PM_ACPI_MMIO_WDT_OFFSET;
  401. break;
  402. default:
  403. return -ENODEV;
  404. }
  405. ret = sp5100_tco_prepare_base(tco, mmio_addr, alt_mmio_addr, dev_name);
  406. if (!ret) {
  407. /* Setup the watchdog timer */
  408. tco_timer_enable(tco);
  409. ret = sp5100_tco_timer_init(tco);
  410. }
  411. release_region(SP5100_IO_PM_INDEX_REG, SP5100_PM_IOPORTS_SIZE);
  412. return ret;
  413. }
  414. static struct watchdog_info sp5100_tco_wdt_info = {
  415. .identity = "SP5100 TCO timer",
  416. .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
  417. };
  418. static const struct watchdog_ops sp5100_tco_wdt_ops = {
  419. .owner = THIS_MODULE,
  420. .start = tco_timer_start,
  421. .stop = tco_timer_stop,
  422. .ping = tco_timer_ping,
  423. .set_timeout = tco_timer_set_timeout,
  424. .get_timeleft = tco_timer_get_timeleft,
  425. };
  426. static int sp5100_tco_probe(struct platform_device *pdev)
  427. {
  428. struct device *dev = &pdev->dev;
  429. struct watchdog_device *wdd;
  430. struct sp5100_tco *tco;
  431. int ret;
  432. tco = devm_kzalloc(dev, sizeof(*tco), GFP_KERNEL);
  433. if (!tco)
  434. return -ENOMEM;
  435. tco->tco_reg_layout = tco_reg_layout(sp5100_tco_pci);
  436. wdd = &tco->wdd;
  437. wdd->parent = dev;
  438. wdd->info = &sp5100_tco_wdt_info;
  439. wdd->ops = &sp5100_tco_wdt_ops;
  440. wdd->timeout = WATCHDOG_HEARTBEAT;
  441. wdd->min_timeout = 1;
  442. wdd->max_timeout = 0xffff;
  443. watchdog_init_timeout(wdd, heartbeat, NULL);
  444. watchdog_set_nowayout(wdd, nowayout);
  445. watchdog_stop_on_reboot(wdd);
  446. watchdog_stop_on_unregister(wdd);
  447. watchdog_set_drvdata(wdd, tco);
  448. ret = sp5100_tco_setupdevice(dev, wdd);
  449. if (ret)
  450. return ret;
  451. ret = devm_watchdog_register_device(dev, wdd);
  452. if (ret)
  453. return ret;
  454. /* Show module parameters */
  455. dev_info(dev, "initialized. heartbeat=%d sec (nowayout=%d)\n",
  456. wdd->timeout, nowayout);
  457. return 0;
  458. }
  459. static struct platform_driver sp5100_tco_driver = {
  460. .probe = sp5100_tco_probe,
  461. .driver = {
  462. .name = TCO_DRIVER_NAME,
  463. },
  464. };
  465. /*
  466. * Data for PCI driver interface
  467. *
  468. * This data only exists for exporting the supported
  469. * PCI ids via MODULE_DEVICE_TABLE. We do not actually
  470. * register a pci_driver, because someone else might
  471. * want to register another driver on the same PCI id.
  472. */
  473. static const struct pci_device_id sp5100_tco_pci_tbl[] = {
  474. { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
  475. PCI_ANY_ID, },
  476. { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID,
  477. PCI_ANY_ID, },
  478. { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, PCI_ANY_ID,
  479. PCI_ANY_ID, },
  480. { PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, PCI_ANY_ID,
  481. PCI_ANY_ID, },
  482. { 0, }, /* End of list */
  483. };
  484. MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
  485. static int __init sp5100_tco_init(void)
  486. {
  487. struct pci_dev *dev = NULL;
  488. int err;
  489. /* Match the PCI device */
  490. for_each_pci_dev(dev) {
  491. if (pci_match_id(sp5100_tco_pci_tbl, dev) != NULL) {
  492. sp5100_tco_pci = dev;
  493. break;
  494. }
  495. }
  496. if (!sp5100_tco_pci)
  497. return -ENODEV;
  498. pr_info("SP5100/SB800 TCO WatchDog Timer Driver\n");
  499. err = platform_driver_register(&sp5100_tco_driver);
  500. if (err)
  501. return err;
  502. sp5100_tco_platform_device =
  503. platform_device_register_simple(TCO_DRIVER_NAME, -1, NULL, 0);
  504. if (IS_ERR(sp5100_tco_platform_device)) {
  505. err = PTR_ERR(sp5100_tco_platform_device);
  506. goto unreg_platform_driver;
  507. }
  508. return 0;
  509. unreg_platform_driver:
  510. platform_driver_unregister(&sp5100_tco_driver);
  511. return err;
  512. }
  513. static void __exit sp5100_tco_exit(void)
  514. {
  515. platform_device_unregister(sp5100_tco_platform_device);
  516. platform_driver_unregister(&sp5100_tco_driver);
  517. }
  518. module_init(sp5100_tco_init);
  519. module_exit(sp5100_tco_exit);
  520. MODULE_AUTHOR("Priyanka Gupta");
  521. MODULE_DESCRIPTION("TCO timer driver for SP5100/SB800 chipset");
  522. MODULE_LICENSE("GPL");