diff options
author | Olof Johansson <olof@lixom.net> | 2015-01-21 20:19:05 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2015-01-21 20:19:05 -0500 |
commit | f50f7070e5de59a168e45831c1e667f04583f563 (patch) | |
tree | d8116eb25aebc6f1ffd3fb043142252bf708c269 | |
parent | a71596933cf792dacc3c5080df298c0fccef1d94 (diff) | |
parent | 1632ff162f305f38667632c465e4bfaab8ef87a2 (diff) |
Merge tag 'renesas-soc3-for-v3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/soc
Merge "Third Round of Renesas ARM Based SoC Updates for v3.20" from Simon
Horman:
* Special-case PM domains with memory-controllers
* tag 'renesas-soc3-for-v3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas:
ARM: shmobile: R-Mobile: Special-case PM domains with memory-controllers
ARM: shmobile: R-Mobile: Generalize adding/looking up special PM domains
ARM: shmobile: R-Mobile: Consolidate rmobile_pd_suspend_*()
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | arch/arm/mach-shmobile/pm-rmobile.c | 155 |
1 files changed, 97 insertions, 58 deletions
diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index 85a7fdd9823b..95018209ff0b 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c | |||
@@ -200,11 +200,10 @@ void rmobile_add_devices_to_domains(struct pm_domain_device data[], | |||
200 | 200 | ||
201 | #else /* !CONFIG_ARCH_SHMOBILE_LEGACY */ | 201 | #else /* !CONFIG_ARCH_SHMOBILE_LEGACY */ |
202 | 202 | ||
203 | static int rmobile_pd_suspend_cpu(void) | 203 | static int rmobile_pd_suspend_busy(void) |
204 | { | 204 | { |
205 | /* | 205 | /* |
206 | * This domain contains the CPU core and therefore it should | 206 | * This domain should not be turned off. |
207 | * only be turned off if the CPU is not in use. | ||
208 | */ | 207 | */ |
209 | return -EBUSY; | 208 | return -EBUSY; |
210 | } | 209 | } |
@@ -218,83 +217,95 @@ static int rmobile_pd_suspend_console(void) | |||
218 | return console_suspend_enabled ? 0 : -EBUSY; | 217 | return console_suspend_enabled ? 0 : -EBUSY; |
219 | } | 218 | } |
220 | 219 | ||
221 | static int rmobile_pd_suspend_debug(void) | 220 | enum pd_types { |
222 | { | 221 | PD_NORMAL, |
223 | /* | 222 | PD_CPU, |
224 | * This domain contains the Coresight-ETM hardware block and | 223 | PD_CONSOLE, |
225 | * therefore it should only be turned off if the debug module is | 224 | PD_DEBUG, |
226 | * not in use. | 225 | PD_MEMCTL, |
227 | */ | 226 | }; |
228 | return -EBUSY; | ||
229 | } | ||
230 | 227 | ||
231 | #define MAX_NUM_CPU_PDS 8 | 228 | #define MAX_NUM_SPECIAL_PDS 16 |
232 | 229 | ||
233 | static unsigned int num_cpu_pds __initdata; | 230 | static struct special_pd { |
234 | static struct device_node *cpu_pds[MAX_NUM_CPU_PDS] __initdata; | 231 | struct device_node *pd; |
235 | static struct device_node *console_pd __initdata; | 232 | enum pd_types type; |
236 | static struct device_node *debug_pd __initdata; | 233 | } special_pds[MAX_NUM_SPECIAL_PDS] __initdata; |
237 | 234 | ||
238 | static void __init get_special_pds(void) | 235 | static unsigned int num_special_pds __initdata; |
236 | |||
237 | static const struct of_device_id special_ids[] __initconst = { | ||
238 | { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG }, | ||
239 | { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, }, | ||
240 | { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, }, | ||
241 | { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, }, | ||
242 | { /* sentinel */ }, | ||
243 | }; | ||
244 | |||
245 | static void __init add_special_pd(struct device_node *np, enum pd_types type) | ||
239 | { | 246 | { |
240 | struct device_node *np, *pd; | ||
241 | unsigned int i; | 247 | unsigned int i; |
248 | struct device_node *pd; | ||
242 | 249 | ||
243 | /* PM domains containing CPUs */ | 250 | pd = of_parse_phandle(np, "power-domains", 0); |
244 | for_each_node_by_type(np, "cpu") { | 251 | if (!pd) |
245 | pd = of_parse_phandle(np, "power-domains", 0); | 252 | return; |
246 | if (!pd) | ||
247 | continue; | ||
248 | |||
249 | for (i = 0; i < num_cpu_pds; i++) | ||
250 | if (pd == cpu_pds[i]) | ||
251 | break; | ||
252 | 253 | ||
253 | if (i < num_cpu_pds) { | 254 | for (i = 0; i < num_special_pds; i++) |
255 | if (pd == special_pds[i].pd && type == special_pds[i].type) { | ||
254 | of_node_put(pd); | 256 | of_node_put(pd); |
255 | continue; | 257 | return; |
256 | } | 258 | } |
257 | 259 | ||
258 | if (num_cpu_pds == MAX_NUM_CPU_PDS) { | 260 | if (num_special_pds == ARRAY_SIZE(special_pds)) { |
259 | pr_warn("Too many CPU PM domains\n"); | 261 | pr_warn("Too many special PM domains\n"); |
260 | of_node_put(pd); | 262 | of_node_put(pd); |
261 | continue; | 263 | return; |
262 | } | ||
263 | |||
264 | cpu_pds[num_cpu_pds++] = pd; | ||
265 | } | 264 | } |
266 | 265 | ||
266 | pr_debug("Special PM domain %s type %d for %s\n", pd->name, type, | ||
267 | np->full_name); | ||
268 | |||
269 | special_pds[num_special_pds].pd = pd; | ||
270 | special_pds[num_special_pds].type = type; | ||
271 | num_special_pds++; | ||
272 | } | ||
273 | |||
274 | static void __init get_special_pds(void) | ||
275 | { | ||
276 | struct device_node *np; | ||
277 | const struct of_device_id *id; | ||
278 | |||
279 | /* PM domains containing CPUs */ | ||
280 | for_each_node_by_type(np, "cpu") | ||
281 | add_special_pd(np, PD_CPU); | ||
282 | |||
267 | /* PM domain containing console */ | 283 | /* PM domain containing console */ |
268 | if (of_stdout) | 284 | if (of_stdout) |
269 | console_pd = of_parse_phandle(of_stdout, "power-domains", 0); | 285 | add_special_pd(of_stdout, PD_CONSOLE); |
270 | 286 | ||
271 | /* PM domain containing Coresight-ETM */ | 287 | /* PM domains containing other special devices */ |
272 | np = of_find_compatible_node(NULL, NULL, "arm,coresight-etm3x"); | 288 | for_each_matching_node_and_match(np, special_ids, &id) |
273 | if (np) { | 289 | add_special_pd(np, (enum pd_types)id->data); |
274 | debug_pd = of_parse_phandle(np, "power-domains", 0); | ||
275 | of_node_put(np); | ||
276 | } | ||
277 | } | 290 | } |
278 | 291 | ||
279 | static void __init put_special_pds(void) | 292 | static void __init put_special_pds(void) |
280 | { | 293 | { |
281 | unsigned int i; | 294 | unsigned int i; |
282 | 295 | ||
283 | for (i = 0; i < num_cpu_pds; i++) | 296 | for (i = 0; i < num_special_pds; i++) |
284 | of_node_put(cpu_pds[i]); | 297 | of_node_put(special_pds[i].pd); |
285 | of_node_put(console_pd); | ||
286 | of_node_put(debug_pd); | ||
287 | } | 298 | } |
288 | 299 | ||
289 | static bool __init pd_contains_cpu(const struct device_node *pd) | 300 | static enum pd_types __init pd_type(const struct device_node *pd) |
290 | { | 301 | { |
291 | unsigned int i; | 302 | unsigned int i; |
292 | 303 | ||
293 | for (i = 0; i < num_cpu_pds; i++) | 304 | for (i = 0; i < num_special_pds; i++) |
294 | if (pd == cpu_pds[i]) | 305 | if (pd == special_pds[i].pd) |
295 | return true; | 306 | return special_pds[i].type; |
296 | 307 | ||
297 | return false; | 308 | return PD_NORMAL; |
298 | } | 309 | } |
299 | 310 | ||
300 | static void __init rmobile_setup_pm_domain(struct device_node *np, | 311 | static void __init rmobile_setup_pm_domain(struct device_node *np, |
@@ -302,18 +313,46 @@ static void __init rmobile_setup_pm_domain(struct device_node *np, | |||
302 | { | 313 | { |
303 | const char *name = pd->genpd.name; | 314 | const char *name = pd->genpd.name; |
304 | 315 | ||
305 | if (pd_contains_cpu(np)) { | 316 | switch (pd_type(np)) { |
317 | case PD_CPU: | ||
318 | /* | ||
319 | * This domain contains the CPU core and therefore it should | ||
320 | * only be turned off if the CPU is not in use. | ||
321 | */ | ||
306 | pr_debug("PM domain %s contains CPU\n", name); | 322 | pr_debug("PM domain %s contains CPU\n", name); |
307 | pd->gov = &pm_domain_always_on_gov; | 323 | pd->gov = &pm_domain_always_on_gov; |
308 | pd->suspend = rmobile_pd_suspend_cpu; | 324 | pd->suspend = rmobile_pd_suspend_busy; |
309 | } else if (np == console_pd) { | 325 | break; |
326 | |||
327 | case PD_CONSOLE: | ||
310 | pr_debug("PM domain %s contains serial console\n", name); | 328 | pr_debug("PM domain %s contains serial console\n", name); |
311 | pd->gov = &pm_domain_always_on_gov; | 329 | pd->gov = &pm_domain_always_on_gov; |
312 | pd->suspend = rmobile_pd_suspend_console; | 330 | pd->suspend = rmobile_pd_suspend_console; |
313 | } else if (np == debug_pd) { | 331 | break; |
332 | |||
333 | case PD_DEBUG: | ||
334 | /* | ||
335 | * This domain contains the Coresight-ETM hardware block and | ||
336 | * therefore it should only be turned off if the debug module | ||
337 | * is not in use. | ||
338 | */ | ||
314 | pr_debug("PM domain %s contains Coresight-ETM\n", name); | 339 | pr_debug("PM domain %s contains Coresight-ETM\n", name); |
315 | pd->gov = &pm_domain_always_on_gov; | 340 | pd->gov = &pm_domain_always_on_gov; |
316 | pd->suspend = rmobile_pd_suspend_debug; | 341 | pd->suspend = rmobile_pd_suspend_busy; |
342 | break; | ||
343 | |||
344 | case PD_MEMCTL: | ||
345 | /* | ||
346 | * This domain contains a memory-controller and therefore it | ||
347 | * should only be turned off if memory is not in use. | ||
348 | */ | ||
349 | pr_debug("PM domain %s contains MEMCTL\n", name); | ||
350 | pd->gov = &pm_domain_always_on_gov; | ||
351 | pd->suspend = rmobile_pd_suspend_busy; | ||
352 | break; | ||
353 | |||
354 | case PD_NORMAL: | ||
355 | break; | ||
317 | } | 356 | } |
318 | 357 | ||
319 | rmobile_init_pm_domain(pd); | 358 | rmobile_init_pm_domain(pd); |