|
@@ -32,6 +32,7 @@
|
|
|
#include "iomap.h"
|
|
|
#include "common.h"
|
|
|
#include "clockdomain.h"
|
|
|
+#include "pm.h"
|
|
|
|
|
|
#define CPU_MASK 0xff0ffff0
|
|
|
#define CPU_CORTEX_A9 0x410FC090
|
|
@@ -118,6 +119,24 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
|
|
|
* 4.3.4.2 Power States of CPU0 and CPU1
|
|
|
*/
|
|
|
if (booted) {
|
|
|
+ /*
|
|
|
+ * GIC distributor control register has changed between
|
|
|
+ * CortexA9 r1pX and r2pX. The Control Register secure
|
|
|
+ * banked version is now composed of 2 bits:
|
|
|
+ * bit 0 == Secure Enable
|
|
|
+ * bit 1 == Non-Secure Enable
|
|
|
+ * The Non-Secure banked register has not changed
|
|
|
+ * Because the ROM Code is based on the r1pX GIC, the CPU1
|
|
|
+ * GIC restoration will cause a problem to CPU0 Non-Secure SW.
|
|
|
+ * The workaround must be:
|
|
|
+ * 1) Before doing the CPU1 wakeup, CPU0 must disable
|
|
|
+ * the GIC distributor
|
|
|
+ * 2) CPU1 must re-enable the GIC distributor on
|
|
|
+ * it's wakeup path.
|
|
|
+ */
|
|
|
+ if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD))
|
|
|
+ gic_dist_disable();
|
|
|
+
|
|
|
clkdm_wakeup(cpu1_clkdm);
|
|
|
clkdm_allow_idle(cpu1_clkdm);
|
|
|
} else {
|
|
@@ -138,7 +157,14 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
|
|
|
|
|
|
static void __init wakeup_secondary(void)
|
|
|
{
|
|
|
+ void *startup_addr = omap_secondary_startup;
|
|
|
void __iomem *base = omap_get_wakeupgen_base();
|
|
|
+
|
|
|
+ if (cpu_is_omap446x()) {
|
|
|
+ startup_addr = omap_secondary_startup_4460;
|
|
|
+ pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Write the address of secondary startup routine into the
|
|
|
* AuxCoreBoot1 where ROM code will jump and start executing
|
|
@@ -146,7 +172,7 @@ static void __init wakeup_secondary(void)
|
|
|
* A barrier is added to ensure that write buffer is drained
|
|
|
*/
|
|
|
if (omap_secure_apis_support())
|
|
|
- omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
|
|
|
+ omap_auxcoreboot_addr(virt_to_phys(startup_addr));
|
|
|
else
|
|
|
__raw_writel(virt_to_phys(omap5_secondary_startup),
|
|
|
base + OMAP_AUX_CORE_BOOT_1);
|