aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory CLEMENT <gregory.clement@free-electrons.com>2014-07-23 09:00:51 -0400
committerJason Cooper <jason@lakedaemon.net>2014-07-24 07:47:37 -0400
commit3b9e4b1441aedcb26079f690aa11f3f9f93e5182 (patch)
tree9d121f165ccf45fc5161b0b57989d863af4e95dc
parentc16788b431d708afb73ffdd41fd8a16ab11bf89e (diff)
ARM: mvebu: add cpuidle support for Armada 370
This commit introduces the cpuidle support for Armada 370. The main difference compared to the already supported Armada XP is that the Armada 370 has an issue caused by "a slow exit process from the deep idle state due to heavy L1/L2 cache cleanup operations performed by the BootROM software" (cf errata GL-BootROM-10). To work around this issue, we replace the restart code of the BootROM by some custom code located in an internal SRAM. For this purpose, we use the common function mvebu_boot_addr_wa() introduced in the commit "ARM: mvebu: Add a common function for the boot address work around". The message in case of failure to suspend the system was switched from the warn level to the debug level. Indeed due to the "slow exit process from the deep idle state" in Armada 370, this situation happens quite often. Using the debug level avoids spamming the kernel logs, but still allows to enable it if needed. Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Link: https://lkml.kernel.org/r/1406120453-29291-15-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--arch/arm/mach-mvebu/pmsu.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
index 0cd2d09475aa..9190ae8626cf 100644
--- a/arch/arm/mach-mvebu/pmsu.c
+++ b/arch/arm/mach-mvebu/pmsu.c
@@ -34,7 +34,6 @@
34#include <asm/tlbflush.h> 34#include <asm/tlbflush.h>
35#include "common.h" 35#include "common.h"
36 36
37static void __iomem *pmsu_mp_base;
38 37
39#define PMSU_BASE_OFFSET 0x100 38#define PMSU_BASE_OFFSET 0x100
40#define PMSU_REG_SIZE 0x1000 39#define PMSU_REG_SIZE 0x1000
@@ -68,17 +67,18 @@ static void __iomem *pmsu_mp_base;
68#define BOOTROM_BASE 0xFFF00000 67#define BOOTROM_BASE 0xFFF00000
69#define BOOTROM_SIZE 0x100000 68#define BOOTROM_SIZE 0x100000
70 69
70#define ARMADA_370_CRYPT0_ENG_TARGET 0x9
71#define ARMADA_370_CRYPT0_ENG_ATTR 0x1
72
71extern void ll_disable_coherency(void); 73extern void ll_disable_coherency(void);
72extern void ll_enable_coherency(void); 74extern void ll_enable_coherency(void);
73 75
74extern void armada_370_xp_cpu_resume(void); 76extern void armada_370_xp_cpu_resume(void);
77static phys_addr_t pmsu_mp_phys_base;
78static void __iomem *pmsu_mp_base;
75 79
76static void *mvebu_cpu_resume; 80static void *mvebu_cpu_resume;
77 81
78static struct platform_device mvebu_v7_cpuidle_device = {
79 .name = "cpuidle-armada-xp",
80};
81
82static struct of_device_id of_pmsu_table[] = { 82static struct of_device_id of_pmsu_table[] = {
83 { .compatible = "marvell,armada-370-pmsu", }, 83 { .compatible = "marvell,armada-370-pmsu", },
84 { .compatible = "marvell,armada-370-xp-pmsu", }, 84 { .compatible = "marvell,armada-370-xp-pmsu", },
@@ -165,6 +165,8 @@ static int __init mvebu_v7_pmsu_init(void)
165 goto out; 165 goto out;
166 } 166 }
167 167
168 pmsu_mp_phys_base = res.start;
169
168 pmsu_mp_base = ioremap(res.start, resource_size(&res)); 170 pmsu_mp_base = ioremap(res.start, resource_size(&res));
169 if (!pmsu_mp_base) { 171 if (!pmsu_mp_base) {
170 pr_err("unable to map registers\n"); 172 pr_err("unable to map registers\n");
@@ -275,7 +277,7 @@ int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
275 "isb " 277 "isb "
276 : : : "r0"); 278 : : : "r0");
277 279
278 pr_warn("Failed to suspend the system\n"); 280 pr_debug("Failed to suspend the system\n");
279 281
280 return 0; 282 return 0;
281} 283}
@@ -325,7 +327,39 @@ static struct notifier_block mvebu_v7_cpu_pm_notifier = {
325 .notifier_call = mvebu_v7_cpu_pm_notify, 327 .notifier_call = mvebu_v7_cpu_pm_notify,
326}; 328};
327 329
328static int __init armada_xp_cpuidle_init(void) 330static struct platform_device mvebu_v7_cpuidle_device;
331
332static __init int armada_370_cpuidle_init(void)
333{
334 struct device_node *np;
335 phys_addr_t redirect_reg;
336
337 np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
338 if (!np)
339 return -ENODEV;
340 of_node_put(np);
341
342 /*
343 * On Armada 370, there is "a slow exit process from the deep
344 * idle state due to heavy L1/L2 cache cleanup operations
345 * performed by the BootROM software". To avoid this, we
346 * replace the restart code of the bootrom by a a simple jump
347 * to the boot address. Then the code located at this boot
348 * address will take care of the initialization.
349 */
350 redirect_reg = pmsu_mp_phys_base + PMSU_BOOT_ADDR_REDIRECT_OFFSET(0);
351 mvebu_setup_boot_addr_wa(ARMADA_370_CRYPT0_ENG_TARGET,
352 ARMADA_370_CRYPT0_ENG_ATTR,
353 redirect_reg);
354
355 mvebu_cpu_resume = armada_370_xp_cpu_resume;
356 mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
357 mvebu_v7_cpuidle_device.name = "cpuidle-armada-370";
358
359 return 0;
360}
361
362static __init int armada_xp_cpuidle_init(void)
329{ 363{
330 struct device_node *np; 364 struct device_node *np;
331 365
@@ -336,6 +370,7 @@ static int __init armada_xp_cpuidle_init(void)
336 370
337 mvebu_cpu_resume = armada_370_xp_cpu_resume; 371 mvebu_cpu_resume = armada_370_xp_cpu_resume;
338 mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend; 372 mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
373 mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp";
339 374
340 return 0; 375 return 0;
341} 376}
@@ -352,6 +387,8 @@ static int __init mvebu_v7_cpu_pm_init(void)
352 387
353 if (of_machine_is_compatible("marvell,armadaxp")) 388 if (of_machine_is_compatible("marvell,armadaxp"))
354 ret = armada_xp_cpuidle_init(); 389 ret = armada_xp_cpuidle_init();
390 else if (of_machine_is_compatible("marvell,armada370"))
391 ret = armada_370_cpuidle_init();
355 else 392 else
356 return 0; 393 return 0;
357 394