diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap-smp.c')
-rw-r--r-- | arch/arm/mach-omap2/omap-smp.c | 41 |
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 | ||
43 | u16 pm44xx_errata; | ||
44 | |||
42 | /* SCU base address */ | 45 | /* SCU base address */ |
43 | static void __iomem *scu_base; | 46 | static 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 | ||
139 | static void __init wakeup_secondary(void) | 171 | static 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); |