diff options
Diffstat (limited to 'arch/arm/mach-bcm2835/bcm2835.c')
-rw-r--r-- | arch/arm/mach-bcm2835/bcm2835.c | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c index f6fea4933571..f0d739f4b7a3 100644 --- a/arch/arm/mach-bcm2835/bcm2835.c +++ b/arch/arm/mach-bcm2835/bcm2835.c | |||
@@ -12,8 +12,10 @@ | |||
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/delay.h> | ||
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
16 | #include <linux/irqchip/bcm2835.h> | 17 | #include <linux/irqchip/bcm2835.h> |
18 | #include <linux/of_address.h> | ||
17 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
18 | #include <linux/bcm2835_timer.h> | 20 | #include <linux/bcm2835_timer.h> |
19 | #include <linux/clk/bcm2835.h> | 21 | #include <linux/clk/bcm2835.h> |
@@ -23,6 +25,48 @@ | |||
23 | 25 | ||
24 | #include <mach/bcm2835_soc.h> | 26 | #include <mach/bcm2835_soc.h> |
25 | 27 | ||
28 | #define PM_RSTC 0x1c | ||
29 | #define PM_WDOG 0x24 | ||
30 | |||
31 | #define PM_PASSWORD 0x5a000000 | ||
32 | #define PM_RSTC_WRCFG_MASK 0x00000030 | ||
33 | #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 | ||
34 | |||
35 | static void __iomem *wdt_regs; | ||
36 | |||
37 | /* | ||
38 | * The machine restart method can be called from an atomic context so we won't | ||
39 | * be able to ioremap the regs then. | ||
40 | */ | ||
41 | static void bcm2835_setup_restart(void) | ||
42 | { | ||
43 | struct device_node *np = of_find_compatible_node(NULL, NULL, | ||
44 | "brcm,bcm2835-pm-wdt"); | ||
45 | if (WARN(!np, "unable to setup watchdog restart")) | ||
46 | return; | ||
47 | |||
48 | wdt_regs = of_iomap(np, 0); | ||
49 | WARN(!wdt_regs, "failed to remap watchdog regs"); | ||
50 | } | ||
51 | |||
52 | static void bcm2835_restart(char mode, const char *cmd) | ||
53 | { | ||
54 | u32 val; | ||
55 | |||
56 | if (!wdt_regs) | ||
57 | return; | ||
58 | |||
59 | /* use a timeout of 10 ticks (~150us) */ | ||
60 | writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG); | ||
61 | val = readl_relaxed(wdt_regs + PM_RSTC); | ||
62 | val &= ~PM_RSTC_WRCFG_MASK; | ||
63 | val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; | ||
64 | writel_relaxed(val, wdt_regs + PM_RSTC); | ||
65 | |||
66 | /* No sleeping, possibly atomic. */ | ||
67 | mdelay(1); | ||
68 | } | ||
69 | |||
26 | static struct map_desc io_map __initdata = { | 70 | static struct map_desc io_map __initdata = { |
27 | .virtual = BCM2835_PERIPH_VIRT, | 71 | .virtual = BCM2835_PERIPH_VIRT, |
28 | .pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS), | 72 | .pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS), |
@@ -30,15 +74,16 @@ static struct map_desc io_map __initdata = { | |||
30 | .type = MT_DEVICE | 74 | .type = MT_DEVICE |
31 | }; | 75 | }; |
32 | 76 | ||
33 | void __init bcm2835_map_io(void) | 77 | static void __init bcm2835_map_io(void) |
34 | { | 78 | { |
35 | iotable_init(&io_map, 1); | 79 | iotable_init(&io_map, 1); |
36 | } | 80 | } |
37 | 81 | ||
38 | void __init bcm2835_init(void) | 82 | static void __init bcm2835_init(void) |
39 | { | 83 | { |
40 | int ret; | 84 | int ret; |
41 | 85 | ||
86 | bcm2835_setup_restart(); | ||
42 | bcm2835_init_clocks(); | 87 | bcm2835_init_clocks(); |
43 | 88 | ||
44 | ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, | 89 | ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, |
@@ -60,5 +105,6 @@ DT_MACHINE_START(BCM2835, "BCM2835") | |||
60 | .handle_irq = bcm2835_handle_irq, | 105 | .handle_irq = bcm2835_handle_irq, |
61 | .init_machine = bcm2835_init, | 106 | .init_machine = bcm2835_init, |
62 | .timer = &bcm2835_timer, | 107 | .timer = &bcm2835_timer, |
108 | .restart = bcm2835_restart, | ||
63 | .dt_compat = bcm2835_compat | 109 | .dt_compat = bcm2835_compat |
64 | MACHINE_END | 110 | MACHINE_END |