2018-05-06 21:58:06 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
2015-02-20 07:57:15 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 Samsung Electronics
|
|
|
|
* Akshay Saraswat <akshay.s@samsung.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <asm/arch/cpu.h>
|
|
|
|
|
|
|
|
.globl relocate_wait_code
|
|
|
|
relocate_wait_code:
|
|
|
|
adr r0, code_base @ r0: source address (start)
|
|
|
|
adr r1, code_end @ r1: source address (end)
|
|
|
|
ldr r2, =0x02073000 @ r2: target address
|
|
|
|
1:
|
|
|
|
ldmia r0!, {r3-r6}
|
|
|
|
stmia r2!, {r3-r6}
|
|
|
|
cmp r0, r1
|
|
|
|
blt 1b
|
|
|
|
b code_end
|
|
|
|
.ltorg
|
|
|
|
/*
|
|
|
|
* Secondary core waits here until Primary wake it up.
|
2022-12-04 15:04:14 +00:00
|
|
|
* Below code is copied to (CFG_IRAM_TOP - 0x1000)
|
2015-02-20 07:57:15 +00:00
|
|
|
* This is a workaround code which is supposed to act as a
|
|
|
|
* substitute/supplement to the iROM code.
|
|
|
|
*
|
|
|
|
* This workaround code is relocated to the address 0x02073000
|
|
|
|
* because that comes out to be the last 4KB of the iRAM
|
|
|
|
* (Base Address - 0x02020000, Limit Address - 0x020740000).
|
|
|
|
*
|
2016-02-06 03:30:11 +00:00
|
|
|
* U-Boot and kernel are aware of this code and flags by the simple
|
2015-02-20 07:57:15 +00:00
|
|
|
* fact that we are implementing a workaround in the last 4KB
|
|
|
|
* of the iRAM and we have already defined these flag and address
|
2016-02-06 03:30:11 +00:00
|
|
|
* values in both kernel and U-Boot for our use.
|
2015-02-20 07:57:15 +00:00
|
|
|
*/
|
|
|
|
code_base:
|
|
|
|
b 1f
|
|
|
|
/*
|
|
|
|
* These addresses are being used as flags in u-boot and kernel.
|
|
|
|
*
|
|
|
|
* Jump address for resume and flag to check for resume/reset:
|
|
|
|
* Resume address - 0x2073008
|
|
|
|
* Resume flag - 0x207300C
|
|
|
|
*
|
|
|
|
* Jump address for cluster switching:
|
|
|
|
* Switch address - 0x2073018
|
|
|
|
*
|
|
|
|
* Jump address for core hotplug:
|
|
|
|
* Hotplug address - 0x207301C
|
|
|
|
*
|
|
|
|
* Jump address for C2 state (Reserved for future not being used right now):
|
|
|
|
* C2 address - 0x2073024
|
|
|
|
*
|
|
|
|
* Managed per core status for the active cluster:
|
|
|
|
* CPU0 state - 0x2073028
|
|
|
|
* CPU1 state - 0x207302C
|
|
|
|
* CPU2 state - 0x2073030
|
|
|
|
* CPU3 state - 0x2073034
|
|
|
|
*
|
|
|
|
* Managed per core GIC status for the active cluster:
|
|
|
|
* CPU0 gic state - 0x2073038
|
|
|
|
* CPU1 gic state - 0x207303C
|
|
|
|
* CPU2 gic state - 0x2073040
|
|
|
|
* CPU3 gic state - 0x2073044
|
|
|
|
*
|
|
|
|
* Logic of the code:
|
|
|
|
* Step-1: Read current CPU status.
|
|
|
|
* Step-2: If it's a resume then continue, else jump to step 4.
|
|
|
|
* Step-3: Clear inform1 PMU register and jump to inform0 value.
|
|
|
|
* Step-4: If it's a switch, C2 or reset, get the hotplug address.
|
|
|
|
* Step-5: If address is not available, enter WFE.
|
|
|
|
* Step-6: If address is available, jump to that address.
|
|
|
|
*/
|
|
|
|
nop @ for backward compatibility
|
|
|
|
.word 0x0 @ REG0: RESUME_ADDR
|
|
|
|
.word 0x0 @ REG1: RESUME_FLAG
|
|
|
|
.word 0x0 @ REG2
|
|
|
|
.word 0x0 @ REG3
|
|
|
|
_switch_addr:
|
|
|
|
.word 0x0 @ REG4: SWITCH_ADDR
|
|
|
|
_hotplug_addr:
|
|
|
|
.word 0x0 @ REG5: CPU1_BOOT_REG
|
|
|
|
.word 0x0 @ REG6
|
|
|
|
_c2_addr:
|
|
|
|
.word 0x0 @ REG7: REG_C2_ADDR
|
|
|
|
_cpu_state:
|
|
|
|
.word 0x1 @ CPU0_STATE : RESET
|
|
|
|
.word 0x2 @ CPU1_STATE : SECONDARY RESET
|
|
|
|
.word 0x2 @ CPU2_STATE : SECONDARY RESET
|
|
|
|
.word 0x2 @ CPU3_STATE : SECONDARY RESET
|
|
|
|
_gic_state:
|
|
|
|
.word 0x0 @ CPU0 - GICD_IGROUPR0
|
|
|
|
.word 0x0 @ CPU1 - GICD_IGROUPR0
|
|
|
|
.word 0x0 @ CPU2 - GICD_IGROUPR0
|
|
|
|
.word 0x0 @ CPU3 - GICD_IGROUPR0
|
|
|
|
1:
|
|
|
|
adr r0, _cpu_state
|
|
|
|
mrc p15, 0, r7, c0, c0, 5 @ read MPIDR
|
|
|
|
and r7, r7, #0xf @ r7 = cpu id
|
|
|
|
/* Read the current cpu state */
|
|
|
|
ldr r10, [r0, r7, lsl #2]
|
|
|
|
svc_entry:
|
|
|
|
tst r10, #(1 << 4)
|
|
|
|
adrne r0, _switch_addr
|
|
|
|
bne wait_for_addr
|
|
|
|
/* Clear INFORM1 */
|
|
|
|
ldr r0, =(0x10040000 + 0x804)
|
|
|
|
ldr r1, [r0]
|
|
|
|
cmp r1, #0x0
|
|
|
|
movne r1, #0x0
|
|
|
|
strne r1, [r0]
|
|
|
|
/* Get INFORM0 */
|
|
|
|
ldrne r1, =(0x10040000 + 0x800)
|
|
|
|
ldrne pc, [r1]
|
|
|
|
tst r10, #(1 << 0)
|
|
|
|
ldrne pc, =0x23e00000
|
|
|
|
adr r0, _hotplug_addr
|
|
|
|
wait_for_addr:
|
|
|
|
ldr r1, [r0]
|
|
|
|
cmp r1, #0x0
|
|
|
|
bxne r1
|
|
|
|
wfe
|
|
|
|
b wait_for_addr
|
|
|
|
.ltorg
|
|
|
|
code_end:
|
|
|
|
mov pc, lr
|