diff options
author | Olof Johansson <olof@lixom.net> | 2015-08-05 05:09:02 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2015-08-05 05:09:02 -0400 |
commit | f9fa55b97090bdc70683c96d425759ae3958ce24 (patch) | |
tree | 1fe949877012dfe5e31fc376426ded83e56d325b | |
parent | b69354dfe25bf0b103ef3ed6c881d34cc442265c (diff) | |
parent | 482d638f98cc626bf01d4c9f6d6d35fc77d630c8 (diff) |
Merge tag 'mvebu-soc-4.3-1' of git://git.infradead.org/linux-mvebu into next/soc
mvebu soc changes for v4.3 (part #1)
- Extend suspend to RAM support in order to add new mvebu SoC
- Add standby support for all Armada 3xx/XP SoCs
* tag 'mvebu-soc-4.3-1' of git://git.infradead.org/linux-mvebu:
ARM: mvebu: Warn about the wake-up sources not taken into account in suspend
ARM: mvebu: Add standby support
ARM: mvebu: Use __init for the PM initialization functions
ARM: mvebu: prepare pm-board.c for the introduction of Armada 38x support
ARM: mvebu: prepare mvebu_pm_store_bootinfo() to support multiple SoCs
ARM: mvebu: do not check machine in mvebu_pm_init()
ARM: mvebu: prepare set_cpu_coherent() for future extension
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | arch/arm/mach-mvebu/coherency.c | 29 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/common.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/pm-board.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/pm.c | 79 |
4 files changed, 103 insertions, 39 deletions
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index e46e9ea1e187..44eedf331ae7 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c | |||
@@ -65,18 +65,6 @@ static const struct of_device_id of_coherency_table[] = { | |||
65 | int ll_enable_coherency(void); | 65 | int ll_enable_coherency(void); |
66 | void ll_add_cpu_to_smp_group(void); | 66 | void ll_add_cpu_to_smp_group(void); |
67 | 67 | ||
68 | int set_cpu_coherent(void) | ||
69 | { | ||
70 | if (!coherency_base) { | ||
71 | pr_warn("Can't make current CPU cache coherent.\n"); | ||
72 | pr_warn("Coherency fabric is not initialized\n"); | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | ll_add_cpu_to_smp_group(); | ||
77 | return ll_enable_coherency(); | ||
78 | } | ||
79 | |||
80 | static int mvebu_hwcc_notifier(struct notifier_block *nb, | 68 | static int mvebu_hwcc_notifier(struct notifier_block *nb, |
81 | unsigned long event, void *__dev) | 69 | unsigned long event, void *__dev) |
82 | { | 70 | { |
@@ -206,6 +194,23 @@ static int coherency_type(void) | |||
206 | return type; | 194 | return type; |
207 | } | 195 | } |
208 | 196 | ||
197 | int set_cpu_coherent(void) | ||
198 | { | ||
199 | int type = coherency_type(); | ||
200 | |||
201 | if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) { | ||
202 | if (!coherency_base) { | ||
203 | pr_warn("Can't make current CPU cache coherent.\n"); | ||
204 | pr_warn("Coherency fabric is not initialized\n"); | ||
205 | return 1; | ||
206 | } | ||
207 | ll_add_cpu_to_smp_group(); | ||
208 | return ll_enable_coherency(); | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
209 | int coherency_available(void) | 214 | int coherency_available(void) |
210 | { | 215 | { |
211 | return coherency_type() != COHERENCY_FABRIC_TYPE_NONE; | 216 | return coherency_type() != COHERENCY_FABRIC_TYPE_NONE; |
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h index 3e0aca1f288a..6b775492cfad 100644 --- a/arch/arm/mach-mvebu/common.h +++ b/arch/arm/mach-mvebu/common.h | |||
@@ -25,6 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev); | |||
25 | 25 | ||
26 | void __iomem *mvebu_get_scu_base(void); | 26 | void __iomem *mvebu_get_scu_base(void); |
27 | 27 | ||
28 | int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)); | 28 | int mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg, |
29 | 29 | u32 srcmd)); | |
30 | #endif | 30 | #endif |
diff --git a/arch/arm/mach-mvebu/pm-board.c b/arch/arm/mach-mvebu/pm-board.c index 301ab38d38ba..db17121d7d63 100644 --- a/arch/arm/mach-mvebu/pm-board.c +++ b/arch/arm/mach-mvebu/pm-board.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Board-level suspend/resume support. | 2 | * Board-level suspend/resume support. |
3 | * | 3 | * |
4 | * Copyright (C) 2014 Marvell | 4 | * Copyright (C) 2014-2015 Marvell |
5 | * | 5 | * |
6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
7 | * | 7 | * |
@@ -20,27 +20,27 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include "common.h" | 21 | #include "common.h" |
22 | 22 | ||
23 | #define ARMADA_XP_GP_PIC_NR_GPIOS 3 | 23 | #define ARMADA_PIC_NR_GPIOS 3 |
24 | 24 | ||
25 | static void __iomem *gpio_ctrl; | 25 | static void __iomem *gpio_ctrl; |
26 | static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; | 26 | static int pic_gpios[ARMADA_PIC_NR_GPIOS]; |
27 | static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; | 27 | static int pic_raw_gpios[ARMADA_PIC_NR_GPIOS]; |
28 | 28 | ||
29 | static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd) | 29 | static void mvebu_armada_pm_enter(void __iomem *sdram_reg, u32 srcmd) |
30 | { | 30 | { |
31 | u32 reg, ackcmd; | 31 | u32 reg, ackcmd; |
32 | int i; | 32 | int i; |
33 | 33 | ||
34 | /* Put 001 as value on the GPIOs */ | 34 | /* Put 001 as value on the GPIOs */ |
35 | reg = readl(gpio_ctrl); | 35 | reg = readl(gpio_ctrl); |
36 | for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) | 36 | for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) |
37 | reg &= ~BIT(pic_raw_gpios[i]); | 37 | reg &= ~BIT(pic_raw_gpios[i]); |
38 | reg |= BIT(pic_raw_gpios[0]); | 38 | reg |= BIT(pic_raw_gpios[0]); |
39 | writel(reg, gpio_ctrl); | 39 | writel(reg, gpio_ctrl); |
40 | 40 | ||
41 | /* Prepare writing 111 to the GPIOs */ | 41 | /* Prepare writing 111 to the GPIOs */ |
42 | ackcmd = readl(gpio_ctrl); | 42 | ackcmd = readl(gpio_ctrl); |
43 | for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) | 43 | for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) |
44 | ackcmd |= BIT(pic_raw_gpios[i]); | 44 | ackcmd |= BIT(pic_raw_gpios[i]); |
45 | 45 | ||
46 | srcmd = cpu_to_le32(srcmd); | 46 | srcmd = cpu_to_le32(srcmd); |
@@ -76,7 +76,7 @@ static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd) | |||
76 | [ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1"); | 76 | [ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1"); |
77 | } | 77 | } |
78 | 78 | ||
79 | static int mvebu_armada_xp_gp_pm_init(void) | 79 | static int __init mvebu_armada_pm_init(void) |
80 | { | 80 | { |
81 | struct device_node *np; | 81 | struct device_node *np; |
82 | struct device_node *gpio_ctrl_np; | 82 | struct device_node *gpio_ctrl_np; |
@@ -89,7 +89,7 @@ static int mvebu_armada_xp_gp_pm_init(void) | |||
89 | if (!np) | 89 | if (!np) |
90 | return -ENODEV; | 90 | return -ENODEV; |
91 | 91 | ||
92 | for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) { | 92 | for (i = 0; i < ARMADA_PIC_NR_GPIOS; i++) { |
93 | char *name; | 93 | char *name; |
94 | struct of_phandle_args args; | 94 | struct of_phandle_args args; |
95 | 95 | ||
@@ -134,11 +134,19 @@ static int mvebu_armada_xp_gp_pm_init(void) | |||
134 | if (!gpio_ctrl) | 134 | if (!gpio_ctrl) |
135 | return -ENOMEM; | 135 | return -ENOMEM; |
136 | 136 | ||
137 | mvebu_pm_init(mvebu_armada_xp_gp_pm_enter); | 137 | mvebu_pm_suspend_init(mvebu_armada_pm_enter); |
138 | 138 | ||
139 | out: | 139 | out: |
140 | of_node_put(np); | 140 | of_node_put(np); |
141 | return ret; | 141 | return ret; |
142 | } | 142 | } |
143 | 143 | ||
144 | late_initcall(mvebu_armada_xp_gp_pm_init); | 144 | /* |
145 | * Registering the mvebu_board_pm_enter callback must be done before | ||
146 | * the platform_suspend_ops will be registered. In the same time we | ||
147 | * also need to have the gpio devices registered. That's why we use a | ||
148 | * device_initcall_sync which is called after all the device_initcall | ||
149 | * (used by the gpio device) but before the late_initcall (used to | ||
150 | * register the platform_suspend_ops) | ||
151 | */ | ||
152 | device_initcall_sync(mvebu_armada_pm_init); | ||
diff --git a/arch/arm/mach-mvebu/pm.c b/arch/arm/mach-mvebu/pm.c index 6573a8f11f70..8d32bf762b86 100644 --- a/arch/arm/mach-mvebu/pm.c +++ b/arch/arm/mach-mvebu/pm.c | |||
@@ -105,12 +105,10 @@ static phys_addr_t mvebu_internal_reg_base(void) | |||
105 | return of_translate_address(np, in_addr); | 105 | return of_translate_address(np, in_addr); |
106 | } | 106 | } |
107 | 107 | ||
108 | static void mvebu_pm_store_bootinfo(void) | 108 | static void mvebu_pm_store_armadaxp_bootinfo(u32 *store_addr) |
109 | { | 109 | { |
110 | u32 *store_addr; | ||
111 | phys_addr_t resume_pc; | 110 | phys_addr_t resume_pc; |
112 | 111 | ||
113 | store_addr = phys_to_virt(BOOT_INFO_ADDR); | ||
114 | resume_pc = virt_to_phys(armada_370_xp_cpu_resume); | 112 | resume_pc = virt_to_phys(armada_370_xp_cpu_resume); |
115 | 113 | ||
116 | /* | 114 | /* |
@@ -151,14 +149,30 @@ static void mvebu_pm_store_bootinfo(void) | |||
151 | writel(BOOT_MAGIC_LIST_END, store_addr); | 149 | writel(BOOT_MAGIC_LIST_END, store_addr); |
152 | } | 150 | } |
153 | 151 | ||
154 | static int mvebu_pm_enter(suspend_state_t state) | 152 | static int mvebu_pm_store_bootinfo(void) |
155 | { | 153 | { |
156 | if (state != PM_SUSPEND_MEM) | 154 | u32 *store_addr; |
157 | return -EINVAL; | 155 | |
156 | store_addr = phys_to_virt(BOOT_INFO_ADDR); | ||
157 | |||
158 | if (of_machine_is_compatible("marvell,armadaxp")) | ||
159 | mvebu_pm_store_armadaxp_bootinfo(store_addr); | ||
160 | else | ||
161 | return -ENODEV; | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int mvebu_enter_suspend(void) | ||
167 | { | ||
168 | int ret; | ||
169 | |||
170 | ret = mvebu_pm_store_bootinfo(); | ||
171 | if (ret) | ||
172 | return ret; | ||
158 | 173 | ||
159 | cpu_pm_enter(); | 174 | cpu_pm_enter(); |
160 | 175 | ||
161 | mvebu_pm_store_bootinfo(); | ||
162 | cpu_suspend(0, mvebu_pm_powerdown); | 176 | cpu_suspend(0, mvebu_pm_powerdown); |
163 | 177 | ||
164 | outer_resume(); | 178 | outer_resume(); |
@@ -168,23 +182,62 @@ static int mvebu_pm_enter(suspend_state_t state) | |||
168 | set_cpu_coherent(); | 182 | set_cpu_coherent(); |
169 | 183 | ||
170 | cpu_pm_exit(); | 184 | cpu_pm_exit(); |
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int mvebu_pm_enter(suspend_state_t state) | ||
189 | { | ||
190 | switch (state) { | ||
191 | case PM_SUSPEND_STANDBY: | ||
192 | cpu_do_idle(); | ||
193 | break; | ||
194 | case PM_SUSPEND_MEM: | ||
195 | pr_warn("Entering suspend to RAM. Only special wake-up sources will resume the system\n"); | ||
196 | return mvebu_enter_suspend(); | ||
197 | default: | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int mvebu_pm_valid(suspend_state_t state) | ||
204 | { | ||
205 | if (state == PM_SUSPEND_STANDBY) | ||
206 | return 1; | ||
207 | |||
208 | if (state == PM_SUSPEND_MEM && mvebu_board_pm_enter != NULL) | ||
209 | return 1; | ||
171 | 210 | ||
172 | return 0; | 211 | return 0; |
173 | } | 212 | } |
174 | 213 | ||
175 | static const struct platform_suspend_ops mvebu_pm_ops = { | 214 | static const struct platform_suspend_ops mvebu_pm_ops = { |
176 | .enter = mvebu_pm_enter, | 215 | .enter = mvebu_pm_enter, |
177 | .valid = suspend_valid_only_mem, | 216 | .valid = mvebu_pm_valid, |
178 | }; | 217 | }; |
179 | 218 | ||
180 | int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)) | 219 | static int __init mvebu_pm_init(void) |
220 | { | ||
221 | if (!of_machine_is_compatible("marvell,armadaxp") && | ||
222 | !of_machine_is_compatible("marvell,armada370") && | ||
223 | !of_machine_is_compatible("marvell,armada380") && | ||
224 | !of_machine_is_compatible("marvell,armada390")) | ||
225 | return -ENODEV; | ||
226 | |||
227 | suspend_set_ops(&mvebu_pm_ops); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | |||
233 | late_initcall(mvebu_pm_init); | ||
234 | |||
235 | int __init mvebu_pm_suspend_init(void (*board_pm_enter)(void __iomem *sdram_reg, | ||
236 | u32 srcmd)) | ||
181 | { | 237 | { |
182 | struct device_node *np; | 238 | struct device_node *np; |
183 | struct resource res; | 239 | struct resource res; |
184 | 240 | ||
185 | if (!of_machine_is_compatible("marvell,armadaxp")) | ||
186 | return -ENODEV; | ||
187 | |||
188 | np = of_find_compatible_node(NULL, NULL, | 241 | np = of_find_compatible_node(NULL, NULL, |
189 | "marvell,armada-xp-sdram-controller"); | 242 | "marvell,armada-xp-sdram-controller"); |
190 | if (!np) | 243 | if (!np) |
@@ -212,7 +265,5 @@ int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)) | |||
212 | 265 | ||
213 | mvebu_board_pm_enter = board_pm_enter; | 266 | mvebu_board_pm_enter = board_pm_enter; |
214 | 267 | ||
215 | suspend_set_ops(&mvebu_pm_ops); | ||
216 | |||
217 | return 0; | 268 | return 0; |
218 | } | 269 | } |