1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * Copyright 2015 Freescale Semiconductor, Inc. 4 * Author: Wang Dongsheng <dongsheng.wang@freescale.com> 5 */ 6 7#include <config.h> 8#include <linux/linkage.h> 9 10#include <asm/armv7.h> 11#include <asm/arch-armv7/generictimer.h> 12#include <asm/psci.h> 13 14#define RCPM_TWAITSR 0x04C 15 16#define SCFG_CORE0_SFT_RST 0x130 17#define SCFG_CORESRENCR 0x204 18 19#define DCFG_CCSR_RSTCR 0x0B0 20#define DCFG_CCSR_RSTCR_RESET_REQ 0x2 21#define DCFG_CCSR_BRR 0x0E4 22#define DCFG_CCSR_SCRATCHRW1 0x200 23 24#define PSCI_FN_PSCI_VERSION_FEATURE_MASK 0x0 25#define PSCI_FN_CPU_SUSPEND_FEATURE_MASK 0x0 26#define PSCI_FN_CPU_OFF_FEATURE_MASK 0x0 27#define PSCI_FN_CPU_ON_FEATURE_MASK 0x0 28#define PSCI_FN_AFFINITY_INFO_FEATURE_MASK 0x0 29#define PSCI_FN_SYSTEM_OFF_FEATURE_MASK 0x0 30#define PSCI_FN_SYSTEM_RESET_FEATURE_MASK 0x0 31#define PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK 0x0 32 33 .pushsection ._secure.text, "ax" 34 35 .arch_extension sec 36 37 .align 5 38 39#define ONE_MS (COUNTER_FREQUENCY / 1000) 40#define RESET_WAIT (30 * ONE_MS) 41 42.globl psci_version 43psci_version: 44 movw r0, #0 45 movt r0, #1 46 47 bx lr 48 49_ls102x_psci_supported_table: 50 .word ARM_PSCI_0_2_FN_PSCI_VERSION 51 .word PSCI_FN_PSCI_VERSION_FEATURE_MASK 52 .word ARM_PSCI_0_2_FN_CPU_SUSPEND 53 .word PSCI_FN_CPU_SUSPEND_FEATURE_MASK 54 .word ARM_PSCI_0_2_FN_CPU_OFF 55 .word PSCI_FN_CPU_OFF_FEATURE_MASK 56 .word ARM_PSCI_0_2_FN_CPU_ON 57 .word PSCI_FN_CPU_ON_FEATURE_MASK 58 .word ARM_PSCI_0_2_FN_AFFINITY_INFO 59 .word PSCI_FN_AFFINITY_INFO_FEATURE_MASK 60 .word ARM_PSCI_0_2_FN_SYSTEM_OFF 61 .word PSCI_FN_SYSTEM_OFF_FEATURE_MASK 62 .word ARM_PSCI_0_2_FN_SYSTEM_RESET 63 .word PSCI_FN_SYSTEM_RESET_FEATURE_MASK 64 .word ARM_PSCI_1_0_FN_SYSTEM_SUSPEND 65 .word PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK 66 .word 0 67 .word ARM_PSCI_RET_NI 68 69.globl psci_features 70psci_features: 71 adr r2, _ls102x_psci_supported_table 721: ldr r3, [r2] 73 cmp r3, #0 74 beq out_psci_features 75 cmp r1, r3 76 addne r2, r2, #8 77 bne 1b 78 79out_psci_features: 80 ldr r0, [r2, #4] 81 bx lr 82 83@ r0: return value ARM_PSCI_RET_SUCCESS or ARM_PSCI_RET_INVAL 84@ r1: input target CPU ID in MPIDR format, original value in r1 may be dropped 85@ r4: output validated CPU ID if ARM_PSCI_RET_SUCCESS returns, meaningless for 86@ ARM_PSCI_RET_INVAL,suppose caller saves r4 before calling 87LENTRY(psci_check_target_cpu_id) 88 @ Get the real CPU number 89 and r4, r1, #0xff 90 mov r0, #ARM_PSCI_RET_INVAL 91 92 @ Bit[31:24], bits must be zero. 93 tst r1, #0xff000000 94 bxne lr 95 96 @ Affinity level 2 - Cluster: only one cluster in LS1021xa. 97 tst r1, #0xff0000 98 bxne lr 99 100 @ Affinity level 1 - Processors: should be in 0xf00 format. 101 lsr r1, r1, #8 102 teq r1, #0xf 103 bxne lr 104 105 @ Affinity level 0 - CPU: only 0, 1 are valid in LS1021xa. 106 cmp r4, #2 107 bxge lr 108 109 mov r0, #ARM_PSCI_RET_SUCCESS 110 bx lr 111ENDPROC(psci_check_target_cpu_id) 112 113 @ r1 = target CPU 114 @ r2 = target PC 115.globl psci_cpu_on 116psci_cpu_on: 117 push {r4, r5, r6, lr} 118 119 @ Clear and Get the correct CPU number 120 @ r1 = 0xf01 121 bl psci_check_target_cpu_id 122 cmp r0, #ARM_PSCI_RET_INVAL 123 beq out_psci_cpu_on 124 125 mov r0, r4 126 mov r1, r2 127 bl psci_save_target_pc 128 mov r1, r4 129 130 @ Get DCFG base address 131 movw r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff) 132 movt r4, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16) 133 134 @ Detect target CPU state 135 ldr r2, [r4, #DCFG_CCSR_BRR] 136 rev r2, r2 137 lsr r2, r2, r1 138 ands r2, r2, #1 139 beq holdoff_release 140 141 @ Reset target CPU 142 @ Get SCFG base address 143 movw r0, #(CONFIG_SYS_FSL_SCFG_ADDR & 0xffff) 144 movt r0, #(CONFIG_SYS_FSL_SCFG_ADDR >> 16) 145 146 @ Enable CORE Soft Reset 147 movw r5, #0 148 movt r5, #(1 << 15) 149 rev r5, r5 150 str r5, [r0, #SCFG_CORESRENCR] 151 152 @ Get CPUx offset register 153 mov r6, #0x4 154 mul r6, r6, r1 155 add r2, r0, r6 156 157 @ Do reset on target CPU 158 movw r5, #0 159 movt r5, #(1 << 15) 160 rev r5, r5 161 str r5, [r2, #SCFG_CORE0_SFT_RST] 162 163 @ Wait target CPU up 164 timer_wait r2, RESET_WAIT 165 166 @ Disable CORE soft reset 167 mov r5, #0 168 str r5, [r0, #SCFG_CORESRENCR] 169 170holdoff_release: 171 @ Release on target CPU 172 ldr r2, [r4, #DCFG_CCSR_BRR] 173 mov r6, #1 174 lsl r6, r6, r1 @ 32 bytes per CPU 175 176 rev r6, r6 177 orr r2, r2, r6 178 str r2, [r4, #DCFG_CCSR_BRR] 179 180 @ Set secondary boot entry 181 ldr r6, =psci_cpu_entry 182 rev r6, r6 183 str r6, [r4, #DCFG_CCSR_SCRATCHRW1] 184 185 isb 186 dsb 187 188 @ Return 189 mov r0, #ARM_PSCI_RET_SUCCESS 190 191out_psci_cpu_on: 192 pop {r4, r5, r6, lr} 193 bx lr 194 195.globl psci_cpu_off 196psci_cpu_off: 197 bl psci_cpu_off_common 198 1991: wfi 200 b 1b 201 202.globl psci_affinity_info 203psci_affinity_info: 204 push {lr} 205 206 mov r0, #ARM_PSCI_RET_INVAL 207 208 @ Verify Affinity level 209 cmp r2, #0 210 bne out_affinity_info 211 212 bl psci_check_target_cpu_id 213 cmp r0, #ARM_PSCI_RET_INVAL 214 beq out_affinity_info 215 mov r1, r4 216 217 @ Get RCPM base address 218 movw r4, #(CONFIG_SYS_FSL_RCPM_ADDR & 0xffff) 219 movt r4, #(CONFIG_SYS_FSL_RCPM_ADDR >> 16) 220 221 mov r0, #PSCI_AFFINITY_LEVEL_ON 222 223 @ Detect target CPU state 224 ldr r2, [r4, #RCPM_TWAITSR] 225 rev r2, r2 226 lsr r2, r2, r1 227 ands r2, r2, #1 228 beq out_affinity_info 229 230 mov r0, #PSCI_AFFINITY_LEVEL_OFF 231 232out_affinity_info: 233 pop {pc} 234 235.globl psci_system_reset 236psci_system_reset: 237 @ Get DCFG base address 238 movw r1, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff) 239 movt r1, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16) 240 241 mov r2, #DCFG_CCSR_RSTCR_RESET_REQ 242 rev r2, r2 243 str r2, [r1, #DCFG_CCSR_RSTCR] 244 2451: wfi 246 b 1b 247 248.globl psci_system_suspend 249psci_system_suspend: 250 push {lr} 251 252 bl ls1_system_suspend 253 254 pop {pc} 255 256 .popsection 257