diff options
Diffstat (limited to 'arch/arm/mach-sunxi/sunxi.c')
-rw-r--r-- | arch/arm/mach-sunxi/sunxi.c | 74 |
1 files changed, 46 insertions, 28 deletions
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 23afb732cb40..706ce35396b8 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c | |||
@@ -10,63 +10,77 @@ | |||
10 | * warranty of any kind, whether express or implied. | 10 | * warranty of any kind, whether express or implied. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/clocksource.h> | ||
13 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/irqchip.h> | ||
16 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
17 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
18 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
19 | #include <linux/io.h> | 21 | #include <linux/io.h> |
20 | #include <linux/sunxi_timer.h> | ||
21 | 22 | ||
22 | #include <linux/irqchip/sunxi.h> | 23 | #include <linux/clk/sunxi.h> |
23 | 24 | ||
24 | #include <asm/mach/arch.h> | 25 | #include <asm/mach/arch.h> |
25 | #include <asm/mach/map.h> | 26 | #include <asm/mach/map.h> |
27 | #include <asm/system_misc.h> | ||
26 | 28 | ||
27 | #include "sunxi.h" | 29 | #include "sunxi.h" |
28 | 30 | ||
29 | #define WATCHDOG_CTRL_REG 0x00 | 31 | #define SUN4I_WATCHDOG_CTRL_REG 0x00 |
30 | #define WATCHDOG_CTRL_RESTART (1 << 0) | 32 | #define SUN4I_WATCHDOG_CTRL_RESTART (1 << 0) |
31 | #define WATCHDOG_MODE_REG 0x04 | 33 | #define SUN4I_WATCHDOG_MODE_REG 0x04 |
32 | #define WATCHDOG_MODE_ENABLE (1 << 0) | 34 | #define SUN4I_WATCHDOG_MODE_ENABLE (1 << 0) |
33 | #define WATCHDOG_MODE_RESET_ENABLE (1 << 1) | 35 | #define SUN4I_WATCHDOG_MODE_RESET_ENABLE (1 << 1) |
34 | 36 | ||
35 | static void __iomem *wdt_base; | 37 | static void __iomem *wdt_base; |
36 | 38 | ||
37 | static void sunxi_setup_restart(void) | 39 | static void sun4i_restart(char mode, const char *cmd) |
38 | { | ||
39 | struct device_node *np = of_find_compatible_node(NULL, NULL, | ||
40 | "allwinner,sunxi-wdt"); | ||
41 | if (WARN(!np, "unable to setup watchdog restart")) | ||
42 | return; | ||
43 | |||
44 | wdt_base = of_iomap(np, 0); | ||
45 | WARN(!wdt_base, "failed to map watchdog base address"); | ||
46 | } | ||
47 | |||
48 | static void sunxi_restart(char mode, const char *cmd) | ||
49 | { | 40 | { |
50 | if (!wdt_base) | 41 | if (!wdt_base) |
51 | return; | 42 | return; |
52 | 43 | ||
53 | /* Enable timer and set reset bit in the watchdog */ | 44 | /* Enable timer and set reset bit in the watchdog */ |
54 | writel(WATCHDOG_MODE_ENABLE | WATCHDOG_MODE_RESET_ENABLE, | 45 | writel(SUN4I_WATCHDOG_MODE_ENABLE | SUN4I_WATCHDOG_MODE_RESET_ENABLE, |
55 | wdt_base + WATCHDOG_MODE_REG); | 46 | wdt_base + SUN4I_WATCHDOG_MODE_REG); |
56 | 47 | ||
57 | /* | 48 | /* |
58 | * Restart the watchdog. The default (and lowest) interval | 49 | * Restart the watchdog. The default (and lowest) interval |
59 | * value for the watchdog is 0.5s. | 50 | * value for the watchdog is 0.5s. |
60 | */ | 51 | */ |
61 | writel(WATCHDOG_CTRL_RESTART, wdt_base + WATCHDOG_CTRL_REG); | 52 | writel(SUN4I_WATCHDOG_CTRL_RESTART, wdt_base + SUN4I_WATCHDOG_CTRL_REG); |
62 | 53 | ||
63 | while (1) { | 54 | while (1) { |
64 | mdelay(5); | 55 | mdelay(5); |
65 | writel(WATCHDOG_MODE_ENABLE | WATCHDOG_MODE_RESET_ENABLE, | 56 | writel(SUN4I_WATCHDOG_MODE_ENABLE | SUN4I_WATCHDOG_MODE_RESET_ENABLE, |
66 | wdt_base + WATCHDOG_MODE_REG); | 57 | wdt_base + SUN4I_WATCHDOG_MODE_REG); |
67 | } | 58 | } |
68 | } | 59 | } |
69 | 60 | ||
61 | static struct of_device_id sunxi_restart_ids[] = { | ||
62 | { .compatible = "allwinner,sun4i-wdt", .data = sun4i_restart }, | ||
63 | { /*sentinel*/ } | ||
64 | }; | ||
65 | |||
66 | static void sunxi_setup_restart(void) | ||
67 | { | ||
68 | const struct of_device_id *of_id; | ||
69 | struct device_node *np; | ||
70 | |||
71 | np = of_find_matching_node(NULL, sunxi_restart_ids); | ||
72 | if (WARN(!np, "unable to setup watchdog restart")) | ||
73 | return; | ||
74 | |||
75 | wdt_base = of_iomap(np, 0); | ||
76 | WARN(!wdt_base, "failed to map watchdog base address"); | ||
77 | |||
78 | of_id = of_match_node(sunxi_restart_ids, np); | ||
79 | WARN(!of_id, "restart function not available"); | ||
80 | |||
81 | arm_pm_restart = of_id->data; | ||
82 | } | ||
83 | |||
70 | static struct map_desc sunxi_io_desc[] __initdata = { | 84 | static struct map_desc sunxi_io_desc[] __initdata = { |
71 | { | 85 | { |
72 | .virtual = (unsigned long) SUNXI_REGS_VIRT_BASE, | 86 | .virtual = (unsigned long) SUNXI_REGS_VIRT_BASE, |
@@ -81,6 +95,12 @@ void __init sunxi_map_io(void) | |||
81 | iotable_init(sunxi_io_desc, ARRAY_SIZE(sunxi_io_desc)); | 95 | iotable_init(sunxi_io_desc, ARRAY_SIZE(sunxi_io_desc)); |
82 | } | 96 | } |
83 | 97 | ||
98 | static void __init sunxi_timer_init(void) | ||
99 | { | ||
100 | sunxi_init_clocks(); | ||
101 | clocksource_of_init(); | ||
102 | } | ||
103 | |||
84 | static void __init sunxi_dt_init(void) | 104 | static void __init sunxi_dt_init(void) |
85 | { | 105 | { |
86 | sunxi_setup_restart(); | 106 | sunxi_setup_restart(); |
@@ -97,9 +117,7 @@ static const char * const sunxi_board_dt_compat[] = { | |||
97 | DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)") | 117 | DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)") |
98 | .init_machine = sunxi_dt_init, | 118 | .init_machine = sunxi_dt_init, |
99 | .map_io = sunxi_map_io, | 119 | .map_io = sunxi_map_io, |
100 | .init_irq = sunxi_init_irq, | 120 | .init_irq = irqchip_init, |
101 | .handle_irq = sunxi_handle_irq, | 121 | .init_time = sunxi_timer_init, |
102 | .restart = sunxi_restart, | ||
103 | .init_time = &sunxi_timer_init, | ||
104 | .dt_compat = sunxi_board_dt_compat, | 122 | .dt_compat = sunxi_board_dt_compat, |
105 | MACHINE_END | 123 | MACHINE_END |