aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEzequiel Garcia <ezequiel.garcia@free-electrons.com>2014-02-10 18:00:25 -0500
committerJason Cooper <jason@lakedaemon.net>2014-02-21 22:43:23 -0500
commit868eb61602d9c020fc9e21b42f3ccd301b36b94d (patch)
treeb26c070e5d546b2c4e18f87ec4d1f00237b6331c
parente97662e1e28da0da0702db213931d8f9a580970a (diff)
watchdog: orion: Make RSTOUT register a separate resource
In order to support other SoC, it's required to distinguish the 'control' timer register, from the 'rstout' register that enables system reset on watchdog expiration. To prevent a compatibility break, this commit adds a fallback to a hardcoded RSTOUT address. Reviewed-by: Guenter Roeck <linux@roeck-us.net> Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Tested-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Acked-by: Wim Van Sebroeck <wim@iguana.be> Tested-By: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--Documentation/devicetree/bindings/watchdog/marvel.txt6
-rw-r--r--arch/arm/mach-dove/include/mach/bridge-regs.h1
-rw-r--r--arch/arm/mach-kirkwood/include/mach/bridge-regs.h1
-rw-r--r--arch/arm/mach-mv78xx0/include/mach/bridge-regs.h1
-rw-r--r--arch/arm/mach-orion5x/include/mach/bridge-regs.h1
-rw-r--r--arch/arm/plat-orion/common.c10
-rw-r--r--drivers/watchdog/orion_wdt.c47
7 files changed, 58 insertions, 9 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/marvel.txt b/Documentation/devicetree/bindings/watchdog/marvel.txt
index 0731fbd2de83..1544fe991d24 100644
--- a/Documentation/devicetree/bindings/watchdog/marvel.txt
+++ b/Documentation/devicetree/bindings/watchdog/marvel.txt
@@ -3,7 +3,9 @@
3Required Properties: 3Required Properties:
4 4
5- Compatibility : "marvell,orion-wdt" 5- Compatibility : "marvell,orion-wdt"
6- reg : Address of the timer registers 6- reg : Should contain two entries: first one with the
7 timer control address, second one with the
8 rstout enable address.
7 9
8Optional properties: 10Optional properties:
9 11
@@ -14,7 +16,7 @@ Example:
14 16
15 wdt@20300 { 17 wdt@20300 {
16 compatible = "marvell,orion-wdt"; 18 compatible = "marvell,orion-wdt";
17 reg = <0x20300 0x28>; 19 reg = <0x20300 0x28>, <0x20108 0x4>;
18 interrupts = <3>; 20 interrupts = <3>;
19 timeout-sec = <10>; 21 timeout-sec = <10>;
20 status = "okay"; 22 status = "okay";
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h
index 5362df3df89f..f4a5b34489b7 100644
--- a/arch/arm/mach-dove/include/mach/bridge-regs.h
+++ b/arch/arm/mach-dove/include/mach/bridge-regs.h
@@ -21,6 +21,7 @@
21#define CPU_CTRL_PCIE1_LINK 0x00000008 21#define CPU_CTRL_PCIE1_LINK 0x00000008
22 22
23#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) 23#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108)
24#define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108)
24#define SOFT_RESET_OUT_EN 0x00000004 25#define SOFT_RESET_OUT_EN 0x00000004
25 26
26#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) 27#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index 8b9d1c9ff199..60f64218d6a6 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -21,6 +21,7 @@
21#define CPU_RESET 0x00000002 21#define CPU_RESET 0x00000002
22 22
23#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) 23#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108)
24#define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108)
24#define SOFT_RESET_OUT_EN 0x00000004 25#define SOFT_RESET_OUT_EN 0x00000004
25 26
26#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) 27#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
index 5f03484584d4..e20d6da234a6 100644
--- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
+++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
@@ -15,6 +15,7 @@
15#define L2_WRITETHROUGH 0x00020000 15#define L2_WRITETHROUGH 0x00020000
16 16
17#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) 17#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108)
18#define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108)
18#define SOFT_RESET_OUT_EN 0x00000004 19#define SOFT_RESET_OUT_EN 0x00000004
19 20
20#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) 21#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c)
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
index f727d03f1688..5766e3fbff69 100644
--- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h
+++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
@@ -18,6 +18,7 @@
18#define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104) 18#define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104)
19 19
20#define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108) 20#define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108)
21#define RSTOUTn_MASK_PHYS (ORION5X_BRIDGE_PHYS_BASE + 0x108)
21 22
22#define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c) 23#define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c)
23 24
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 830ff07f3385..3ec6e8e8d368 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -595,14 +595,16 @@ void __init orion_spi_1_init(unsigned long mapbase)
595/***************************************************************************** 595/*****************************************************************************
596 * Watchdog 596 * Watchdog
597 ****************************************************************************/ 597 ****************************************************************************/
598static struct resource orion_wdt_resource = 598static struct resource orion_wdt_resource[] = {
599 DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x28); 599 DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x04),
600 DEFINE_RES_MEM(RSTOUTn_MASK_PHYS, 0x04),
601};
600 602
601static struct platform_device orion_wdt_device = { 603static struct platform_device orion_wdt_device = {
602 .name = "orion_wdt", 604 .name = "orion_wdt",
603 .id = -1, 605 .id = -1,
604 .num_resources = 1, 606 .num_resources = ARRAY_SIZE(orion_wdt_resource),
605 .resource = &orion_wdt_resource, 607 .resource = orion_wdt_resource,
606}; 608};
607 609
608void __init orion_wdt_init(void) 610void __init orion_wdt_init(void)
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index b7067acd43a2..6061b838d396 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -26,6 +26,12 @@
26#include <linux/of.h> 26#include <linux/of.h>
27#include <mach/bridge-regs.h> 27#include <mach/bridge-regs.h>
28 28
29/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
30#define ORION_RSTOUT_MASK_OFFSET 0x20108
31
32/* Internal registers can be configured at any 1 MiB aligned address */
33#define INTERNAL_REGS_MASK ~(SZ_1M - 1)
34
29/* 35/*
30 * Watchdog timer block registers. 36 * Watchdog timer block registers.
31 */ 37 */
@@ -44,6 +50,7 @@ static unsigned int wdt_max_duration; /* (seconds) */
44static struct clk *clk; 50static struct clk *clk;
45static unsigned int wdt_tclk; 51static unsigned int wdt_tclk;
46static void __iomem *wdt_reg; 52static void __iomem *wdt_reg;
53static void __iomem *wdt_rstout;
47 54
48static int orion_wdt_ping(struct watchdog_device *wdt_dev) 55static int orion_wdt_ping(struct watchdog_device *wdt_dev)
49{ 56{
@@ -64,14 +71,14 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
64 atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN); 71 atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
65 72
66 /* Enable reset on watchdog */ 73 /* Enable reset on watchdog */
67 atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); 74 atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
68 return 0; 75 return 0;
69} 76}
70 77
71static int orion_wdt_stop(struct watchdog_device *wdt_dev) 78static int orion_wdt_stop(struct watchdog_device *wdt_dev)
72{ 79{
73 /* Disable reset on watchdog */ 80 /* Disable reset on watchdog */
74 atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0); 81 atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, 0);
75 82
76 /* Disable watchdog timer */ 83 /* Disable watchdog timer */
77 atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0); 84 atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
@@ -82,7 +89,7 @@ static int orion_wdt_enabled(void)
82{ 89{
83 bool enabled, running; 90 bool enabled, running;
84 91
85 enabled = readl(RSTOUTn_MASK) & WDT_RESET_OUT_EN; 92 enabled = readl(wdt_rstout) & WDT_RESET_OUT_EN;
86 running = readl(wdt_reg + TIMER_CTRL) & WDT_EN; 93 running = readl(wdt_reg + TIMER_CTRL) & WDT_EN;
87 94
88 return enabled && running; 95 return enabled && running;
@@ -126,6 +133,33 @@ static irqreturn_t orion_wdt_irq(int irq, void *devid)
126 return IRQ_HANDLED; 133 return IRQ_HANDLED;
127} 134}
128 135
136/*
137 * The original devicetree binding for this driver specified only
138 * one memory resource, so in order to keep DT backwards compatibility
139 * we try to fallback to a hardcoded register address, if the resource
140 * is missing from the devicetree.
141 */
142static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
143 phys_addr_t internal_regs)
144{
145 struct resource *res;
146 phys_addr_t rstout;
147
148 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
149 if (res)
150 return devm_ioremap(&pdev->dev, res->start,
151 resource_size(res));
152
153 /* This workaround works only for "orion-wdt", DT-enabled */
154 if (!of_device_is_compatible(pdev->dev.of_node, "marvell,orion-wdt"))
155 return NULL;
156
157 rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET;
158
159 WARN(1, FW_BUG "falling back to harcoded RSTOUT reg 0x%x\n", rstout);
160 return devm_ioremap(&pdev->dev, rstout, 0x4);
161}
162
129static int orion_wdt_probe(struct platform_device *pdev) 163static int orion_wdt_probe(struct platform_device *pdev)
130{ 164{
131 struct resource *res; 165 struct resource *res;
@@ -153,6 +187,13 @@ static int orion_wdt_probe(struct platform_device *pdev)
153 goto disable_clk; 187 goto disable_clk;
154 } 188 }
155 189
190 wdt_rstout = orion_wdt_ioremap_rstout(pdev, res->start &
191 INTERNAL_REGS_MASK);
192 if (!wdt_rstout) {
193 ret = -ENODEV;
194 goto disable_clk;
195 }
196
156 wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; 197 wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
157 198
158 orion_wdt.timeout = wdt_max_duration; 199 orion_wdt.timeout = wdt_max_duration;