diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/Kconfig | 3 | ||||
-rw-r--r-- | drivers/mfd/lpc_ich.c | 171 | ||||
-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 |
6 files changed, 306 insertions, 447 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 211f5dee9b68..1e9a7d5ec919 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -785,7 +785,8 @@ config LPC_ICH | |||
785 | help | 785 | help |
786 | The LPC bridge function of the Intel ICH provides support for | 786 | The LPC bridge function of the Intel ICH provides support for |
787 | many functional units. This driver provides needed support for | 787 | many functional units. This driver provides needed support for |
788 | other drivers to control these functions, currently GPIO. | 788 | other drivers to control these functions, currently GPIO and |
789 | watchdog. | ||
789 | 790 | ||
790 | config MFD_RDC321X | 791 | config MFD_RDC321X |
791 | tristate "Support for RDC-R321x southbridge" | 792 | tristate "Support for RDC-R321x southbridge" |
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 7e3a7b6ab022..027cc8f86132 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c | |||
@@ -65,14 +65,42 @@ | |||
65 | #define ACPIBASE 0x40 | 65 | #define ACPIBASE 0x40 |
66 | #define ACPIBASE_GPE_OFF 0x28 | 66 | #define ACPIBASE_GPE_OFF 0x28 |
67 | #define ACPIBASE_GPE_END 0x2f | 67 | #define ACPIBASE_GPE_END 0x2f |
68 | #define ACPIBASE_SMI_OFF 0x30 | ||
69 | #define ACPIBASE_SMI_END 0x33 | ||
70 | #define ACPIBASE_TCO_OFF 0x60 | ||
71 | #define ACPIBASE_TCO_END 0x7f | ||
68 | #define ACPICTRL 0x44 | 72 | #define ACPICTRL 0x44 |
69 | 73 | ||
74 | #define ACPIBASE_GCS_OFF 0x3410 | ||
75 | #define ACPIBASE_GCS_END 0x3414 | ||
76 | |||
70 | #define GPIOBASE 0x48 | 77 | #define GPIOBASE 0x48 |
71 | #define GPIOCTRL 0x4C | 78 | #define GPIOCTRL 0x4C |
72 | 79 | ||
80 | #define RCBABASE 0xf0 | ||
81 | |||
82 | #define wdt_io_res(i) wdt_res(0, i) | ||
83 | #define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) | ||
84 | #define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) | ||
85 | |||
73 | static int lpc_ich_acpi_save = -1; | 86 | static int lpc_ich_acpi_save = -1; |
74 | static int lpc_ich_gpio_save = -1; | 87 | static int lpc_ich_gpio_save = -1; |
75 | 88 | ||
89 | static struct resource wdt_ich_res[] = { | ||
90 | /* ACPI - TCO */ | ||
91 | { | ||
92 | .flags = IORESOURCE_IO, | ||
93 | }, | ||
94 | /* ACPI - SMI */ | ||
95 | { | ||
96 | .flags = IORESOURCE_IO, | ||
97 | }, | ||
98 | /* GCS */ | ||
99 | { | ||
100 | .flags = IORESOURCE_MEM, | ||
101 | }, | ||
102 | }; | ||
103 | |||
76 | static struct resource gpio_ich_res[] = { | 104 | static struct resource gpio_ich_res[] = { |
77 | /* GPIO */ | 105 | /* GPIO */ |
78 | { | 106 | { |
@@ -85,10 +113,17 @@ static struct resource gpio_ich_res[] = { | |||
85 | }; | 113 | }; |
86 | 114 | ||
87 | enum lpc_cells { | 115 | enum lpc_cells { |
88 | LPC_GPIO = 0, | 116 | LPC_WDT = 0, |
117 | LPC_GPIO, | ||
89 | }; | 118 | }; |
90 | 119 | ||
91 | static struct mfd_cell lpc_ich_cells[] = { | 120 | static struct mfd_cell lpc_ich_cells[] = { |
121 | [LPC_WDT] = { | ||
122 | .name = "iTCO_wdt", | ||
123 | .num_resources = ARRAY_SIZE(wdt_ich_res), | ||
124 | .resources = wdt_ich_res, | ||
125 | .ignore_resource_conflicts = true, | ||
126 | }, | ||
92 | [LPC_GPIO] = { | 127 | [LPC_GPIO] = { |
93 | .name = "gpio_ich", | 128 | .name = "gpio_ich", |
94 | .num_resources = ARRAY_SIZE(gpio_ich_res), | 129 | .num_resources = ARRAY_SIZE(gpio_ich_res), |
@@ -162,218 +197,276 @@ enum lpc_chipsets { | |||
162 | struct lpc_ich_info lpc_chipset_info[] __devinitdata = { | 197 | struct lpc_ich_info lpc_chipset_info[] __devinitdata = { |
163 | [LPC_ICH] = { | 198 | [LPC_ICH] = { |
164 | .name = "ICH", | 199 | .name = "ICH", |
200 | .iTCO_version = 1, | ||
165 | }, | 201 | }, |
166 | [LPC_ICH0] = { | 202 | [LPC_ICH0] = { |
167 | .name = "ICH0", | 203 | .name = "ICH0", |
204 | .iTCO_version = 1, | ||
168 | }, | 205 | }, |
169 | [LPC_ICH2] = { | 206 | [LPC_ICH2] = { |
170 | .name = "ICH2", | 207 | .name = "ICH2", |
208 | .iTCO_version = 1, | ||
171 | }, | 209 | }, |
172 | [LPC_ICH2M] = { | 210 | [LPC_ICH2M] = { |
173 | .name = "ICH2-M", | 211 | .name = "ICH2-M", |
212 | .iTCO_version = 1, | ||
174 | }, | 213 | }, |
175 | [LPC_ICH3] = { | 214 | [LPC_ICH3] = { |
176 | .name = "ICH3-S", | 215 | .name = "ICH3-S", |
216 | .iTCO_version = 1, | ||
177 | }, | 217 | }, |
178 | [LPC_ICH3M] = { | 218 | [LPC_ICH3M] = { |
179 | .name = "ICH3-M", | 219 | .name = "ICH3-M", |
220 | .iTCO_version = 1, | ||
180 | }, | 221 | }, |
181 | [LPC_ICH4] = { | 222 | [LPC_ICH4] = { |
182 | .name = "ICH4", | 223 | .name = "ICH4", |
224 | .iTCO_version = 1, | ||
183 | }, | 225 | }, |
184 | [LPC_ICH4M] = { | 226 | [LPC_ICH4M] = { |
185 | .name = "ICH4-M", | 227 | .name = "ICH4-M", |
228 | .iTCO_version = 1, | ||
186 | }, | 229 | }, |
187 | [LPC_CICH] = { | 230 | [LPC_CICH] = { |
188 | .name = "C-ICH", | 231 | .name = "C-ICH", |
232 | .iTCO_version = 1, | ||
189 | }, | 233 | }, |
190 | [LPC_ICH5] = { | 234 | [LPC_ICH5] = { |
191 | .name = "ICH5 or ICH5R", | 235 | .name = "ICH5 or ICH5R", |
236 | .iTCO_version = 1, | ||
192 | }, | 237 | }, |
193 | [LPC_6300ESB] = { | 238 | [LPC_6300ESB] = { |
194 | .name = "6300ESB", | 239 | .name = "6300ESB", |
240 | .iTCO_version = 1, | ||
195 | }, | 241 | }, |
196 | [LPC_ICH6] = { | 242 | [LPC_ICH6] = { |
197 | .name = "ICH6 or ICH6R", | 243 | .name = "ICH6 or ICH6R", |
244 | .iTCO_version = 2, | ||
198 | .gpio_version = ICH_V6_GPIO, | 245 | .gpio_version = ICH_V6_GPIO, |
199 | }, | 246 | }, |
200 | [LPC_ICH6M] = { | 247 | [LPC_ICH6M] = { |
201 | .name = "ICH6-M", | 248 | .name = "ICH6-M", |
249 | .iTCO_version = 2, | ||
202 | .gpio_version = ICH_V6_GPIO, | 250 | .gpio_version = ICH_V6_GPIO, |
203 | }, | 251 | }, |
204 | [LPC_ICH6W] = { | 252 | [LPC_ICH6W] = { |
205 | .name = "ICH6W or ICH6RW", | 253 | .name = "ICH6W or ICH6RW", |
254 | .iTCO_version = 2, | ||
206 | .gpio_version = ICH_V6_GPIO, | 255 | .gpio_version = ICH_V6_GPIO, |
207 | }, | 256 | }, |
208 | [LPC_631XESB] = { | 257 | [LPC_631XESB] = { |
209 | .name = "631xESB/632xESB", | 258 | .name = "631xESB/632xESB", |
259 | .iTCO_version = 2, | ||
210 | .gpio_version = ICH_V6_GPIO, | 260 | .gpio_version = ICH_V6_GPIO, |
211 | }, | 261 | }, |
212 | [LPC_ICH7] = { | 262 | [LPC_ICH7] = { |
213 | .name = "ICH7 or ICH7R", | 263 | .name = "ICH7 or ICH7R", |
264 | .iTCO_version = 2, | ||
214 | .gpio_version = ICH_V7_GPIO, | 265 | .gpio_version = ICH_V7_GPIO, |
215 | }, | 266 | }, |
216 | [LPC_ICH7DH] = { | 267 | [LPC_ICH7DH] = { |
217 | .name = "ICH7DH", | 268 | .name = "ICH7DH", |
269 | .iTCO_version = 2, | ||
218 | .gpio_version = ICH_V7_GPIO, | 270 | .gpio_version = ICH_V7_GPIO, |
219 | }, | 271 | }, |
220 | [LPC_ICH7M] = { | 272 | [LPC_ICH7M] = { |
221 | .name = "ICH7-M or ICH7-U", | 273 | .name = "ICH7-M or ICH7-U", |
274 | .iTCO_version = 2, | ||
222 | .gpio_version = ICH_V7_GPIO, | 275 | .gpio_version = ICH_V7_GPIO, |
223 | }, | 276 | }, |
224 | [LPC_ICH7MDH] = { | 277 | [LPC_ICH7MDH] = { |
225 | .name = "ICH7-M DH", | 278 | .name = "ICH7-M DH", |
279 | .iTCO_version = 2, | ||
226 | .gpio_version = ICH_V7_GPIO, | 280 | .gpio_version = ICH_V7_GPIO, |
227 | }, | 281 | }, |
228 | [LPC_NM10] = { | 282 | [LPC_NM10] = { |
229 | .name = "NM10", | 283 | .name = "NM10", |
284 | .iTCO_version = 2, | ||
230 | }, | 285 | }, |
231 | [LPC_ICH8] = { | 286 | [LPC_ICH8] = { |
232 | .name = "ICH8 or ICH8R", | 287 | .name = "ICH8 or ICH8R", |
288 | .iTCO_version = 2, | ||
233 | .gpio_version = ICH_V7_GPIO, | 289 | .gpio_version = ICH_V7_GPIO, |
234 | }, | 290 | }, |
235 | [LPC_ICH8DH] = { | 291 | [LPC_ICH8DH] = { |
236 | .name = "ICH8DH", | 292 | .name = "ICH8DH", |
293 | .iTCO_version = 2, | ||
237 | .gpio_version = ICH_V7_GPIO, | 294 | .gpio_version = ICH_V7_GPIO, |
238 | }, | 295 | }, |
239 | [LPC_ICH8DO] = { | 296 | [LPC_ICH8DO] = { |
240 | .name = "ICH8DO", | 297 | .name = "ICH8DO", |
298 | .iTCO_version = 2, | ||
241 | .gpio_version = ICH_V7_GPIO, | 299 | .gpio_version = ICH_V7_GPIO, |
242 | }, | 300 | }, |
243 | [LPC_ICH8M] = { | 301 | [LPC_ICH8M] = { |
244 | .name = "ICH8M", | 302 | .name = "ICH8M", |
303 | .iTCO_version = 2, | ||
245 | .gpio_version = ICH_V7_GPIO, | 304 | .gpio_version = ICH_V7_GPIO, |
246 | }, | 305 | }, |
247 | [LPC_ICH8ME] = { | 306 | [LPC_ICH8ME] = { |
248 | .name = "ICH8M-E", | 307 | .name = "ICH8M-E", |
308 | .iTCO_version = 2, | ||
249 | .gpio_version = ICH_V7_GPIO, | 309 | .gpio_version = ICH_V7_GPIO, |
250 | }, | 310 | }, |
251 | [LPC_ICH9] = { | 311 | [LPC_ICH9] = { |
252 | .name = "ICH9", | 312 | .name = "ICH9", |
313 | .iTCO_version = 2, | ||
253 | .gpio_version = ICH_V9_GPIO, | 314 | .gpio_version = ICH_V9_GPIO, |
254 | }, | 315 | }, |
255 | [LPC_ICH9R] = { | 316 | [LPC_ICH9R] = { |
256 | .name = "ICH9R", | 317 | .name = "ICH9R", |
318 | .iTCO_version = 2, | ||
257 | .gpio_version = ICH_V9_GPIO, | 319 | .gpio_version = ICH_V9_GPIO, |
258 | }, | 320 | }, |
259 | [LPC_ICH9DH] = { | 321 | [LPC_ICH9DH] = { |
260 | .name = "ICH9DH", | 322 | .name = "ICH9DH", |
323 | .iTCO_version = 2, | ||
261 | .gpio_version = ICH_V9_GPIO, | 324 | .gpio_version = ICH_V9_GPIO, |
262 | }, | 325 | }, |
263 | [LPC_ICH9DO] = { | 326 | [LPC_ICH9DO] = { |
264 | .name = "ICH9DO", | 327 | .name = "ICH9DO", |
328 | .iTCO_version = 2, | ||
265 | .gpio_version = ICH_V9_GPIO, | 329 | .gpio_version = ICH_V9_GPIO, |
266 | }, | 330 | }, |
267 | [LPC_ICH9M] = { | 331 | [LPC_ICH9M] = { |
268 | .name = "ICH9M", | 332 | .name = "ICH9M", |
333 | .iTCO_version = 2, | ||
269 | .gpio_version = ICH_V9_GPIO, | 334 | .gpio_version = ICH_V9_GPIO, |
270 | }, | 335 | }, |
271 | [LPC_ICH9ME] = { | 336 | [LPC_ICH9ME] = { |
272 | .name = "ICH9M-E", | 337 | .name = "ICH9M-E", |
338 | .iTCO_version = 2, | ||
273 | .gpio_version = ICH_V9_GPIO, | 339 | .gpio_version = ICH_V9_GPIO, |
274 | }, | 340 | }, |
275 | [LPC_ICH10] = { | 341 | [LPC_ICH10] = { |
276 | .name = "ICH10", | 342 | .name = "ICH10", |
343 | .iTCO_version = 2, | ||
277 | .gpio_version = ICH_V10CONS_GPIO, | 344 | .gpio_version = ICH_V10CONS_GPIO, |
278 | }, | 345 | }, |
279 | [LPC_ICH10R] = { | 346 | [LPC_ICH10R] = { |
280 | .name = "ICH10R", | 347 | .name = "ICH10R", |
348 | .iTCO_version = 2, | ||
281 | .gpio_version = ICH_V10CONS_GPIO, | 349 | .gpio_version = ICH_V10CONS_GPIO, |
282 | }, | 350 | }, |
283 | [LPC_ICH10D] = { | 351 | [LPC_ICH10D] = { |
284 | .name = "ICH10D", | 352 | .name = "ICH10D", |
353 | .iTCO_version = 2, | ||
285 | .gpio_version = ICH_V10CORP_GPIO, | 354 | .gpio_version = ICH_V10CORP_GPIO, |
286 | }, | 355 | }, |
287 | [LPC_ICH10DO] = { | 356 | [LPC_ICH10DO] = { |
288 | .name = "ICH10DO", | 357 | .name = "ICH10DO", |
358 | .iTCO_version = 2, | ||
289 | .gpio_version = ICH_V10CORP_GPIO, | 359 | .gpio_version = ICH_V10CORP_GPIO, |
290 | }, | 360 | }, |
291 | [LPC_PCH] = { | 361 | [LPC_PCH] = { |
292 | .name = "PCH Desktop Full Featured", | 362 | .name = "PCH Desktop Full Featured", |
363 | .iTCO_version = 2, | ||
293 | .gpio_version = ICH_V5_GPIO, | 364 | .gpio_version = ICH_V5_GPIO, |
294 | }, | 365 | }, |
295 | [LPC_PCHM] = { | 366 | [LPC_PCHM] = { |
296 | .name = "PCH Mobile Full Featured", | 367 | .name = "PCH Mobile Full Featured", |
368 | .iTCO_version = 2, | ||
297 | .gpio_version = ICH_V5_GPIO, | 369 | .gpio_version = ICH_V5_GPIO, |
298 | }, | 370 | }, |
299 | [LPC_P55] = { | 371 | [LPC_P55] = { |
300 | .name = "P55", | 372 | .name = "P55", |
373 | .iTCO_version = 2, | ||
301 | .gpio_version = ICH_V5_GPIO, | 374 | .gpio_version = ICH_V5_GPIO, |
302 | }, | 375 | }, |
303 | [LPC_PM55] = { | 376 | [LPC_PM55] = { |
304 | .name = "PM55", | 377 | .name = "PM55", |
378 | .iTCO_version = 2, | ||
305 | .gpio_version = ICH_V5_GPIO, | 379 | .gpio_version = ICH_V5_GPIO, |
306 | }, | 380 | }, |
307 | [LPC_H55] = { | 381 | [LPC_H55] = { |
308 | .name = "H55", | 382 | .name = "H55", |
383 | .iTCO_version = 2, | ||
309 | .gpio_version = ICH_V5_GPIO, | 384 | .gpio_version = ICH_V5_GPIO, |
310 | }, | 385 | }, |
311 | [LPC_QM57] = { | 386 | [LPC_QM57] = { |
312 | .name = "QM57", | 387 | .name = "QM57", |
388 | .iTCO_version = 2, | ||
313 | .gpio_version = ICH_V5_GPIO, | 389 | .gpio_version = ICH_V5_GPIO, |
314 | }, | 390 | }, |
315 | [LPC_H57] = { | 391 | [LPC_H57] = { |
316 | .name = "H57", | 392 | .name = "H57", |
393 | .iTCO_version = 2, | ||
317 | .gpio_version = ICH_V5_GPIO, | 394 | .gpio_version = ICH_V5_GPIO, |
318 | }, | 395 | }, |
319 | [LPC_HM55] = { | 396 | [LPC_HM55] = { |
320 | .name = "HM55", | 397 | .name = "HM55", |
398 | .iTCO_version = 2, | ||
321 | .gpio_version = ICH_V5_GPIO, | 399 | .gpio_version = ICH_V5_GPIO, |
322 | }, | 400 | }, |
323 | [LPC_Q57] = { | 401 | [LPC_Q57] = { |
324 | .name = "Q57", | 402 | .name = "Q57", |
403 | .iTCO_version = 2, | ||
325 | .gpio_version = ICH_V5_GPIO, | 404 | .gpio_version = ICH_V5_GPIO, |
326 | }, | 405 | }, |
327 | [LPC_HM57] = { | 406 | [LPC_HM57] = { |
328 | .name = "HM57", | 407 | .name = "HM57", |
408 | .iTCO_version = 2, | ||
329 | .gpio_version = ICH_V5_GPIO, | 409 | .gpio_version = ICH_V5_GPIO, |
330 | }, | 410 | }, |
331 | [LPC_PCHMSFF] = { | 411 | [LPC_PCHMSFF] = { |
332 | .name = "PCH Mobile SFF Full Featured", | 412 | .name = "PCH Mobile SFF Full Featured", |
413 | .iTCO_version = 2, | ||
333 | .gpio_version = ICH_V5_GPIO, | 414 | .gpio_version = ICH_V5_GPIO, |
334 | }, | 415 | }, |
335 | [LPC_QS57] = { | 416 | [LPC_QS57] = { |
336 | .name = "QS57", | 417 | .name = "QS57", |
418 | .iTCO_version = 2, | ||
337 | .gpio_version = ICH_V5_GPIO, | 419 | .gpio_version = ICH_V5_GPIO, |
338 | }, | 420 | }, |
339 | [LPC_3400] = { | 421 | [LPC_3400] = { |
340 | .name = "3400", | 422 | .name = "3400", |
423 | .iTCO_version = 2, | ||
341 | .gpio_version = ICH_V5_GPIO, | 424 | .gpio_version = ICH_V5_GPIO, |
342 | }, | 425 | }, |
343 | [LPC_3420] = { | 426 | [LPC_3420] = { |
344 | .name = "3420", | 427 | .name = "3420", |
428 | .iTCO_version = 2, | ||
345 | .gpio_version = ICH_V5_GPIO, | 429 | .gpio_version = ICH_V5_GPIO, |
346 | }, | 430 | }, |
347 | [LPC_3450] = { | 431 | [LPC_3450] = { |
348 | .name = "3450", | 432 | .name = "3450", |
433 | .iTCO_version = 2, | ||
349 | .gpio_version = ICH_V5_GPIO, | 434 | .gpio_version = ICH_V5_GPIO, |
350 | }, | 435 | }, |
351 | [LPC_EP80579] = { | 436 | [LPC_EP80579] = { |
352 | .name = "EP80579", | 437 | .name = "EP80579", |
438 | .iTCO_version = 2, | ||
353 | }, | 439 | }, |
354 | [LPC_CPT] = { | 440 | [LPC_CPT] = { |
355 | .name = "Cougar Point", | 441 | .name = "Cougar Point", |
442 | .iTCO_version = 2, | ||
356 | .gpio_version = ICH_V5_GPIO, | 443 | .gpio_version = ICH_V5_GPIO, |
357 | }, | 444 | }, |
358 | [LPC_CPTD] = { | 445 | [LPC_CPTD] = { |
359 | .name = "Cougar Point Desktop", | 446 | .name = "Cougar Point Desktop", |
447 | .iTCO_version = 2, | ||
360 | .gpio_version = ICH_V5_GPIO, | 448 | .gpio_version = ICH_V5_GPIO, |
361 | }, | 449 | }, |
362 | [LPC_CPTM] = { | 450 | [LPC_CPTM] = { |
363 | .name = "Cougar Point Mobile", | 451 | .name = "Cougar Point Mobile", |
452 | .iTCO_version = 2, | ||
364 | .gpio_version = ICH_V5_GPIO, | 453 | .gpio_version = ICH_V5_GPIO, |
365 | }, | 454 | }, |
366 | [LPC_PBG] = { | 455 | [LPC_PBG] = { |
367 | .name = "Patsburg", | 456 | .name = "Patsburg", |
457 | .iTCO_version = 2, | ||
368 | }, | 458 | }, |
369 | [LPC_DH89XXCC] = { | 459 | [LPC_DH89XXCC] = { |
370 | .name = "DH89xxCC", | 460 | .name = "DH89xxCC", |
461 | .iTCO_version = 2, | ||
371 | }, | 462 | }, |
372 | [LPC_PPT] = { | 463 | [LPC_PPT] = { |
373 | .name = "Panther Point", | 464 | .name = "Panther Point", |
465 | .iTCO_version = 2, | ||
374 | }, | 466 | }, |
375 | [LPC_LPT] = { | 467 | [LPC_LPT] = { |
376 | .name = "Lynx Point", | 468 | .name = "Lynx Point", |
469 | .iTCO_version = 2, | ||
377 | }, | 470 | }, |
378 | }; | 471 | }; |
379 | 472 | ||
@@ -666,12 +759,88 @@ gpio_done: | |||
666 | return ret; | 759 | return ret; |
667 | } | 760 | } |
668 | 761 | ||
762 | static int __devinit lpc_ich_init_wdt(struct pci_dev *dev, | ||
763 | const struct pci_device_id *id) | ||
764 | { | ||
765 | u32 base_addr_cfg; | ||
766 | u32 base_addr; | ||
767 | int ret; | ||
768 | bool acpi_conflict = false; | ||
769 | struct resource *res; | ||
770 | |||
771 | /* Setup power management base register */ | ||
772 | pci_read_config_dword(dev, ACPIBASE, &base_addr_cfg); | ||
773 | base_addr = base_addr_cfg & 0x0000ff80; | ||
774 | if (!base_addr) { | ||
775 | dev_err(&dev->dev, "I/O space for ACPI uninitialized\n"); | ||
776 | ret = -ENODEV; | ||
777 | goto wdt_done; | ||
778 | } | ||
779 | |||
780 | res = wdt_io_res(ICH_RES_IO_TCO); | ||
781 | res->start = base_addr + ACPIBASE_TCO_OFF; | ||
782 | res->end = base_addr + ACPIBASE_TCO_END; | ||
783 | ret = acpi_check_resource_conflict(res); | ||
784 | if (ret) { | ||
785 | acpi_conflict = true; | ||
786 | goto wdt_done; | ||
787 | } | ||
788 | |||
789 | res = wdt_io_res(ICH_RES_IO_SMI); | ||
790 | res->start = base_addr + ACPIBASE_SMI_OFF; | ||
791 | res->end = base_addr + ACPIBASE_SMI_END; | ||
792 | ret = acpi_check_resource_conflict(res); | ||
793 | if (ret) { | ||
794 | acpi_conflict = true; | ||
795 | goto wdt_done; | ||
796 | } | ||
797 | lpc_ich_enable_acpi_space(dev); | ||
798 | |||
799 | /* | ||
800 | * Get the Memory-Mapped GCS register. To get access to it | ||
801 | * we have to read RCBA from PCI Config space 0xf0 and use | ||
802 | * it as base. GCS = RCBA + ICH6_GCS(0x3410). | ||
803 | */ | ||
804 | if (lpc_chipset_info[id->driver_data].iTCO_version == 2) { | ||
805 | pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); | ||
806 | base_addr = base_addr_cfg & 0xffffc000; | ||
807 | if (!(base_addr_cfg & 1)) { | ||
808 | pr_err("RCBA is disabled by hardware/BIOS, " | ||
809 | "device disabled\n"); | ||
810 | ret = -ENODEV; | ||
811 | goto wdt_done; | ||
812 | } | ||
813 | res = wdt_mem_res(ICH_RES_MEM_GCS); | ||
814 | res->start = base_addr + ACPIBASE_GCS_OFF; | ||
815 | res->end = base_addr + ACPIBASE_GCS_END; | ||
816 | ret = acpi_check_resource_conflict(res); | ||
817 | if (ret) { | ||
818 | acpi_conflict = true; | ||
819 | goto wdt_done; | ||
820 | } | ||
821 | } | ||
822 | |||
823 | lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id); | ||
824 | ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT], | ||
825 | 1, NULL, 0); | ||
826 | |||
827 | wdt_done: | ||
828 | if (acpi_conflict) | ||
829 | pr_warn("Resource conflict(s) found affecting %s\n", | ||
830 | lpc_ich_cells[LPC_WDT].name); | ||
831 | return ret; | ||
832 | } | ||
833 | |||
669 | static int __devinit lpc_ich_probe(struct pci_dev *dev, | 834 | static int __devinit lpc_ich_probe(struct pci_dev *dev, |
670 | const struct pci_device_id *id) | 835 | const struct pci_device_id *id) |
671 | { | 836 | { |
672 | int ret; | 837 | int ret; |
673 | bool cell_added = false; | 838 | bool cell_added = false; |
674 | 839 | ||
840 | ret = lpc_ich_init_wdt(dev, id); | ||
841 | if (!ret) | ||
842 | cell_added = true; | ||
843 | |||
675 | ret = lpc_ich_init_gpio(dev, id); | 844 | ret = lpc_ich_init_gpio(dev, id); |
676 | if (!ret) | 845 | if (!ret) |
677 | cell_added = true; | 846 | cell_added = true; |
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 | } |