diff options
Diffstat (limited to 'arch/arm/mach-picoxcell/common.c')
-rw-r--r-- | arch/arm/mach-picoxcell/common.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c index febee47bc116..a2e8ae8b5821 100644 --- a/arch/arm/mach-picoxcell/common.c +++ b/arch/arm/mach-picoxcell/common.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * All enquiries to support@picochip.com | 8 | * All enquiries to support@picochip.com |
9 | */ | 9 | */ |
10 | #include <linux/delay.h> | ||
10 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
11 | #include <linux/irqdomain.h> | 12 | #include <linux/irqdomain.h> |
12 | #include <linux/of.h> | 13 | #include <linux/of.h> |
@@ -23,6 +24,26 @@ | |||
23 | 24 | ||
24 | #include "common.h" | 25 | #include "common.h" |
25 | 26 | ||
27 | #define WDT_CTRL_REG_EN_MASK (1 << 0) | ||
28 | #define WDT_CTRL_REG_OFFS (0x00) | ||
29 | #define WDT_TIMEOUT_REG_OFFS (0x04) | ||
30 | static void __iomem *wdt_regs; | ||
31 | |||
32 | /* | ||
33 | * The machine restart method can be called from an atomic context so we won't | ||
34 | * be able to ioremap the regs then. | ||
35 | */ | ||
36 | static void picoxcell_setup_restart(void) | ||
37 | { | ||
38 | struct device_node *np = of_find_compatible_node(NULL, NULL, | ||
39 | "snps,dw-apb-wdg"); | ||
40 | if (WARN(!np, "unable to setup watchdog restart")) | ||
41 | return; | ||
42 | |||
43 | wdt_regs = of_iomap(np, 0); | ||
44 | WARN(!wdt_regs, "failed to remap watchdog regs"); | ||
45 | } | ||
46 | |||
26 | static struct map_desc io_map __initdata = { | 47 | static struct map_desc io_map __initdata = { |
27 | .virtual = PHYS_TO_IO(PICOXCELL_PERIPH_BASE), | 48 | .virtual = PHYS_TO_IO(PICOXCELL_PERIPH_BASE), |
28 | .pfn = __phys_to_pfn(PICOXCELL_PERIPH_BASE), | 49 | .pfn = __phys_to_pfn(PICOXCELL_PERIPH_BASE), |
@@ -38,6 +59,7 @@ static void __init picoxcell_map_io(void) | |||
38 | static void __init picoxcell_init_machine(void) | 59 | static void __init picoxcell_init_machine(void) |
39 | { | 60 | { |
40 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | 61 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); |
62 | picoxcell_setup_restart(); | ||
41 | } | 63 | } |
42 | 64 | ||
43 | static const char *picoxcell_dt_match[] = { | 65 | static const char *picoxcell_dt_match[] = { |
@@ -56,6 +78,20 @@ static void __init picoxcell_init_irq(void) | |||
56 | of_irq_init(vic_of_match); | 78 | of_irq_init(vic_of_match); |
57 | } | 79 | } |
58 | 80 | ||
81 | static void picoxcell_wdt_restart(char mode, const char *cmd) | ||
82 | { | ||
83 | /* | ||
84 | * Configure the watchdog to reset with the shortest possible timeout | ||
85 | * and give it chance to do the reset. | ||
86 | */ | ||
87 | if (wdt_regs) { | ||
88 | writel_relaxed(WDT_CTRL_REG_EN_MASK, wdt_regs + WDT_CTRL_REG_OFFS); | ||
89 | writel_relaxed(0, wdt_regs + WDT_TIMEOUT_REG_OFFS); | ||
90 | /* No sleeping, possibly atomic. */ | ||
91 | mdelay(500); | ||
92 | } | ||
93 | } | ||
94 | |||
59 | DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") | 95 | DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") |
60 | .map_io = picoxcell_map_io, | 96 | .map_io = picoxcell_map_io, |
61 | .nr_irqs = NR_IRQS_LEGACY, | 97 | .nr_irqs = NR_IRQS_LEGACY, |
@@ -64,4 +100,5 @@ DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") | |||
64 | .timer = &picoxcell_timer, | 100 | .timer = &picoxcell_timer, |
65 | .init_machine = picoxcell_init_machine, | 101 | .init_machine = picoxcell_init_machine, |
66 | .dt_compat = picoxcell_dt_match, | 102 | .dt_compat = picoxcell_dt_match, |
103 | .restart = picoxcell_wdt_restart, | ||
67 | MACHINE_END | 104 | MACHINE_END |