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 4d05fa8a4e4..cd42d921940 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -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 @@ -39,6 +40,8 @@  #define OMAP5_CORE_COUNT	0x2 +u16 pm44xx_errata; +  /* SCU base address */  static void __iomem *scu_base; @@ -118,8 +121,37 @@ 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)) { +			local_irq_disable(); +			gic_dist_disable(); +		} +  		clkdm_wakeup(cpu1_clkdm);  		clkdm_allow_idle(cpu1_clkdm); + +		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) { +			while (gic_dist_disabled()) { +				udelay(1); +				cpu_relax(); +			} +			gic_timer_retrigger(); +			local_irq_enable(); +		}  	} else {  		dsb_sev();  		booted = true; @@ -138,7 +170,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 +185,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);  |