Commit 868eb616 authored by Ezequiel Garcia's avatar Ezequiel Garcia Committed by Jason Cooper

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: default avatarGuenter Roeck <linux@roeck-us.net>
Tested-by: default avatarSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: default avatarWilly Tarreau <w@1wt.eu>
Signed-off-by: default avatarEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Acked-by: default avatarWim Van Sebroeck <wim@iguana.be>
Tested-By: default avatarJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: default avatarJason Cooper <jason@lakedaemon.net>
parent e97662e1
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
Required Properties: Required Properties:
- Compatibility : "marvell,orion-wdt" - Compatibility : "marvell,orion-wdt"
- reg : Address of the timer registers - reg : Should contain two entries: first one with the
timer control address, second one with the
rstout enable address.
Optional properties: Optional properties:
...@@ -14,7 +16,7 @@ Example: ...@@ -14,7 +16,7 @@ Example:
wdt@20300 { wdt@20300 {
compatible = "marvell,orion-wdt"; compatible = "marvell,orion-wdt";
reg = <0x20300 0x28>; reg = <0x20300 0x28>, <0x20108 0x4>;
interrupts = <3>; interrupts = <3>;
timeout-sec = <10>; timeout-sec = <10>;
status = "okay"; status = "okay";
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define CPU_CTRL_PCIE1_LINK 0x00000008 #define CPU_CTRL_PCIE1_LINK 0x00000008
#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108)
#define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108)
#define SOFT_RESET_OUT_EN 0x00000004 #define SOFT_RESET_OUT_EN 0x00000004
#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define CPU_RESET 0x00000002 #define CPU_RESET 0x00000002
#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108)
#define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108)
#define SOFT_RESET_OUT_EN 0x00000004 #define SOFT_RESET_OUT_EN 0x00000004
#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define L2_WRITETHROUGH 0x00020000 #define L2_WRITETHROUGH 0x00020000
#define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108)
#define RSTOUTn_MASK_PHYS (BRIDGE_PHYS_BASE + 0x0108)
#define SOFT_RESET_OUT_EN 0x00000004 #define SOFT_RESET_OUT_EN 0x00000004
#define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104) #define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104)
#define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108) #define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108)
#define RSTOUTn_MASK_PHYS (ORION5X_BRIDGE_PHYS_BASE + 0x108)
#define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c) #define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c)
......
...@@ -595,14 +595,16 @@ void __init orion_spi_1_init(unsigned long mapbase) ...@@ -595,14 +595,16 @@ void __init orion_spi_1_init(unsigned long mapbase)
/***************************************************************************** /*****************************************************************************
* Watchdog * Watchdog
****************************************************************************/ ****************************************************************************/
static struct resource orion_wdt_resource = static struct resource orion_wdt_resource[] = {
DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x28); DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x04),
DEFINE_RES_MEM(RSTOUTn_MASK_PHYS, 0x04),
};
static struct platform_device orion_wdt_device = { static struct platform_device orion_wdt_device = {
.name = "orion_wdt", .name = "orion_wdt",
.id = -1, .id = -1,
.num_resources = 1, .num_resources = ARRAY_SIZE(orion_wdt_resource),
.resource = &orion_wdt_resource, .resource = orion_wdt_resource,
}; };
void __init orion_wdt_init(void) void __init orion_wdt_init(void)
......
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
#include <linux/of.h> #include <linux/of.h>
#include <mach/bridge-regs.h> #include <mach/bridge-regs.h>
/* RSTOUT mask register physical address for Orion5x, Kirkwood and Dove */
#define ORION_RSTOUT_MASK_OFFSET 0x20108
/* Internal registers can be configured at any 1 MiB aligned address */
#define INTERNAL_REGS_MASK ~(SZ_1M - 1)
/* /*
* Watchdog timer block registers. * Watchdog timer block registers.
*/ */
...@@ -44,6 +50,7 @@ static unsigned int wdt_max_duration; /* (seconds) */ ...@@ -44,6 +50,7 @@ static unsigned int wdt_max_duration; /* (seconds) */
static struct clk *clk; static struct clk *clk;
static unsigned int wdt_tclk; static unsigned int wdt_tclk;
static void __iomem *wdt_reg; static void __iomem *wdt_reg;
static void __iomem *wdt_rstout;
static int orion_wdt_ping(struct watchdog_device *wdt_dev) static int orion_wdt_ping(struct watchdog_device *wdt_dev)
{ {
...@@ -64,14 +71,14 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev) ...@@ -64,14 +71,14 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev)
atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN); atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, WDT_EN);
/* Enable reset on watchdog */ /* Enable reset on watchdog */
atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN); atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, WDT_RESET_OUT_EN);
return 0; return 0;
} }
static int orion_wdt_stop(struct watchdog_device *wdt_dev) static int orion_wdt_stop(struct watchdog_device *wdt_dev)
{ {
/* Disable reset on watchdog */ /* Disable reset on watchdog */
atomic_io_modify(RSTOUTn_MASK, WDT_RESET_OUT_EN, 0); atomic_io_modify(wdt_rstout, WDT_RESET_OUT_EN, 0);
/* Disable watchdog timer */ /* Disable watchdog timer */
atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0); atomic_io_modify(wdt_reg + TIMER_CTRL, WDT_EN, 0);
...@@ -82,7 +89,7 @@ static int orion_wdt_enabled(void) ...@@ -82,7 +89,7 @@ static int orion_wdt_enabled(void)
{ {
bool enabled, running; bool enabled, running;
enabled = readl(RSTOUTn_MASK) & WDT_RESET_OUT_EN; enabled = readl(wdt_rstout) & WDT_RESET_OUT_EN;
running = readl(wdt_reg + TIMER_CTRL) & WDT_EN; running = readl(wdt_reg + TIMER_CTRL) & WDT_EN;
return enabled && running; return enabled && running;
...@@ -126,6 +133,33 @@ static irqreturn_t orion_wdt_irq(int irq, void *devid) ...@@ -126,6 +133,33 @@ static irqreturn_t orion_wdt_irq(int irq, void *devid)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/*
* The original devicetree binding for this driver specified only
* one memory resource, so in order to keep DT backwards compatibility
* we try to fallback to a hardcoded register address, if the resource
* is missing from the devicetree.
*/
static void __iomem *orion_wdt_ioremap_rstout(struct platform_device *pdev,
phys_addr_t internal_regs)
{
struct resource *res;
phys_addr_t rstout;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res)
return devm_ioremap(&pdev->dev, res->start,
resource_size(res));
/* This workaround works only for "orion-wdt", DT-enabled */
if (!of_device_is_compatible(pdev->dev.of_node, "marvell,orion-wdt"))
return NULL;
rstout = internal_regs + ORION_RSTOUT_MASK_OFFSET;
WARN(1, FW_BUG "falling back to harcoded RSTOUT reg 0x%x\n", rstout);
return devm_ioremap(&pdev->dev, rstout, 0x4);
}
static int orion_wdt_probe(struct platform_device *pdev) static int orion_wdt_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
...@@ -153,6 +187,13 @@ static int orion_wdt_probe(struct platform_device *pdev) ...@@ -153,6 +187,13 @@ static int orion_wdt_probe(struct platform_device *pdev)
goto disable_clk; goto disable_clk;
} }
wdt_rstout = orion_wdt_ioremap_rstout(pdev, res->start &
INTERNAL_REGS_MASK);
if (!wdt_rstout) {
ret = -ENODEV;
goto disable_clk;
}
wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
orion_wdt.timeout = wdt_max_duration; orion_wdt.timeout = wdt_max_duration;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment