aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorAaron Sierra <asierra@xes-inc.com>2012-04-20 15:14:11 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-09 11:20:09 -0400
commit887c8ec7219fc8eba78bb8f44a74c660934e9b98 (patch)
treec7f5b2d24c984a7ca57120dd057cd3cd2f6efee2 /drivers/watchdog
parent16c5c023aac86228e3e94c4bf6d19708ea861a05 (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/Kconfig1
-rw-r--r--drivers/watchdog/iTCO_vendor.h6
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c43
-rw-r--r--drivers/watchdog/iTCO_wdt.c529
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
563config ITCO_WDT 563config 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
3extern void iTCO_vendor_pre_start(unsigned long, unsigned int); 3extern void iTCO_vendor_pre_start(struct resource *, unsigned int);
4extern void iTCO_vendor_pre_stop(unsigned long); 4extern void iTCO_vendor_pre_stop(struct resource *);
5extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int); 5extern void iTCO_vendor_pre_keepalive(struct resource *, unsigned int);
6extern void iTCO_vendor_pre_set_heartbeat(unsigned int); 6extern void iTCO_vendor_pre_set_heartbeat(unsigned int);
7extern int iTCO_vendor_check_noreboot_on(void); 7extern 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
85static void supermicro_old_pre_start(unsigned long acpibase) 80static 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
95static void supermicro_old_pre_stop(unsigned long acpibase) 90static 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
273static void broken_bios_start(unsigned long acpibase) 268static 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
284static void broken_bios_stop(unsigned long acpibase) 279static 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
299void iTCO_vendor_pre_start(unsigned long acpibase, 294void 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}
314EXPORT_SYMBOL(iTCO_vendor_pre_start); 309EXPORT_SYMBOL(iTCO_vendor_pre_start);
315 310
316void iTCO_vendor_pre_stop(unsigned long acpibase) 311void 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}
330EXPORT_SYMBOL(iTCO_vendor_pre_stop); 325EXPORT_SYMBOL(iTCO_vendor_pre_stop);
331 326
332void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat) 327void 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 */
73enum 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
134static 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 */
205static 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};
372MODULE_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;
393static struct { /* this is private data for the iTCO_wdt device */ 93static 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 */
407static 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 */
411static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 110static 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
789static int __devinit iTCO_wdt_init(struct pci_dev *pdev, 488static 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
514static 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
894unreg_region: 630unreg_tco:
895 release_region(TCOBASE, 0x20); 631 release_region(iTCO_wdt_private.tco_res->start,
896unreg_smi_en: 632 resource_size(iTCO_wdt_private.tco_res));
897 release_region(SMI_EN, 4); 633unreg_smi:
898out_unmap: 634 release_region(iTCO_wdt_private.smi_res->start,
635 resource_size(iTCO_wdt_private.smi_res));
636unmap_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);
901out: 639unreg_gcs:
902 iTCO_wdt_private.ACPIBASE = 0;
903 return ret;
904}
905
906static 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; 643out:
920} 644 iTCO_wdt_private.tco_res = NULL;
921 645 iTCO_wdt_private.smi_res = NULL;
922static 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
947static int __devexit iTCO_wdt_remove(struct platform_device *dev) 652static 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
989unreg_platform_driver:
990 platform_driver_unregister(&iTCO_wdt_driver);
991 return err;
992} 686}
993 687
994static void __exit iTCO_wdt_cleanup_module(void) 688static 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}