diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 14:22:55 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 14:22:55 -0400 |
| commit | 7dcca3e92a34bf8ffdc4c01a49182ce1cb6ff534 (patch) | |
| tree | 4886858a740aff0c993a8110add73d749e79b5aa | |
| parent | b9bb6fb73b3e112d241a5edd146740be9a0c3cc0 (diff) | |
| parent | cf82f52d3619d2e15c83ec9a03c6ce8cdf6c6b58 (diff) | |
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
"This contains following changes:
- Octeon: convert to watchdog-API and apply some fixes
- Cadence wdt: remove dependency on ARCH
- add DT bindings for qcom + msm
- bcm281xx: Remove use of seq_printf return value
- stmp3xxx_rtc_wdt + pnx4008_wdt: fix broken email addresses"
* git://www.linux-watchdog.org/linux-watchdog:
watchdog: stmp3xxx_rtc_wdt: fix broken email address
watchdog: pnx4008_wdt: fix broken email address
watchdog: octeon: use fixed length string for register names
watchdog: octeon: fix some trivial coding style issues
watchdog: octeon: convert to WATCHDOG_CORE API
watchdog: cadence: Remove Kconfig dependency on ARCH
ARM: msm: add watchdog entries to DT timer binding doc
ARM: qcom: add description of KPSS WDT for IPQ8064
watchdog: qcom: use timer devicetree binding
watchdog: bcm281xx: Remove use of seq_printf return value
| -rw-r--r-- | Documentation/devicetree/bindings/arm/msm/timer.txt | 16 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom-ipq8064.dtsi | 14 | ||||
| -rw-r--r-- | drivers/watchdog/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/watchdog/bcm_kona_wdt.c | 27 | ||||
| -rw-r--r-- | drivers/watchdog/octeon-wdt-main.c | 201 | ||||
| -rw-r--r-- | drivers/watchdog/pnx4008_wdt.c | 2 | ||||
| -rw-r--r-- | drivers/watchdog/qcom-wdt.c | 21 | ||||
| -rw-r--r-- | drivers/watchdog/stmp3xxx_rtc_wdt.c | 4 |
8 files changed, 109 insertions, 178 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/timer.txt b/Documentation/devicetree/bindings/arm/msm/timer.txt index 74607b6c1117..5e10c345548f 100644 --- a/Documentation/devicetree/bindings/arm/msm/timer.txt +++ b/Documentation/devicetree/bindings/arm/msm/timer.txt | |||
| @@ -9,11 +9,17 @@ Properties: | |||
| 9 | "qcom,scss-timer" - scorpion subsystem | 9 | "qcom,scss-timer" - scorpion subsystem |
| 10 | 10 | ||
| 11 | - interrupts : Interrupts for the debug timer, the first general purpose | 11 | - interrupts : Interrupts for the debug timer, the first general purpose |
| 12 | timer, and optionally a second general purpose timer in that | 12 | timer, and optionally a second general purpose timer, and |
| 13 | order. | 13 | optionally as well, 2 watchdog interrupts, in that order. |
| 14 | 14 | ||
| 15 | - reg : Specifies the base address of the timer registers. | 15 | - reg : Specifies the base address of the timer registers. |
| 16 | 16 | ||
| 17 | - clocks: Reference to the parent clocks, one per output clock. The parents | ||
| 18 | must appear in the same order as the clock names. | ||
| 19 | |||
| 20 | - clock-names: The name of the clocks as free-form strings. They should be in | ||
| 21 | the same order as the clocks. | ||
| 22 | |||
| 17 | - clock-frequency : The frequency of the debug timer and the general purpose | 23 | - clock-frequency : The frequency of the debug timer and the general purpose |
| 18 | timer(s) in Hz in that order. | 24 | timer(s) in Hz in that order. |
| 19 | 25 | ||
| @@ -29,9 +35,13 @@ Example: | |||
| 29 | compatible = "qcom,scss-timer", "qcom,msm-timer"; | 35 | compatible = "qcom,scss-timer", "qcom,msm-timer"; |
| 30 | interrupts = <1 1 0x301>, | 36 | interrupts = <1 1 0x301>, |
| 31 | <1 2 0x301>, | 37 | <1 2 0x301>, |
| 32 | <1 3 0x301>; | 38 | <1 3 0x301>, |
| 39 | <1 4 0x301>, | ||
| 40 | <1 5 0x301>; | ||
| 33 | reg = <0x0200a000 0x100>; | 41 | reg = <0x0200a000 0x100>; |
| 34 | clock-frequency = <19200000>, | 42 | clock-frequency = <19200000>, |
| 35 | <32768>; | 43 | <32768>; |
| 44 | clocks = <&sleep_clk>; | ||
| 45 | clock-names = "sleep"; | ||
| 36 | cpu-offset = <0x40000>; | 46 | cpu-offset = <0x40000>; |
| 37 | }; | 47 | }; |
diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi index 1bc5fdd0e4b3..9f727d8eadf6 100644 --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi | |||
| @@ -61,6 +61,14 @@ | |||
| 61 | }; | 61 | }; |
| 62 | }; | 62 | }; |
| 63 | 63 | ||
| 64 | clocks { | ||
| 65 | sleep_clk: sleep_clk { | ||
| 66 | compatible = "fixed-clock"; | ||
| 67 | clock-frequency = <32768>; | ||
| 68 | #clock-cells = <0>; | ||
| 69 | }; | ||
| 70 | }; | ||
| 71 | |||
| 64 | soc: soc { | 72 | soc: soc { |
| 65 | #address-cells = <1>; | 73 | #address-cells = <1>; |
| 66 | #size-cells = <1>; | 74 | #size-cells = <1>; |
| @@ -105,10 +113,14 @@ | |||
| 105 | compatible = "qcom,kpss-timer", "qcom,msm-timer"; | 113 | compatible = "qcom,kpss-timer", "qcom,msm-timer"; |
| 106 | interrupts = <1 1 0x301>, | 114 | interrupts = <1 1 0x301>, |
| 107 | <1 2 0x301>, | 115 | <1 2 0x301>, |
| 108 | <1 3 0x301>; | 116 | <1 3 0x301>, |
| 117 | <1 4 0x301>, | ||
| 118 | <1 5 0x301>; | ||
| 109 | reg = <0x0200a000 0x100>; | 119 | reg = <0x0200a000 0x100>; |
| 110 | clock-frequency = <25000000>, | 120 | clock-frequency = <25000000>, |
| 111 | <32768>; | 121 | <32768>; |
| 122 | clocks = <&sleep_clk>; | ||
| 123 | clock-names = "sleep"; | ||
| 112 | cpu-offset = <0x80000>; | 124 | cpu-offset = <0x80000>; |
| 113 | }; | 125 | }; |
| 114 | 126 | ||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index ce4f3a7f95fd..e5e7c5505de7 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
| @@ -169,7 +169,6 @@ config AT91SAM9X_WATCHDOG | |||
| 169 | 169 | ||
| 170 | config CADENCE_WATCHDOG | 170 | config CADENCE_WATCHDOG |
| 171 | tristate "Cadence Watchdog Timer" | 171 | tristate "Cadence Watchdog Timer" |
| 172 | depends on ARM | ||
| 173 | select WATCHDOG_CORE | 172 | select WATCHDOG_CORE |
| 174 | help | 173 | help |
| 175 | Say Y here if you want to include support for the watchdog | 174 | Say Y here if you want to include support for the watchdog |
| @@ -1190,6 +1189,7 @@ config OCTEON_WDT | |||
| 1190 | tristate "Cavium OCTEON SOC family Watchdog Timer" | 1189 | tristate "Cavium OCTEON SOC family Watchdog Timer" |
| 1191 | depends on CAVIUM_OCTEON_SOC | 1190 | depends on CAVIUM_OCTEON_SOC |
| 1192 | default y | 1191 | default y |
| 1192 | select WATCHDOG_CORE | ||
| 1193 | select EXPORT_UASM if OCTEON_WDT = m | 1193 | select EXPORT_UASM if OCTEON_WDT = m |
| 1194 | help | 1194 | help |
| 1195 | Hardware driver for OCTEON's on chip watchdog timer. | 1195 | Hardware driver for OCTEON's on chip watchdog timer. |
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c index 4e37db3539a4..22d8ae65772a 100644 --- a/drivers/watchdog/bcm_kona_wdt.c +++ b/drivers/watchdog/bcm_kona_wdt.c | |||
| @@ -99,12 +99,14 @@ static int secure_register_read(struct bcm_kona_wdt *wdt, uint32_t offset) | |||
| 99 | 99 | ||
| 100 | static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data) | 100 | static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data) |
| 101 | { | 101 | { |
| 102 | int ctl_val, cur_val, ret; | 102 | int ctl_val, cur_val; |
| 103 | unsigned long flags; | 103 | unsigned long flags; |
| 104 | struct bcm_kona_wdt *wdt = s->private; | 104 | struct bcm_kona_wdt *wdt = s->private; |
| 105 | 105 | ||
| 106 | if (!wdt) | 106 | if (!wdt) { |
| 107 | return seq_puts(s, "No device pointer\n"); | 107 | seq_puts(s, "No device pointer\n"); |
| 108 | return 0; | ||
| 109 | } | ||
| 108 | 110 | ||
| 109 | spin_lock_irqsave(&wdt->lock, flags); | 111 | spin_lock_irqsave(&wdt->lock, flags); |
| 110 | ctl_val = secure_register_read(wdt, SECWDOG_CTRL_REG); | 112 | ctl_val = secure_register_read(wdt, SECWDOG_CTRL_REG); |
| @@ -112,7 +114,7 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data) | |||
| 112 | spin_unlock_irqrestore(&wdt->lock, flags); | 114 | spin_unlock_irqrestore(&wdt->lock, flags); |
| 113 | 115 | ||
| 114 | if (ctl_val < 0 || cur_val < 0) { | 116 | if (ctl_val < 0 || cur_val < 0) { |
| 115 | ret = seq_puts(s, "Error accessing hardware\n"); | 117 | seq_puts(s, "Error accessing hardware\n"); |
| 116 | } else { | 118 | } else { |
| 117 | int ctl, cur, ctl_sec, cur_sec, res; | 119 | int ctl, cur, ctl_sec, cur_sec, res; |
| 118 | 120 | ||
| @@ -121,15 +123,18 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data) | |||
| 121 | cur = cur_val & SECWDOG_COUNT_MASK; | 123 | cur = cur_val & SECWDOG_COUNT_MASK; |
| 122 | ctl_sec = TICKS_TO_SECS(ctl, wdt); | 124 | ctl_sec = TICKS_TO_SECS(ctl, wdt); |
| 123 | cur_sec = TICKS_TO_SECS(cur, wdt); | 125 | cur_sec = TICKS_TO_SECS(cur, wdt); |
| 124 | ret = seq_printf(s, "Resolution: %d / %d\n" | 126 | seq_printf(s, |
| 125 | "Control: %d s / %d (%#x) ticks\n" | 127 | "Resolution: %d / %d\n" |
| 126 | "Current: %d s / %d (%#x) ticks\n" | 128 | "Control: %d s / %d (%#x) ticks\n" |
| 127 | "Busy count: %lu\n", res, | 129 | "Current: %d s / %d (%#x) ticks\n" |
| 128 | wdt->resolution, ctl_sec, ctl, ctl, cur_sec, | 130 | "Busy count: %lu\n", |
| 129 | cur, cur, wdt->busy_count); | 131 | res, wdt->resolution, |
| 132 | ctl_sec, ctl, ctl, | ||
| 133 | cur_sec, cur, cur, | ||
| 134 | wdt->busy_count); | ||
| 130 | } | 135 | } |
| 131 | 136 | ||
| 132 | return ret; | 137 | return 0; |
| 133 | } | 138 | } |
| 134 | 139 | ||
| 135 | static int bcm_kona_dbg_open(struct inode *inode, struct file *file) | 140 | static int bcm_kona_dbg_open(struct inode *inode, struct file *file) |
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 8453531545df..14521c8b3d5a 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks | 4 | * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks |
| 5 | * | 5 | * |
| 6 | * Converted to use WATCHDOG_CORE by Aaro Koskinen <aaro.koskinen@iki.fi>. | ||
| 7 | * | ||
| 6 | * Some parts derived from wdt.c | 8 | * Some parts derived from wdt.c |
| 7 | * | 9 | * |
| 8 | * (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>, | 10 | * (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>, |
| @@ -103,13 +105,10 @@ MODULE_PARM_DESC(nowayout, | |||
| 103 | "Watchdog cannot be stopped once started (default=" | 105 | "Watchdog cannot be stopped once started (default=" |
| 104 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 106 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
| 105 | 107 | ||
| 106 | static unsigned long octeon_wdt_is_open; | 108 | static u32 nmi_stage1_insns[64] __initdata; |
| 107 | static char expect_close; | ||
| 108 | |||
| 109 | static u32 __initdata nmi_stage1_insns[64]; | ||
| 110 | /* We need one branch and therefore one relocation per target label. */ | 109 | /* We need one branch and therefore one relocation per target label. */ |
| 111 | static struct uasm_label __initdata labels[5]; | 110 | static struct uasm_label labels[5] __initdata; |
| 112 | static struct uasm_reloc __initdata relocs[5]; | 111 | static struct uasm_reloc relocs[5] __initdata; |
| 113 | 112 | ||
| 114 | enum lable_id { | 113 | enum lable_id { |
| 115 | label_enter_bootloader = 1 | 114 | label_enter_bootloader = 1 |
| @@ -218,7 +217,8 @@ static void __init octeon_wdt_build_stage1(void) | |||
| 218 | pr_debug("\t.set pop\n"); | 217 | pr_debug("\t.set pop\n"); |
| 219 | 218 | ||
| 220 | if (len > 32) | 219 | if (len > 32) |
| 221 | panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", len); | 220 | panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", |
| 221 | len); | ||
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static int cpu2core(int cpu) | 224 | static int cpu2core(int cpu) |
| @@ -294,6 +294,7 @@ static void octeon_wdt_write_hex(u64 value, int digits) | |||
| 294 | { | 294 | { |
| 295 | int d; | 295 | int d; |
| 296 | int v; | 296 | int v; |
| 297 | |||
| 297 | for (d = 0; d < digits; d++) { | 298 | for (d = 0; d < digits; d++) { |
| 298 | v = (value >> ((digits - d - 1) * 4)) & 0xf; | 299 | v = (value >> ((digits - d - 1) * 4)) & 0xf; |
| 299 | if (v >= 10) | 300 | if (v >= 10) |
| @@ -303,7 +304,7 @@ static void octeon_wdt_write_hex(u64 value, int digits) | |||
| 303 | } | 304 | } |
| 304 | } | 305 | } |
| 305 | 306 | ||
| 306 | const char *reg_name[] = { | 307 | static const char reg_name[][3] = { |
| 307 | "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", | 308 | "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", |
| 308 | "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", | 309 | "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", |
| 309 | "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", | 310 | "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
| @@ -444,7 +445,7 @@ static int octeon_wdt_cpu_callback(struct notifier_block *nfb, | |||
| 444 | return NOTIFY_OK; | 445 | return NOTIFY_OK; |
| 445 | } | 446 | } |
| 446 | 447 | ||
| 447 | static void octeon_wdt_ping(void) | 448 | static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog) |
| 448 | { | 449 | { |
| 449 | int cpu; | 450 | int cpu; |
| 450 | int coreid; | 451 | int coreid; |
| @@ -457,10 +458,12 @@ static void octeon_wdt_ping(void) | |||
| 457 | !cpumask_test_cpu(cpu, &irq_enabled_cpus)) { | 458 | !cpumask_test_cpu(cpu, &irq_enabled_cpus)) { |
| 458 | /* We have to enable the irq */ | 459 | /* We have to enable the irq */ |
| 459 | int irq = OCTEON_IRQ_WDOG0 + coreid; | 460 | int irq = OCTEON_IRQ_WDOG0 + coreid; |
| 461 | |||
| 460 | enable_irq(irq); | 462 | enable_irq(irq); |
| 461 | cpumask_set_cpu(cpu, &irq_enabled_cpus); | 463 | cpumask_set_cpu(cpu, &irq_enabled_cpus); |
| 462 | } | 464 | } |
| 463 | } | 465 | } |
| 466 | return 0; | ||
| 464 | } | 467 | } |
| 465 | 468 | ||
| 466 | static void octeon_wdt_calc_parameters(int t) | 469 | static void octeon_wdt_calc_parameters(int t) |
| @@ -489,7 +492,8 @@ static void octeon_wdt_calc_parameters(int t) | |||
| 489 | timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8; | 492 | timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8; |
| 490 | } | 493 | } |
| 491 | 494 | ||
| 492 | static int octeon_wdt_set_heartbeat(int t) | 495 | static int octeon_wdt_set_timeout(struct watchdog_device *wdog, |
| 496 | unsigned int t) | ||
| 493 | { | 497 | { |
| 494 | int cpu; | 498 | int cpu; |
| 495 | int coreid; | 499 | int coreid; |
| @@ -509,158 +513,45 @@ static int octeon_wdt_set_heartbeat(int t) | |||
| 509 | cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64); | 513 | cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64); |
| 510 | cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); | 514 | cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1); |
| 511 | } | 515 | } |
| 512 | octeon_wdt_ping(); /* Get the irqs back on. */ | 516 | octeon_wdt_ping(wdog); /* Get the irqs back on. */ |
| 513 | return 0; | 517 | return 0; |
| 514 | } | 518 | } |
| 515 | 519 | ||
| 516 | /** | 520 | static int octeon_wdt_start(struct watchdog_device *wdog) |
| 517 | * octeon_wdt_write: | ||
| 518 | * @file: file handle to the watchdog | ||
| 519 | * @buf: buffer to write (unused as data does not matter here | ||
| 520 | * @count: count of bytes | ||
| 521 | * @ppos: pointer to the position to write. No seeks allowed | ||
| 522 | * | ||
| 523 | * A write to a watchdog device is defined as a keepalive signal. Any | ||
| 524 | * write of data will do, as we we don't define content meaning. | ||
| 525 | */ | ||
| 526 | |||
| 527 | static ssize_t octeon_wdt_write(struct file *file, const char __user *buf, | ||
| 528 | size_t count, loff_t *ppos) | ||
| 529 | { | ||
| 530 | if (count) { | ||
| 531 | if (!nowayout) { | ||
| 532 | size_t i; | ||
| 533 | |||
| 534 | /* In case it was set long ago */ | ||
| 535 | expect_close = 0; | ||
| 536 | |||
| 537 | for (i = 0; i != count; i++) { | ||
| 538 | char c; | ||
| 539 | if (get_user(c, buf + i)) | ||
| 540 | return -EFAULT; | ||
| 541 | if (c == 'V') | ||
| 542 | expect_close = 1; | ||
| 543 | } | ||
| 544 | } | ||
| 545 | octeon_wdt_ping(); | ||
| 546 | } | ||
| 547 | return count; | ||
| 548 | } | ||
| 549 | |||
| 550 | /** | ||
| 551 | * octeon_wdt_ioctl: | ||
| 552 | * @file: file handle to the device | ||
| 553 | * @cmd: watchdog command | ||
| 554 | * @arg: argument pointer | ||
| 555 | * | ||
| 556 | * The watchdog API defines a common set of functions for all | ||
| 557 | * watchdogs according to their available features. We only | ||
| 558 | * actually usefully support querying capabilities and setting | ||
| 559 | * the timeout. | ||
| 560 | */ | ||
| 561 | |||
| 562 | static long octeon_wdt_ioctl(struct file *file, unsigned int cmd, | ||
| 563 | unsigned long arg) | ||
| 564 | { | ||
| 565 | void __user *argp = (void __user *)arg; | ||
| 566 | int __user *p = argp; | ||
| 567 | int new_heartbeat; | ||
| 568 | |||
| 569 | static struct watchdog_info ident = { | ||
| 570 | .options = WDIOF_SETTIMEOUT| | ||
| 571 | WDIOF_MAGICCLOSE| | ||
| 572 | WDIOF_KEEPALIVEPING, | ||
| 573 | .firmware_version = 1, | ||
| 574 | .identity = "OCTEON", | ||
| 575 | }; | ||
| 576 | |||
| 577 | switch (cmd) { | ||
| 578 | case WDIOC_GETSUPPORT: | ||
| 579 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
| 580 | case WDIOC_GETSTATUS: | ||
| 581 | case WDIOC_GETBOOTSTATUS: | ||
| 582 | return put_user(0, p); | ||
| 583 | case WDIOC_KEEPALIVE: | ||
| 584 | octeon_wdt_ping(); | ||
| 585 | return 0; | ||
| 586 | case WDIOC_SETTIMEOUT: | ||
| 587 | if (get_user(new_heartbeat, p)) | ||
| 588 | return -EFAULT; | ||
| 589 | if (octeon_wdt_set_heartbeat(new_heartbeat)) | ||
| 590 | return -EINVAL; | ||
| 591 | /* Fall through. */ | ||
| 592 | case WDIOC_GETTIMEOUT: | ||
| 593 | return put_user(heartbeat, p); | ||
| 594 | default: | ||
| 595 | return -ENOTTY; | ||
| 596 | } | ||
| 597 | } | ||
| 598 | |||
| 599 | /** | ||
| 600 | * octeon_wdt_open: | ||
| 601 | * @inode: inode of device | ||
| 602 | * @file: file handle to device | ||
| 603 | * | ||
| 604 | * The watchdog device has been opened. The watchdog device is single | ||
| 605 | * open and on opening we do a ping to reset the counters. | ||
| 606 | */ | ||
| 607 | |||
| 608 | static int octeon_wdt_open(struct inode *inode, struct file *file) | ||
| 609 | { | 521 | { |
| 610 | if (test_and_set_bit(0, &octeon_wdt_is_open)) | 522 | octeon_wdt_ping(wdog); |
| 611 | return -EBUSY; | ||
| 612 | /* | ||
| 613 | * Activate | ||
| 614 | */ | ||
| 615 | octeon_wdt_ping(); | ||
| 616 | do_coundown = 1; | 523 | do_coundown = 1; |
| 617 | return nonseekable_open(inode, file); | 524 | return 0; |
| 618 | } | 525 | } |
| 619 | 526 | ||
| 620 | /** | 527 | static int octeon_wdt_stop(struct watchdog_device *wdog) |
| 621 | * octeon_wdt_release: | ||
| 622 | * @inode: inode to board | ||
| 623 | * @file: file handle to board | ||
| 624 | * | ||
| 625 | * The watchdog has a configurable API. There is a religious dispute | ||
| 626 | * between people who want their watchdog to be able to shut down and | ||
| 627 | * those who want to be sure if the watchdog manager dies the machine | ||
| 628 | * reboots. In the former case we disable the counters, in the latter | ||
| 629 | * case you have to open it again very soon. | ||
| 630 | */ | ||
| 631 | |||
| 632 | static int octeon_wdt_release(struct inode *inode, struct file *file) | ||
| 633 | { | 528 | { |
| 634 | if (expect_close) { | 529 | do_coundown = 0; |
| 635 | do_coundown = 0; | 530 | octeon_wdt_ping(wdog); |
| 636 | octeon_wdt_ping(); | ||
| 637 | } else { | ||
| 638 | pr_crit("WDT device closed unexpectedly. WDT will not stop!\n"); | ||
| 639 | } | ||
| 640 | clear_bit(0, &octeon_wdt_is_open); | ||
| 641 | expect_close = 0; | ||
| 642 | return 0; | 531 | return 0; |
| 643 | } | 532 | } |
| 644 | 533 | ||
| 645 | static const struct file_operations octeon_wdt_fops = { | 534 | static struct notifier_block octeon_wdt_cpu_notifier = { |
| 646 | .owner = THIS_MODULE, | 535 | .notifier_call = octeon_wdt_cpu_callback, |
| 647 | .llseek = no_llseek, | ||
| 648 | .write = octeon_wdt_write, | ||
| 649 | .unlocked_ioctl = octeon_wdt_ioctl, | ||
| 650 | .open = octeon_wdt_open, | ||
| 651 | .release = octeon_wdt_release, | ||
| 652 | }; | 536 | }; |
| 653 | 537 | ||
| 654 | static struct miscdevice octeon_wdt_miscdev = { | 538 | static const struct watchdog_info octeon_wdt_info = { |
| 655 | .minor = WATCHDOG_MINOR, | 539 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, |
| 656 | .name = "watchdog", | 540 | .identity = "OCTEON", |
| 657 | .fops = &octeon_wdt_fops, | ||
| 658 | }; | 541 | }; |
| 659 | 542 | ||
| 660 | static struct notifier_block octeon_wdt_cpu_notifier = { | 543 | static const struct watchdog_ops octeon_wdt_ops = { |
| 661 | .notifier_call = octeon_wdt_cpu_callback, | 544 | .owner = THIS_MODULE, |
| 545 | .start = octeon_wdt_start, | ||
| 546 | .stop = octeon_wdt_stop, | ||
| 547 | .ping = octeon_wdt_ping, | ||
| 548 | .set_timeout = octeon_wdt_set_timeout, | ||
| 662 | }; | 549 | }; |
| 663 | 550 | ||
| 551 | static struct watchdog_device octeon_wdt = { | ||
| 552 | .info = &octeon_wdt_info, | ||
| 553 | .ops = &octeon_wdt_ops, | ||
| 554 | }; | ||
| 664 | 555 | ||
| 665 | /** | 556 | /** |
| 666 | * Module/ driver initialization. | 557 | * Module/ driver initialization. |
| @@ -685,7 +576,8 @@ static int __init octeon_wdt_init(void) | |||
| 685 | max_timeout_sec = 6; | 576 | max_timeout_sec = 6; |
| 686 | do { | 577 | do { |
| 687 | max_timeout_sec--; | 578 | max_timeout_sec--; |
| 688 | timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * max_timeout_sec) >> 8; | 579 | timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * |
| 580 | max_timeout_sec) >> 8; | ||
| 689 | } while (timeout_cnt > 65535); | 581 | } while (timeout_cnt > 65535); |
| 690 | 582 | ||
| 691 | BUG_ON(timeout_cnt == 0); | 583 | BUG_ON(timeout_cnt == 0); |
| @@ -694,11 +586,15 @@ static int __init octeon_wdt_init(void) | |||
| 694 | 586 | ||
| 695 | pr_info("Initial granularity %d Sec\n", timeout_sec); | 587 | pr_info("Initial granularity %d Sec\n", timeout_sec); |
| 696 | 588 | ||
| 697 | ret = misc_register(&octeon_wdt_miscdev); | 589 | octeon_wdt.timeout = timeout_sec; |
| 590 | octeon_wdt.max_timeout = UINT_MAX; | ||
| 591 | |||
| 592 | watchdog_set_nowayout(&octeon_wdt, nowayout); | ||
| 593 | |||
| 594 | ret = watchdog_register_device(&octeon_wdt); | ||
| 698 | if (ret) { | 595 | if (ret) { |
| 699 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", | 596 | pr_err("watchdog_register_device() failed: %d\n", ret); |
| 700 | WATCHDOG_MINOR, ret); | 597 | return ret; |
| 701 | goto out; | ||
| 702 | } | 598 | } |
| 703 | 599 | ||
| 704 | /* Build the NMI handler ... */ | 600 | /* Build the NMI handler ... */ |
| @@ -721,8 +617,7 @@ static int __init octeon_wdt_init(void) | |||
| 721 | __register_hotcpu_notifier(&octeon_wdt_cpu_notifier); | 617 | __register_hotcpu_notifier(&octeon_wdt_cpu_notifier); |
| 722 | cpu_notifier_register_done(); | 618 | cpu_notifier_register_done(); |
| 723 | 619 | ||
| 724 | out: | 620 | return 0; |
| 725 | return ret; | ||
| 726 | } | 621 | } |
| 727 | 622 | ||
| 728 | /** | 623 | /** |
| @@ -732,7 +627,7 @@ static void __exit octeon_wdt_cleanup(void) | |||
| 732 | { | 627 | { |
| 733 | int cpu; | 628 | int cpu; |
| 734 | 629 | ||
| 735 | misc_deregister(&octeon_wdt_miscdev); | 630 | watchdog_unregister_device(&octeon_wdt); |
| 736 | 631 | ||
| 737 | cpu_notifier_register_begin(); | 632 | cpu_notifier_register_begin(); |
| 738 | __unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); | 633 | __unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); |
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 55e220150103..b9c6049c3e78 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c | |||
| @@ -216,7 +216,7 @@ static struct platform_driver platform_wdt_driver = { | |||
| 216 | module_platform_driver(platform_wdt_driver); | 216 | module_platform_driver(platform_wdt_driver); |
| 217 | 217 | ||
| 218 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); | 218 | MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); |
| 219 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); | 219 | MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>"); |
| 220 | MODULE_DESCRIPTION("PNX4008 Watchdog Driver"); | 220 | MODULE_DESCRIPTION("PNX4008 Watchdog Driver"); |
| 221 | 221 | ||
| 222 | module_param(heartbeat, uint, 0); | 222 | module_param(heartbeat, uint, 0); |
diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index aa85618c4d03..aa03ca8f2d9b 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c | |||
| @@ -20,9 +20,9 @@ | |||
| 20 | #include <linux/reboot.h> | 20 | #include <linux/reboot.h> |
| 21 | #include <linux/watchdog.h> | 21 | #include <linux/watchdog.h> |
| 22 | 22 | ||
| 23 | #define WDT_RST 0x0 | 23 | #define WDT_RST 0x38 |
| 24 | #define WDT_EN 0x8 | 24 | #define WDT_EN 0x40 |
| 25 | #define WDT_BITE_TIME 0x24 | 25 | #define WDT_BITE_TIME 0x5C |
| 26 | 26 | ||
| 27 | struct qcom_wdt { | 27 | struct qcom_wdt { |
| 28 | struct watchdog_device wdd; | 28 | struct watchdog_device wdd; |
| @@ -117,6 +117,8 @@ static int qcom_wdt_probe(struct platform_device *pdev) | |||
| 117 | { | 117 | { |
| 118 | struct qcom_wdt *wdt; | 118 | struct qcom_wdt *wdt; |
| 119 | struct resource *res; | 119 | struct resource *res; |
| 120 | struct device_node *np = pdev->dev.of_node; | ||
| 121 | u32 percpu_offset; | ||
| 120 | int ret; | 122 | int ret; |
| 121 | 123 | ||
| 122 | wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); | 124 | wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); |
| @@ -124,6 +126,14 @@ static int qcom_wdt_probe(struct platform_device *pdev) | |||
| 124 | return -ENOMEM; | 126 | return -ENOMEM; |
| 125 | 127 | ||
| 126 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 128 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 129 | |||
| 130 | /* We use CPU0's DGT for the watchdog */ | ||
| 131 | if (of_property_read_u32(np, "cpu-offset", &percpu_offset)) | ||
| 132 | percpu_offset = 0; | ||
| 133 | |||
| 134 | res->start += percpu_offset; | ||
| 135 | res->end += percpu_offset; | ||
| 136 | |||
| 127 | wdt->base = devm_ioremap_resource(&pdev->dev, res); | 137 | wdt->base = devm_ioremap_resource(&pdev->dev, res); |
| 128 | if (IS_ERR(wdt->base)) | 138 | if (IS_ERR(wdt->base)) |
| 129 | return PTR_ERR(wdt->base); | 139 | return PTR_ERR(wdt->base); |
| @@ -203,9 +213,8 @@ static int qcom_wdt_remove(struct platform_device *pdev) | |||
| 203 | } | 213 | } |
| 204 | 214 | ||
| 205 | static const struct of_device_id qcom_wdt_of_table[] = { | 215 | static const struct of_device_id qcom_wdt_of_table[] = { |
| 206 | { .compatible = "qcom,kpss-wdt-msm8960", }, | 216 | { .compatible = "qcom,kpss-timer" }, |
| 207 | { .compatible = "qcom,kpss-wdt-apq8064", }, | 217 | { .compatible = "qcom,scss-timer" }, |
| 208 | { .compatible = "qcom,kpss-wdt-ipq8064", }, | ||
| 209 | { }, | 218 | { }, |
| 210 | }; | 219 | }; |
| 211 | MODULE_DEVICE_TABLE(of, qcom_wdt_of_table); | 220 | MODULE_DEVICE_TABLE(of, qcom_wdt_of_table); |
diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index a62b1b6decf4..e7f0d5b60d3d 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28 | 2 | * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28 |
| 3 | * | 3 | * |
| 4 | * Author: Wolfram Sang <w.sang@pengutronix.de> | 4 | * Author: Wolfram Sang <kernel@pengutronix.de> |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2011-12 Wolfram Sang, Pengutronix | 6 | * Copyright (C) 2011-12 Wolfram Sang, Pengutronix |
| 7 | * | 7 | * |
| @@ -129,4 +129,4 @@ module_platform_driver(stmp3xxx_wdt_driver); | |||
| 129 | 129 | ||
| 130 | MODULE_DESCRIPTION("STMP3XXX RTC Watchdog Driver"); | 130 | MODULE_DESCRIPTION("STMP3XXX RTC Watchdog Driver"); |
| 131 | MODULE_LICENSE("GPL v2"); | 131 | MODULE_LICENSE("GPL v2"); |
| 132 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); | 132 | MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>"); |
