1*41c79775SPatrick Delaunay // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 2*41c79775SPatrick Delaunay /* 3*41c79775SPatrick Delaunay * Copyright (C) 2018, STMicroelectronics - All Rights Reserved 4*41c79775SPatrick Delaunay */ 5*41c79775SPatrick Delaunay 6*41c79775SPatrick Delaunay #include <config.h> 7*41c79775SPatrick Delaunay #include <common.h> 8*41c79775SPatrick Delaunay #include <asm/armv7.h> 9*41c79775SPatrick Delaunay #include <asm/gic.h> 10*41c79775SPatrick Delaunay #include <asm/io.h> 11*41c79775SPatrick Delaunay #include <asm/psci.h> 12*41c79775SPatrick Delaunay #include <asm/secure.h> 13*41c79775SPatrick Delaunay 14*41c79775SPatrick Delaunay #define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0 15*41c79775SPatrick Delaunay #define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1 16*41c79775SPatrick Delaunay 17*41c79775SPatrick Delaunay #define MPIDR_AFF0 GENMASK(7, 0) 18*41c79775SPatrick Delaunay 19*41c79775SPatrick Delaunay #define RCC_MP_GRSTCSETR (STM32_RCC_BASE + 0x0404) 20*41c79775SPatrick Delaunay #define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) 21*41c79775SPatrick Delaunay #define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) 22*41c79775SPatrick Delaunay #define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) 23*41c79775SPatrick Delaunay 24*41c79775SPatrick Delaunay #define STM32MP1_PSCI_NR_CPUS 2 25*41c79775SPatrick Delaunay #if STM32MP1_PSCI_NR_CPUS > CONFIG_ARMV7_PSCI_NR_CPUS 26*41c79775SPatrick Delaunay #error "invalid value for CONFIG_ARMV7_PSCI_NR_CPUS" 27*41c79775SPatrick Delaunay #endif 28*41c79775SPatrick Delaunay 29*41c79775SPatrick Delaunay u8 psci_state[STM32MP1_PSCI_NR_CPUS] __secure_data = { 30*41c79775SPatrick Delaunay PSCI_AFFINITY_LEVEL_ON, 31*41c79775SPatrick Delaunay PSCI_AFFINITY_LEVEL_OFF}; 32*41c79775SPatrick Delaunay 33*41c79775SPatrick Delaunay void __secure psci_set_state(int cpu, u8 state) 34*41c79775SPatrick Delaunay { 35*41c79775SPatrick Delaunay psci_state[cpu] = state; 36*41c79775SPatrick Delaunay dsb(); 37*41c79775SPatrick Delaunay isb(); 38*41c79775SPatrick Delaunay } 39*41c79775SPatrick Delaunay 40*41c79775SPatrick Delaunay static u32 __secure stm32mp_get_gicd_base_address(void) 41*41c79775SPatrick Delaunay { 42*41c79775SPatrick Delaunay u32 periphbase; 43*41c79775SPatrick Delaunay 44*41c79775SPatrick Delaunay /* get the GIC base address from the CBAR register */ 45*41c79775SPatrick Delaunay asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase)); 46*41c79775SPatrick Delaunay 47*41c79775SPatrick Delaunay return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET; 48*41c79775SPatrick Delaunay } 49*41c79775SPatrick Delaunay 50*41c79775SPatrick Delaunay static void __secure stm32mp_smp_kick_all_cpus(void) 51*41c79775SPatrick Delaunay { 52*41c79775SPatrick Delaunay u32 gic_dist_addr; 53*41c79775SPatrick Delaunay 54*41c79775SPatrick Delaunay gic_dist_addr = stm32mp_get_gicd_base_address(); 55*41c79775SPatrick Delaunay 56*41c79775SPatrick Delaunay /* kick all CPUs (except this one) by writing to GICD_SGIR */ 57*41c79775SPatrick Delaunay writel(1U << 24, gic_dist_addr + GICD_SGIR); 58*41c79775SPatrick Delaunay } 59*41c79775SPatrick Delaunay 60*41c79775SPatrick Delaunay void __secure psci_arch_cpu_entry(void) 61*41c79775SPatrick Delaunay { 62*41c79775SPatrick Delaunay u32 cpu = psci_get_cpu_id(); 63*41c79775SPatrick Delaunay 64*41c79775SPatrick Delaunay psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON); 65*41c79775SPatrick Delaunay } 66*41c79775SPatrick Delaunay 67*41c79775SPatrick Delaunay int __secure psci_features(u32 function_id, u32 psci_fid) 68*41c79775SPatrick Delaunay { 69*41c79775SPatrick Delaunay switch (psci_fid) { 70*41c79775SPatrick Delaunay case ARM_PSCI_0_2_FN_PSCI_VERSION: 71*41c79775SPatrick Delaunay case ARM_PSCI_0_2_FN_CPU_OFF: 72*41c79775SPatrick Delaunay case ARM_PSCI_0_2_FN_CPU_ON: 73*41c79775SPatrick Delaunay case ARM_PSCI_0_2_FN_AFFINITY_INFO: 74*41c79775SPatrick Delaunay case ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE: 75*41c79775SPatrick Delaunay case ARM_PSCI_0_2_FN_SYSTEM_OFF: 76*41c79775SPatrick Delaunay case ARM_PSCI_0_2_FN_SYSTEM_RESET: 77*41c79775SPatrick Delaunay return 0x0; 78*41c79775SPatrick Delaunay } 79*41c79775SPatrick Delaunay return ARM_PSCI_RET_NI; 80*41c79775SPatrick Delaunay } 81*41c79775SPatrick Delaunay 82*41c79775SPatrick Delaunay unsigned int __secure psci_version(u32 function_id) 83*41c79775SPatrick Delaunay { 84*41c79775SPatrick Delaunay return ARM_PSCI_VER_1_0; 85*41c79775SPatrick Delaunay } 86*41c79775SPatrick Delaunay 87*41c79775SPatrick Delaunay int __secure psci_affinity_info(u32 function_id, u32 target_affinity, 88*41c79775SPatrick Delaunay u32 lowest_affinity_level) 89*41c79775SPatrick Delaunay { 90*41c79775SPatrick Delaunay u32 cpu = target_affinity & MPIDR_AFF0; 91*41c79775SPatrick Delaunay 92*41c79775SPatrick Delaunay if (lowest_affinity_level > 0) 93*41c79775SPatrick Delaunay return ARM_PSCI_RET_INVAL; 94*41c79775SPatrick Delaunay 95*41c79775SPatrick Delaunay if (target_affinity & ~MPIDR_AFF0) 96*41c79775SPatrick Delaunay return ARM_PSCI_RET_INVAL; 97*41c79775SPatrick Delaunay 98*41c79775SPatrick Delaunay if (cpu >= STM32MP1_PSCI_NR_CPUS) 99*41c79775SPatrick Delaunay return ARM_PSCI_RET_INVAL; 100*41c79775SPatrick Delaunay 101*41c79775SPatrick Delaunay return psci_state[cpu]; 102*41c79775SPatrick Delaunay } 103*41c79775SPatrick Delaunay 104*41c79775SPatrick Delaunay int __secure psci_migrate_info_type(u32 function_id) 105*41c79775SPatrick Delaunay { 106*41c79775SPatrick Delaunay /* Trusted OS is either not present or does not require migration */ 107*41c79775SPatrick Delaunay return 2; 108*41c79775SPatrick Delaunay } 109*41c79775SPatrick Delaunay 110*41c79775SPatrick Delaunay int __secure psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc, 111*41c79775SPatrick Delaunay u32 context_id) 112*41c79775SPatrick Delaunay { 113*41c79775SPatrick Delaunay u32 cpu = target_cpu & MPIDR_AFF0; 114*41c79775SPatrick Delaunay 115*41c79775SPatrick Delaunay if (target_cpu & ~MPIDR_AFF0) 116*41c79775SPatrick Delaunay return ARM_PSCI_RET_INVAL; 117*41c79775SPatrick Delaunay 118*41c79775SPatrick Delaunay if (cpu >= STM32MP1_PSCI_NR_CPUS) 119*41c79775SPatrick Delaunay return ARM_PSCI_RET_INVAL; 120*41c79775SPatrick Delaunay 121*41c79775SPatrick Delaunay if (psci_state[cpu] == PSCI_AFFINITY_LEVEL_ON) 122*41c79775SPatrick Delaunay return ARM_PSCI_RET_ALREADY_ON; 123*41c79775SPatrick Delaunay 124*41c79775SPatrick Delaunay /* store target PC and context id*/ 125*41c79775SPatrick Delaunay psci_save(cpu, pc, context_id); 126*41c79775SPatrick Delaunay 127*41c79775SPatrick Delaunay /* write entrypoint in backup RAM register */ 128*41c79775SPatrick Delaunay writel((u32)&psci_cpu_entry, TAMP_BACKUP_BRANCH_ADDRESS); 129*41c79775SPatrick Delaunay psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON_PENDING); 130*41c79775SPatrick Delaunay 131*41c79775SPatrick Delaunay /* write magic number in backup register */ 132*41c79775SPatrick Delaunay if (cpu == 0x01) 133*41c79775SPatrick Delaunay writel(BOOT_API_A7_CORE1_MAGIC_NUMBER, 134*41c79775SPatrick Delaunay TAMP_BACKUP_MAGIC_NUMBER); 135*41c79775SPatrick Delaunay else 136*41c79775SPatrick Delaunay writel(BOOT_API_A7_CORE0_MAGIC_NUMBER, 137*41c79775SPatrick Delaunay TAMP_BACKUP_MAGIC_NUMBER); 138*41c79775SPatrick Delaunay 139*41c79775SPatrick Delaunay stm32mp_smp_kick_all_cpus(); 140*41c79775SPatrick Delaunay 141*41c79775SPatrick Delaunay return ARM_PSCI_RET_SUCCESS; 142*41c79775SPatrick Delaunay } 143*41c79775SPatrick Delaunay 144*41c79775SPatrick Delaunay int __secure psci_cpu_off(u32 function_id) 145*41c79775SPatrick Delaunay { 146*41c79775SPatrick Delaunay u32 cpu; 147*41c79775SPatrick Delaunay 148*41c79775SPatrick Delaunay cpu = psci_get_cpu_id(); 149*41c79775SPatrick Delaunay 150*41c79775SPatrick Delaunay psci_cpu_off_common(); 151*41c79775SPatrick Delaunay psci_set_state(cpu, PSCI_AFFINITY_LEVEL_OFF); 152*41c79775SPatrick Delaunay 153*41c79775SPatrick Delaunay /* reset core: wfi is managed by BootRom */ 154*41c79775SPatrick Delaunay if (cpu == 0x01) 155*41c79775SPatrick Delaunay writel(RCC_MP_GRSTCSETR_MPUP1RST, RCC_MP_GRSTCSETR); 156*41c79775SPatrick Delaunay else 157*41c79775SPatrick Delaunay writel(RCC_MP_GRSTCSETR_MPUP0RST, RCC_MP_GRSTCSETR); 158*41c79775SPatrick Delaunay 159*41c79775SPatrick Delaunay /* just waiting reset */ 160*41c79775SPatrick Delaunay while (1) 161*41c79775SPatrick Delaunay wfi(); 162*41c79775SPatrick Delaunay } 163*41c79775SPatrick Delaunay 164*41c79775SPatrick Delaunay void __secure psci_system_reset(u32 function_id) 165*41c79775SPatrick Delaunay { 166*41c79775SPatrick Delaunay /* System reset */ 167*41c79775SPatrick Delaunay writel(RCC_MP_GRSTCSETR_MPSYSRST, RCC_MP_GRSTCSETR); 168*41c79775SPatrick Delaunay /* just waiting reset */ 169*41c79775SPatrick Delaunay while (1) 170*41c79775SPatrick Delaunay wfi(); 171*41c79775SPatrick Delaunay } 172*41c79775SPatrick Delaunay 173*41c79775SPatrick Delaunay void __secure psci_system_off(u32 function_id) 174*41c79775SPatrick Delaunay { 175*41c79775SPatrick Delaunay /* System Off is not managed, waiting user power off 176*41c79775SPatrick Delaunay * TODO: handle I2C write in PMIC Main Control register bit 0 = SWOFF 177*41c79775SPatrick Delaunay */ 178*41c79775SPatrick Delaunay while (1) 179*41c79775SPatrick Delaunay wfi(); 180*41c79775SPatrick Delaunay } 181