diff options
author | Anson Huang <b20788@freescale.com> | 2011-07-20 15:57:05 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-01-09 20:21:35 +0800 |
commit | a0c4816452847d92c60d4a2657a90ff25ff905cc (patch) | |
tree | a7b218e58723aad1b2e9527c7cc6ff861629ed0a /arch/arm/mach-mx6/platsmp.c | |
parent | a8bdc6da5f247b747bde34f5a97f0feb894d50e7 (diff) |
ENGR00153429 [WDOG]Workaround for SMP wdog reset
1. Copy mx6_secondary_startup to iRAM;
2. CPU0 reset CPUx, then waiting CPUx reset OK, and
clear CPUx's boot_entry;
3. CPUx reset OK, waiting CPU0 to clear its parameter;
4. All these steps done, CPUx go on boot;
Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'arch/arm/mach-mx6/platsmp.c')
-rw-r--r-- | arch/arm/mach-mx6/platsmp.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/arch/arm/mach-mx6/platsmp.c b/arch/arm/mach-mx6/platsmp.c index 66ab4e60dfe2..123063b31ecc 100644 --- a/arch/arm/mach-mx6/platsmp.c +++ b/arch/arm/mach-mx6/platsmp.c @@ -30,6 +30,7 @@ #include <asm/smp_scu.h> #include <mach/mx6.h> #include "src-reg.h" +#include <asm/io.h> static DEFINE_SPINLOCK(boot_lock); @@ -61,7 +62,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long boot_entry; void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR); - int val; + void *boot_iram_base; + unsigned int val; /* * set synchronisation state between this boot processor @@ -69,24 +71,38 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) */ spin_lock(&boot_lock); - /* set entry point for cpu1-cpu3*/ - boot_entry = virt_to_phys(mx6_secondary_startup); + /* boot entry is at the last 4K iRAM, from 0x93f000 */ + boot_entry = MX6Q_IRAM_BASE_ADDR + MX6Q_IRAM_SIZE; + boot_iram_base = (void *)ioremap(boot_entry, SZ_4K); + memcpy((void *)boot_iram_base, mx6_secondary_startup, SZ_1K); + /* set entry point for cpu1-cpu3*/ writel(boot_entry, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu); - writel(0, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu + 4); + writel(virt_to_phys(mx6_secondary_startup), + src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu + 4); smp_wmb(); dsb(); flush_cache_all(); - /* reset cpu n */ + /* reset cpu<n> */ val = readl(src_base + SRC_SCR_OFFSET); val |= 1 << (BP_SRC_SCR_CORE0_RST + cpu); val |= 1 << (BP_SRC_SCR_CORES_DBG_RST + cpu); writel(val, src_base + SRC_SCR_OFFSET); + val = jiffies; + /* wait cpu<n> boot up and clear boot_entry, timeout is 500ms */ + while (__raw_readl(src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu) != 0) { + if (time_after(jiffies, val + HZ / 2)) { + printk(KERN_WARNING "cpu %d: boot up failed!\n", cpu); + break; + } + } + /* let cpu<n> out of loop, call secondary_startup function*/ writel(0, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu + 4); + smp_send_reschedule(cpu); /* * now the secondary core is starting up let it run its |