/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
__CPUINIT
ENTRY(mx6_secondary_startup)
- /*************************************************************
- The following code include workaround for smp wdog reset issue,
- when system reset, core1~core3 will check its GPR register, if
- it contain a valid pointer, they will continue to run, but
- since when a reset happen, DRAM can't be access before its
- controller initialized, so we must make sure the pointer value
- is in iRAM space, also, ARM recommend that there should not be
- any AXI access pending in the system if we want to reset
- individual CPU, it is better to put CPU in WFI state before
- reset, so now we implement the following flow to make sure
- this scenario:
- _______________________ _______________________
- | CPU0 | ----> | CPU<n> |
- |_______________________| | |_______________________|
- | | |
- | | |
- \|/ | \|/
- _______________________ | _______________________
- | GPR<n*2+2>=parameter | | | Rom jump to boot_entry|
- |_______________________| | |_______________________|
- | | |
- | | |
- \|/ | \|/
- _______________________ | _______________________
- | GPR<n*2+1>=boot_entry | | -- | GPR<n*2+1>=0 |
- |_______________________| | | |_______________________|
- | | | |
- | | | | <----------------
- \|/ | | \|/ |
- _______________________ | | _____________ N _________
- | Reset CPU<n> |____| | ---> /CPU<n*2+2>=0?\ ------->| WFI |
- |_______________________| | | \_____________/ |_________|
- | | | | ^
---------------> | | | | Y |
-| \|/ | | \|/ |
-| N _____________ | | |
--------------/GPR<n*2+1>=0?\ <--------- | |
- \_____________/ | |
- | | |
- Y | | |
- \|/ | |
- _______________________ | |
- | GPR<n*2+2>=0 | ---------- |
- |_______________________| |
- | |
- | |
- \|/ |
- _______________________ |
- | IPI software irq |---------------------------------------------
- |_______________________|
-
-
- This function code is copied to iRAM 0x93f000, since
- there is function call below, such as v7_invalidate_l1 and
- secondary_startup, we have to use absolute address jump,
- to get the physical address of these functions, we need
- the offset of physical and virtual address, the
- offset is passed from GPR parameter, currently we store
- it at r8, future code change should avoid using r8.
-*****************************************************************************/
/* Invalidate L1 I-cache first */
mov r1, #0x0
mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache
- /* count the offset value and store it in r8 */
- ldr r3, =mx6_secondary_startup
- mrc p15, 0, r0, c0, c0, 5
- and r0, r0, #15
- ldr r1, =0x020d8024
- add r1, r0, LSL#3
- ldr r0, [r1]
- sub r8, r3, r0
-
+ /* Invalidate L1 D-cache */
+ bl v7_invalidate_l1
+ /* Set ARM working mode */
msr cpsr_fsxc, #0xd3
- /* must enable gic cpu, then cpu<n> can wakeup when cpu0
- send a software irq*/
- ldr r1, =0xa00100
- mov r0, #0x1
- str r0, [r1]
- mov r0, #0xf0
- str r0, [r1, #0x4]
- mov r0, #0x2
- str r0, [r1, #0x8]
-
- /* read cpu number in order to clear related GPRx */
- mrc p15, 0, r0, c0, c0, 5
+ mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
- ldr r1, =0x020d8020
+ ldr r1, = 0x020d8020
add r1, r0, LSL#3
- /* clear GPR boot_entry register */
+
+ /*Clear SRC_GPR register */
mov r0, #0
str r0, [r1]
+ str r0, [r1, #0x4]
- /* check whether GPR paremeter register is cleared */
- ldr r0, [r1, #0x4]
- cmp r0, #0x0
- beq 4f
-3:
- wfi
- ldr r0, [r1, #0x4]
- cmp r0, #0x0
- bne 3b
-4:
- /* invalidate l1-cache first */
- ldr r0, =v7_invalidate_l1
- sub r0, r0, r8
- mov lr, pc
- add lr, lr, #0x4
- mov pc, r0
- ldr r0, =secondary_startup
- sub r0, r0, r8
-
- /* jump to secondary_startup */
- mov pc, r0
+ /* Jump to secondary_startup */
+ b secondary_startup
ENDPROC(mx6_secondary_startup)
/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
{
trace_hardirqs_off();
+ spin_lock(&boot_lock);
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
/*
* Synchronise with the boot thread.
*/
- spin_lock(&boot_lock);
+
spin_unlock(&boot_lock);
}
{
unsigned long boot_entry;
void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
- void *boot_iram_base;
unsigned int val;
/*
*/
spin_lock(&boot_lock);
- /* 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*/
+ boot_entry = virt_to_phys(mx6_secondary_startup);
+
writel(boot_entry, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu);
- writel(virt_to_phys(mx6_secondary_startup),
- src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu + 4);
+ writel(0, src_base + SRC_GPR1_OFFSET + 4 * 2 * cpu + 4);
smp_wmb();
dsb();
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, (unsigned long)(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);
-
- /* unmap iram base */
- iounmap(boot_iram_base);
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish