diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-14 01:43:50 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-14 01:43:50 +0300 |
commit | 41531f58a6513b86f8f379117eca82502022b4a9 (patch) | |
tree | 18d69ef03890d23e6b7d379467ea6cf07f377bfe /drivers/watchdog/dw_wdt.c | |
parent | 80a17a5f501ea048d86f81d629c94062b76610d4 (diff) | |
parent | 1991a55dc87e8f2557bc90d7f0062b7110ab8437 (diff) | |
download | linux-41531f58a6513b86f8f379117eca82502022b4a9.tar.xz |
Merge tag 'linux-watchdog-4.17-rc1' of git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck:
- Add Nuvoton NPCM watchdog driver
- renesas_wdt: Add R-Car Gen2 support
- renesas_wdt: add suspend/resume and restart handler support
- hpwdt: convert to watchdog core and improve NMI
- improve timeout setting/handling in various drivers
- coh901327: make license text and module licence match
- fix error handling in asm9260_wdt, sprd_wdt and davinci_wdt
- aspeed imrovements
- dw improvements (for control register & suspend/resume)
- add SPDX identifiers for watchdog subsystem
* tag 'linux-watchdog-4.17-rc1' of git://www.linux-watchdog.org/linux-watchdog: (35 commits)
watchdog: davinci_wdt: fix error handling in davinci_wdt_probe()
watchdog: add SPDX identifiers for watchdog subsystem
watchdog: aspeed: Allow configuring for alternate boot
watchdog: Add Nuvoton NPCM watchdog driver
dt-bindings: watchdog: Add Nuvoton NPCM description
watchdog: dw: save/restore control and timeout across suspend/resume
watchdog: dw: RMW the control register
watchdog: sprd_wdt: Fix error handling in sprd_wdt_enable()
watchdog: aspeed: Fix translation of reset mode to ctrl register
watchdog: renesas_wdt: Add restart handler
watchdog: renesas_wdt: Add R-Car Gen2 support
watchdog: renesas_wdt: Add suspend/resume support
watchdog: f71808e_wdt: Fix WD_EN register read
watchdog: hpwdt: Update driver version.
watchdog: hpwdt: Add dynamic debug
watchdog: hpwdt: Programable Pretimeout NMI
watchdog: hpwdt: remove allow_kdump module parameter.
watchdog: hpwdt: condition early return of NMI handler on iLO5
watchdog: hpwdt: Modify to use watchdog core.
watchdog: hpwdt: Update nmi_panic message.
...
Diffstat (limited to 'drivers/watchdog/dw_wdt.c')
-rw-r--r-- | drivers/watchdog/dw_wdt.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index c2f4ff516230..501aebb5b81f 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -34,6 +34,7 @@ #define WDOG_CONTROL_REG_OFFSET 0x00 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 +#define WDOG_CONTROL_REG_RESP_MODE_MASK 0x02 #define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04 #define WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT 4 #define WDOG_CURRENT_COUNT_REG_OFFSET 0x08 @@ -56,6 +57,9 @@ struct dw_wdt { unsigned long rate; struct watchdog_device wdd; struct reset_control *rst; + /* Save/restore */ + u32 control; + u32 timeout; }; #define to_dw_wdt(wdd) container_of(wdd, struct dw_wdt, wdd) @@ -121,14 +125,23 @@ static int dw_wdt_set_timeout(struct watchdog_device *wdd, unsigned int top_s) return 0; } +static void dw_wdt_arm_system_reset(struct dw_wdt *dw_wdt) +{ + u32 val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); + + /* Disable interrupt mode; always perform system reset. */ + val &= ~WDOG_CONTROL_REG_RESP_MODE_MASK; + /* Enable watchdog. */ + val |= WDOG_CONTROL_REG_WDT_EN_MASK; + writel(val, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); +} + static int dw_wdt_start(struct watchdog_device *wdd) { struct dw_wdt *dw_wdt = to_dw_wdt(wdd); dw_wdt_set_timeout(wdd, wdd->timeout); - - writel(WDOG_CONTROL_REG_WDT_EN_MASK, - dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); + dw_wdt_arm_system_reset(dw_wdt); return 0; } @@ -152,16 +165,13 @@ static int dw_wdt_restart(struct watchdog_device *wdd, unsigned long action, void *data) { struct dw_wdt *dw_wdt = to_dw_wdt(wdd); - u32 val; writel(0, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); - val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); - if (val & WDOG_CONTROL_REG_WDT_EN_MASK) + if (dw_wdt_is_enabled(dw_wdt)) writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt->regs + WDOG_COUNTER_RESTART_REG_OFFSET); else - writel(WDOG_CONTROL_REG_WDT_EN_MASK, - dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); + dw_wdt_arm_system_reset(dw_wdt); /* wait for reset to assert... */ mdelay(500); @@ -198,6 +208,9 @@ static int dw_wdt_suspend(struct device *dev) { struct dw_wdt *dw_wdt = dev_get_drvdata(dev); + dw_wdt->control = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); + dw_wdt->timeout = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); + clk_disable_unprepare(dw_wdt->clk); return 0; @@ -211,6 +224,9 @@ static int dw_wdt_resume(struct device *dev) if (err) return err; + writel(dw_wdt->timeout, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); + writel(dw_wdt->control, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); + dw_wdt_ping(&dw_wdt->wdd); return 0; |