summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx6/platsmp.c
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2011-07-20 15:57:05 +0800
committerJason Liu <r64343@freescale.com>2012-01-09 20:21:35 +0800
commita0c4816452847d92c60d4a2657a90ff25ff905cc (patch)
treea7b218e58723aad1b2e9527c7cc6ff861629ed0a /arch/arm/mach-mx6/platsmp.c
parenta8bdc6da5f247b747bde34f5a97f0feb894d50e7 (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.c26
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