1 /* 2 * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <platform_def.h> 10 11 #include <arch_helpers.h> 12 #include <common/debug.h> 13 #include <drivers/arm/css/css_scpi.h> 14 #include <drivers/arm/gicv2.h> 15 #include <lib/mmio.h> 16 #include <lib/psci/psci.h> 17 18 #include <sunxi_mmap.h> 19 #include <sunxi_private.h> 20 21 /* 22 * The addresses for the SCP exception vectors are defined in the or1k 23 * architecture specification. 24 */ 25 #define OR1K_VEC_FIRST 0x01 26 #define OR1K_VEC_LAST 0x0e 27 #define OR1K_VEC_ADDR(n) (0x100 * (n)) 28 29 /* 30 * This magic value is the little-endian representation of the or1k 31 * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the 32 * first instruction in the SCP firmware. 33 */ 34 #define SCP_FIRMWARE_MAGIC 0xb4400012 35 36 #define CPU_PWR_LVL MPIDR_AFFLVL0 37 #define CLUSTER_PWR_LVL MPIDR_AFFLVL1 38 #define SYSTEM_PWR_LVL MPIDR_AFFLVL2 39 40 #define CPU_PWR_STATE(state) \ 41 ((state)->pwr_domain_state[CPU_PWR_LVL]) 42 #define CLUSTER_PWR_STATE(state) \ 43 ((state)->pwr_domain_state[CLUSTER_PWR_LVL]) 44 #define SYSTEM_PWR_STATE(state) \ 45 ((state)->pwr_domain_state[SYSTEM_PWR_LVL]) 46 47 static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state) 48 { 49 if (is_local_state_run(psci_state)) { 50 return scpi_power_on; 51 } 52 if (is_local_state_retn(psci_state)) { 53 return scpi_power_retention; 54 } 55 return scpi_power_off; 56 } 57 58 static void sunxi_cpu_standby(plat_local_state_t cpu_state) 59 { 60 u_register_t scr = read_scr_el3(); 61 62 assert(is_local_state_retn(cpu_state)); 63 64 write_scr_el3(scr | SCR_IRQ_BIT); 65 wfi(); 66 write_scr_el3(scr); 67 } 68 69 static int sunxi_pwr_domain_on(u_register_t mpidr) 70 { 71 scpi_set_css_power_state(mpidr, 72 scpi_power_on, 73 scpi_power_on, 74 scpi_power_on); 75 76 return PSCI_E_SUCCESS; 77 } 78 79 static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) 80 { 81 plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state); 82 plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state); 83 plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state); 84 85 if (is_local_state_off(cpu_pwr_state)) { 86 gicv2_cpuif_disable(); 87 } 88 89 scpi_set_css_power_state(read_mpidr(), 90 scpi_map_state(cpu_pwr_state), 91 scpi_map_state(cluster_pwr_state), 92 scpi_map_state(system_pwr_state)); 93 } 94 95 static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) 96 { 97 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { 98 gicv2_distif_init(); 99 } 100 if (is_local_state_off(CPU_PWR_STATE(target_state))) { 101 gicv2_pcpu_distif_init(); 102 gicv2_cpuif_enable(); 103 } 104 } 105 106 static void __dead2 sunxi_system_off(void) 107 { 108 uint32_t ret; 109 110 gicv2_cpuif_disable(); 111 112 /* Send the power down request to the SCP. */ 113 ret = scpi_sys_power_state(scpi_system_shutdown); 114 if (ret != SCP_OK) { 115 ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret); 116 } 117 118 psci_power_down_wfi(); 119 } 120 121 static void __dead2 sunxi_system_reset(void) 122 { 123 uint32_t ret; 124 125 gicv2_cpuif_disable(); 126 127 /* Send the system reset request to the SCP. */ 128 ret = scpi_sys_power_state(scpi_system_reboot); 129 if (ret != SCP_OK) { 130 ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret); 131 } 132 133 psci_power_down_wfi(); 134 } 135 136 static int sunxi_validate_power_state(unsigned int power_state, 137 psci_power_state_t *req_state) 138 { 139 unsigned int power_level = psci_get_pstate_pwrlvl(power_state); 140 unsigned int type = psci_get_pstate_type(power_state); 141 142 assert(req_state != NULL); 143 144 if (power_level > PLAT_MAX_PWR_LVL) { 145 return PSCI_E_INVALID_PARAMS; 146 } 147 148 if (type == PSTATE_TYPE_STANDBY) { 149 /* Only one retention power state is supported. */ 150 if (psci_get_pstate_id(power_state) > 0) { 151 return PSCI_E_INVALID_PARAMS; 152 } 153 /* The SoC cannot be suspended without losing state */ 154 if (power_level == SYSTEM_PWR_LVL) { 155 return PSCI_E_INVALID_PARAMS; 156 } 157 for (unsigned int i = 0; i <= power_level; ++i) { 158 req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; 159 } 160 } else { 161 /* Only one off power state is supported. */ 162 if (psci_get_pstate_id(power_state) > 0) { 163 return PSCI_E_INVALID_PARAMS; 164 } 165 for (unsigned int i = 0; i <= power_level; ++i) { 166 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 167 } 168 } 169 /* Higher power domain levels should all remain running */ 170 for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) { 171 req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN; 172 } 173 174 return PSCI_E_SUCCESS; 175 } 176 177 static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state) 178 { 179 assert(req_state != NULL); 180 181 for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) { 182 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 183 } 184 } 185 186 static const plat_psci_ops_t sunxi_scpi_psci_ops = { 187 .cpu_standby = sunxi_cpu_standby, 188 .pwr_domain_on = sunxi_pwr_domain_on, 189 .pwr_domain_off = sunxi_pwr_domain_off, 190 .pwr_domain_suspend = sunxi_pwr_domain_off, 191 .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, 192 .pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish, 193 .system_off = sunxi_system_off, 194 .system_reset = sunxi_system_reset, 195 .validate_power_state = sunxi_validate_power_state, 196 .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, 197 .get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state, 198 }; 199 200 int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops) 201 { 202 *psci_ops = &sunxi_scpi_psci_ops; 203 204 /* Check for a valid SCP firmware. */ 205 if (mmio_read_32(SUNXI_SCP_BASE) != SCP_FIRMWARE_MAGIC) { 206 return -1; 207 } 208 209 /* Program SCP exception vectors to the firmware entrypoint. */ 210 for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) { 211 uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i); 212 uint32_t offset = SUNXI_SCP_BASE - vector; 213 214 mmio_write_32(vector, offset >> 2); 215 clean_dcache_range(vector, sizeof(uint32_t)); 216 } 217 218 /* Take the SCP out of reset. */ 219 mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); 220 221 /* Wait for the SCP firmware to boot. */ 222 return scpi_wait_ready(); 223 } 224