aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap-smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/omap-smp.c')
-rw-r--r--arch/arm/mach-omap2/omap-smp.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 4d05fa8a4e48..cd42d921940d 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -32,6 +32,7 @@
32#include "iomap.h" 32#include "iomap.h"
33#include "common.h" 33#include "common.h"
34#include "clockdomain.h" 34#include "clockdomain.h"
35#include "pm.h"
35 36
36#define CPU_MASK 0xff0ffff0 37#define CPU_MASK 0xff0ffff0
37#define CPU_CORTEX_A9 0x410FC090 38#define CPU_CORTEX_A9 0x410FC090
@@ -39,6 +40,8 @@
39 40
40#define OMAP5_CORE_COUNT 0x2 41#define OMAP5_CORE_COUNT 0x2
41 42
43u16 pm44xx_errata;
44
42/* SCU base address */ 45/* SCU base address */
43static void __iomem *scu_base; 46static void __iomem *scu_base;
44 47
@@ -118,8 +121,37 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
118 * 4.3.4.2 Power States of CPU0 and CPU1 121 * 4.3.4.2 Power States of CPU0 and CPU1
119 */ 122 */
120 if (booted) { 123 if (booted) {
124 /*
125 * GIC distributor control register has changed between
126 * CortexA9 r1pX and r2pX. The Control Register secure
127 * banked version is now composed of 2 bits:
128 * bit 0 == Secure Enable
129 * bit 1 == Non-Secure Enable
130 * The Non-Secure banked register has not changed
131 * Because the ROM Code is based on the r1pX GIC, the CPU1
132 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
133 * The workaround must be:
134 * 1) Before doing the CPU1 wakeup, CPU0 must disable
135 * the GIC distributor
136 * 2) CPU1 must re-enable the GIC distributor on
137 * it's wakeup path.
138 */
139 if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
140 local_irq_disable();
141 gic_dist_disable();
142 }
143
121 clkdm_wakeup(cpu1_clkdm); 144 clkdm_wakeup(cpu1_clkdm);
122 clkdm_allow_idle(cpu1_clkdm); 145 clkdm_allow_idle(cpu1_clkdm);
146
147 if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
148 while (gic_dist_disabled()) {
149 udelay(1);
150 cpu_relax();
151 }
152 gic_timer_retrigger();
153 local_irq_enable();
154 }
123 } else { 155 } else {
124 dsb_sev(); 156 dsb_sev();
125 booted = true; 157 booted = true;
@@ -138,7 +170,14 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
138 170
139static void __init wakeup_secondary(void) 171static void __init wakeup_secondary(void)
140{ 172{
173 void *startup_addr = omap_secondary_startup;
141 void __iomem *base = omap_get_wakeupgen_base(); 174 void __iomem *base = omap_get_wakeupgen_base();
175
176 if (cpu_is_omap446x()) {
177 startup_addr = omap_secondary_startup_4460;
178 pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
179 }
180
142 /* 181 /*
143 * Write the address of secondary startup routine into the 182 * Write the address of secondary startup routine into the
144 * AuxCoreBoot1 where ROM code will jump and start executing 183 * AuxCoreBoot1 where ROM code will jump and start executing
@@ -146,7 +185,7 @@ static void __init wakeup_secondary(void)
146 * A barrier is added to ensure that write buffer is drained 185 * A barrier is added to ensure that write buffer is drained
147 */ 186 */
148 if (omap_secure_apis_support()) 187 if (omap_secure_apis_support())
149 omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup)); 188 omap_auxcoreboot_addr(virt_to_phys(startup_addr));
150 else 189 else
151 __raw_writel(virt_to_phys(omap5_secondary_startup), 190 __raw_writel(virt_to_phys(omap5_secondary_startup),
152 base + OMAP_AUX_CORE_BOOT_1); 191 base + OMAP_AUX_CORE_BOOT_1);