diff options
author | Maxime Ripard <maxime.ripard@free-electrons.com> | 2013-03-11 20:21:11 +0100 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2013-08-16 23:19:30 +0200 |
commit | 06d71bcfee91b2be105f43c85fcd3960e179818b (patch) | |
tree | aefe974c11bf22236ffd9a814a8939797d940ec0 | |
parent | 2d7945100b1ade1de73ddc397c17d0c40b278fb4 (diff) |
ARM: sun6i: Add restart code for the A31
The Allwinner A31 has a different watchdog, with a slightly different
register layout, that requires a different restart code.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
-rw-r--r-- | Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt (renamed from Documentation/devicetree/bindings/watchdog/sun4i-wdt.txt) | 5 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/sunxi.c | 43 |
2 files changed, 43 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/sun4i-wdt.txt b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt index ecd650adff3..e39cb266c8f 100644 --- a/Documentation/devicetree/bindings/watchdog/sun4i-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/sunxi-wdt.txt @@ -1,8 +1,9 @@ -Allwinner sun4i Watchdog timer +Allwinner SoCs Watchdog timer Required properties: -- compatible : should be "allwinner,sun4i-wdt" +- compatible : should be "allwinner,<soc-family>-wdt", the currently supported + SoC families being sun4i and sun6i - reg : Specifies base physical address and size of the registers. Example: diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 11326d9f13d..223995e0481 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -27,10 +27,19 @@ #include <asm/system_misc.h> #define SUN4I_WATCHDOG_CTRL_REG 0x00 -#define SUN4I_WATCHDOG_CTRL_RESTART (1 << 0) +#define SUN4I_WATCHDOG_CTRL_RESTART BIT(0) #define SUN4I_WATCHDOG_MODE_REG 0x04 -#define SUN4I_WATCHDOG_MODE_ENABLE (1 << 0) -#define SUN4I_WATCHDOG_MODE_RESET_ENABLE (1 << 1) +#define SUN4I_WATCHDOG_MODE_ENABLE BIT(0) +#define SUN4I_WATCHDOG_MODE_RESET_ENABLE BIT(1) + +#define SUN6I_WATCHDOG1_IRQ_REG 0x00 +#define SUN6I_WATCHDOG1_CTRL_REG 0x10 +#define SUN6I_WATCHDOG1_CTRL_RESTART BIT(0) +#define SUN6I_WATCHDOG1_CONFIG_REG 0x14 +#define SUN6I_WATCHDOG1_CONFIG_RESTART BIT(0) +#define SUN6I_WATCHDOG1_CONFIG_IRQ BIT(1) +#define SUN6I_WATCHDOG1_MODE_REG 0x18 +#define SUN6I_WATCHDOG1_MODE_ENABLE BIT(0) static void __iomem *wdt_base; @@ -56,8 +65,36 @@ static void sun4i_restart(enum reboot_mode mode, const char *cmd) } } +static void sun6i_restart(enum reboot_mode mode, const char *cmd) +{ + if (!wdt_base) + return; + + /* Disable interrupts */ + writel(0, wdt_base + SUN6I_WATCHDOG1_IRQ_REG); + + /* We want to disable the IRQ and just reset the whole system */ + writel(SUN6I_WATCHDOG1_CONFIG_RESTART, + wdt_base + SUN6I_WATCHDOG1_CONFIG_REG); + + /* Enable timer. The default and lowest interval value is 0.5s */ + writel(SUN6I_WATCHDOG1_MODE_ENABLE, + wdt_base + SUN6I_WATCHDOG1_MODE_REG); + + /* Restart the watchdog. */ + writel(SUN6I_WATCHDOG1_CTRL_RESTART, + wdt_base + SUN6I_WATCHDOG1_CTRL_REG); + + while (1) { + mdelay(5); + writel(SUN6I_WATCHDOG1_MODE_ENABLE, + wdt_base + SUN6I_WATCHDOG1_MODE_REG); + } +} + static struct of_device_id sunxi_restart_ids[] = { { .compatible = "allwinner,sun4i-wdt", .data = sun4i_restart }, + { .compatible = "allwinner,sun6i-wdt", .data = sun6i_restart }, { /*sentinel*/ } }; |