diff options
author | Wim Van Sebroeck <wim@linux-watchdog.org> | 2018-03-13 14:14:41 -0400 |
---|---|---|
committer | Wim Van Sebroeck <wim@linux-watchdog.org> | 2018-03-13 14:14:41 -0400 |
commit | 2e8ebed6ede01f187f8a06bbae3e3b3325bda36c (patch) | |
tree | 4c4594857bb0b1455dcabae3c5638fcbe53c46b2 | |
parent | 1462eecfc534fbfe85645d632527b358354fa3f4 (diff) | |
parent | 8c088370c2a684acad45e0035d9f2dfd85087db0 (diff) |
Merge branch 'v4.16-fixes'
-rw-r--r-- | drivers/watchdog/aspeed_wdt.c | 9 | ||||
-rw-r--r-- | drivers/watchdog/dw_wdt.c | 32 | ||||
-rw-r--r-- | drivers/watchdog/sprd_wdt.c | 4 |
3 files changed, 33 insertions, 12 deletions
diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index ca5b91e2eb92..d1987d63b37c 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c | |||
@@ -232,11 +232,14 @@ static int aspeed_wdt_probe(struct platform_device *pdev) | |||
232 | wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC | WDT_CTRL_RESET_SYSTEM; | 232 | wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC | WDT_CTRL_RESET_SYSTEM; |
233 | } else { | 233 | } else { |
234 | if (!strcmp(reset_type, "cpu")) | 234 | if (!strcmp(reset_type, "cpu")) |
235 | wdt->ctrl |= WDT_CTRL_RESET_MODE_ARM_CPU; | 235 | wdt->ctrl |= WDT_CTRL_RESET_MODE_ARM_CPU | |
236 | WDT_CTRL_RESET_SYSTEM; | ||
236 | else if (!strcmp(reset_type, "soc")) | 237 | else if (!strcmp(reset_type, "soc")) |
237 | wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC; | 238 | wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC | |
239 | WDT_CTRL_RESET_SYSTEM; | ||
238 | else if (!strcmp(reset_type, "system")) | 240 | else if (!strcmp(reset_type, "system")) |
239 | wdt->ctrl |= WDT_CTRL_RESET_SYSTEM; | 241 | wdt->ctrl |= WDT_CTRL_RESET_MODE_FULL_CHIP | |
242 | WDT_CTRL_RESET_SYSTEM; | ||
240 | else if (strcmp(reset_type, "none")) | 243 | else if (strcmp(reset_type, "none")) |
241 | return -EINVAL; | 244 | return -EINVAL; |
242 | } | 245 | } |
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 @@ | |||
34 | 34 | ||
35 | #define WDOG_CONTROL_REG_OFFSET 0x00 | 35 | #define WDOG_CONTROL_REG_OFFSET 0x00 |
36 | #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 | 36 | #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 |
37 | #define WDOG_CONTROL_REG_RESP_MODE_MASK 0x02 | ||
37 | #define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04 | 38 | #define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04 |
38 | #define WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT 4 | 39 | #define WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT 4 |
39 | #define WDOG_CURRENT_COUNT_REG_OFFSET 0x08 | 40 | #define WDOG_CURRENT_COUNT_REG_OFFSET 0x08 |
@@ -56,6 +57,9 @@ struct dw_wdt { | |||
56 | unsigned long rate; | 57 | unsigned long rate; |
57 | struct watchdog_device wdd; | 58 | struct watchdog_device wdd; |
58 | struct reset_control *rst; | 59 | struct reset_control *rst; |
60 | /* Save/restore */ | ||
61 | u32 control; | ||
62 | u32 timeout; | ||
59 | }; | 63 | }; |
60 | 64 | ||
61 | #define to_dw_wdt(wdd) container_of(wdd, struct dw_wdt, wdd) | 65 | #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) | |||
121 | return 0; | 125 | return 0; |
122 | } | 126 | } |
123 | 127 | ||
128 | static void dw_wdt_arm_system_reset(struct dw_wdt *dw_wdt) | ||
129 | { | ||
130 | u32 val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); | ||
131 | |||
132 | /* Disable interrupt mode; always perform system reset. */ | ||
133 | val &= ~WDOG_CONTROL_REG_RESP_MODE_MASK; | ||
134 | /* Enable watchdog. */ | ||
135 | val |= WDOG_CONTROL_REG_WDT_EN_MASK; | ||
136 | writel(val, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); | ||
137 | } | ||
138 | |||
124 | static int dw_wdt_start(struct watchdog_device *wdd) | 139 | static int dw_wdt_start(struct watchdog_device *wdd) |
125 | { | 140 | { |
126 | struct dw_wdt *dw_wdt = to_dw_wdt(wdd); | 141 | struct dw_wdt *dw_wdt = to_dw_wdt(wdd); |
127 | 142 | ||
128 | dw_wdt_set_timeout(wdd, wdd->timeout); | 143 | dw_wdt_set_timeout(wdd, wdd->timeout); |
129 | 144 | dw_wdt_arm_system_reset(dw_wdt); | |
130 | writel(WDOG_CONTROL_REG_WDT_EN_MASK, | ||
131 | dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); | ||
132 | 145 | ||
133 | return 0; | 146 | return 0; |
134 | } | 147 | } |
@@ -152,16 +165,13 @@ static int dw_wdt_restart(struct watchdog_device *wdd, | |||
152 | unsigned long action, void *data) | 165 | unsigned long action, void *data) |
153 | { | 166 | { |
154 | struct dw_wdt *dw_wdt = to_dw_wdt(wdd); | 167 | struct dw_wdt *dw_wdt = to_dw_wdt(wdd); |
155 | u32 val; | ||
156 | 168 | ||
157 | writel(0, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); | 169 | writel(0, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); |
158 | val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); | 170 | if (dw_wdt_is_enabled(dw_wdt)) |
159 | if (val & WDOG_CONTROL_REG_WDT_EN_MASK) | ||
160 | writel(WDOG_COUNTER_RESTART_KICK_VALUE, | 171 | writel(WDOG_COUNTER_RESTART_KICK_VALUE, |
161 | dw_wdt->regs + WDOG_COUNTER_RESTART_REG_OFFSET); | 172 | dw_wdt->regs + WDOG_COUNTER_RESTART_REG_OFFSET); |
162 | else | 173 | else |
163 | writel(WDOG_CONTROL_REG_WDT_EN_MASK, | 174 | dw_wdt_arm_system_reset(dw_wdt); |
164 | dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); | ||
165 | 175 | ||
166 | /* wait for reset to assert... */ | 176 | /* wait for reset to assert... */ |
167 | mdelay(500); | 177 | mdelay(500); |
@@ -198,6 +208,9 @@ static int dw_wdt_suspend(struct device *dev) | |||
198 | { | 208 | { |
199 | struct dw_wdt *dw_wdt = dev_get_drvdata(dev); | 209 | struct dw_wdt *dw_wdt = dev_get_drvdata(dev); |
200 | 210 | ||
211 | dw_wdt->control = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); | ||
212 | dw_wdt->timeout = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); | ||
213 | |||
201 | clk_disable_unprepare(dw_wdt->clk); | 214 | clk_disable_unprepare(dw_wdt->clk); |
202 | 215 | ||
203 | return 0; | 216 | return 0; |
@@ -211,6 +224,9 @@ static int dw_wdt_resume(struct device *dev) | |||
211 | if (err) | 224 | if (err) |
212 | return err; | 225 | return err; |
213 | 226 | ||
227 | writel(dw_wdt->timeout, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); | ||
228 | writel(dw_wdt->control, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); | ||
229 | |||
214 | dw_wdt_ping(&dw_wdt->wdd); | 230 | dw_wdt_ping(&dw_wdt->wdd); |
215 | 231 | ||
216 | return 0; | 232 | return 0; |
diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c index a8b280ff33e0..b4d484a42b70 100644 --- a/drivers/watchdog/sprd_wdt.c +++ b/drivers/watchdog/sprd_wdt.c | |||
@@ -154,8 +154,10 @@ static int sprd_wdt_enable(struct sprd_wdt *wdt) | |||
154 | if (ret) | 154 | if (ret) |
155 | return ret; | 155 | return ret; |
156 | ret = clk_prepare_enable(wdt->rtc_enable); | 156 | ret = clk_prepare_enable(wdt->rtc_enable); |
157 | if (ret) | 157 | if (ret) { |
158 | clk_disable_unprepare(wdt->enable); | ||
158 | return ret; | 159 | return ret; |
160 | } | ||
159 | 161 | ||
160 | sprd_wdt_unlock(wdt->base); | 162 | sprd_wdt_unlock(wdt->base); |
161 | val = readl_relaxed(wdt->base + SPRD_WDT_CTRL); | 163 | val = readl_relaxed(wdt->base + SPRD_WDT_CTRL); |