1/* 2 * Copyright (C) 2013 Samsung Electronics 3 * Akshay Saraswat <akshay.s@samsung.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8#include <config.h> 9#include <asm/arch/cpu.h> 10 11 .globl relocate_wait_code 12relocate_wait_code: 13 adr r0, code_base @ r0: source address (start) 14 adr r1, code_end @ r1: source address (end) 15 ldr r2, =0x02073000 @ r2: target address 161: 17 ldmia r0!, {r3-r6} 18 stmia r2!, {r3-r6} 19 cmp r0, r1 20 blt 1b 21 b code_end 22 .ltorg 23/* 24 * Secondary core waits here until Primary wake it up. 25 * Below code is copied to CONFIG_EXYNOS_RELOCATE_CODE_BASE. 26 * This is a workaround code which is supposed to act as a 27 * substitute/supplement to the iROM code. 28 * 29 * This workaround code is relocated to the address 0x02073000 30 * because that comes out to be the last 4KB of the iRAM 31 * (Base Address - 0x02020000, Limit Address - 0x020740000). 32 * 33 * U-boot and kernel are aware of this code and flags by the simple 34 * fact that we are implementing a workaround in the last 4KB 35 * of the iRAM and we have already defined these flag and address 36 * values in both kernel and U-boot for our use. 37 */ 38code_base: 39 b 1f 40/* 41 * These addresses are being used as flags in u-boot and kernel. 42 * 43 * Jump address for resume and flag to check for resume/reset: 44 * Resume address - 0x2073008 45 * Resume flag - 0x207300C 46 * 47 * Jump address for cluster switching: 48 * Switch address - 0x2073018 49 * 50 * Jump address for core hotplug: 51 * Hotplug address - 0x207301C 52 * 53 * Jump address for C2 state (Reserved for future not being used right now): 54 * C2 address - 0x2073024 55 * 56 * Managed per core status for the active cluster: 57 * CPU0 state - 0x2073028 58 * CPU1 state - 0x207302C 59 * CPU2 state - 0x2073030 60 * CPU3 state - 0x2073034 61 * 62 * Managed per core GIC status for the active cluster: 63 * CPU0 gic state - 0x2073038 64 * CPU1 gic state - 0x207303C 65 * CPU2 gic state - 0x2073040 66 * CPU3 gic state - 0x2073044 67 * 68 * Logic of the code: 69 * Step-1: Read current CPU status. 70 * Step-2: If it's a resume then continue, else jump to step 4. 71 * Step-3: Clear inform1 PMU register and jump to inform0 value. 72 * Step-4: If it's a switch, C2 or reset, get the hotplug address. 73 * Step-5: If address is not available, enter WFE. 74 * Step-6: If address is available, jump to that address. 75 */ 76 nop @ for backward compatibility 77 .word 0x0 @ REG0: RESUME_ADDR 78 .word 0x0 @ REG1: RESUME_FLAG 79 .word 0x0 @ REG2 80 .word 0x0 @ REG3 81_switch_addr: 82 .word 0x0 @ REG4: SWITCH_ADDR 83_hotplug_addr: 84 .word 0x0 @ REG5: CPU1_BOOT_REG 85 .word 0x0 @ REG6 86_c2_addr: 87 .word 0x0 @ REG7: REG_C2_ADDR 88_cpu_state: 89 .word 0x1 @ CPU0_STATE : RESET 90 .word 0x2 @ CPU1_STATE : SECONDARY RESET 91 .word 0x2 @ CPU2_STATE : SECONDARY RESET 92 .word 0x2 @ CPU3_STATE : SECONDARY RESET 93_gic_state: 94 .word 0x0 @ CPU0 - GICD_IGROUPR0 95 .word 0x0 @ CPU1 - GICD_IGROUPR0 96 .word 0x0 @ CPU2 - GICD_IGROUPR0 97 .word 0x0 @ CPU3 - GICD_IGROUPR0 981: 99 adr r0, _cpu_state 100 mrc p15, 0, r7, c0, c0, 5 @ read MPIDR 101 and r7, r7, #0xf @ r7 = cpu id 102/* Read the current cpu state */ 103 ldr r10, [r0, r7, lsl #2] 104svc_entry: 105 tst r10, #(1 << 4) 106 adrne r0, _switch_addr 107 bne wait_for_addr 108/* Clear INFORM1 */ 109 ldr r0, =(0x10040000 + 0x804) 110 ldr r1, [r0] 111 cmp r1, #0x0 112 movne r1, #0x0 113 strne r1, [r0] 114/* Get INFORM0 */ 115 ldrne r1, =(0x10040000 + 0x800) 116 ldrne pc, [r1] 117 tst r10, #(1 << 0) 118 ldrne pc, =0x23e00000 119 adr r0, _hotplug_addr 120wait_for_addr: 121 ldr r1, [r0] 122 cmp r1, #0x0 123 bxne r1 124 wfe 125 b wait_for_addr 126 .ltorg 127code_end: 128 mov pc, lr 129