summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2/omap-smp.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-11-07 01:47:02 (GMT)
committerTony Lindgren <tony@atomide.com>2012-11-07 01:47:02 (GMT)
commitb1d2037a6c3c754ef7f527249ab2e1dee51e73dd (patch)
treedeaa9a4ccac205b288aff709f39c0b622d0b91b7 /arch/arm/mach-omap2/omap-smp.c
parent3d70f8c617a436c7146ecb81df2265b4626dfe89 (diff)
parentcd8ce159031813eb870a5f3d5b27c3be36cd6e3a (diff)
downloadlinux-fsl-qoriq-b1d2037a6c3c754ef7f527249ab2e1dee51e73dd.tar.xz
Merge tag 'for_3.8-fixes-pm' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-v3.8/fixes-non-critical-v2
Some non-regression fixes for OMAP4460 PM support.
Diffstat (limited to 'arch/arm/mach-omap2/omap-smp.c')
-rw-r--r--arch/arm/mach-omap2/omap-smp.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 4d05fa8..49a08df 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
@@ -118,8 +119,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 +168,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 +183,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);