diff options
Diffstat (limited to 'arch/mips/lantiq/xway/reset.c')
-rw-r--r-- | arch/mips/lantiq/xway/reset.c | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c index 8b66bd87f0c1..22c55f73aa9d 100644 --- a/arch/mips/lantiq/xway/reset.c +++ b/arch/mips/lantiq/xway/reset.c | |||
@@ -11,26 +11,31 @@ | |||
11 | #include <linux/ioport.h> | 11 | #include <linux/ioport.h> |
12 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
14 | #include <linux/delay.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | |||
14 | #include <asm/reboot.h> | 18 | #include <asm/reboot.h> |
15 | 19 | ||
16 | #include <lantiq_soc.h> | 20 | #include <lantiq_soc.h> |
17 | 21 | ||
22 | #include "../prom.h" | ||
23 | |||
18 | #define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y)) | 24 | #define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y)) |
19 | #define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x)) | 25 | #define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x)) |
20 | 26 | ||
21 | /* register definitions */ | 27 | /* reset request register */ |
22 | #define LTQ_RCU_RST 0x0010 | 28 | #define RCU_RST_REQ 0x0010 |
23 | #define LTQ_RCU_RST_ALL 0x40000000 | 29 | /* reset status register */ |
24 | 30 | #define RCU_RST_STAT 0x0014 | |
25 | #define LTQ_RCU_RST_STAT 0x0014 | ||
26 | #define LTQ_RCU_STAT_SHIFT 26 | ||
27 | 31 | ||
28 | static struct resource ltq_rcu_resource = { | 32 | /* reboot bit */ |
29 | .name = "rcu", | 33 | #define RCU_RD_SRST BIT(30) |
30 | .start = LTQ_RCU_BASE_ADDR, | 34 | /* reset cause */ |
31 | .end = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1, | 35 | #define RCU_STAT_SHIFT 26 |
32 | .flags = IORESOURCE_MEM, | 36 | /* boot selection */ |
33 | }; | 37 | #define RCU_BOOT_SEL_SHIFT 26 |
38 | #define RCU_BOOT_SEL_MASK 0x7 | ||
34 | 39 | ||
35 | /* remapped base addr of the reset control unit */ | 40 | /* remapped base addr of the reset control unit */ |
36 | static void __iomem *ltq_rcu_membase; | 41 | static void __iomem *ltq_rcu_membase; |
@@ -38,48 +43,64 @@ static void __iomem *ltq_rcu_membase; | |||
38 | /* This function is used by the watchdog driver */ | 43 | /* This function is used by the watchdog driver */ |
39 | int ltq_reset_cause(void) | 44 | int ltq_reset_cause(void) |
40 | { | 45 | { |
41 | u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT); | 46 | u32 val = ltq_rcu_r32(RCU_RST_STAT); |
42 | return val >> LTQ_RCU_STAT_SHIFT; | 47 | return val >> RCU_STAT_SHIFT; |
43 | } | 48 | } |
44 | EXPORT_SYMBOL_GPL(ltq_reset_cause); | 49 | EXPORT_SYMBOL_GPL(ltq_reset_cause); |
45 | 50 | ||
51 | /* allow platform code to find out what source we booted from */ | ||
52 | unsigned char ltq_boot_select(void) | ||
53 | { | ||
54 | u32 val = ltq_rcu_r32(RCU_RST_STAT); | ||
55 | return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK; | ||
56 | } | ||
57 | |||
58 | /* reset a io domain for u micro seconds */ | ||
59 | void ltq_reset_once(unsigned int module, ulong u) | ||
60 | { | ||
61 | ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ); | ||
62 | udelay(u); | ||
63 | ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ); | ||
64 | } | ||
65 | |||
46 | static void ltq_machine_restart(char *command) | 66 | static void ltq_machine_restart(char *command) |
47 | { | 67 | { |
48 | pr_notice("System restart\n"); | ||
49 | local_irq_disable(); | 68 | local_irq_disable(); |
50 | ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST); | 69 | ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ); |
51 | unreachable(); | 70 | unreachable(); |
52 | } | 71 | } |
53 | 72 | ||
54 | static void ltq_machine_halt(void) | 73 | static void ltq_machine_halt(void) |
55 | { | 74 | { |
56 | pr_notice("System halted.\n"); | ||
57 | local_irq_disable(); | 75 | local_irq_disable(); |
58 | unreachable(); | 76 | unreachable(); |
59 | } | 77 | } |
60 | 78 | ||
61 | static void ltq_machine_power_off(void) | 79 | static void ltq_machine_power_off(void) |
62 | { | 80 | { |
63 | pr_notice("Please turn off the power now.\n"); | ||
64 | local_irq_disable(); | 81 | local_irq_disable(); |
65 | unreachable(); | 82 | unreachable(); |
66 | } | 83 | } |
67 | 84 | ||
68 | static int __init mips_reboot_setup(void) | 85 | static int __init mips_reboot_setup(void) |
69 | { | 86 | { |
70 | /* insert and request the memory region */ | 87 | struct resource res; |
71 | if (insert_resource(&iomem_resource, <q_rcu_resource) < 0) | 88 | struct device_node *np = |
72 | panic("Failed to insert rcu memory"); | 89 | of_find_compatible_node(NULL, NULL, "lantiq,rcu-xway"); |
90 | |||
91 | /* check if all the reset register range is available */ | ||
92 | if (!np) | ||
93 | panic("Failed to load reset resources from devicetree"); | ||
94 | |||
95 | if (of_address_to_resource(np, 0, &res)) | ||
96 | panic("Failed to get rcu memory range"); | ||
73 | 97 | ||
74 | if (request_mem_region(ltq_rcu_resource.start, | 98 | if (request_mem_region(res.start, resource_size(&res), res.name) < 0) |
75 | resource_size(<q_rcu_resource), "rcu") < 0) | 99 | pr_err("Failed to request rcu memory"); |
76 | panic("Failed to request rcu memory"); | ||
77 | 100 | ||
78 | /* remap rcu register range */ | 101 | ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res)); |
79 | ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start, | ||
80 | resource_size(<q_rcu_resource)); | ||
81 | if (!ltq_rcu_membase) | 102 | if (!ltq_rcu_membase) |
82 | panic("Failed to remap rcu memory"); | 103 | panic("Failed to remap core memory"); |
83 | 104 | ||
84 | _machine_restart = ltq_machine_restart; | 105 | _machine_restart = ltq_machine_restart; |
85 | _machine_halt = ltq_machine_halt; | 106 | _machine_halt = ltq_machine_halt; |