aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <krzk@kernel.org>2017-04-04 15:32:35 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-12 06:41:22 -0400
commit4dc1eb47fbea4018715f017ff83b77e1a8d79f62 (patch)
tree9af4f3452b2c3ce9b118954f7951df21ec7552df
parentb18877ff66cf564c0e2f31086239ceb6b82cb4f4 (diff)
watchdog: s3c2410: Fix infinite interrupt in soft mode
[ Upstream commit 0b445549ea6f91ffea78a976fe89b932db6e077a ] In soft (no-reboot) mode, the driver self-pings watchdog upon expiration of an interrupt. However the interrupt itself was not cleared thus on first hit, the system enters infinite interrupt handling loop. On Odroid U3 (Exynos4412), when booted with s3c2410_wdt.soft_noboot=1 argument the console is flooded: # killall -9 watchdog [ 60.523760] s3c2410-wdt 10060000.watchdog: watchdog timer expired (irq) [ 60.536744] s3c2410-wdt 10060000.watchdog: watchdog timer expired (irq) Fix this by writing something to the WTCLRINT register to clear the interrupt. The register WTCLRINT however appeared in S3C6410 so a new watchdog quirk and flavor are needed. Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/devicetree/bindings/watchdog/samsung-wdt.txt9
-rw-r--r--drivers/watchdog/s3c2410_wdt.c21
2 files changed, 23 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt b/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
index 8f3d96af81d7..1f6e101e299a 100644
--- a/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
@@ -6,10 +6,11 @@ occurred.
6 6
7Required properties: 7Required properties:
8- compatible : should be one among the following 8- compatible : should be one among the following
9 (a) "samsung,s3c2410-wdt" for Exynos4 and previous SoCs 9 - "samsung,s3c2410-wdt" for S3C2410
10 (b) "samsung,exynos5250-wdt" for Exynos5250 10 - "samsung,s3c6410-wdt" for S3C6410, S5PV210 and Exynos4
11 (c) "samsung,exynos5420-wdt" for Exynos5420 11 - "samsung,exynos5250-wdt" for Exynos5250
12 (c) "samsung,exynos7-wdt" for Exynos7 12 - "samsung,exynos5420-wdt" for Exynos5420
13 - "samsung,exynos7-wdt" for Exynos7
13 14
14- reg : base physical address of the controller and length of memory mapped 15- reg : base physical address of the controller and length of memory mapped
15 region. 16 region.
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 59e95762a6de..c5a567a73f59 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -46,6 +46,7 @@
46#define S3C2410_WTCON 0x00 46#define S3C2410_WTCON 0x00
47#define S3C2410_WTDAT 0x04 47#define S3C2410_WTDAT 0x04
48#define S3C2410_WTCNT 0x08 48#define S3C2410_WTCNT 0x08
49#define S3C2410_WTCLRINT 0x0c
49 50
50#define S3C2410_WTCNT_MAXCNT 0xffff 51#define S3C2410_WTCNT_MAXCNT 0xffff
51 52
@@ -72,6 +73,7 @@
72#define EXYNOS5_WDT_MASK_RESET_REG_OFFSET 0x040c 73#define EXYNOS5_WDT_MASK_RESET_REG_OFFSET 0x040c
73#define QUIRK_HAS_PMU_CONFIG (1 << 0) 74#define QUIRK_HAS_PMU_CONFIG (1 << 0)
74#define QUIRK_HAS_RST_STAT (1 << 1) 75#define QUIRK_HAS_RST_STAT (1 << 1)
76#define QUIRK_HAS_WTCLRINT_REG (1 << 2)
75 77
76/* These quirks require that we have a PMU register map */ 78/* These quirks require that we have a PMU register map */
77#define QUIRKS_HAVE_PMUREG (QUIRK_HAS_PMU_CONFIG | \ 79#define QUIRKS_HAVE_PMUREG (QUIRK_HAS_PMU_CONFIG | \
@@ -143,13 +145,18 @@ static const struct s3c2410_wdt_variant drv_data_s3c2410 = {
143}; 145};
144 146
145#ifdef CONFIG_OF 147#ifdef CONFIG_OF
148static const struct s3c2410_wdt_variant drv_data_s3c6410 = {
149 .quirks = QUIRK_HAS_WTCLRINT_REG,
150};
151
146static const struct s3c2410_wdt_variant drv_data_exynos5250 = { 152static const struct s3c2410_wdt_variant drv_data_exynos5250 = {
147 .disable_reg = EXYNOS5_WDT_DISABLE_REG_OFFSET, 153 .disable_reg = EXYNOS5_WDT_DISABLE_REG_OFFSET,
148 .mask_reset_reg = EXYNOS5_WDT_MASK_RESET_REG_OFFSET, 154 .mask_reset_reg = EXYNOS5_WDT_MASK_RESET_REG_OFFSET,
149 .mask_bit = 20, 155 .mask_bit = 20,
150 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, 156 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
151 .rst_stat_bit = 20, 157 .rst_stat_bit = 20,
152 .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT, 158 .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT \
159 | QUIRK_HAS_WTCLRINT_REG,
153}; 160};
154 161
155static const struct s3c2410_wdt_variant drv_data_exynos5420 = { 162static const struct s3c2410_wdt_variant drv_data_exynos5420 = {
@@ -158,7 +165,8 @@ static const struct s3c2410_wdt_variant drv_data_exynos5420 = {
158 .mask_bit = 0, 165 .mask_bit = 0,
159 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, 166 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
160 .rst_stat_bit = 9, 167 .rst_stat_bit = 9,
161 .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT, 168 .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT \
169 | QUIRK_HAS_WTCLRINT_REG,
162}; 170};
163 171
164static const struct s3c2410_wdt_variant drv_data_exynos7 = { 172static const struct s3c2410_wdt_variant drv_data_exynos7 = {
@@ -167,12 +175,15 @@ static const struct s3c2410_wdt_variant drv_data_exynos7 = {
167 .mask_bit = 23, 175 .mask_bit = 23,
168 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET, 176 .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
169 .rst_stat_bit = 23, /* A57 WDTRESET */ 177 .rst_stat_bit = 23, /* A57 WDTRESET */
170 .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT, 178 .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT \
179 | QUIRK_HAS_WTCLRINT_REG,
171}; 180};
172 181
173static const struct of_device_id s3c2410_wdt_match[] = { 182static const struct of_device_id s3c2410_wdt_match[] = {
174 { .compatible = "samsung,s3c2410-wdt", 183 { .compatible = "samsung,s3c2410-wdt",
175 .data = &drv_data_s3c2410 }, 184 .data = &drv_data_s3c2410 },
185 { .compatible = "samsung,s3c6410-wdt",
186 .data = &drv_data_s3c6410 },
176 { .compatible = "samsung,exynos5250-wdt", 187 { .compatible = "samsung,exynos5250-wdt",
177 .data = &drv_data_exynos5250 }, 188 .data = &drv_data_exynos5250 },
178 { .compatible = "samsung,exynos5420-wdt", 189 { .compatible = "samsung,exynos5420-wdt",
@@ -418,6 +429,10 @@ static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
418 dev_info(wdt->dev, "watchdog timer expired (irq)\n"); 429 dev_info(wdt->dev, "watchdog timer expired (irq)\n");
419 430
420 s3c2410wdt_keepalive(&wdt->wdt_device); 431 s3c2410wdt_keepalive(&wdt->wdt_device);
432
433 if (wdt->drv_data->quirks & QUIRK_HAS_WTCLRINT_REG)
434 writel(0x1, wdt->reg_base + S3C2410_WTCLRINT);
435
421 return IRQ_HANDLED; 436 return IRQ_HANDLED;
422} 437}
423 438