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