diff options
author | Aaron Sierra <asierra@xes-inc.com> | 2012-04-20 15:14:11 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-05-09 11:20:09 -0400 |
commit | 887c8ec7219fc8eba78bb8f44a74c660934e9b98 (patch) | |
tree | c7f5b2d24c984a7ca57120dd057cd3cd2f6efee2 /drivers/watchdog | |
parent | 16c5c023aac86228e3e94c4bf6d19708ea861a05 (diff) |
watchdog: Convert iTCO_wdt driver to mfd model
This patch converts the iTCO_wdt driver to use the multi-function device
driver model. It uses resources discovered by the lpc_ich driver, so that
it no longer does its own PCI scanning.
Signed-off-by: Aaron Sierra <asierra@xes-inc.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/Kconfig | 1 | ||||
-rw-r--r-- | drivers/watchdog/iTCO_vendor.h | 6 | ||||
-rw-r--r-- | drivers/watchdog/iTCO_vendor_support.c | 43 | ||||
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 529 |
4 files changed, 134 insertions, 445 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 37096246c937..a9ed0878abfc 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -563,6 +563,7 @@ config INTEL_SCU_WATCHDOG | |||
563 | config ITCO_WDT | 563 | config ITCO_WDT |
564 | tristate "Intel TCO Timer/Watchdog" | 564 | tristate "Intel TCO Timer/Watchdog" |
565 | depends on (X86 || IA64) && PCI | 565 | depends on (X86 || IA64) && PCI |
566 | select LPC_ICH | ||
566 | ---help--- | 567 | ---help--- |
567 | Hardware driver for the intel TCO timer based watchdog devices. | 568 | Hardware driver for the intel TCO timer based watchdog devices. |
568 | These drivers are included in the Intel 82801 I/O Controller | 569 | These drivers are included in the Intel 82801 I/O Controller |
diff --git a/drivers/watchdog/iTCO_vendor.h b/drivers/watchdog/iTCO_vendor.h index 9e27e6422f66..3c57b45537a2 100644 --- a/drivers/watchdog/iTCO_vendor.h +++ b/drivers/watchdog/iTCO_vendor.h | |||
@@ -1,8 +1,8 @@ | |||
1 | /* iTCO Vendor Specific Support hooks */ | 1 | /* iTCO Vendor Specific Support hooks */ |
2 | #ifdef CONFIG_ITCO_VENDOR_SUPPORT | 2 | #ifdef CONFIG_ITCO_VENDOR_SUPPORT |
3 | extern void iTCO_vendor_pre_start(unsigned long, unsigned int); | 3 | extern void iTCO_vendor_pre_start(struct resource *, unsigned int); |
4 | extern void iTCO_vendor_pre_stop(unsigned long); | 4 | extern void iTCO_vendor_pre_stop(struct resource *); |
5 | extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int); | 5 | extern void iTCO_vendor_pre_keepalive(struct resource *, unsigned int); |
6 | extern void iTCO_vendor_pre_set_heartbeat(unsigned int); | 6 | extern void iTCO_vendor_pre_set_heartbeat(unsigned int); |
7 | extern int iTCO_vendor_check_noreboot_on(void); | 7 | extern int iTCO_vendor_check_noreboot_on(void); |
8 | #else | 8 | #else |
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c index 2721d29ce243..b6b2f90b5d44 100644 --- a/drivers/watchdog/iTCO_vendor_support.c +++ b/drivers/watchdog/iTCO_vendor_support.c | |||
@@ -35,11 +35,6 @@ | |||
35 | 35 | ||
36 | #include "iTCO_vendor.h" | 36 | #include "iTCO_vendor.h" |
37 | 37 | ||
38 | /* iTCO defines */ | ||
39 | #define SMI_EN (acpibase + 0x30) /* SMI Control and Enable Register */ | ||
40 | #define TCOBASE (acpibase + 0x60) /* TCO base address */ | ||
41 | #define TCO1_STS (TCOBASE + 0x04) /* TCO1 Status Register */ | ||
42 | |||
43 | /* List of vendor support modes */ | 38 | /* List of vendor support modes */ |
44 | /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ | 39 | /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ |
45 | #define SUPERMICRO_OLD_BOARD 1 | 40 | #define SUPERMICRO_OLD_BOARD 1 |
@@ -82,24 +77,24 @@ MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=" | |||
82 | * 20.6 seconds. | 77 | * 20.6 seconds. |
83 | */ | 78 | */ |
84 | 79 | ||
85 | static void supermicro_old_pre_start(unsigned long acpibase) | 80 | static void supermicro_old_pre_start(struct resource *smires) |
86 | { | 81 | { |
87 | unsigned long val32; | 82 | unsigned long val32; |
88 | 83 | ||
89 | /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ | 84 | /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ |
90 | val32 = inl(SMI_EN); | 85 | val32 = inl(smires->start); |
91 | val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ | 86 | val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ |
92 | outl(val32, SMI_EN); /* Needed to activate watchdog */ | 87 | outl(val32, smires->start); /* Needed to activate watchdog */ |
93 | } | 88 | } |
94 | 89 | ||
95 | static void supermicro_old_pre_stop(unsigned long acpibase) | 90 | static void supermicro_old_pre_stop(struct resource *smires) |
96 | { | 91 | { |
97 | unsigned long val32; | 92 | unsigned long val32; |
98 | 93 | ||
99 | /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */ | 94 | /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */ |
100 | val32 = inl(SMI_EN); | 95 | val32 = inl(smires->start); |
101 | val32 |= 0x00002000; /* Turn on SMI clearing watchdog */ | 96 | val32 |= 0x00002000; /* Turn on SMI clearing watchdog */ |
102 | outl(val32, SMI_EN); /* Needed to deactivate watchdog */ | 97 | outl(val32, smires->start); /* Needed to deactivate watchdog */ |
103 | } | 98 | } |
104 | 99 | ||
105 | /* | 100 | /* |
@@ -270,66 +265,66 @@ static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat) | |||
270 | * Don't use this fix if you don't need to!!! | 265 | * Don't use this fix if you don't need to!!! |
271 | */ | 266 | */ |
272 | 267 | ||
273 | static void broken_bios_start(unsigned long acpibase) | 268 | static void broken_bios_start(struct resource *smires) |
274 | { | 269 | { |
275 | unsigned long val32; | 270 | unsigned long val32; |
276 | 271 | ||
277 | val32 = inl(SMI_EN); | 272 | val32 = inl(smires->start); |
278 | /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# | 273 | /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# |
279 | Bit 0: GBL_SMI_EN -> 0 = No SMI# will be generated by ICH. */ | 274 | Bit 0: GBL_SMI_EN -> 0 = No SMI# will be generated by ICH. */ |
280 | val32 &= 0xffffdffe; | 275 | val32 &= 0xffffdffe; |
281 | outl(val32, SMI_EN); | 276 | outl(val32, smires->start); |
282 | } | 277 | } |
283 | 278 | ||
284 | static void broken_bios_stop(unsigned long acpibase) | 279 | static void broken_bios_stop(struct resource *smires) |
285 | { | 280 | { |
286 | unsigned long val32; | 281 | unsigned long val32; |
287 | 282 | ||
288 | val32 = inl(SMI_EN); | 283 | val32 = inl(smires->start); |
289 | /* Bit 13: TCO_EN -> 1 = Enables TCO logic generating an SMI# | 284 | /* Bit 13: TCO_EN -> 1 = Enables TCO logic generating an SMI# |
290 | Bit 0: GBL_SMI_EN -> 1 = Turn global SMI on again. */ | 285 | Bit 0: GBL_SMI_EN -> 1 = Turn global SMI on again. */ |
291 | val32 |= 0x00002001; | 286 | val32 |= 0x00002001; |
292 | outl(val32, SMI_EN); | 287 | outl(val32, smires->start); |
293 | } | 288 | } |
294 | 289 | ||
295 | /* | 290 | /* |
296 | * Generic Support Functions | 291 | * Generic Support Functions |
297 | */ | 292 | */ |
298 | 293 | ||
299 | void iTCO_vendor_pre_start(unsigned long acpibase, | 294 | void iTCO_vendor_pre_start(struct resource *smires, |
300 | unsigned int heartbeat) | 295 | unsigned int heartbeat) |
301 | { | 296 | { |
302 | switch (vendorsupport) { | 297 | switch (vendorsupport) { |
303 | case SUPERMICRO_OLD_BOARD: | 298 | case SUPERMICRO_OLD_BOARD: |
304 | supermicro_old_pre_start(acpibase); | 299 | supermicro_old_pre_start(smires); |
305 | break; | 300 | break; |
306 | case SUPERMICRO_NEW_BOARD: | 301 | case SUPERMICRO_NEW_BOARD: |
307 | supermicro_new_pre_start(heartbeat); | 302 | supermicro_new_pre_start(heartbeat); |
308 | break; | 303 | break; |
309 | case BROKEN_BIOS: | 304 | case BROKEN_BIOS: |
310 | broken_bios_start(acpibase); | 305 | broken_bios_start(smires); |
311 | break; | 306 | break; |
312 | } | 307 | } |
313 | } | 308 | } |
314 | EXPORT_SYMBOL(iTCO_vendor_pre_start); | 309 | EXPORT_SYMBOL(iTCO_vendor_pre_start); |
315 | 310 | ||
316 | void iTCO_vendor_pre_stop(unsigned long acpibase) | 311 | void iTCO_vendor_pre_stop(struct resource *smires) |
317 | { | 312 | { |
318 | switch (vendorsupport) { | 313 | switch (vendorsupport) { |
319 | case SUPERMICRO_OLD_BOARD: | 314 | case SUPERMICRO_OLD_BOARD: |
320 | supermicro_old_pre_stop(acpibase); | 315 | supermicro_old_pre_stop(smires); |
321 | break; | 316 | break; |
322 | case SUPERMICRO_NEW_BOARD: | 317 | case SUPERMICRO_NEW_BOARD: |
323 | supermicro_new_pre_stop(); | 318 | supermicro_new_pre_stop(); |
324 | break; | 319 | break; |
325 | case BROKEN_BIOS: | 320 | case BROKEN_BIOS: |
326 | broken_bios_stop(acpibase); | 321 | broken_bios_stop(smires); |
327 | break; | 322 | break; |
328 | } | 323 | } |
329 | } | 324 | } |
330 | EXPORT_SYMBOL(iTCO_vendor_pre_stop); | 325 | EXPORT_SYMBOL(iTCO_vendor_pre_stop); |
331 | 326 | ||
332 | void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat) | 327 | void iTCO_vendor_pre_keepalive(struct resource *smires, unsigned int heartbeat) |
333 | { | 328 | { |
334 | if (vendorsupport == SUPERMICRO_NEW_BOARD) | 329 | if (vendorsupport == SUPERMICRO_NEW_BOARD) |
335 | supermicro_new_pre_set_heartbeat(heartbeat); | 330 | supermicro_new_pre_set_heartbeat(heartbeat); |
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 9fecb95645a3..741528b032e2 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -66,316 +66,16 @@ | |||
66 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ | 66 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ |
67 | #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ | 67 | #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ |
68 | #include <linux/io.h> /* For inb/outb/... */ | 68 | #include <linux/io.h> /* For inb/outb/... */ |
69 | #include <linux/mfd/core.h> | ||
70 | #include <linux/mfd/lpc_ich.h> | ||
69 | 71 | ||
70 | #include "iTCO_vendor.h" | 72 | #include "iTCO_vendor.h" |
71 | 73 | ||
72 | /* TCO related info */ | ||
73 | enum iTCO_chipsets { | ||
74 | TCO_ICH = 0, /* ICH */ | ||
75 | TCO_ICH0, /* ICH0 */ | ||
76 | TCO_ICH2, /* ICH2 */ | ||
77 | TCO_ICH2M, /* ICH2-M */ | ||
78 | TCO_ICH3, /* ICH3-S */ | ||
79 | TCO_ICH3M, /* ICH3-M */ | ||
80 | TCO_ICH4, /* ICH4 */ | ||
81 | TCO_ICH4M, /* ICH4-M */ | ||
82 | TCO_CICH, /* C-ICH */ | ||
83 | TCO_ICH5, /* ICH5 & ICH5R */ | ||
84 | TCO_6300ESB, /* 6300ESB */ | ||
85 | TCO_ICH6, /* ICH6 & ICH6R */ | ||
86 | TCO_ICH6M, /* ICH6-M */ | ||
87 | TCO_ICH6W, /* ICH6W & ICH6RW */ | ||
88 | TCO_631XESB, /* 631xESB/632xESB */ | ||
89 | TCO_ICH7, /* ICH7 & ICH7R */ | ||
90 | TCO_ICH7DH, /* ICH7DH */ | ||
91 | TCO_ICH7M, /* ICH7-M & ICH7-U */ | ||
92 | TCO_ICH7MDH, /* ICH7-M DH */ | ||
93 | TCO_NM10, /* NM10 */ | ||
94 | TCO_ICH8, /* ICH8 & ICH8R */ | ||
95 | TCO_ICH8DH, /* ICH8DH */ | ||
96 | TCO_ICH8DO, /* ICH8DO */ | ||
97 | TCO_ICH8M, /* ICH8M */ | ||
98 | TCO_ICH8ME, /* ICH8M-E */ | ||
99 | TCO_ICH9, /* ICH9 */ | ||
100 | TCO_ICH9R, /* ICH9R */ | ||
101 | TCO_ICH9DH, /* ICH9DH */ | ||
102 | TCO_ICH9DO, /* ICH9DO */ | ||
103 | TCO_ICH9M, /* ICH9M */ | ||
104 | TCO_ICH9ME, /* ICH9M-E */ | ||
105 | TCO_ICH10, /* ICH10 */ | ||
106 | TCO_ICH10R, /* ICH10R */ | ||
107 | TCO_ICH10D, /* ICH10D */ | ||
108 | TCO_ICH10DO, /* ICH10DO */ | ||
109 | TCO_PCH, /* PCH Desktop Full Featured */ | ||
110 | TCO_PCHM, /* PCH Mobile Full Featured */ | ||
111 | TCO_P55, /* P55 */ | ||
112 | TCO_PM55, /* PM55 */ | ||
113 | TCO_H55, /* H55 */ | ||
114 | TCO_QM57, /* QM57 */ | ||
115 | TCO_H57, /* H57 */ | ||
116 | TCO_HM55, /* HM55 */ | ||
117 | TCO_Q57, /* Q57 */ | ||
118 | TCO_HM57, /* HM57 */ | ||
119 | TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ | ||
120 | TCO_QS57, /* QS57 */ | ||
121 | TCO_3400, /* 3400 */ | ||
122 | TCO_3420, /* 3420 */ | ||
123 | TCO_3450, /* 3450 */ | ||
124 | TCO_EP80579, /* EP80579 */ | ||
125 | TCO_CPT, /* Cougar Point */ | ||
126 | TCO_CPTD, /* Cougar Point Desktop */ | ||
127 | TCO_CPTM, /* Cougar Point Mobile */ | ||
128 | TCO_PBG, /* Patsburg */ | ||
129 | TCO_DH89XXCC, /* DH89xxCC */ | ||
130 | TCO_PPT, /* Panther Point */ | ||
131 | TCO_LPT, /* Lynx Point */ | ||
132 | }; | ||
133 | |||
134 | static struct { | ||
135 | char *name; | ||
136 | unsigned int iTCO_version; | ||
137 | } iTCO_chipset_info[] __devinitdata = { | ||
138 | {"ICH", 1}, | ||
139 | {"ICH0", 1}, | ||
140 | {"ICH2", 1}, | ||
141 | {"ICH2-M", 1}, | ||
142 | {"ICH3-S", 1}, | ||
143 | {"ICH3-M", 1}, | ||
144 | {"ICH4", 1}, | ||
145 | {"ICH4-M", 1}, | ||
146 | {"C-ICH", 1}, | ||
147 | {"ICH5 or ICH5R", 1}, | ||
148 | {"6300ESB", 1}, | ||
149 | {"ICH6 or ICH6R", 2}, | ||
150 | {"ICH6-M", 2}, | ||
151 | {"ICH6W or ICH6RW", 2}, | ||
152 | {"631xESB/632xESB", 2}, | ||
153 | {"ICH7 or ICH7R", 2}, | ||
154 | {"ICH7DH", 2}, | ||
155 | {"ICH7-M or ICH7-U", 2}, | ||
156 | {"ICH7-M DH", 2}, | ||
157 | {"NM10", 2}, | ||
158 | {"ICH8 or ICH8R", 2}, | ||
159 | {"ICH8DH", 2}, | ||
160 | {"ICH8DO", 2}, | ||
161 | {"ICH8M", 2}, | ||
162 | {"ICH8M-E", 2}, | ||
163 | {"ICH9", 2}, | ||
164 | {"ICH9R", 2}, | ||
165 | {"ICH9DH", 2}, | ||
166 | {"ICH9DO", 2}, | ||
167 | {"ICH9M", 2}, | ||
168 | {"ICH9M-E", 2}, | ||
169 | {"ICH10", 2}, | ||
170 | {"ICH10R", 2}, | ||
171 | {"ICH10D", 2}, | ||
172 | {"ICH10DO", 2}, | ||
173 | {"PCH Desktop Full Featured", 2}, | ||
174 | {"PCH Mobile Full Featured", 2}, | ||
175 | {"P55", 2}, | ||
176 | {"PM55", 2}, | ||
177 | {"H55", 2}, | ||
178 | {"QM57", 2}, | ||
179 | {"H57", 2}, | ||
180 | {"HM55", 2}, | ||
181 | {"Q57", 2}, | ||
182 | {"HM57", 2}, | ||
183 | {"PCH Mobile SFF Full Featured", 2}, | ||
184 | {"QS57", 2}, | ||
185 | {"3400", 2}, | ||
186 | {"3420", 2}, | ||
187 | {"3450", 2}, | ||
188 | {"EP80579", 2}, | ||
189 | {"Cougar Point", 2}, | ||
190 | {"Cougar Point Desktop", 2}, | ||
191 | {"Cougar Point Mobile", 2}, | ||
192 | {"Patsburg", 2}, | ||
193 | {"DH89xxCC", 2}, | ||
194 | {"Panther Point", 2}, | ||
195 | {"Lynx Point", 2}, | ||
196 | {NULL, 0} | ||
197 | }; | ||
198 | |||
199 | /* | ||
200 | * This data only exists for exporting the supported PCI ids | ||
201 | * via MODULE_DEVICE_TABLE. We do not actually register a | ||
202 | * pci_driver, because the I/O Controller Hub has also other | ||
203 | * functions that probably will be registered by other drivers. | ||
204 | */ | ||
205 | static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = { | ||
206 | { PCI_VDEVICE(INTEL, 0x2410), TCO_ICH}, | ||
207 | { PCI_VDEVICE(INTEL, 0x2420), TCO_ICH0}, | ||
208 | { PCI_VDEVICE(INTEL, 0x2440), TCO_ICH2}, | ||
209 | { PCI_VDEVICE(INTEL, 0x244c), TCO_ICH2M}, | ||
210 | { PCI_VDEVICE(INTEL, 0x2480), TCO_ICH3}, | ||
211 | { PCI_VDEVICE(INTEL, 0x248c), TCO_ICH3M}, | ||
212 | { PCI_VDEVICE(INTEL, 0x24c0), TCO_ICH4}, | ||
213 | { PCI_VDEVICE(INTEL, 0x24cc), TCO_ICH4M}, | ||
214 | { PCI_VDEVICE(INTEL, 0x2450), TCO_CICH}, | ||
215 | { PCI_VDEVICE(INTEL, 0x24d0), TCO_ICH5}, | ||
216 | { PCI_VDEVICE(INTEL, 0x25a1), TCO_6300ESB}, | ||
217 | { PCI_VDEVICE(INTEL, 0x2640), TCO_ICH6}, | ||
218 | { PCI_VDEVICE(INTEL, 0x2641), TCO_ICH6M}, | ||
219 | { PCI_VDEVICE(INTEL, 0x2642), TCO_ICH6W}, | ||
220 | { PCI_VDEVICE(INTEL, 0x2670), TCO_631XESB}, | ||
221 | { PCI_VDEVICE(INTEL, 0x2671), TCO_631XESB}, | ||
222 | { PCI_VDEVICE(INTEL, 0x2672), TCO_631XESB}, | ||
223 | { PCI_VDEVICE(INTEL, 0x2673), TCO_631XESB}, | ||
224 | { PCI_VDEVICE(INTEL, 0x2674), TCO_631XESB}, | ||
225 | { PCI_VDEVICE(INTEL, 0x2675), TCO_631XESB}, | ||
226 | { PCI_VDEVICE(INTEL, 0x2676), TCO_631XESB}, | ||
227 | { PCI_VDEVICE(INTEL, 0x2677), TCO_631XESB}, | ||
228 | { PCI_VDEVICE(INTEL, 0x2678), TCO_631XESB}, | ||
229 | { PCI_VDEVICE(INTEL, 0x2679), TCO_631XESB}, | ||
230 | { PCI_VDEVICE(INTEL, 0x267a), TCO_631XESB}, | ||
231 | { PCI_VDEVICE(INTEL, 0x267b), TCO_631XESB}, | ||
232 | { PCI_VDEVICE(INTEL, 0x267c), TCO_631XESB}, | ||
233 | { PCI_VDEVICE(INTEL, 0x267d), TCO_631XESB}, | ||
234 | { PCI_VDEVICE(INTEL, 0x267e), TCO_631XESB}, | ||
235 | { PCI_VDEVICE(INTEL, 0x267f), TCO_631XESB}, | ||
236 | { PCI_VDEVICE(INTEL, 0x27b8), TCO_ICH7}, | ||
237 | { PCI_VDEVICE(INTEL, 0x27b0), TCO_ICH7DH}, | ||
238 | { PCI_VDEVICE(INTEL, 0x27b9), TCO_ICH7M}, | ||
239 | { PCI_VDEVICE(INTEL, 0x27bd), TCO_ICH7MDH}, | ||
240 | { PCI_VDEVICE(INTEL, 0x27bc), TCO_NM10}, | ||
241 | { PCI_VDEVICE(INTEL, 0x2810), TCO_ICH8}, | ||
242 | { PCI_VDEVICE(INTEL, 0x2812), TCO_ICH8DH}, | ||
243 | { PCI_VDEVICE(INTEL, 0x2814), TCO_ICH8DO}, | ||
244 | { PCI_VDEVICE(INTEL, 0x2815), TCO_ICH8M}, | ||
245 | { PCI_VDEVICE(INTEL, 0x2811), TCO_ICH8ME}, | ||
246 | { PCI_VDEVICE(INTEL, 0x2918), TCO_ICH9}, | ||
247 | { PCI_VDEVICE(INTEL, 0x2916), TCO_ICH9R}, | ||
248 | { PCI_VDEVICE(INTEL, 0x2912), TCO_ICH9DH}, | ||
249 | { PCI_VDEVICE(INTEL, 0x2914), TCO_ICH9DO}, | ||
250 | { PCI_VDEVICE(INTEL, 0x2919), TCO_ICH9M}, | ||
251 | { PCI_VDEVICE(INTEL, 0x2917), TCO_ICH9ME}, | ||
252 | { PCI_VDEVICE(INTEL, 0x3a18), TCO_ICH10}, | ||
253 | { PCI_VDEVICE(INTEL, 0x3a16), TCO_ICH10R}, | ||
254 | { PCI_VDEVICE(INTEL, 0x3a1a), TCO_ICH10D}, | ||
255 | { PCI_VDEVICE(INTEL, 0x3a14), TCO_ICH10DO}, | ||
256 | { PCI_VDEVICE(INTEL, 0x3b00), TCO_PCH}, | ||
257 | { PCI_VDEVICE(INTEL, 0x3b01), TCO_PCHM}, | ||
258 | { PCI_VDEVICE(INTEL, 0x3b02), TCO_P55}, | ||
259 | { PCI_VDEVICE(INTEL, 0x3b03), TCO_PM55}, | ||
260 | { PCI_VDEVICE(INTEL, 0x3b06), TCO_H55}, | ||
261 | { PCI_VDEVICE(INTEL, 0x3b07), TCO_QM57}, | ||
262 | { PCI_VDEVICE(INTEL, 0x3b08), TCO_H57}, | ||
263 | { PCI_VDEVICE(INTEL, 0x3b09), TCO_HM55}, | ||
264 | { PCI_VDEVICE(INTEL, 0x3b0a), TCO_Q57}, | ||
265 | { PCI_VDEVICE(INTEL, 0x3b0b), TCO_HM57}, | ||
266 | { PCI_VDEVICE(INTEL, 0x3b0d), TCO_PCHMSFF}, | ||
267 | { PCI_VDEVICE(INTEL, 0x3b0f), TCO_QS57}, | ||
268 | { PCI_VDEVICE(INTEL, 0x3b12), TCO_3400}, | ||
269 | { PCI_VDEVICE(INTEL, 0x3b14), TCO_3420}, | ||
270 | { PCI_VDEVICE(INTEL, 0x3b16), TCO_3450}, | ||
271 | { PCI_VDEVICE(INTEL, 0x5031), TCO_EP80579}, | ||
272 | { PCI_VDEVICE(INTEL, 0x1c41), TCO_CPT}, | ||
273 | { PCI_VDEVICE(INTEL, 0x1c42), TCO_CPTD}, | ||
274 | { PCI_VDEVICE(INTEL, 0x1c43), TCO_CPTM}, | ||
275 | { PCI_VDEVICE(INTEL, 0x1c44), TCO_CPT}, | ||
276 | { PCI_VDEVICE(INTEL, 0x1c45), TCO_CPT}, | ||
277 | { PCI_VDEVICE(INTEL, 0x1c46), TCO_CPT}, | ||
278 | { PCI_VDEVICE(INTEL, 0x1c47), TCO_CPT}, | ||
279 | { PCI_VDEVICE(INTEL, 0x1c48), TCO_CPT}, | ||
280 | { PCI_VDEVICE(INTEL, 0x1c49), TCO_CPT}, | ||
281 | { PCI_VDEVICE(INTEL, 0x1c4a), TCO_CPT}, | ||
282 | { PCI_VDEVICE(INTEL, 0x1c4b), TCO_CPT}, | ||
283 | { PCI_VDEVICE(INTEL, 0x1c4c), TCO_CPT}, | ||
284 | { PCI_VDEVICE(INTEL, 0x1c4d), TCO_CPT}, | ||
285 | { PCI_VDEVICE(INTEL, 0x1c4e), TCO_CPT}, | ||
286 | { PCI_VDEVICE(INTEL, 0x1c4f), TCO_CPT}, | ||
287 | { PCI_VDEVICE(INTEL, 0x1c50), TCO_CPT}, | ||
288 | { PCI_VDEVICE(INTEL, 0x1c51), TCO_CPT}, | ||
289 | { PCI_VDEVICE(INTEL, 0x1c52), TCO_CPT}, | ||
290 | { PCI_VDEVICE(INTEL, 0x1c53), TCO_CPT}, | ||
291 | { PCI_VDEVICE(INTEL, 0x1c54), TCO_CPT}, | ||
292 | { PCI_VDEVICE(INTEL, 0x1c55), TCO_CPT}, | ||
293 | { PCI_VDEVICE(INTEL, 0x1c56), TCO_CPT}, | ||
294 | { PCI_VDEVICE(INTEL, 0x1c57), TCO_CPT}, | ||
295 | { PCI_VDEVICE(INTEL, 0x1c58), TCO_CPT}, | ||
296 | { PCI_VDEVICE(INTEL, 0x1c59), TCO_CPT}, | ||
297 | { PCI_VDEVICE(INTEL, 0x1c5a), TCO_CPT}, | ||
298 | { PCI_VDEVICE(INTEL, 0x1c5b), TCO_CPT}, | ||
299 | { PCI_VDEVICE(INTEL, 0x1c5c), TCO_CPT}, | ||
300 | { PCI_VDEVICE(INTEL, 0x1c5d), TCO_CPT}, | ||
301 | { PCI_VDEVICE(INTEL, 0x1c5e), TCO_CPT}, | ||
302 | { PCI_VDEVICE(INTEL, 0x1c5f), TCO_CPT}, | ||
303 | { PCI_VDEVICE(INTEL, 0x1d40), TCO_PBG}, | ||
304 | { PCI_VDEVICE(INTEL, 0x1d41), TCO_PBG}, | ||
305 | { PCI_VDEVICE(INTEL, 0x2310), TCO_DH89XXCC}, | ||
306 | { PCI_VDEVICE(INTEL, 0x1e40), TCO_PPT}, | ||
307 | { PCI_VDEVICE(INTEL, 0x1e41), TCO_PPT}, | ||
308 | { PCI_VDEVICE(INTEL, 0x1e42), TCO_PPT}, | ||
309 | { PCI_VDEVICE(INTEL, 0x1e43), TCO_PPT}, | ||
310 | { PCI_VDEVICE(INTEL, 0x1e44), TCO_PPT}, | ||
311 | { PCI_VDEVICE(INTEL, 0x1e45), TCO_PPT}, | ||
312 | { PCI_VDEVICE(INTEL, 0x1e46), TCO_PPT}, | ||
313 | { PCI_VDEVICE(INTEL, 0x1e47), TCO_PPT}, | ||
314 | { PCI_VDEVICE(INTEL, 0x1e48), TCO_PPT}, | ||
315 | { PCI_VDEVICE(INTEL, 0x1e49), TCO_PPT}, | ||
316 | { PCI_VDEVICE(INTEL, 0x1e4a), TCO_PPT}, | ||
317 | { PCI_VDEVICE(INTEL, 0x1e4b), TCO_PPT}, | ||
318 | { PCI_VDEVICE(INTEL, 0x1e4c), TCO_PPT}, | ||
319 | { PCI_VDEVICE(INTEL, 0x1e4d), TCO_PPT}, | ||
320 | { PCI_VDEVICE(INTEL, 0x1e4e), TCO_PPT}, | ||
321 | { PCI_VDEVICE(INTEL, 0x1e4f), TCO_PPT}, | ||
322 | { PCI_VDEVICE(INTEL, 0x1e50), TCO_PPT}, | ||
323 | { PCI_VDEVICE(INTEL, 0x1e51), TCO_PPT}, | ||
324 | { PCI_VDEVICE(INTEL, 0x1e52), TCO_PPT}, | ||
325 | { PCI_VDEVICE(INTEL, 0x1e53), TCO_PPT}, | ||
326 | { PCI_VDEVICE(INTEL, 0x1e54), TCO_PPT}, | ||
327 | { PCI_VDEVICE(INTEL, 0x1e55), TCO_PPT}, | ||
328 | { PCI_VDEVICE(INTEL, 0x1e56), TCO_PPT}, | ||
329 | { PCI_VDEVICE(INTEL, 0x1e57), TCO_PPT}, | ||
330 | { PCI_VDEVICE(INTEL, 0x1e58), TCO_PPT}, | ||
331 | { PCI_VDEVICE(INTEL, 0x1e59), TCO_PPT}, | ||
332 | { PCI_VDEVICE(INTEL, 0x1e5a), TCO_PPT}, | ||
333 | { PCI_VDEVICE(INTEL, 0x1e5b), TCO_PPT}, | ||
334 | { PCI_VDEVICE(INTEL, 0x1e5c), TCO_PPT}, | ||
335 | { PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT}, | ||
336 | { PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT}, | ||
337 | { PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT}, | ||
338 | { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT}, | ||
339 | { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT}, | ||
340 | { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT}, | ||
341 | { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT}, | ||
342 | { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT}, | ||
343 | { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT}, | ||
344 | { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT}, | ||
345 | { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT}, | ||
346 | { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT}, | ||
347 | { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT}, | ||
348 | { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT}, | ||
349 | { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT}, | ||
350 | { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT}, | ||
351 | { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT}, | ||
352 | { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT}, | ||
353 | { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT}, | ||
354 | { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT}, | ||
355 | { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT}, | ||
356 | { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT}, | ||
357 | { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT}, | ||
358 | { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT}, | ||
359 | { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT}, | ||
360 | { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT}, | ||
361 | { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT}, | ||
362 | { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT}, | ||
363 | { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT}, | ||
364 | { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT}, | ||
365 | { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT}, | ||
366 | { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT}, | ||
367 | { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT}, | ||
368 | { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT}, | ||
369 | { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT}, | ||
370 | { 0, }, /* End of list */ | ||
371 | }; | ||
372 | MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); | ||
373 | |||
374 | /* Address definitions for the TCO */ | 74 | /* Address definitions for the TCO */ |
375 | /* TCO base address */ | 75 | /* TCO base address */ |
376 | #define TCOBASE (iTCO_wdt_private.ACPIBASE + 0x60) | 76 | #define TCOBASE (iTCO_wdt_private.tco_res->start) |
377 | /* SMI Control and Enable Register */ | 77 | /* SMI Control and Enable Register */ |
378 | #define SMI_EN (iTCO_wdt_private.ACPIBASE + 0x30) | 78 | #define SMI_EN (iTCO_wdt_private.smi_res->start) |
379 | 79 | ||
380 | #define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */ | 80 | #define TCO_RLD (TCOBASE + 0x00) /* TCO Timer Reload and Curr. Value */ |
381 | #define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */ | 81 | #define TCOv1_TMR (TCOBASE + 0x01) /* TCOv1 Timer Initial Value */ |
@@ -393,19 +93,18 @@ static char expect_release; | |||
393 | static struct { /* this is private data for the iTCO_wdt device */ | 93 | static struct { /* this is private data for the iTCO_wdt device */ |
394 | /* TCO version/generation */ | 94 | /* TCO version/generation */ |
395 | unsigned int iTCO_version; | 95 | unsigned int iTCO_version; |
396 | /* The device's ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ | 96 | struct resource *tco_res; |
397 | unsigned long ACPIBASE; | 97 | struct resource *smi_res; |
98 | struct resource *gcs_res; | ||
398 | /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ | 99 | /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ |
399 | unsigned long __iomem *gcs; | 100 | unsigned long __iomem *gcs; |
400 | /* the lock for io operations */ | 101 | /* the lock for io operations */ |
401 | spinlock_t io_lock; | 102 | spinlock_t io_lock; |
103 | struct platform_device *dev; | ||
402 | /* the PCI-device */ | 104 | /* the PCI-device */ |
403 | struct pci_dev *pdev; | 105 | struct pci_dev *pdev; |
404 | } iTCO_wdt_private; | 106 | } iTCO_wdt_private; |
405 | 107 | ||
406 | /* the watchdog platform device */ | ||
407 | static struct platform_device *iTCO_wdt_platform_device; | ||
408 | |||
409 | /* module parameters */ | 108 | /* module parameters */ |
410 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ | 109 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ |
411 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 110 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
@@ -485,7 +184,7 @@ static int iTCO_wdt_start(void) | |||
485 | 184 | ||
486 | spin_lock(&iTCO_wdt_private.io_lock); | 185 | spin_lock(&iTCO_wdt_private.io_lock); |
487 | 186 | ||
488 | iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat); | 187 | iTCO_vendor_pre_start(iTCO_wdt_private.smi_res, heartbeat); |
489 | 188 | ||
490 | /* disable chipset's NO_REBOOT bit */ | 189 | /* disable chipset's NO_REBOOT bit */ |
491 | if (iTCO_wdt_unset_NO_REBOOT_bit()) { | 190 | if (iTCO_wdt_unset_NO_REBOOT_bit()) { |
@@ -519,7 +218,7 @@ static int iTCO_wdt_stop(void) | |||
519 | 218 | ||
520 | spin_lock(&iTCO_wdt_private.io_lock); | 219 | spin_lock(&iTCO_wdt_private.io_lock); |
521 | 220 | ||
522 | iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE); | 221 | iTCO_vendor_pre_stop(iTCO_wdt_private.smi_res); |
523 | 222 | ||
524 | /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ | 223 | /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ |
525 | val = inw(TCO1_CNT); | 224 | val = inw(TCO1_CNT); |
@@ -541,7 +240,7 @@ static int iTCO_wdt_keepalive(void) | |||
541 | { | 240 | { |
542 | spin_lock(&iTCO_wdt_private.io_lock); | 241 | spin_lock(&iTCO_wdt_private.io_lock); |
543 | 242 | ||
544 | iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); | 243 | iTCO_vendor_pre_keepalive(iTCO_wdt_private.smi_res, heartbeat); |
545 | 244 | ||
546 | /* Reload the timer by writing to the TCO Timer Counter register */ | 245 | /* Reload the timer by writing to the TCO Timer Counter register */ |
547 | if (iTCO_wdt_private.iTCO_version == 2) | 246 | if (iTCO_wdt_private.iTCO_version == 2) |
@@ -786,83 +485,120 @@ static struct miscdevice iTCO_wdt_miscdev = { | |||
786 | * Init & exit routines | 485 | * Init & exit routines |
787 | */ | 486 | */ |
788 | 487 | ||
789 | static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | 488 | static void __devexit iTCO_wdt_cleanup(void) |
790 | const struct pci_device_id *ent, struct platform_device *dev) | 489 | { |
490 | /* Stop the timer before we leave */ | ||
491 | if (!nowayout) | ||
492 | iTCO_wdt_stop(); | ||
493 | |||
494 | /* Deregister */ | ||
495 | misc_deregister(&iTCO_wdt_miscdev); | ||
496 | |||
497 | /* release resources */ | ||
498 | release_region(iTCO_wdt_private.tco_res->start, | ||
499 | resource_size(iTCO_wdt_private.tco_res)); | ||
500 | release_region(iTCO_wdt_private.smi_res->start, | ||
501 | resource_size(iTCO_wdt_private.smi_res)); | ||
502 | if (iTCO_wdt_private.iTCO_version == 2) { | ||
503 | iounmap(iTCO_wdt_private.gcs); | ||
504 | release_mem_region(iTCO_wdt_private.gcs_res->start, | ||
505 | resource_size(iTCO_wdt_private.gcs_res)); | ||
506 | } | ||
507 | |||
508 | iTCO_wdt_private.tco_res = NULL; | ||
509 | iTCO_wdt_private.smi_res = NULL; | ||
510 | iTCO_wdt_private.gcs_res = NULL; | ||
511 | iTCO_wdt_private.gcs = NULL; | ||
512 | } | ||
513 | |||
514 | static int __devinit iTCO_wdt_probe(struct platform_device *dev) | ||
791 | { | 515 | { |
792 | int ret; | 516 | int ret = -ENODEV; |
793 | u32 base_address; | ||
794 | unsigned long RCBA; | ||
795 | unsigned long val32; | 517 | unsigned long val32; |
518 | struct lpc_ich_info *ich_info = dev->dev.platform_data; | ||
519 | |||
520 | if (!ich_info) | ||
521 | goto out; | ||
522 | |||
523 | spin_lock_init(&iTCO_wdt_private.io_lock); | ||
524 | |||
525 | iTCO_wdt_private.tco_res = | ||
526 | platform_get_resource(dev, IORESOURCE_IO, ICH_RES_IO_TCO); | ||
527 | if (!iTCO_wdt_private.tco_res) | ||
528 | goto out; | ||
529 | |||
530 | iTCO_wdt_private.smi_res = | ||
531 | platform_get_resource(dev, IORESOURCE_IO, ICH_RES_IO_SMI); | ||
532 | if (!iTCO_wdt_private.smi_res) | ||
533 | goto out; | ||
534 | |||
535 | iTCO_wdt_private.iTCO_version = ich_info->iTCO_version; | ||
536 | iTCO_wdt_private.dev = dev; | ||
537 | iTCO_wdt_private.pdev = to_pci_dev(dev->dev.parent); | ||
796 | 538 | ||
797 | /* | 539 | /* |
798 | * Find the ACPI/PM base I/O address which is the base | 540 | * Get the Memory-Mapped GCS register, we need it for the |
799 | * for the TCO registers (TCOBASE=ACPIBASE + 0x60) | 541 | * NO_REBOOT flag (TCO v2). |
800 | * ACPIBASE is bits [15:7] from 0x40-0x43 | ||
801 | */ | 542 | */ |
802 | pci_read_config_dword(pdev, 0x40, &base_address); | ||
803 | base_address &= 0x0000ff80; | ||
804 | if (base_address == 0x00000000) { | ||
805 | /* Something's wrong here, ACPIBASE has to be set */ | ||
806 | pr_err("failed to get TCOBASE address, device disabled by hardware/BIOS\n"); | ||
807 | return -ENODEV; | ||
808 | } | ||
809 | iTCO_wdt_private.iTCO_version = | ||
810 | iTCO_chipset_info[ent->driver_data].iTCO_version; | ||
811 | iTCO_wdt_private.ACPIBASE = base_address; | ||
812 | iTCO_wdt_private.pdev = pdev; | ||
813 | |||
814 | /* Get the Memory-Mapped GCS register, we need it for the | ||
815 | NO_REBOOT flag (TCO v2). To get access to it you have to | ||
816 | read RCBA from PCI Config space 0xf0 and use it as base. | ||
817 | GCS = RCBA + ICH6_GCS(0x3410). */ | ||
818 | if (iTCO_wdt_private.iTCO_version == 2) { | 543 | if (iTCO_wdt_private.iTCO_version == 2) { |
819 | pci_read_config_dword(pdev, 0xf0, &base_address); | 544 | iTCO_wdt_private.gcs_res = platform_get_resource(dev, |
820 | if ((base_address & 1) == 0) { | 545 | IORESOURCE_MEM, |
821 | pr_err("RCBA is disabled by hardware/BIOS, device disabled\n"); | 546 | ICH_RES_MEM_GCS); |
822 | ret = -ENODEV; | 547 | |
548 | if (!iTCO_wdt_private.gcs_res) | ||
549 | goto out; | ||
550 | |||
551 | if (!request_mem_region(iTCO_wdt_private.gcs_res->start, | ||
552 | resource_size(iTCO_wdt_private.gcs_res), dev->name)) { | ||
553 | ret = -EBUSY; | ||
823 | goto out; | 554 | goto out; |
824 | } | 555 | } |
825 | RCBA = base_address & 0xffffc000; | 556 | iTCO_wdt_private.gcs = ioremap(iTCO_wdt_private.gcs_res->start, |
826 | iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); | 557 | resource_size(iTCO_wdt_private.gcs_res)); |
558 | if (!iTCO_wdt_private.gcs) { | ||
559 | ret = -EIO; | ||
560 | goto unreg_gcs; | ||
561 | } | ||
827 | } | 562 | } |
828 | 563 | ||
829 | /* Check chipset's NO_REBOOT bit */ | 564 | /* Check chipset's NO_REBOOT bit */ |
830 | if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { | 565 | if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { |
831 | pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); | 566 | pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); |
832 | ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ | 567 | ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ |
833 | goto out_unmap; | 568 | goto unmap_gcs; |
834 | } | 569 | } |
835 | 570 | ||
836 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | 571 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ |
837 | iTCO_wdt_set_NO_REBOOT_bit(); | 572 | iTCO_wdt_set_NO_REBOOT_bit(); |
838 | 573 | ||
839 | /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ | 574 | /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ |
840 | if (!request_region(SMI_EN, 4, "iTCO_wdt")) { | 575 | if (!request_region(iTCO_wdt_private.smi_res->start, |
841 | pr_err("I/O address 0x%04lx already in use, device disabled\n", | 576 | resource_size(iTCO_wdt_private.smi_res), dev->name)) { |
577 | pr_err("I/O address 0x%04llx already in use, device disabled\n", | ||
842 | SMI_EN); | 578 | SMI_EN); |
843 | ret = -EIO; | 579 | ret = -EBUSY; |
844 | goto out_unmap; | 580 | goto unmap_gcs; |
845 | } | 581 | } |
846 | if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) { | 582 | if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) { |
847 | /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ | 583 | /* |
584 | * Bit 13: TCO_EN -> 0 | ||
585 | * Disables TCO logic generating an SMI# | ||
586 | */ | ||
848 | val32 = inl(SMI_EN); | 587 | val32 = inl(SMI_EN); |
849 | val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ | 588 | val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ |
850 | outl(val32, SMI_EN); | 589 | outl(val32, SMI_EN); |
851 | } | 590 | } |
852 | 591 | ||
853 | /* The TCO I/O registers reside in a 32-byte range pointed to | 592 | if (!request_region(iTCO_wdt_private.tco_res->start, |
854 | by the TCOBASE value */ | 593 | resource_size(iTCO_wdt_private.tco_res), dev->name)) { |
855 | if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { | 594 | pr_err("I/O address 0x%04llx already in use, device disabled\n", |
856 | pr_err("I/O address 0x%04lx already in use, device disabled\n", | ||
857 | TCOBASE); | 595 | TCOBASE); |
858 | ret = -EIO; | 596 | ret = -EBUSY; |
859 | goto unreg_smi_en; | 597 | goto unreg_smi; |
860 | } | 598 | } |
861 | 599 | ||
862 | pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n", | 600 | pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n", |
863 | iTCO_chipset_info[ent->driver_data].name, | 601 | ich_info->name, ich_info->iTCO_version, TCOBASE); |
864 | iTCO_chipset_info[ent->driver_data].iTCO_version, | ||
865 | TCOBASE); | ||
866 | 602 | ||
867 | /* Clear out the (probably old) status */ | 603 | /* Clear out the (probably old) status */ |
868 | outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ | 604 | outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ |
@@ -883,7 +619,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
883 | if (ret != 0) { | 619 | if (ret != 0) { |
884 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", | 620 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", |
885 | WATCHDOG_MINOR, ret); | 621 | WATCHDOG_MINOR, ret); |
886 | goto unreg_region; | 622 | goto unreg_tco; |
887 | } | 623 | } |
888 | 624 | ||
889 | pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n", | 625 | pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n", |
@@ -891,62 +627,31 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, | |||
891 | 627 | ||
892 | return 0; | 628 | return 0; |
893 | 629 | ||
894 | unreg_region: | 630 | unreg_tco: |
895 | release_region(TCOBASE, 0x20); | 631 | release_region(iTCO_wdt_private.tco_res->start, |
896 | unreg_smi_en: | 632 | resource_size(iTCO_wdt_private.tco_res)); |
897 | release_region(SMI_EN, 4); | 633 | unreg_smi: |
898 | out_unmap: | 634 | release_region(iTCO_wdt_private.smi_res->start, |
635 | resource_size(iTCO_wdt_private.smi_res)); | ||
636 | unmap_gcs: | ||
899 | if (iTCO_wdt_private.iTCO_version == 2) | 637 | if (iTCO_wdt_private.iTCO_version == 2) |
900 | iounmap(iTCO_wdt_private.gcs); | 638 | iounmap(iTCO_wdt_private.gcs); |
901 | out: | 639 | unreg_gcs: |
902 | iTCO_wdt_private.ACPIBASE = 0; | ||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | static void __devexit iTCO_wdt_cleanup(void) | ||
907 | { | ||
908 | /* Stop the timer before we leave */ | ||
909 | if (!nowayout) | ||
910 | iTCO_wdt_stop(); | ||
911 | |||
912 | /* Deregister */ | ||
913 | misc_deregister(&iTCO_wdt_miscdev); | ||
914 | release_region(TCOBASE, 0x20); | ||
915 | release_region(SMI_EN, 4); | ||
916 | if (iTCO_wdt_private.iTCO_version == 2) | 640 | if (iTCO_wdt_private.iTCO_version == 2) |
917 | iounmap(iTCO_wdt_private.gcs); | 641 | release_mem_region(iTCO_wdt_private.gcs_res->start, |
918 | pci_dev_put(iTCO_wdt_private.pdev); | 642 | resource_size(iTCO_wdt_private.gcs_res)); |
919 | iTCO_wdt_private.ACPIBASE = 0; | 643 | out: |
920 | } | 644 | iTCO_wdt_private.tco_res = NULL; |
921 | 645 | iTCO_wdt_private.smi_res = NULL; | |
922 | static int __devinit iTCO_wdt_probe(struct platform_device *dev) | 646 | iTCO_wdt_private.gcs_res = NULL; |
923 | { | 647 | iTCO_wdt_private.gcs = NULL; |
924 | int ret = -ENODEV; | ||
925 | int found = 0; | ||
926 | struct pci_dev *pdev = NULL; | ||
927 | const struct pci_device_id *ent; | ||
928 | |||
929 | spin_lock_init(&iTCO_wdt_private.io_lock); | ||
930 | |||
931 | for_each_pci_dev(pdev) { | ||
932 | ent = pci_match_id(iTCO_wdt_pci_tbl, pdev); | ||
933 | if (ent) { | ||
934 | found++; | ||
935 | ret = iTCO_wdt_init(pdev, ent, dev); | ||
936 | if (!ret) | ||
937 | break; | ||
938 | } | ||
939 | } | ||
940 | |||
941 | if (!found) | ||
942 | pr_info("No device detected\n"); | ||
943 | 648 | ||
944 | return ret; | 649 | return ret; |
945 | } | 650 | } |
946 | 651 | ||
947 | static int __devexit iTCO_wdt_remove(struct platform_device *dev) | 652 | static int __devexit iTCO_wdt_remove(struct platform_device *dev) |
948 | { | 653 | { |
949 | if (iTCO_wdt_private.ACPIBASE) | 654 | if (iTCO_wdt_private.tco_res || iTCO_wdt_private.smi_res) |
950 | iTCO_wdt_cleanup(); | 655 | iTCO_wdt_cleanup(); |
951 | 656 | ||
952 | return 0; | 657 | return 0; |
@@ -977,23 +682,11 @@ static int __init iTCO_wdt_init_module(void) | |||
977 | if (err) | 682 | if (err) |
978 | return err; | 683 | return err; |
979 | 684 | ||
980 | iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, | ||
981 | -1, NULL, 0); | ||
982 | if (IS_ERR(iTCO_wdt_platform_device)) { | ||
983 | err = PTR_ERR(iTCO_wdt_platform_device); | ||
984 | goto unreg_platform_driver; | ||
985 | } | ||
986 | |||
987 | return 0; | 685 | return 0; |
988 | |||
989 | unreg_platform_driver: | ||
990 | platform_driver_unregister(&iTCO_wdt_driver); | ||
991 | return err; | ||
992 | } | 686 | } |
993 | 687 | ||
994 | static void __exit iTCO_wdt_cleanup_module(void) | 688 | static void __exit iTCO_wdt_cleanup_module(void) |
995 | { | 689 | { |
996 | platform_device_unregister(iTCO_wdt_platform_device); | ||
997 | platform_driver_unregister(&iTCO_wdt_driver); | 690 | platform_driver_unregister(&iTCO_wdt_driver); |
998 | pr_info("Watchdog Module Unloaded\n"); | 691 | pr_info("Watchdog Module Unloaded\n"); |
999 | } | 692 | } |