diff options
author | Michal Simek <michal.simek@xilinx.com> | 2013-03-20 08:56:15 -0400 |
---|---|---|
committer | Michal Simek <michal.simek@xilinx.com> | 2013-04-04 03:24:00 -0400 |
commit | c7c28b0fdd06d8eb9414d21f8956b7c773ceea93 (patch) | |
tree | 6fc4e35405878f88f30bd779af7ad4e10a149a94 | |
parent | aa7eb2bb4e4a22e41bbe4612ff46e5885b13c33e (diff) |
arm: zynq: Add hotplug support
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
-rw-r--r-- | arch/arm/mach-zynq/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-zynq/hotplug.c | 104 | ||||
-rw-r--r-- | arch/arm/mach-zynq/platsmp.c | 3 |
4 files changed, 113 insertions, 0 deletions
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile index b595d22134ec..1b25d92ebf22 100644 --- a/arch/arm/mach-zynq/Makefile +++ b/arch/arm/mach-zynq/Makefile | |||
@@ -4,4 +4,7 @@ | |||
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := common.o slcr.o | 6 | obj-y := common.o slcr.o |
7 | CFLAGS_REMOVE_hotplug.o =-march=armv6k | ||
8 | CFLAGS_hotplug.o =-Wa,-march=armv7-a -mcpu=cortex-a9 | ||
9 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | ||
7 | obj-$(CONFIG_SMP) += headsmp.o platsmp.o | 10 | obj-$(CONFIG_SMP) += headsmp.o platsmp.o |
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index fd308f8b18d9..fbbd0e21c404 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h | |||
@@ -34,4 +34,7 @@ extern struct smp_operations zynq_smp_ops __initdata; | |||
34 | extern void __iomem *zynq_slcr_base; | 34 | extern void __iomem *zynq_slcr_base; |
35 | extern void __iomem *zynq_scu_base; | 35 | extern void __iomem *zynq_scu_base; |
36 | 36 | ||
37 | /* Hotplug */ | ||
38 | extern void zynq_platform_cpu_die(unsigned int cpu); | ||
39 | |||
37 | #endif | 40 | #endif |
diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c new file mode 100644 index 000000000000..c89672bd1de2 --- /dev/null +++ b/arch/arm/mach-zynq/hotplug.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012-2013 Xilinx | ||
3 | * | ||
4 | * based on linux/arch/arm/mach-realview/hotplug.c | ||
5 | * | ||
6 | * Copyright (C) 2002 ARM Ltd. | ||
7 | * All Rights Reserved | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/smp.h> | ||
16 | |||
17 | #include <asm/cacheflush.h> | ||
18 | #include <asm/cp15.h> | ||
19 | #include "common.h" | ||
20 | |||
21 | static inline void zynq_cpu_enter_lowpower(void) | ||
22 | { | ||
23 | unsigned int v; | ||
24 | |||
25 | flush_cache_all(); | ||
26 | asm volatile( | ||
27 | " mcr p15, 0, %1, c7, c5, 0\n" | ||
28 | " dsb\n" | ||
29 | /* | ||
30 | * Turn off coherency | ||
31 | */ | ||
32 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
33 | " bic %0, %0, #0x40\n" | ||
34 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
35 | " mrc p15, 0, %0, c1, c0, 0\n" | ||
36 | " bic %0, %0, %2\n" | ||
37 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
38 | : "=&r" (v) | ||
39 | : "r" (0), "Ir" (CR_C) | ||
40 | : "cc"); | ||
41 | } | ||
42 | |||
43 | static inline void zynq_cpu_leave_lowpower(void) | ||
44 | { | ||
45 | unsigned int v; | ||
46 | |||
47 | asm volatile( | ||
48 | " mrc p15, 0, %0, c1, c0, 0\n" | ||
49 | " orr %0, %0, %1\n" | ||
50 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
51 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
52 | " orr %0, %0, #0x40\n" | ||
53 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
54 | : "=&r" (v) | ||
55 | : "Ir" (CR_C) | ||
56 | : "cc"); | ||
57 | } | ||
58 | |||
59 | static inline void zynq_platform_do_lowpower(unsigned int cpu, int *spurious) | ||
60 | { | ||
61 | /* | ||
62 | * there is no power-control hardware on this platform, so all | ||
63 | * we can do is put the core into WFI; this is safe as the calling | ||
64 | * code will have already disabled interrupts | ||
65 | */ | ||
66 | for (;;) { | ||
67 | dsb(); | ||
68 | wfi(); | ||
69 | |||
70 | /* | ||
71 | * Getting here, means that we have come out of WFI without | ||
72 | * having been woken up - this shouldn't happen | ||
73 | * | ||
74 | * Just note it happening - when we're woken, we can report | ||
75 | * its occurrence. | ||
76 | */ | ||
77 | (*spurious)++; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * platform-specific code to shutdown a CPU | ||
83 | * | ||
84 | * Called with IRQs disabled | ||
85 | */ | ||
86 | void zynq_platform_cpu_die(unsigned int cpu) | ||
87 | { | ||
88 | int spurious = 0; | ||
89 | |||
90 | /* | ||
91 | * we're ready for shutdown now, so do it | ||
92 | */ | ||
93 | zynq_cpu_enter_lowpower(); | ||
94 | zynq_platform_do_lowpower(cpu, &spurious); | ||
95 | |||
96 | /* | ||
97 | * bring this CPU back into the world of cache | ||
98 | * coherency, and then restore interrupts | ||
99 | */ | ||
100 | zynq_cpu_leave_lowpower(); | ||
101 | |||
102 | if (spurious) | ||
103 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
104 | } | ||
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c index cdfd888ca783..3072cbd7ec6f 100644 --- a/arch/arm/mach-zynq/platsmp.c +++ b/arch/arm/mach-zynq/platsmp.c | |||
@@ -146,4 +146,7 @@ struct smp_operations zynq_smp_ops __initdata = { | |||
146 | .smp_prepare_cpus = zynq_smp_prepare_cpus, | 146 | .smp_prepare_cpus = zynq_smp_prepare_cpus, |
147 | .smp_secondary_init = zynq_secondary_init, | 147 | .smp_secondary_init = zynq_secondary_init, |
148 | .smp_boot_secondary = zynq_boot_secondary, | 148 | .smp_boot_secondary = zynq_boot_secondary, |
149 | #ifdef CONFIG_HOTPLUG_CPU | ||
150 | .cpu_die = zynq_platform_cpu_die, | ||
151 | #endif | ||
149 | }; | 152 | }; |