diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 18:55:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 18:55:00 -0500 |
commit | 324889b6bd2a89e0d69a2f9d133d6cf24579ab6c (patch) | |
tree | 8478d5b164113186cc735968de831cf680940b79 /drivers/watchdog | |
parent | 3ff6a468b45b5dfeb0e903e56f4eb27d34b2437c (diff) | |
parent | cb711a1931363b8ad4dc98df4a92c262ced8eeb4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
* git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
[WATCHDOG] iTCO_wdt.c - cleanup chipset documentation
[WATCHDOG] iTCO_wdt: Add support for Intel Ibex Peak
[WATCHDOG] CPUFREQ: S3C24XX Watchdog frequency scaling support.
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 68 | ||||
-rw-r--r-- | drivers/watchdog/s3c2410_wdt.c | 89 |
2 files changed, 112 insertions, 45 deletions
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 6a51edde6ea7..e44fbb31bc6f 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * intel TCO Watchdog Driver (Used in i82801 and i63xxESB chipsets) | 2 | * intel TCO Watchdog Driver |
3 | * | 3 | * |
4 | * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>. | 4 | * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>. |
5 | * | 5 | * |
@@ -14,47 +14,22 @@ | |||
14 | * | 14 | * |
15 | * The TCO watchdog is implemented in the following I/O controller hubs: | 15 | * The TCO watchdog is implemented in the following I/O controller hubs: |
16 | * (See the intel documentation on http://developer.intel.com.) | 16 | * (See the intel documentation on http://developer.intel.com.) |
17 | * 82801AA (ICH) : document number 290655-003, 290677-014, | 17 | * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO) |
18 | * 82801AB (ICHO) : document number 290655-003, 290677-014, | 18 | * document number 290687-002, 298242-027: 82801BA (ICH2) |
19 | * 82801BA (ICH2) : document number 290687-002, 298242-027, | 19 | * document number 290733-003, 290739-013: 82801CA (ICH3-S) |
20 | * 82801BAM (ICH2-M) : document number 290687-002, 298242-027, | 20 | * document number 290716-001, 290718-007: 82801CAM (ICH3-M) |
21 | * 82801CA (ICH3-S) : document number 290733-003, 290739-013, | 21 | * document number 290744-001, 290745-025: 82801DB (ICH4) |
22 | * 82801CAM (ICH3-M) : document number 290716-001, 290718-007, | 22 | * document number 252337-001, 252663-008: 82801DBM (ICH4-M) |
23 | * 82801DB (ICH4) : document number 290744-001, 290745-025, | 23 | * document number 273599-001, 273645-002: 82801E (C-ICH) |
24 | * 82801DBM (ICH4-M) : document number 252337-001, 252663-008, | 24 | * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R) |
25 | * 82801E (C-ICH) : document number 273599-001, 273645-002, | 25 | * document number 300641-004, 300884-013: 6300ESB |
26 | * 82801EB (ICH5) : document number 252516-001, 252517-028, | 26 | * document number 301473-002, 301474-026: 82801F (ICH6) |
27 | * 82801ER (ICH5R) : document number 252516-001, 252517-028, | 27 | * document number 313082-001, 313075-006: 631xESB, 632xESB |
28 | * 6300ESB (6300ESB) : document number 300641-004, 300884-013, | 28 | * document number 307013-003, 307014-024: 82801G (ICH7) |
29 | * 82801FB (ICH6) : document number 301473-002, 301474-026, | 29 | * document number 313056-003, 313057-017: 82801H (ICH8) |
30 | * 82801FR (ICH6R) : document number 301473-002, 301474-026, | 30 | * document number 316972-004, 316973-012: 82801I (ICH9) |
31 | * 82801FBM (ICH6-M) : document number 301473-002, 301474-026, | 31 | * document number 319973-002, 319974-002: 82801J (ICH10) |
32 | * 82801FW (ICH6W) : document number 301473-001, 301474-026, | 32 | * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) |
33 | * 82801FRW (ICH6RW) : document number 301473-001, 301474-026, | ||
34 | * 631xESB (631xESB) : document number 313082-001, 313075-006, | ||
35 | * 632xESB (632xESB) : document number 313082-001, 313075-006, | ||
36 | * 82801GB (ICH7) : document number 307013-003, 307014-024, | ||
37 | * 82801GR (ICH7R) : document number 307013-003, 307014-024, | ||
38 | * 82801GDH (ICH7DH) : document number 307013-003, 307014-024, | ||
39 | * 82801GBM (ICH7-M) : document number 307013-003, 307014-024, | ||
40 | * 82801GHM (ICH7-M DH) : document number 307013-003, 307014-024, | ||
41 | * 82801GU (ICH7-U) : document number 307013-003, 307014-024, | ||
42 | * 82801HB (ICH8) : document number 313056-003, 313057-017, | ||
43 | * 82801HR (ICH8R) : document number 313056-003, 313057-017, | ||
44 | * 82801HBM (ICH8M) : document number 313056-003, 313057-017, | ||
45 | * 82801HH (ICH8DH) : document number 313056-003, 313057-017, | ||
46 | * 82801HO (ICH8DO) : document number 313056-003, 313057-017, | ||
47 | * 82801HEM (ICH8M-E) : document number 313056-003, 313057-017, | ||
48 | * 82801IB (ICH9) : document number 316972-004, 316973-012, | ||
49 | * 82801IR (ICH9R) : document number 316972-004, 316973-012, | ||
50 | * 82801IH (ICH9DH) : document number 316972-004, 316973-012, | ||
51 | * 82801IO (ICH9DO) : document number 316972-004, 316973-012, | ||
52 | * 82801IBM (ICH9M) : document number 316972-004, 316973-012, | ||
53 | * 82801IEM (ICH9M-E) : document number 316972-004, 316973-012, | ||
54 | * 82801JIB (ICH10) : document number 319973-002, 319974-002, | ||
55 | * 82801JIR (ICH10R) : document number 319973-002, 319974-002, | ||
56 | * 82801JD (ICH10D) : document number 319973-002, 319974-002, | ||
57 | * 82801JDO (ICH10DO) : document number 319973-002, 319974-002 | ||
58 | */ | 33 | */ |
59 | 34 | ||
60 | /* | 35 | /* |
@@ -122,6 +97,9 @@ enum iTCO_chipsets { | |||
122 | TCO_ICH10R, /* ICH10R */ | 97 | TCO_ICH10R, /* ICH10R */ |
123 | TCO_ICH10D, /* ICH10D */ | 98 | TCO_ICH10D, /* ICH10D */ |
124 | TCO_ICH10DO, /* ICH10DO */ | 99 | TCO_ICH10DO, /* ICH10DO */ |
100 | TCO_PCH, /* PCH Desktop Full Featured */ | ||
101 | TCO_PCHM, /* PCH Mobile Full Featured */ | ||
102 | TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ | ||
125 | }; | 103 | }; |
126 | 104 | ||
127 | static struct { | 105 | static struct { |
@@ -162,6 +140,9 @@ static struct { | |||
162 | {"ICH10R", 2}, | 140 | {"ICH10R", 2}, |
163 | {"ICH10D", 2}, | 141 | {"ICH10D", 2}, |
164 | {"ICH10DO", 2}, | 142 | {"ICH10DO", 2}, |
143 | {"PCH Desktop Full Featured", 2}, | ||
144 | {"PCH Mobile Full Featured", 2}, | ||
145 | {"PCH Mobile SFF Full Featured", 2}, | ||
165 | {NULL, 0} | 146 | {NULL, 0} |
166 | }; | 147 | }; |
167 | 148 | ||
@@ -230,6 +211,9 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { | |||
230 | { ITCO_PCI_DEVICE(0x3a16, TCO_ICH10R)}, | 211 | { ITCO_PCI_DEVICE(0x3a16, TCO_ICH10R)}, |
231 | { ITCO_PCI_DEVICE(0x3a1a, TCO_ICH10D)}, | 212 | { ITCO_PCI_DEVICE(0x3a1a, TCO_ICH10D)}, |
232 | { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)}, | 213 | { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)}, |
214 | { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, | ||
215 | { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, | ||
216 | { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, | ||
233 | { 0, }, /* End of list */ | 217 | { 0, }, /* End of list */ |
234 | }; | 218 | }; |
235 | MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); | 219 | MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index b57ac6b49147..85b93e15d011 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/clk.h> | 36 | #include <linux/clk.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/io.h> | 38 | #include <linux/io.h> |
39 | #include <linux/cpufreq.h> | ||
39 | 40 | ||
40 | #include <mach/map.h> | 41 | #include <mach/map.h> |
41 | 42 | ||
@@ -142,9 +143,14 @@ static void s3c2410wdt_start(void) | |||
142 | spin_unlock(&wdt_lock); | 143 | spin_unlock(&wdt_lock); |
143 | } | 144 | } |
144 | 145 | ||
146 | static inline int s3c2410wdt_is_running(void) | ||
147 | { | ||
148 | return readl(wdt_base + S3C2410_WTCON) & S3C2410_WTCON_ENABLE; | ||
149 | } | ||
150 | |||
145 | static int s3c2410wdt_set_heartbeat(int timeout) | 151 | static int s3c2410wdt_set_heartbeat(int timeout) |
146 | { | 152 | { |
147 | unsigned int freq = clk_get_rate(wdt_clock); | 153 | unsigned long freq = clk_get_rate(wdt_clock); |
148 | unsigned int count; | 154 | unsigned int count; |
149 | unsigned int divisor = 1; | 155 | unsigned int divisor = 1; |
150 | unsigned long wtcon; | 156 | unsigned long wtcon; |
@@ -155,7 +161,7 @@ static int s3c2410wdt_set_heartbeat(int timeout) | |||
155 | freq /= 128; | 161 | freq /= 128; |
156 | count = timeout * freq; | 162 | count = timeout * freq; |
157 | 163 | ||
158 | DBG("%s: count=%d, timeout=%d, freq=%d\n", | 164 | DBG("%s: count=%d, timeout=%d, freq=%lu\n", |
159 | __func__, count, timeout, freq); | 165 | __func__, count, timeout, freq); |
160 | 166 | ||
161 | /* if the count is bigger than the watchdog register, | 167 | /* if the count is bigger than the watchdog register, |
@@ -324,6 +330,73 @@ static irqreturn_t s3c2410wdt_irq(int irqno, void *param) | |||
324 | s3c2410wdt_keepalive(); | 330 | s3c2410wdt_keepalive(); |
325 | return IRQ_HANDLED; | 331 | return IRQ_HANDLED; |
326 | } | 332 | } |
333 | |||
334 | |||
335 | #ifdef CONFIG_CPU_FREQ | ||
336 | |||
337 | static int s3c2410wdt_cpufreq_transition(struct notifier_block *nb, | ||
338 | unsigned long val, void *data) | ||
339 | { | ||
340 | int ret; | ||
341 | |||
342 | if (!s3c2410wdt_is_running()) | ||
343 | goto done; | ||
344 | |||
345 | if (val == CPUFREQ_PRECHANGE) { | ||
346 | /* To ensure that over the change we don't cause the | ||
347 | * watchdog to trigger, we perform an keep-alive if | ||
348 | * the watchdog is running. | ||
349 | */ | ||
350 | |||
351 | s3c2410wdt_keepalive(); | ||
352 | } else if (val == CPUFREQ_POSTCHANGE) { | ||
353 | s3c2410wdt_stop(); | ||
354 | |||
355 | ret = s3c2410wdt_set_heartbeat(tmr_margin); | ||
356 | |||
357 | if (ret >= 0) | ||
358 | s3c2410wdt_start(); | ||
359 | else | ||
360 | goto err; | ||
361 | } | ||
362 | |||
363 | done: | ||
364 | return 0; | ||
365 | |||
366 | err: | ||
367 | dev_err(wdt_dev, "cannot set new value for timeout %d\n", tmr_margin); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | static struct notifier_block s3c2410wdt_cpufreq_transition_nb = { | ||
372 | .notifier_call = s3c2410wdt_cpufreq_transition, | ||
373 | }; | ||
374 | |||
375 | static inline int s3c2410wdt_cpufreq_register(void) | ||
376 | { | ||
377 | return cpufreq_register_notifier(&s3c2410wdt_cpufreq_transition_nb, | ||
378 | CPUFREQ_TRANSITION_NOTIFIER); | ||
379 | } | ||
380 | |||
381 | static inline void s3c2410wdt_cpufreq_deregister(void) | ||
382 | { | ||
383 | cpufreq_unregister_notifier(&s3c2410wdt_cpufreq_transition_nb, | ||
384 | CPUFREQ_TRANSITION_NOTIFIER); | ||
385 | } | ||
386 | |||
387 | #else | ||
388 | static inline int s3c2410wdt_cpufreq_register(void) | ||
389 | { | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static inline void s3c2410wdt_cpufreq_deregister(void) | ||
394 | { | ||
395 | } | ||
396 | #endif | ||
397 | |||
398 | |||
399 | |||
327 | /* device interface */ | 400 | /* device interface */ |
328 | 401 | ||
329 | static int __devinit s3c2410wdt_probe(struct platform_device *pdev) | 402 | static int __devinit s3c2410wdt_probe(struct platform_device *pdev) |
@@ -387,6 +460,11 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) | |||
387 | 460 | ||
388 | clk_enable(wdt_clock); | 461 | clk_enable(wdt_clock); |
389 | 462 | ||
463 | if (s3c2410wdt_cpufreq_register() < 0) { | ||
464 | printk(KERN_ERR PFX "failed to register cpufreq\n"); | ||
465 | goto err_clk; | ||
466 | } | ||
467 | |||
390 | /* see if we can actually set the requested timer margin, and if | 468 | /* see if we can actually set the requested timer margin, and if |
391 | * not, try the default value */ | 469 | * not, try the default value */ |
392 | 470 | ||
@@ -407,7 +485,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) | |||
407 | if (ret) { | 485 | if (ret) { |
408 | dev_err(dev, "cannot register miscdev on minor=%d (%d)\n", | 486 | dev_err(dev, "cannot register miscdev on minor=%d (%d)\n", |
409 | WATCHDOG_MINOR, ret); | 487 | WATCHDOG_MINOR, ret); |
410 | goto err_clk; | 488 | goto err_cpufreq; |
411 | } | 489 | } |
412 | 490 | ||
413 | if (tmr_atboot && started == 0) { | 491 | if (tmr_atboot && started == 0) { |
@@ -432,6 +510,9 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) | |||
432 | 510 | ||
433 | return 0; | 511 | return 0; |
434 | 512 | ||
513 | err_cpufreq: | ||
514 | s3c2410wdt_cpufreq_deregister(); | ||
515 | |||
435 | err_clk: | 516 | err_clk: |
436 | clk_disable(wdt_clock); | 517 | clk_disable(wdt_clock); |
437 | clk_put(wdt_clock); | 518 | clk_put(wdt_clock); |
@@ -451,6 +532,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) | |||
451 | 532 | ||
452 | static int __devexit s3c2410wdt_remove(struct platform_device *dev) | 533 | static int __devexit s3c2410wdt_remove(struct platform_device *dev) |
453 | { | 534 | { |
535 | s3c2410wdt_cpufreq_deregister(); | ||
536 | |||
454 | release_resource(wdt_mem); | 537 | release_resource(wdt_mem); |
455 | kfree(wdt_mem); | 538 | kfree(wdt_mem); |
456 | wdt_mem = NULL; | 539 | wdt_mem = NULL; |