aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 18:55:00 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 18:55:00 -0500
commit324889b6bd2a89e0d69a2f9d133d6cf24579ab6c (patch)
tree8478d5b164113186cc735968de831cf680940b79 /drivers/watchdog
parent3ff6a468b45b5dfeb0e903e56f4eb27d34b2437c (diff)
parentcb711a1931363b8ad4dc98df4a92c262ced8eeb4 (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.c68
-rw-r--r--drivers/watchdog/s3c2410_wdt.c89
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
127static struct { 105static 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};
235MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); 219MODULE_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
146static inline int s3c2410wdt_is_running(void)
147{
148 return readl(wdt_base + S3C2410_WTCON) & S3C2410_WTCON_ENABLE;
149}
150
145static int s3c2410wdt_set_heartbeat(int timeout) 151static 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
337static 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
363done:
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
371static struct notifier_block s3c2410wdt_cpufreq_transition_nb = {
372 .notifier_call = s3c2410wdt_cpufreq_transition,
373};
374
375static inline int s3c2410wdt_cpufreq_register(void)
376{
377 return cpufreq_register_notifier(&s3c2410wdt_cpufreq_transition_nb,
378 CPUFREQ_TRANSITION_NOTIFIER);
379}
380
381static inline void s3c2410wdt_cpufreq_deregister(void)
382{
383 cpufreq_unregister_notifier(&s3c2410wdt_cpufreq_transition_nb,
384 CPUFREQ_TRANSITION_NOTIFIER);
385}
386
387#else
388static inline int s3c2410wdt_cpufreq_register(void)
389{
390 return 0;
391}
392
393static inline void s3c2410wdt_cpufreq_deregister(void)
394{
395}
396#endif
397
398
399
327/* device interface */ 400/* device interface */
328 401
329static int __devinit s3c2410wdt_probe(struct platform_device *pdev) 402static 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
452static int __devexit s3c2410wdt_remove(struct platform_device *dev) 533static 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;