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