1 /* 2 * Copyright (c) 2017-2020, 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 <drivers/delay_timer.h> 16 #include <lib/mmio.h> 17 #include <lib/psci/psci.h> 18 #include <plat/common/platform.h> 19 20 #include <sunxi_cpucfg.h> 21 #include <sunxi_def.h> 22 #include <sunxi_mmap.h> 23 #include <sunxi_private.h> 24 25 #define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010) 26 #define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014) 27 #define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018) 28 29 #define CPU_PWR_LVL MPIDR_AFFLVL0 30 #define CLUSTER_PWR_LVL MPIDR_AFFLVL1 31 #define SYSTEM_PWR_LVL MPIDR_AFFLVL2 32 33 #define CPU_PWR_STATE(state) \ 34 ((state)->pwr_domain_state[CPU_PWR_LVL]) 35 #define CLUSTER_PWR_STATE(state) \ 36 ((state)->pwr_domain_state[CLUSTER_PWR_LVL]) 37 #define SYSTEM_PWR_STATE(state) \ 38 ((state)->pwr_domain_state[SYSTEM_PWR_LVL]) 39 40 #define mpidr_is_valid(mpidr) (plat_core_pos_by_mpidr(mpidr) >= 0) 41 42 /* 43 * The addresses for the SCP exception vectors are defined in the or1k 44 * architecture specification. 45 */ 46 #define OR1K_VEC_FIRST 0x01 47 #define OR1K_VEC_LAST 0x0e 48 #define OR1K_VEC_ADDR(n) (0x100 * (n)) 49 50 /* 51 * This magic value is the little-endian representation of the or1k 52 * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the 53 * first instruction in the SCP firmware. 54 */ 55 #define SCP_FIRMWARE_MAGIC 0xb4400012 56 57 static bool scpi_available; 58 59 static inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state) 60 { 61 if (is_local_state_run(psci_state)) 62 return scpi_power_on; 63 if (is_local_state_retn(psci_state)) 64 return scpi_power_retention; 65 return scpi_power_off; 66 } 67 68 static void sunxi_cpu_standby(plat_local_state_t cpu_state) 69 { 70 u_register_t scr = read_scr_el3(); 71 72 assert(is_local_state_retn(cpu_state)); 73 74 write_scr_el3(scr | SCR_IRQ_BIT); 75 wfi(); 76 write_scr_el3(scr); 77 } 78 79 static int sunxi_pwr_domain_on(u_register_t mpidr) 80 { 81 if (mpidr_is_valid(mpidr) == 0) 82 return PSCI_E_INTERN_FAIL; 83 84 if (scpi_available) { 85 scpi_set_css_power_state(mpidr, 86 scpi_power_on, 87 scpi_power_on, 88 scpi_power_on); 89 } else { 90 sunxi_cpu_on(mpidr); 91 } 92 93 return PSCI_E_SUCCESS; 94 } 95 96 static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) 97 { 98 plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state); 99 plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state); 100 plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state); 101 102 if (is_local_state_off(cpu_pwr_state)) 103 gicv2_cpuif_disable(); 104 105 if (scpi_available) { 106 scpi_set_css_power_state(read_mpidr(), 107 scpi_map_state(cpu_pwr_state), 108 scpi_map_state(cluster_pwr_state), 109 scpi_map_state(system_pwr_state)); 110 } 111 } 112 113 static void __dead2 sunxi_pwr_down_wfi(const psci_power_state_t *target_state) 114 { 115 sunxi_cpu_off(read_mpidr()); 116 117 while (1) 118 wfi(); 119 } 120 121 static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) 122 { 123 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) 124 gicv2_distif_init(); 125 if (is_local_state_off(CPU_PWR_STATE(target_state))) { 126 gicv2_pcpu_distif_init(); 127 gicv2_cpuif_enable(); 128 } 129 } 130 131 static void __dead2 sunxi_system_off(void) 132 { 133 gicv2_cpuif_disable(); 134 135 if (scpi_available) { 136 /* Send the power down request to the SCP */ 137 uint32_t ret = scpi_sys_power_state(scpi_system_shutdown); 138 139 if (ret != SCP_OK) 140 ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret); 141 } 142 143 /* Turn off all secondary CPUs */ 144 sunxi_disable_secondary_cpus(read_mpidr()); 145 146 sunxi_power_down(); 147 148 udelay(1000); 149 ERROR("PSCI: Cannot turn off system, halting\n"); 150 wfi(); 151 panic(); 152 } 153 154 static void __dead2 sunxi_system_reset(void) 155 { 156 gicv2_cpuif_disable(); 157 158 if (scpi_available) { 159 /* Send the system reset request to the SCP */ 160 uint32_t ret = scpi_sys_power_state(scpi_system_reboot); 161 162 if (ret != SCP_OK) 163 ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret); 164 } 165 166 /* Reset the whole system when the watchdog times out */ 167 mmio_write_32(SUNXI_WDOG0_CFG_REG, 1); 168 /* Enable the watchdog with the shortest timeout (0.5 seconds) */ 169 mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1); 170 /* Wait for twice the watchdog timeout before panicking */ 171 mdelay(1000); 172 173 ERROR("PSCI: System reset failed\n"); 174 wfi(); 175 panic(); 176 } 177 178 static int sunxi_validate_power_state(unsigned int power_state, 179 psci_power_state_t *req_state) 180 { 181 unsigned int power_level = psci_get_pstate_pwrlvl(power_state); 182 unsigned int type = psci_get_pstate_type(power_state); 183 184 assert(req_state != NULL); 185 186 if (power_level > PLAT_MAX_PWR_LVL) 187 return PSCI_E_INVALID_PARAMS; 188 189 if (type == PSTATE_TYPE_STANDBY) { 190 /* Only one retention power state is supported. */ 191 if (psci_get_pstate_id(power_state) > 0) 192 return PSCI_E_INVALID_PARAMS; 193 /* The SoC cannot be suspended without losing state */ 194 if (power_level == SYSTEM_PWR_LVL) 195 return PSCI_E_INVALID_PARAMS; 196 for (unsigned int i = 0; i <= power_level; ++i) 197 req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; 198 } else { 199 /* Only one off power state is supported. */ 200 if (psci_get_pstate_id(power_state) > 0) 201 return PSCI_E_INVALID_PARAMS; 202 for (unsigned int i = 0; i <= power_level; ++i) 203 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 204 } 205 /* Higher power domain levels should all remain running */ 206 for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) 207 req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN; 208 209 return PSCI_E_SUCCESS; 210 } 211 212 static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint) 213 { 214 /* The non-secure entry point must be in DRAM */ 215 if (ns_entrypoint >= SUNXI_DRAM_BASE) 216 return PSCI_E_SUCCESS; 217 218 return PSCI_E_INVALID_ADDRESS; 219 } 220 221 static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state) 222 { 223 assert(req_state); 224 225 for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) 226 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 227 } 228 229 static int sunxi_get_node_hw_state(u_register_t mpidr, 230 unsigned int power_level) 231 { 232 unsigned int cluster_state, cpu_state; 233 unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr); 234 235 /* SoC power level (always on if PSCI works). */ 236 if (power_level == SYSTEM_PWR_LVL) 237 return HW_ON; 238 if (scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state)) 239 return PSCI_E_NOT_SUPPORTED; 240 /* Cluster power level (full power state available). */ 241 if (power_level == CLUSTER_PWR_LVL) { 242 if (cluster_state == scpi_power_on) 243 return HW_ON; 244 if (cluster_state == scpi_power_retention) 245 return HW_STANDBY; 246 return HW_OFF; 247 } 248 /* CPU power level (one bit boolean for on or off). */ 249 return ((cpu_state & BIT(cpu)) != 0) ? HW_ON : HW_OFF; 250 } 251 252 static plat_psci_ops_t sunxi_psci_ops = { 253 .cpu_standby = sunxi_cpu_standby, 254 .pwr_domain_on = sunxi_pwr_domain_on, 255 .pwr_domain_off = sunxi_pwr_domain_off, 256 .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, 257 .system_off = sunxi_system_off, 258 .system_reset = sunxi_system_reset, 259 .validate_power_state = sunxi_validate_power_state, 260 .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, 261 }; 262 263 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 264 const plat_psci_ops_t **psci_ops) 265 { 266 assert(psci_ops); 267 268 /* Program all CPU entry points. */ 269 for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) { 270 mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu), 271 sec_entrypoint & 0xffffffff); 272 mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu), 273 sec_entrypoint >> 32); 274 } 275 276 /* Check for a valid SCP firmware, and boot the SCP if found. */ 277 if (mmio_read_32(SUNXI_SCP_BASE) == SCP_FIRMWARE_MAGIC) { 278 /* Program SCP exception vectors to the firmware entrypoint. */ 279 for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) { 280 uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i); 281 uint32_t offset = SUNXI_SCP_BASE - vector; 282 283 mmio_write_32(vector, offset >> 2); 284 clean_dcache_range(vector, sizeof(uint32_t)); 285 } 286 /* Take the SCP out of reset. */ 287 mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); 288 /* Wait for the SCP firmware to boot. */ 289 if (scpi_wait_ready() == 0) 290 scpi_available = true; 291 } 292 293 NOTICE("PSCI: System suspend is %s\n", 294 scpi_available ? "available via SCPI" : "unavailable"); 295 if (scpi_available) { 296 /* Suspend is only available via SCPI. */ 297 sunxi_psci_ops.pwr_domain_suspend = sunxi_pwr_domain_off; 298 sunxi_psci_ops.pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish; 299 sunxi_psci_ops.get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state; 300 sunxi_psci_ops.get_node_hw_state = sunxi_get_node_hw_state; 301 } else { 302 /* This is only needed when SCPI is unavailable. */ 303 sunxi_psci_ops.pwr_domain_pwr_down_wfi = sunxi_pwr_down_wfi; 304 } 305 306 *psci_ops = &sunxi_psci_ops; 307 308 return 0; 309 } 310