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 void sunxi_cpu_standby(plat_local_state_t cpu_state) 48 { 49 u_register_t scr = read_scr_el3(); 50 51 assert(is_local_state_retn(cpu_state)); 52 53 write_scr_el3(scr | SCR_IRQ_BIT); 54 wfi(); 55 write_scr_el3(scr); 56 } 57 58 static int sunxi_pwr_domain_on(u_register_t mpidr) 59 { 60 scpi_set_css_power_state(mpidr, 61 scpi_power_on, 62 scpi_power_on, 63 scpi_power_on); 64 65 return PSCI_E_SUCCESS; 66 } 67 68 static void sunxi_pwr_domain_off(const psci_power_state_t *target_state) 69 { 70 plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state); 71 plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state); 72 plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state); 73 74 if (is_local_state_off(cpu_pwr_state)) { 75 gicv2_cpuif_disable(); 76 } 77 78 scpi_set_css_power_state(read_mpidr(), 79 cpu_pwr_state, 80 cluster_pwr_state, 81 system_pwr_state); 82 } 83 84 static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state) 85 { 86 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { 87 gicv2_distif_init(); 88 } 89 if (is_local_state_off(CPU_PWR_STATE(target_state))) { 90 gicv2_pcpu_distif_init(); 91 gicv2_cpuif_enable(); 92 } 93 } 94 95 static void __dead2 sunxi_system_off(void) 96 { 97 uint32_t ret; 98 99 gicv2_cpuif_disable(); 100 101 /* Send the power down request to the SCP. */ 102 ret = scpi_sys_power_state(scpi_system_shutdown); 103 if (ret != SCP_OK) { 104 ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret); 105 } 106 107 psci_power_down_wfi(); 108 } 109 110 static void __dead2 sunxi_system_reset(void) 111 { 112 uint32_t ret; 113 114 gicv2_cpuif_disable(); 115 116 /* Send the system reset request to the SCP. */ 117 ret = scpi_sys_power_state(scpi_system_reboot); 118 if (ret != SCP_OK) { 119 ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret); 120 } 121 122 psci_power_down_wfi(); 123 } 124 125 static int sunxi_validate_power_state(unsigned int power_state, 126 psci_power_state_t *req_state) 127 { 128 unsigned int power_level = psci_get_pstate_pwrlvl(power_state); 129 unsigned int type = psci_get_pstate_type(power_state); 130 131 assert(req_state != NULL); 132 133 if (power_level > PLAT_MAX_PWR_LVL) { 134 return PSCI_E_INVALID_PARAMS; 135 } 136 137 if (type == PSTATE_TYPE_STANDBY) { 138 /* Only one retention power state is supported. */ 139 if (psci_get_pstate_id(power_state) > 0) { 140 return PSCI_E_INVALID_PARAMS; 141 } 142 /* The SoC cannot be suspended without losing state */ 143 if (power_level == SYSTEM_PWR_LVL) { 144 return PSCI_E_INVALID_PARAMS; 145 } 146 for (unsigned int i = 0; i <= power_level; ++i) { 147 req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; 148 } 149 } else { 150 /* Only one off power state is supported. */ 151 if (psci_get_pstate_id(power_state) > 0) { 152 return PSCI_E_INVALID_PARAMS; 153 } 154 for (unsigned int i = 0; i <= power_level; ++i) { 155 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 156 } 157 } 158 /* Higher power domain levels should all remain running */ 159 for (unsigned int i = power_level + 1; i <= PLAT_MAX_PWR_LVL; ++i) { 160 req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN; 161 } 162 163 return PSCI_E_SUCCESS; 164 } 165 166 static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state) 167 { 168 assert(req_state != NULL); 169 170 for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) { 171 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 172 } 173 } 174 175 static const plat_psci_ops_t sunxi_scpi_psci_ops = { 176 .cpu_standby = sunxi_cpu_standby, 177 .pwr_domain_on = sunxi_pwr_domain_on, 178 .pwr_domain_off = sunxi_pwr_domain_off, 179 .pwr_domain_suspend = sunxi_pwr_domain_off, 180 .pwr_domain_on_finish = sunxi_pwr_domain_on_finish, 181 .pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish, 182 .system_off = sunxi_system_off, 183 .system_reset = sunxi_system_reset, 184 .validate_power_state = sunxi_validate_power_state, 185 .validate_ns_entrypoint = sunxi_validate_ns_entrypoint, 186 .get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state, 187 }; 188 189 int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops) 190 { 191 *psci_ops = &sunxi_scpi_psci_ops; 192 193 /* Check for a valid SCP firmware. */ 194 if (mmio_read_32(SUNXI_SCP_BASE) != SCP_FIRMWARE_MAGIC) { 195 return -1; 196 } 197 198 /* Program SCP exception vectors to the firmware entrypoint. */ 199 for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) { 200 uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i); 201 uint32_t offset = SUNXI_SCP_BASE - vector; 202 203 mmio_write_32(vector, offset >> 2); 204 } 205 206 /* Take the SCP out of reset. */ 207 mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0)); 208 209 /* Wait for the SCP firmware to boot. */ 210 return scpi_wait_ready(); 211 } 212