iTCO_wdt.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  1. /*
  2. * intel TCO Watchdog Driver
  3. *
  4. * (c) Copyright 2006-2011 Wim Van Sebroeck <wim@iguana.be>.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. *
  11. * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
  12. * provide warranty for any of this software. This material is
  13. * provided "AS-IS" and at no charge.
  14. *
  15. * The TCO watchdog is implemented in the following I/O controller hubs:
  16. * (See the intel documentation on http://developer.intel.com.)
  17. * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO)
  18. * document number 290687-002, 298242-027: 82801BA (ICH2)
  19. * document number 290733-003, 290739-013: 82801CA (ICH3-S)
  20. * document number 290716-001, 290718-007: 82801CAM (ICH3-M)
  21. * document number 290744-001, 290745-025: 82801DB (ICH4)
  22. * document number 252337-001, 252663-008: 82801DBM (ICH4-M)
  23. * document number 273599-001, 273645-002: 82801E (C-ICH)
  24. * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R)
  25. * document number 300641-004, 300884-013: 6300ESB
  26. * document number 301473-002, 301474-026: 82801F (ICH6)
  27. * document number 313082-001, 313075-006: 631xESB, 632xESB
  28. * document number 307013-003, 307014-024: 82801G (ICH7)
  29. * document number 322896-001, 322897-001: NM10
  30. * document number 313056-003, 313057-017: 82801H (ICH8)
  31. * document number 316972-004, 316973-012: 82801I (ICH9)
  32. * document number 319973-002, 319974-002: 82801J (ICH10)
  33. * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
  34. * document number 320066-003, 320257-008: EP80597 (IICH)
  35. * document number 324645-001, 324646-001: Cougar Point (CPT)
  36. * document number TBD : Patsburg (PBG)
  37. * document number TBD : DH89xxCC
  38. * document number TBD : Panther Point
  39. * document number TBD : Lynx Point
  40. */
  41. /*
  42. * Includes, defines, variables, module parameters, ...
  43. */
  44. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  45. /* Module and version information */
  46. #define DRV_NAME "iTCO_wdt"
  47. #define DRV_VERSION "1.07"
  48. /* Includes */
  49. #include <linux/module.h> /* For module specific items */
  50. #include <linux/moduleparam.h> /* For new moduleparam's */
  51. #include <linux/types.h> /* For standard types (like size_t) */
  52. #include <linux/errno.h> /* For the -ENODEV/... values */
  53. #include <linux/kernel.h> /* For printk/panic/... */
  54. #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV
  55. (WATCHDOG_MINOR) */
  56. #include <linux/watchdog.h> /* For the watchdog specific items */
  57. #include <linux/init.h> /* For __init/__exit/... */
  58. #include <linux/fs.h> /* For file operations */
  59. #include <linux/platform_device.h> /* For platform_driver framework */
  60. #include <linux/pci.h> /* For pci functions */
  61. #include <linux/ioport.h> /* For io-port access */
  62. #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
  63. #include <linux/uaccess.h> /* For copy_to_user/put_user/... */
  64. #include <linux/io.h> /* For inb/outb/... */
  65. #include "iTCO_vendor.h"
  66. /* TCO related info */
  67. enum iTCO_chipsets {
  68. TCO_ICH = 0, /* ICH */
  69. TCO_ICH0, /* ICH0 */
  70. TCO_ICH2, /* ICH2 */
  71. TCO_ICH2M, /* ICH2-M */
  72. TCO_ICH3, /* ICH3-S */
  73. TCO_ICH3M, /* ICH3-M */
  74. TCO_ICH4, /* ICH4 */
  75. TCO_ICH4M, /* ICH4-M */
  76. TCO_CICH, /* C-ICH */
  77. TCO_ICH5, /* ICH5 & ICH5R */
  78. TCO_6300ESB, /* 6300ESB */
  79. TCO_ICH6, /* ICH6 & ICH6R */
  80. TCO_ICH6M, /* ICH6-M */
  81. TCO_ICH6W, /* ICH6W & ICH6RW */
  82. TCO_631XESB, /* 631xESB/632xESB */
  83. TCO_ICH7, /* ICH7 & ICH7R */
  84. TCO_ICH7DH, /* ICH7DH */
  85. TCO_ICH7M, /* ICH7-M & ICH7-U */
  86. TCO_ICH7MDH, /* ICH7-M DH */
  87. TCO_NM10, /* NM10 */
  88. TCO_ICH8, /* ICH8 & ICH8R */
  89. TCO_ICH8DH, /* ICH8DH */
  90. TCO_ICH8DO, /* ICH8DO */
  91. TCO_ICH8M, /* ICH8M */
  92. TCO_ICH8ME, /* ICH8M-E */
  93. TCO_ICH9, /* ICH9 */
  94. TCO_ICH9R, /* ICH9R */
  95. TCO_ICH9DH, /* ICH9DH */
  96. TCO_ICH9DO, /* ICH9DO */
  97. TCO_ICH9M, /* ICH9M */
  98. TCO_ICH9ME, /* ICH9M-E */
  99. TCO_ICH10, /* ICH10 */
  100. TCO_ICH10R, /* ICH10R */
  101. TCO_ICH10D, /* ICH10D */
  102. TCO_ICH10DO, /* ICH10DO */
  103. TCO_PCH, /* PCH Desktop Full Featured */
  104. TCO_PCHM, /* PCH Mobile Full Featured */
  105. TCO_P55, /* P55 */
  106. TCO_PM55, /* PM55 */
  107. TCO_H55, /* H55 */
  108. TCO_QM57, /* QM57 */
  109. TCO_H57, /* H57 */
  110. TCO_HM55, /* HM55 */
  111. TCO_Q57, /* Q57 */
  112. TCO_HM57, /* HM57 */
  113. TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */
  114. TCO_QS57, /* QS57 */
  115. TCO_3400, /* 3400 */
  116. TCO_3420, /* 3420 */
  117. TCO_3450, /* 3450 */
  118. TCO_EP80579, /* EP80579 */
  119. TCO_CPT, /* Cougar Point */
  120. TCO_CPTD, /* Cougar Point Desktop */
  121. TCO_CPTM, /* Cougar Point Mobile */
  122. TCO_PBG, /* Patsburg */
  123. TCO_DH89XXCC, /* DH89xxCC */
  124. TCO_PPT, /* Panther Point */
  125. TCO_LPT, /* Lynx Point */
  126. };
  127. static struct {
  128. char *name;
  129. unsigned int iTCO_version;
  130. } iTCO_chipset_info[] __devinitdata = {
  131. {"ICH", 1},
  132. {"ICH0", 1},
  133. {"ICH2", 1},
  134. {"ICH2-M", 1},
  135. {"ICH3-S", 1},
  136. {"ICH3-M", 1},
  137. {"ICH4", 1},
  138. {"ICH4-M", 1},
  139. {"C-ICH", 1},
  140. {"ICH5 or ICH5R", 1},
  141. {"6300ESB", 1},
  142. {"ICH6 or ICH6R", 2},
  143. {"ICH6-M", 2},
  144. {"ICH6W or ICH6RW", 2},
  145. {"631xESB/632xESB", 2},
  146. {"ICH7 or ICH7R", 2},
  147. {"ICH7DH", 2},
  148. {"ICH7-M or ICH7-U", 2},
  149. {"ICH7-M DH", 2},
  150. {"NM10", 2},
  151. {"ICH8 or ICH8R", 2},
  152. {"ICH8DH", 2},
  153. {"ICH8DO", 2},
  154. {"ICH8M", 2},
  155. {"ICH8M-E", 2},
  156. {"ICH9", 2},
  157. {"ICH9R", 2},
  158. {"ICH9DH", 2},
  159. {"ICH9DO", 2},
  160. {"ICH9M", 2},
  161. {"ICH9M-E", 2},
  162. {"ICH10", 2},
  163. {"ICH10R", 2},
  164. {"ICH10D", 2},
  165. {"ICH10DO", 2},
  166. {"PCH Desktop Full Featured", 2},
  167. {"PCH Mobile Full Featured", 2},
  168. {"P55", 2},
  169. {"PM55", 2},
  170. {"H55", 2},
  171. {"QM57", 2},
  172. {"H57", 2},
  173. {"HM55", 2},
  174. {"Q57", 2},
  175. {"HM57", 2},
  176. {"PCH Mobile SFF Full Featured", 2},
  177. {"QS57", 2},
  178. {"3400", 2},
  179. {"3420", 2},
  180. {"3450", 2},
  181. {"EP80579", 2},
  182. {"Cougar Point", 2},
  183. {"Cougar Point Desktop", 2},
  184. {"Cougar Point Mobile", 2},
  185. {"Patsburg", 2},
  186. {"DH89xxCC", 2},
  187. {"Panther Point", 2},
  188. {"Lynx Point", 2},
  189. {NULL, 0}
  190. };
  191. /*
  192. * This data only exists for exporting the supported PCI ids
  193. * via MODULE_DEVICE_TABLE. We do not actually register a
  194. * pci_driver, because the I/O Controller Hub has also other
  195. * functions that probably will be registered by other drivers.
  196. */
  197. static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
  198. { PCI_VDEVICE(INTEL, 0x2410), TCO_ICH},
  199. { PCI_VDEVICE(INTEL, 0x2420), TCO_ICH0},
  200. { PCI_VDEVICE(INTEL, 0x2440), TCO_ICH2},
  201. { PCI_VDEVICE(INTEL, 0x244c), TCO_ICH2M},
  202. { PCI_VDEVICE(INTEL, 0x2480), TCO_ICH3},
  203. { PCI_VDEVICE(INTEL, 0x248c), TCO_ICH3M},
  204. { PCI_VDEVICE(INTEL, 0x24c0), TCO_ICH4},
  205. { PCI_VDEVICE(INTEL, 0x24cc), TCO_ICH4M},
  206. { PCI_VDEVICE(INTEL, 0x2450), TCO_CICH},
  207. { PCI_VDEVICE(INTEL, 0x24d0), TCO_ICH5},
  208. { PCI_VDEVICE(INTEL, 0x25a1), TCO_6300ESB},
  209. { PCI_VDEVICE(INTEL, 0x2640), TCO_ICH6},
  210. { PCI_VDEVICE(INTEL, 0x2641), TCO_ICH6M},
  211. { PCI_VDEVICE(INTEL, 0x2642), TCO_ICH6W},
  212. { PCI_VDEVICE(INTEL, 0x2670), TCO_631XESB},
  213. { PCI_VDEVICE(INTEL, 0x2671), TCO_631XESB},
  214. { PCI_VDEVICE(INTEL, 0x2672), TCO_631XESB},
  215. { PCI_VDEVICE(INTEL, 0x2673), TCO_631XESB},
  216. { PCI_VDEVICE(INTEL, 0x2674), TCO_631XESB},
  217. { PCI_VDEVICE(INTEL, 0x2675), TCO_631XESB},
  218. { PCI_VDEVICE(INTEL, 0x2676), TCO_631XESB},
  219. { PCI_VDEVICE(INTEL, 0x2677), TCO_631XESB},
  220. { PCI_VDEVICE(INTEL, 0x2678), TCO_631XESB},
  221. { PCI_VDEVICE(INTEL, 0x2679), TCO_631XESB},
  222. { PCI_VDEVICE(INTEL, 0x267a), TCO_631XESB},
  223. { PCI_VDEVICE(INTEL, 0x267b), TCO_631XESB},
  224. { PCI_VDEVICE(INTEL, 0x267c), TCO_631XESB},
  225. { PCI_VDEVICE(INTEL, 0x267d), TCO_631XESB},
  226. { PCI_VDEVICE(INTEL, 0x267e), TCO_631XESB},
  227. { PCI_VDEVICE(INTEL, 0x267f), TCO_631XESB},
  228. { PCI_VDEVICE(INTEL, 0x27b8), TCO_ICH7},
  229. { PCI_VDEVICE(INTEL, 0x27b0), TCO_ICH7DH},
  230. { PCI_VDEVICE(INTEL, 0x27b9), TCO_ICH7M},
  231. { PCI_VDEVICE(INTEL, 0x27bd), TCO_ICH7MDH},
  232. { PCI_VDEVICE(INTEL, 0x27bc), TCO_NM10},
  233. { PCI_VDEVICE(INTEL, 0x2810), TCO_ICH8},
  234. { PCI_VDEVICE(INTEL, 0x2812), TCO_ICH8DH},
  235. { PCI_VDEVICE(INTEL, 0x2814), TCO_ICH8DO},
  236. { PCI_VDEVICE(INTEL, 0x2815), TCO_ICH8M},
  237. { PCI_VDEVICE(INTEL, 0x2811), TCO_ICH8ME},
  238. { PCI_VDEVICE(INTEL, 0x2918), TCO_ICH9},
  239. { PCI_VDEVICE(INTEL, 0x2916), TCO_ICH9R},
  240. { PCI_VDEVICE(INTEL, 0x2912), TCO_ICH9DH},
  241. { PCI_VDEVICE(INTEL, 0x2914), TCO_ICH9DO},
  242. { PCI_VDEVICE(INTEL, 0x2919), TCO_ICH9M},
  243. { PCI_VDEVICE(INTEL, 0x2917), TCO_ICH9ME},
  244. { PCI_VDEVICE(INTEL, 0x3a18), TCO_ICH10},
  245. { PCI_VDEVICE(INTEL, 0x3a16), TCO_ICH10R},
  246. { PCI_VDEVICE(INTEL, 0x3a1a), TCO_ICH10D},
  247. { PCI_VDEVICE(INTEL, 0x3a14), TCO_ICH10DO},
  248. { PCI_VDEVICE(INTEL, 0x3b00), TCO_PCH},
  249. { PCI_VDEVICE(INTEL, 0x3b01), TCO_PCHM},
  250. { PCI_VDEVICE(INTEL, 0x3b02), TCO_P55},
  251. { PCI_VDEVICE(INTEL, 0x3b03), TCO_PM55},
  252. { PCI_VDEVICE(INTEL, 0x3b06), TCO_H55},
  253. { PCI_VDEVICE(INTEL, 0x3b07), TCO_QM57},
  254. { PCI_VDEVICE(INTEL, 0x3b08), TCO_H57},
  255. { PCI_VDEVICE(INTEL, 0x3b09), TCO_HM55},
  256. { PCI_VDEVICE(INTEL, 0x3b0a), TCO_Q57},
  257. { PCI_VDEVICE(INTEL, 0x3b0b), TCO_HM57},
  258. { PCI_VDEVICE(INTEL, 0x3b0d), TCO_PCHMSFF},
  259. { PCI_VDEVICE(INTEL, 0x3b0f), TCO_QS57},
  260. { PCI_VDEVICE(INTEL, 0x3b12), TCO_3400},
  261. { PCI_VDEVICE(INTEL, 0x3b14), TCO_3420},
  262. { PCI_VDEVICE(INTEL, 0x3b16), TCO_3450},
  263. { PCI_VDEVICE(INTEL, 0x5031), TCO_EP80579},
  264. { PCI_VDEVICE(INTEL, 0x1c41), TCO_CPT},
  265. { PCI_VDEVICE(INTEL, 0x1c42), TCO_CPTD},
  266. { PCI_VDEVICE(INTEL, 0x1c43), TCO_CPTM},
  267. { PCI_VDEVICE(INTEL, 0x1c44), TCO_CPT},
  268. { PCI_VDEVICE(INTEL, 0x1c45), TCO_CPT},
  269. { PCI_VDEVICE(INTEL, 0x1c46), TCO_CPT},
  270. { PCI_VDEVICE(INTEL, 0x1c47), TCO_CPT},
  271. { PCI_VDEVICE(INTEL, 0x1c48), TCO_CPT},
  272. { PCI_VDEVICE(INTEL, 0x1c49), TCO_CPT},
  273. { PCI_VDEVICE(INTEL, 0x1c4a), TCO_CPT},
  274. { PCI_VDEVICE(INTEL, 0x1c4b), TCO_CPT},
  275. { PCI_VDEVICE(INTEL, 0x1c4c), TCO_CPT},
  276. { PCI_VDEVICE(INTEL, 0x1c4d), TCO_CPT},
  277. { PCI_VDEVICE(INTEL, 0x1c4e), TCO_CPT},
  278. { PCI_VDEVICE(INTEL, 0x1c4f), TCO_CPT},
  279. { PCI_VDEVICE(INTEL, 0x1c50), TCO_CPT},
  280. { PCI_VDEVICE(INTEL, 0x1c51), TCO_CPT},
  281. { PCI_VDEVICE(INTEL, 0x1c52), TCO_CPT},
  282. { PCI_VDEVICE(INTEL, 0x1c53), TCO_CPT},
  283. { PCI_VDEVICE(INTEL, 0x1c54), TCO_CPT},
  284. { PCI_VDEVICE(INTEL, 0x1c55), TCO_CPT},
  285. { PCI_VDEVICE(INTEL, 0x1c56), TCO_CPT},
  286. { PCI_VDEVICE(INTEL, 0x1c57), TCO_CPT},
  287. { PCI_VDEVICE(INTEL, 0x1c58), TCO_CPT},
  288. { PCI_VDEVICE(INTEL, 0x1c59), TCO_CPT},
  289. { PCI_VDEVICE(INTEL, 0x1c5a), TCO_CPT},
  290. { PCI_VDEVICE(INTEL, 0x1c5b), TCO_CPT},
  291. { PCI_VDEVICE(INTEL, 0x1c5c), TCO_CPT},
  292. { PCI_VDEVICE(INTEL, 0x1c5d), TCO_CPT},
  293. { PCI_VDEVICE(INTEL, 0x1c5e), TCO_CPT},
  294. { PCI_VDEVICE(INTEL, 0x1c5f), TCO_CPT},
  295. { PCI_VDEVICE(INTEL, 0x1d40), TCO_PBG},
  296. { PCI_VDEVICE(INTEL, 0x1d41), TCO_PBG},
  297. { PCI_VDEVICE(INTEL, 0x2310), TCO_DH89XXCC},
  298. { PCI_VDEVICE(INTEL, 0x1e40), TCO_PPT},
  299. { PCI_VDEVICE(INTEL, 0x1e41), TCO_PPT},
  300. { PCI_VDEVICE(INTEL, 0x1e42), TCO_PPT},
  301. { PCI_VDEVICE(INTEL, 0x1e43), TCO_PPT},
  302. { PCI_VDEVICE(INTEL, 0x1e44), TCO_PPT},
  303. { PCI_VDEVICE(INTEL, 0x1e45), TCO_PPT},
  304. { PCI_VDEVICE(INTEL, 0x1e46), TCO_PPT},
  305. { PCI_VDEVICE(INTEL, 0x1e47), TCO_PPT},
  306. { PCI_VDEVICE(INTEL, 0x1e48), TCO_PPT},
  307. { PCI_VDEVICE(INTEL, 0x1e49), TCO_PPT},
  308. { PCI_VDEVICE(INTEL, 0x1e4a), TCO_PPT},
  309. { PCI_VDEVICE(INTEL, 0x1e4b), TCO_PPT},
  310. { PCI_VDEVICE(INTEL, 0x1e4c), TCO_PPT},
  311. { PCI_VDEVICE(INTEL, 0x1e4d), TCO_PPT},
  312. { PCI_VDEVICE(INTEL, 0x1e4e), TCO_PPT},
  313. { PCI_VDEVICE(INTEL, 0x1e4f), TCO_PPT},
  314. { PCI_VDEVICE(INTEL, 0x1e50), TCO_PPT},
  315. { PCI_VDEVICE(INTEL, 0x1e51), TCO_PPT},
  316. { PCI_VDEVICE(INTEL, 0x1e52), TCO_PPT},
  317. { PCI_VDEVICE(INTEL, 0x1e53), TCO_PPT},
  318. { PCI_VDEVICE(INTEL, 0x1e54), TCO_PPT},
  319. { PCI_VDEVICE(INTEL, 0x1e55), TCO_PPT},
  320. { PCI_VDEVICE(INTEL, 0x1e56), TCO_PPT},
  321. { PCI_VDEVICE(INTEL, 0x1e57), TCO_PPT},
  322. { PCI_VDEVICE(INTEL, 0x1e58), TCO_PPT},
  323. { PCI_VDEVICE(INTEL, 0x1e59), TCO_PPT},
  324. { PCI_VDEVICE(INTEL, 0x1e5a), TCO_PPT},
  325. { PCI_VDEVICE(INTEL, 0x1e5b), TCO_PPT},
  326. { PCI_VDEVICE(INTEL, 0x1e5c), TCO_PPT},
  327. { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT},
  328. { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT},
  329. { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT},
  330. { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT},
  331. { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT},
  332. { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT},
  333. { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT},
  334. { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT},
  335. { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT},
  336. { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT},
  337. { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT},
  338. { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT},
  339. { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT},
  340. { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT},
  341. { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT},
  342. { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT},
  343. { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT},
  344. { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT},
  345. { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT},
  346. { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT},
  347. { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT},
  348. { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT},
  349. { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT},
  350. { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT},
  351. { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT},
  352. { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT},
  353. { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT},
  354. { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT},
  355. { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT},
  356. { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT},
  357. { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT},
  358. { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT},
  359. { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT},
  360. { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT},
  361. { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT},
  362. { 0, }, /* End of list */
  363. };
  364. MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
  365. /* Address definitions for the TCO */
  366. /* TCO base address */
  367. #define TCOBASE (iTCO_wdt_private.ACPIBASE + 0x60)
  368. /* SMI Control and Enable Register */
  369. #define SMI_EN (iTCO_wdt_private.ACPIBASE + 0x30)
  370. #define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */
  371. #define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */
  372. #define TCO_DAT_IN (TCOBASE + 0x02) /* TCO Data In Register */
  373. #define TCO_DAT_OUT (TCOBASE + 0x03) /* TCO Data Out Register */
  374. #define TCO1_STS (TCOBASE + 0x04) /* TCO1 Status Register */
  375. #define TCO2_STS (TCOBASE + 0x06) /* TCO2 Status Register */
  376. #define TCO1_CNT (TCOBASE + 0x08) /* TCO1 Control Register */
  377. #define TCO2_CNT (TCOBASE + 0x0a) /* TCO2 Control Register */
  378. #define TCOv2_TMR (TCOBASE + 0x12) /* TCOv2 Timer Initial Value */
  379. /* internal variables */
  380. static unsigned long is_active;
  381. static char expect_release;
  382. static struct { /* this is private data for the iTCO_wdt device */
  383. /* TCO version/generation */
  384. unsigned int iTCO_version;
  385. /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */
  386. unsigned long ACPIBASE;
  387. /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/
  388. unsigned long __iomem *gcs;
  389. /* the lock for io operations */
  390. spinlock_t io_lock;
  391. /* the PCI-device */
  392. struct pci_dev *pdev;
  393. } iTCO_wdt_private;
  394. /* the watchdog platform device */
  395. static struct platform_device *iTCO_wdt_platform_device;
  396. /* module parameters */
  397. #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
  398. static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
  399. module_param(heartbeat, int, 0);
  400. MODULE_PARM_DESC(heartbeat, "Watchdog timeout in seconds. "
  401. "5..76 (TCO v1) or 3..614 (TCO v2), default="
  402. __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
  403. static bool nowayout = WATCHDOG_NOWAYOUT;
  404. module_param(nowayout, bool, 0);
  405. MODULE_PARM_DESC(nowayout,
  406. "Watchdog cannot be stopped once started (default="
  407. __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  408. static int turn_SMI_watchdog_clear_off = 1;
  409. module_param(turn_SMI_watchdog_clear_off, int, 0);
  410. MODULE_PARM_DESC(turn_SMI_watchdog_clear_off,
  411. "Turn off SMI clearing watchdog (depends on TCO-version)(default=1)");
  412. /*
  413. * Some TCO specific functions
  414. */
  415. static inline unsigned int seconds_to_ticks(int seconds)
  416. {
  417. /* the internal timer is stored as ticks which decrement
  418. * every 0.6 seconds */
  419. return (seconds * 10) / 6;
  420. }
  421. static void iTCO_wdt_set_NO_REBOOT_bit(void)
  422. {
  423. u32 val32;
  424. /* Set the NO_REBOOT bit: this disables reboots */
  425. if (iTCO_wdt_private.iTCO_version == 2) {
  426. val32 = readl(iTCO_wdt_private.gcs);
  427. val32 |= 0x00000020;
  428. writel(val32, iTCO_wdt_private.gcs);
  429. } else if (iTCO_wdt_private.iTCO_version == 1) {
  430. pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
  431. val32 |= 0x00000002;
  432. pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
  433. }
  434. }
  435. static int iTCO_wdt_unset_NO_REBOOT_bit(void)
  436. {
  437. int ret = 0;
  438. u32 val32;
  439. /* Unset the NO_REBOOT bit: this enables reboots */
  440. if (iTCO_wdt_private.iTCO_version == 2) {
  441. val32 = readl(iTCO_wdt_private.gcs);
  442. val32 &= 0xffffffdf;
  443. writel(val32, iTCO_wdt_private.gcs);
  444. val32 = readl(iTCO_wdt_private.gcs);
  445. if (val32 & 0x00000020)
  446. ret = -EIO;
  447. } else if (iTCO_wdt_private.iTCO_version == 1) {
  448. pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
  449. val32 &= 0xfffffffd;
  450. pci_write_config_dword(iTCO_wdt_private.pdev, 0xd4, val32);
  451. pci_read_config_dword(iTCO_wdt_private.pdev, 0xd4, &val32);
  452. if (val32 & 0x00000002)
  453. ret = -EIO;
  454. }
  455. return ret; /* returns: 0 = OK, -EIO = Error */
  456. }
  457. static int iTCO_wdt_start(void)
  458. {
  459. unsigned int val;
  460. spin_lock(&iTCO_wdt_private.io_lock);
  461. iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat);
  462. /* disable chipset's NO_REBOOT bit */
  463. if (iTCO_wdt_unset_NO_REBOOT_bit()) {
  464. spin_unlock(&iTCO_wdt_private.io_lock);
  465. pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
  466. return -EIO;
  467. }
  468. /* Force the timer to its reload value by writing to the TCO_RLD
  469. register */
  470. if (iTCO_wdt_private.iTCO_version == 2)
  471. outw(0x01, TCO_RLD);
  472. else if (iTCO_wdt_private.iTCO_version == 1)
  473. outb(0x01, TCO_RLD);
  474. /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
  475. val = inw(TCO1_CNT);
  476. val &= 0xf7ff;
  477. outw(val, TCO1_CNT);
  478. val = inw(TCO1_CNT);
  479. spin_unlock(&iTCO_wdt_private.io_lock);
  480. if (val & 0x0800)
  481. return -1;
  482. return 0;
  483. }
  484. static int iTCO_wdt_stop(void)
  485. {
  486. unsigned int val;
  487. spin_lock(&iTCO_wdt_private.io_lock);
  488. iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE);
  489. /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
  490. val = inw(TCO1_CNT);
  491. val |= 0x0800;
  492. outw(val, TCO1_CNT);
  493. val = inw(TCO1_CNT);
  494. /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
  495. iTCO_wdt_set_NO_REBOOT_bit();
  496. spin_unlock(&iTCO_wdt_private.io_lock);
  497. if ((val & 0x0800) == 0)
  498. return -1;
  499. return 0;
  500. }
  501. static int iTCO_wdt_keepalive(void)
  502. {
  503. spin_lock(&iTCO_wdt_private.io_lock);
  504. iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat);
  505. /* Reload the timer by writing to the TCO Timer Counter register */
  506. if (iTCO_wdt_private.iTCO_version == 2)
  507. outw(0x01, TCO_RLD);
  508. else if (iTCO_wdt_private.iTCO_version == 1) {
  509. /* Reset the timeout status bit so that the timer
  510. * needs to count down twice again before rebooting */
  511. outw(0x0008, TCO1_STS); /* write 1 to clear bit */
  512. outb(0x01, TCO_RLD);
  513. }
  514. spin_unlock(&iTCO_wdt_private.io_lock);
  515. return 0;
  516. }
  517. static int iTCO_wdt_set_heartbeat(int t)
  518. {
  519. unsigned int val16;
  520. unsigned char val8;
  521. unsigned int tmrval;
  522. tmrval = seconds_to_ticks(t);
  523. /* For TCO v1 the timer counts down twice before rebooting */
  524. if (iTCO_wdt_private.iTCO_version == 1)
  525. tmrval /= 2;
  526. /* from the specs: */
  527. /* "Values of 0h-3h are ignored and should not be attempted" */
  528. if (tmrval < 0x04)
  529. return -EINVAL;
  530. if (((iTCO_wdt_private.iTCO_version == 2) && (tmrval > 0x3ff)) ||
  531. ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f)))
  532. return -EINVAL;
  533. iTCO_vendor_pre_set_heartbeat(tmrval);
  534. /* Write new heartbeat to watchdog */
  535. if (iTCO_wdt_private.iTCO_version == 2) {
  536. spin_lock(&iTCO_wdt_private.io_lock);
  537. val16 = inw(TCOv2_TMR);
  538. val16 &= 0xfc00;
  539. val16 |= tmrval;
  540. outw(val16, TCOv2_TMR);
  541. val16 = inw(TCOv2_TMR);
  542. spin_unlock(&iTCO_wdt_private.io_lock);
  543. if ((val16 & 0x3ff) != tmrval)
  544. return -EINVAL;
  545. } else if (iTCO_wdt_private.iTCO_version == 1) {
  546. spin_lock(&iTCO_wdt_private.io_lock);
  547. val8 = inb(TCOv1_TMR);
  548. val8 &= 0xc0;
  549. val8 |= (tmrval & 0xff);
  550. outb(val8, TCOv1_TMR);
  551. val8 = inb(TCOv1_TMR);
  552. spin_unlock(&iTCO_wdt_private.io_lock);
  553. if ((val8 & 0x3f) != tmrval)
  554. return -EINVAL;
  555. }
  556. heartbeat = t;
  557. return 0;
  558. }
  559. static int iTCO_wdt_get_timeleft(int *time_left)
  560. {
  561. unsigned int val16;
  562. unsigned char val8;
  563. /* read the TCO Timer */
  564. if (iTCO_wdt_private.iTCO_version == 2) {
  565. spin_lock(&iTCO_wdt_private.io_lock);
  566. val16 = inw(TCO_RLD);
  567. val16 &= 0x3ff;
  568. spin_unlock(&iTCO_wdt_private.io_lock);
  569. *time_left = (val16 * 6) / 10;
  570. } else if (iTCO_wdt_private.iTCO_version == 1) {
  571. spin_lock(&iTCO_wdt_private.io_lock);
  572. val8 = inb(TCO_RLD);
  573. val8 &= 0x3f;
  574. if (!(inw(TCO1_STS) & 0x0008))
  575. val8 += (inb(TCOv1_TMR) & 0x3f);
  576. spin_unlock(&iTCO_wdt_private.io_lock);
  577. *time_left = (val8 * 6) / 10;
  578. } else
  579. return -EINVAL;
  580. return 0;
  581. }
  582. /*
  583. * /dev/watchdog handling
  584. */
  585. static int iTCO_wdt_open(struct inode *inode, struct file *file)
  586. {
  587. /* /dev/watchdog can only be opened once */
  588. if (test_and_set_bit(0, &is_active))
  589. return -EBUSY;
  590. /*
  591. * Reload and activate timer
  592. */
  593. iTCO_wdt_start();
  594. return nonseekable_open(inode, file);
  595. }
  596. static int iTCO_wdt_release(struct inode *inode, struct file *file)
  597. {
  598. /*
  599. * Shut off the timer.
  600. */
  601. if (expect_release == 42) {
  602. iTCO_wdt_stop();
  603. } else {
  604. pr_crit("Unexpected close, not stopping watchdog!\n");
  605. iTCO_wdt_keepalive();
  606. }
  607. clear_bit(0, &is_active);
  608. expect_release = 0;
  609. return 0;
  610. }
  611. static ssize_t iTCO_wdt_write(struct file *file, const char __user *data,
  612. size_t len, loff_t *ppos)
  613. {
  614. /* See if we got the magic character 'V' and reload the timer */
  615. if (len) {
  616. if (!nowayout) {
  617. size_t i;
  618. /* note: just in case someone wrote the magic
  619. character five months ago... */
  620. expect_release = 0;
  621. /* scan to see whether or not we got the
  622. magic character */
  623. for (i = 0; i != len; i++) {
  624. char c;
  625. if (get_user(c, data + i))
  626. return -EFAULT;
  627. if (c == 'V')
  628. expect_release = 42;
  629. }
  630. }
  631. /* someone wrote to us, we should reload the timer */
  632. iTCO_wdt_keepalive();
  633. }
  634. return len;
  635. }
  636. static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd,
  637. unsigned long arg)
  638. {
  639. int new_options, retval = -EINVAL;
  640. int new_heartbeat;
  641. void __user *argp = (void __user *)arg;
  642. int __user *p = argp;
  643. static const struct watchdog_info ident = {
  644. .options = WDIOF_SETTIMEOUT |
  645. WDIOF_KEEPALIVEPING |
  646. WDIOF_MAGICCLOSE,
  647. .firmware_version = 0,
  648. .identity = DRV_NAME,
  649. };
  650. switch (cmd) {
  651. case WDIOC_GETSUPPORT:
  652. return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
  653. case WDIOC_GETSTATUS:
  654. case WDIOC_GETBOOTSTATUS:
  655. return put_user(0, p);
  656. case WDIOC_SETOPTIONS:
  657. {
  658. if (get_user(new_options, p))
  659. return -EFAULT;
  660. if (new_options & WDIOS_DISABLECARD) {
  661. iTCO_wdt_stop();
  662. retval = 0;
  663. }
  664. if (new_options & WDIOS_ENABLECARD) {
  665. iTCO_wdt_keepalive();
  666. iTCO_wdt_start();
  667. retval = 0;
  668. }
  669. return retval;
  670. }
  671. case WDIOC_KEEPALIVE:
  672. iTCO_wdt_keepalive();
  673. return 0;
  674. case WDIOC_SETTIMEOUT:
  675. {
  676. if (get_user(new_heartbeat, p))
  677. return -EFAULT;
  678. if (iTCO_wdt_set_heartbeat(new_heartbeat))
  679. return -EINVAL;
  680. iTCO_wdt_keepalive();
  681. /* Fall */
  682. }
  683. case WDIOC_GETTIMEOUT:
  684. return put_user(heartbeat, p);
  685. case WDIOC_GETTIMELEFT:
  686. {
  687. int time_left;
  688. if (iTCO_wdt_get_timeleft(&time_left))
  689. return -EINVAL;
  690. return put_user(time_left, p);
  691. }
  692. default:
  693. return -ENOTTY;
  694. }
  695. }
  696. /*
  697. * Kernel Interfaces
  698. */
  699. static const struct file_operations iTCO_wdt_fops = {
  700. .owner = THIS_MODULE,
  701. .llseek = no_llseek,
  702. .write = iTCO_wdt_write,
  703. .unlocked_ioctl = iTCO_wdt_ioctl,
  704. .open = iTCO_wdt_open,
  705. .release = iTCO_wdt_release,
  706. };
  707. static struct miscdevice iTCO_wdt_miscdev = {
  708. .minor = WATCHDOG_MINOR,
  709. .name = "watchdog",
  710. .fops = &iTCO_wdt_fops,
  711. };
  712. /*
  713. * Init & exit routines
  714. */
  715. static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
  716. const struct pci_device_id *ent, struct platform_device *dev)
  717. {
  718. int ret;
  719. u32 base_address;
  720. unsigned long RCBA;
  721. unsigned long val32;
  722. /*
  723. * Find the ACPI/PM base I/O address which is the base
  724. * for the TCO registers (TCOBASE=ACPIBASE + 0x60)
  725. * ACPIBASE is bits [15:7] from 0x40-0x43
  726. */
  727. pci_read_config_dword(pdev, 0x40, &base_address);
  728. base_address &= 0x0000ff80;
  729. if (base_address == 0x00000000) {
  730. /* Something's wrong here, ACPIBASE has to be set */
  731. pr_err("failed to get TCOBASE address, device disabled by hardware/BIOS\n");
  732. return -ENODEV;
  733. }
  734. iTCO_wdt_private.iTCO_version =
  735. iTCO_chipset_info[ent->driver_data].iTCO_version;
  736. iTCO_wdt_private.ACPIBASE = base_address;
  737. iTCO_wdt_private.pdev = pdev;
  738. /* Get the Memory-Mapped GCS register, we need it for the
  739. NO_REBOOT flag (TCO v2). To get access to it you have to
  740. read RCBA from PCI Config space 0xf0 and use it as base.
  741. GCS = RCBA + ICH6_GCS(0x3410). */
  742. if (iTCO_wdt_private.iTCO_version == 2) {
  743. pci_read_config_dword(pdev, 0xf0, &base_address);
  744. if ((base_address & 1) == 0) {
  745. pr_err("RCBA is disabled by hardware/BIOS, device disabled\n");
  746. ret = -ENODEV;
  747. goto out;
  748. }
  749. RCBA = base_address & 0xffffc000;
  750. iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4);
  751. }
  752. /* Check chipset's NO_REBOOT bit */
  753. if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
  754. pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
  755. ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
  756. goto out_unmap;
  757. }
  758. /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
  759. iTCO_wdt_set_NO_REBOOT_bit();
  760. /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
  761. if (!request_region(SMI_EN, 4, "iTCO_wdt")) {
  762. pr_err("I/O address 0x%04lx already in use, device disabled\n",
  763. SMI_EN);
  764. ret = -EIO;
  765. goto out_unmap;
  766. }
  767. if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) {
  768. /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
  769. val32 = inl(SMI_EN);
  770. val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
  771. outl(val32, SMI_EN);
  772. }
  773. /* The TCO I/O registers reside in a 32-byte range pointed to
  774. by the TCOBASE value */
  775. if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) {
  776. pr_err("I/O address 0x%04lx already in use, device disabled\n",
  777. TCOBASE);
  778. ret = -EIO;
  779. goto unreg_smi_en;
  780. }
  781. pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n",
  782. iTCO_chipset_info[ent->driver_data].name,
  783. iTCO_chipset_info[ent->driver_data].iTCO_version,
  784. TCOBASE);
  785. /* Clear out the (probably old) status */
  786. outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
  787. outw(0x0002, TCO2_STS); /* Clear SECOND_TO_STS bit */
  788. outw(0x0004, TCO2_STS); /* Clear BOOT_STS bit */
  789. /* Make sure the watchdog is not running */
  790. iTCO_wdt_stop();
  791. /* Check that the heartbeat value is within it's range;
  792. if not reset to the default */
  793. if (iTCO_wdt_set_heartbeat(heartbeat)) {
  794. iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT);
  795. pr_info("timeout value out of range, using %d\n", heartbeat);
  796. }
  797. ret = misc_register(&iTCO_wdt_miscdev);
  798. if (ret != 0) {
  799. pr_err("cannot register miscdev on minor=%d (err=%d)\n",
  800. WATCHDOG_MINOR, ret);
  801. goto unreg_region;
  802. }
  803. pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
  804. heartbeat, nowayout);
  805. return 0;
  806. unreg_region:
  807. release_region(TCOBASE, 0x20);
  808. unreg_smi_en:
  809. release_region(SMI_EN, 4);
  810. out_unmap:
  811. if (iTCO_wdt_private.iTCO_version == 2)
  812. iounmap(iTCO_wdt_private.gcs);
  813. out:
  814. iTCO_wdt_private.ACPIBASE = 0;
  815. return ret;
  816. }
  817. static void __devexit iTCO_wdt_cleanup(void)
  818. {
  819. /* Stop the timer before we leave */
  820. if (!nowayout)
  821. iTCO_wdt_stop();
  822. /* Deregister */
  823. misc_deregister(&iTCO_wdt_miscdev);
  824. release_region(TCOBASE, 0x20);
  825. release_region(SMI_EN, 4);
  826. if (iTCO_wdt_private.iTCO_version == 2)
  827. iounmap(iTCO_wdt_private.gcs);
  828. pci_dev_put(iTCO_wdt_private.pdev);
  829. iTCO_wdt_private.ACPIBASE = 0;
  830. }
  831. static int __devinit iTCO_wdt_probe(struct platform_device *dev)
  832. {
  833. int ret = -ENODEV;
  834. int found = 0;
  835. struct pci_dev *pdev = NULL;
  836. const struct pci_device_id *ent;
  837. spin_lock_init(&iTCO_wdt_private.io_lock);
  838. for_each_pci_dev(pdev) {
  839. ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
  840. if (ent) {
  841. found++;
  842. ret = iTCO_wdt_init(pdev, ent, dev);
  843. if (!ret)
  844. break;
  845. }
  846. }
  847. if (!found)
  848. pr_info("No device detected\n");
  849. return ret;
  850. }
  851. static int __devexit iTCO_wdt_remove(struct platform_device *dev)
  852. {
  853. if (iTCO_wdt_private.ACPIBASE)
  854. iTCO_wdt_cleanup();
  855. return 0;
  856. }
  857. static void iTCO_wdt_shutdown(struct platform_device *dev)
  858. {
  859. iTCO_wdt_stop();
  860. }
  861. static struct platform_driver iTCO_wdt_driver = {
  862. .probe = iTCO_wdt_probe,
  863. .remove = __devexit_p(iTCO_wdt_remove),
  864. .shutdown = iTCO_wdt_shutdown,
  865. .driver = {
  866. .owner = THIS_MODULE,
  867. .name = DRV_NAME,
  868. },
  869. };
  870. static int __init iTCO_wdt_init_module(void)
  871. {
  872. int err;
  873. pr_info("Intel TCO WatchDog Timer Driver v%s\n", DRV_VERSION);
  874. err = platform_driver_register(&iTCO_wdt_driver);
  875. if (err)
  876. return err;
  877. iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME,
  878. -1, NULL, 0);
  879. if (IS_ERR(iTCO_wdt_platform_device)) {
  880. err = PTR_ERR(iTCO_wdt_platform_device);
  881. goto unreg_platform_driver;
  882. }
  883. return 0;
  884. unreg_platform_driver:
  885. platform_driver_unregister(&iTCO_wdt_driver);
  886. return err;
  887. }
  888. static void __exit iTCO_wdt_cleanup_module(void)
  889. {
  890. platform_device_unregister(iTCO_wdt_platform_device);
  891. platform_driver_unregister(&iTCO_wdt_driver);
  892. pr_info("Watchdog Module Unloaded\n");
  893. }
  894. module_init(iTCO_wdt_init_module);
  895. module_exit(iTCO_wdt_cleanup_module);
  896. MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
  897. MODULE_DESCRIPTION("Intel TCO WatchDog Timer Driver");
  898. MODULE_VERSION(DRV_VERSION);
  899. MODULE_LICENSE("GPL");
  900. MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);