aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mvebu
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2014-06-30 08:09:25 -0400
committerJason Cooper <jason@lakedaemon.net>2014-06-30 14:15:11 -0400
commit6509dc74c9f55ffaa558738b96c4da8b98d39571 (patch)
tree12c6dbdf141658a4851db2a9b32f535eab62d595 /arch/arm/mach-mvebu
parent011788907ba955f87875fcfb4914881b28f7f99d (diff)
ARM: mvebu: fix cpuidle implementation to work on big-endian systems
On Marvell Armada XP, when a CPU comes back from deep idle state of cpuidle, it restarts its execution at armada_370_xp_cpu_resume(), which puts back the CPU into the coherency, and then calls the generic cpu_resume() function. While this works on little-endian configurations, it doesn't work on big-endian configurations because the CPU restarts in little-endian, and therefore must be switched back to big-endian to operate properly. To achieve this, a 'setend be' instruction must be executed in big-endian configurations. However, the ARM_BE8() macro that is used to implement nice compile-time conditional for ARM LE vs. ARM BE8 is not easily usable in inline assembly. Therefore, this patch moves the armada_370_xp_cpu_resume() C function, which was anyway just a block of inline assembly, into a proper pmsu_ll.S file, and adds the appropriate ARM_BE8(setend be) instruction. Without this patch, an Armada XP big endian configuration with cpuidle enabled fails to boot, as it hangs as soon as one of the CPU hits the deep idle state. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Link: https://lkml.kernel.org/r/1404130165-3593-1-git-send-email-thomas.petazzoni@free-electrons.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'arch/arm/mach-mvebu')
-rw-r--r--arch/arm/mach-mvebu/Makefile2
-rw-r--r--arch/arm/mach-mvebu/pmsu.c9
-rw-r--r--arch/arm/mach-mvebu/pmsu_ll.S25
3 files changed, 28 insertions, 8 deletions
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 2ecb828e4a8b..1636cdbef01a 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -7,7 +7,7 @@ CFLAGS_pmsu.o := -march=armv7-a
7obj-y += system-controller.o mvebu-soc-id.o 7obj-y += system-controller.o mvebu-soc-id.o
8 8
9ifeq ($(CONFIG_MACH_MVEBU_V7),y) 9ifeq ($(CONFIG_MACH_MVEBU_V7),y)
10obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o 10obj-y += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o
11obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o 11obj-$(CONFIG_SMP) += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o
12obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 12obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
13endif 13endif
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
index 53a55c8520bf..a1d407c0febe 100644
--- a/arch/arm/mach-mvebu/pmsu.c
+++ b/arch/arm/mach-mvebu/pmsu.c
@@ -66,6 +66,8 @@ static void __iomem *pmsu_mp_base;
66extern void ll_disable_coherency(void); 66extern void ll_disable_coherency(void);
67extern void ll_enable_coherency(void); 67extern void ll_enable_coherency(void);
68 68
69extern void armada_370_xp_cpu_resume(void);
70
69static struct platform_device armada_xp_cpuidle_device = { 71static struct platform_device armada_xp_cpuidle_device = {
70 .name = "cpuidle-armada-370-xp", 72 .name = "cpuidle-armada-370-xp",
71}; 73};
@@ -140,13 +142,6 @@ static void armada_370_xp_pmsu_enable_l2_powerdown_onidle(void)
140 writel(reg, pmsu_mp_base + L2C_NFABRIC_PM_CTL); 142 writel(reg, pmsu_mp_base + L2C_NFABRIC_PM_CTL);
141} 143}
142 144
143static void armada_370_xp_cpu_resume(void)
144{
145 asm volatile("bl ll_add_cpu_to_smp_group\n\t"
146 "bl ll_enable_coherency\n\t"
147 "b cpu_resume\n\t");
148}
149
150/* No locking is needed because we only access per-CPU registers */ 145/* No locking is needed because we only access per-CPU registers */
151void armada_370_xp_pmsu_idle_prepare(bool deepidle) 146void armada_370_xp_pmsu_idle_prepare(bool deepidle)
152{ 147{
diff --git a/arch/arm/mach-mvebu/pmsu_ll.S b/arch/arm/mach-mvebu/pmsu_ll.S
new file mode 100644
index 000000000000..fc3de68d8c54
--- /dev/null
+++ b/arch/arm/mach-mvebu/pmsu_ll.S
@@ -0,0 +1,25 @@
1/*
2 * Copyright (C) 2014 Marvell
3 *
4 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
5 * Gregory Clement <gregory.clement@free-electrons.com>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14
15/*
16 * This is the entry point through which CPUs exiting cpuidle deep
17 * idle state are going.
18 */
19ENTRY(armada_370_xp_cpu_resume)
20ARM_BE8(setend be ) @ go BE8 if entered LE
21 bl ll_add_cpu_to_smp_group
22 bl ll_enable_coherency
23 b cpu_resume
24ENDPROC(armada_370_xp_cpu_resume)
25