aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2015-08-05 05:09:02 -0400
committerOlof Johansson <olof@lixom.net>2015-08-05 05:09:02 -0400
commitf9fa55b97090bdc70683c96d425759ae3958ce24 (patch)
tree1fe949877012dfe5e31fc376426ded83e56d325b
parentb69354dfe25bf0b103ef3ed6c881d34cc442265c (diff)
parent482d638f98cc626bf01d4c9f6d6d35fc77d630c8 (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.c29
-rw-r--r--arch/arm/mach-mvebu/common.h4
-rw-r--r--arch/arm/mach-mvebu/pm-board.c30
-rw-r--r--arch/arm/mach-mvebu/pm.c79
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[] = {
65int ll_enable_coherency(void); 65int ll_enable_coherency(void);
66void ll_add_cpu_to_smp_group(void); 66void ll_add_cpu_to_smp_group(void);
67 67
68int 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
80static int mvebu_hwcc_notifier(struct notifier_block *nb, 68static 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
197int 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
209int coherency_available(void) 214int 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
26void __iomem *mvebu_get_scu_base(void); 26void __iomem *mvebu_get_scu_base(void);
27 27
28int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)); 28int 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
25static void __iomem *gpio_ctrl; 25static void __iomem *gpio_ctrl;
26static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; 26static int pic_gpios[ARMADA_PIC_NR_GPIOS];
27static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS]; 27static int pic_raw_gpios[ARMADA_PIC_NR_GPIOS];
28 28
29static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd) 29static 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
79static int mvebu_armada_xp_gp_pm_init(void) 79static 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
139out: 139out:
140 of_node_put(np); 140 of_node_put(np);
141 return ret; 141 return ret;
142} 142}
143 143
144late_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 */
152device_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
108static void mvebu_pm_store_bootinfo(void) 108static 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
154static int mvebu_pm_enter(suspend_state_t state) 152static 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
166static 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
188static 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
203static 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
175static const struct platform_suspend_ops mvebu_pm_ops = { 214static 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
180int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd)) 219static 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
233late_initcall(mvebu_pm_init);
234
235int __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}