1 /* 2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <assert.h> 9 #include <cci.h> 10 #include <console.h> 11 #include <debug.h> 12 #include <gicv2.h> 13 #include <hi3660.h> 14 #include <hi3660_crg.h> 15 #include <mmio.h> 16 #include <psci.h> 17 #include "drivers/pwrc/hisi_pwrc.h" 18 19 #include "hikey960_def.h" 20 #include "hikey960_private.h" 21 22 #define CORE_PWR_STATE(state) \ 23 ((state)->pwr_domain_state[MPIDR_AFFLVL0]) 24 #define CLUSTER_PWR_STATE(state) \ 25 ((state)->pwr_domain_state[MPIDR_AFFLVL1]) 26 #define SYSTEM_PWR_STATE(state) \ 27 ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) 28 29 #define DMAC_GLB_REG_SEC 0x694 30 #define AXI_CONF_BASE 0x820 31 32 static uintptr_t hikey960_sec_entrypoint; 33 34 static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state) 35 { 36 unsigned long scr; 37 38 scr = read_scr_el3(); 39 40 /* Enable Physical IRQ and FIQ to wake the CPU */ 41 write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); 42 43 /* Add barrier before CPU enter WFI state */ 44 isb(); 45 dsb(); 46 wfi(); 47 48 /* 49 * Restore SCR to the original value, synchronisazion of 50 * scr_el3 is done by eret while el3_exit to save some 51 * execution cycles. 52 */ 53 write_scr_el3(scr); 54 } 55 56 static int hikey960_pwr_domain_on(u_register_t mpidr) 57 { 58 unsigned int core = mpidr & MPIDR_CPU_MASK; 59 unsigned int cluster = 60 (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; 61 int cluster_stat = cluster_is_powered_on(cluster); 62 63 hisi_set_cpu_boot_flag(cluster, core); 64 65 mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), 66 hikey960_sec_entrypoint >> 2); 67 68 if (cluster_stat) 69 hisi_powerup_core(cluster, core); 70 else 71 hisi_powerup_cluster(cluster, core); 72 73 return PSCI_E_SUCCESS; 74 } 75 76 static void 77 hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state) 78 { 79 if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) 80 cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); 81 82 gicv2_pcpu_distif_init(); 83 gicv2_cpuif_enable(); 84 } 85 86 void hikey960_pwr_domain_off(const psci_power_state_t *target_state) 87 { 88 unsigned long mpidr = read_mpidr_el1(); 89 unsigned int core = mpidr & MPIDR_CPU_MASK; 90 unsigned int cluster = 91 (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; 92 93 clr_ex(); 94 isb(); 95 dsbsy(); 96 97 gicv2_cpuif_disable(); 98 99 hisi_clear_cpu_boot_flag(cluster, core); 100 hisi_powerdn_core(cluster, core); 101 102 /* check if any core is powered up */ 103 if (hisi_test_cpu_down(cluster, core)) { 104 105 cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); 106 107 isb(); 108 dsbsy(); 109 110 hisi_powerdn_cluster(cluster, core); 111 } 112 } 113 114 static void __dead2 hikey960_system_reset(void) 115 { 116 mmio_write_32(SCTRL_SCPEREN1_REG, 117 SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS); 118 mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef); 119 panic(); 120 } 121 122 int hikey960_validate_power_state(unsigned int power_state, 123 psci_power_state_t *req_state) 124 { 125 unsigned int pstate = psci_get_pstate_type(power_state); 126 unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 127 int i; 128 129 assert(req_state); 130 131 if (pwr_lvl > PLAT_MAX_PWR_LVL) 132 return PSCI_E_INVALID_PARAMS; 133 134 /* Sanity check the requested state */ 135 if (pstate == PSTATE_TYPE_STANDBY) { 136 /* 137 * It's possible to enter standby only on power level 0 138 * Ignore any other power level. 139 */ 140 if (pwr_lvl != MPIDR_AFFLVL0) 141 return PSCI_E_INVALID_PARAMS; 142 143 req_state->pwr_domain_state[MPIDR_AFFLVL0] = 144 PLAT_MAX_RET_STATE; 145 } else { 146 for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) 147 req_state->pwr_domain_state[i] = 148 PLAT_MAX_OFF_STATE; 149 } 150 151 /* 152 * We expect the 'state id' to be zero. 153 */ 154 if (psci_get_pstate_id(power_state)) 155 return PSCI_E_INVALID_PARAMS; 156 157 return PSCI_E_SUCCESS; 158 } 159 160 static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint) 161 { 162 /* 163 * Check if the non secure entrypoint lies within the non 164 * secure DRAM. 165 */ 166 if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) 167 return PSCI_E_SUCCESS; 168 169 return PSCI_E_INVALID_ADDRESS; 170 } 171 172 static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state) 173 { 174 u_register_t mpidr = read_mpidr_el1(); 175 unsigned int core = mpidr & MPIDR_CPU_MASK; 176 unsigned int cluster = 177 (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; 178 179 if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) 180 return; 181 182 if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { 183 clr_ex(); 184 isb(); 185 dsbsy(); 186 187 gicv2_cpuif_disable(); 188 189 hisi_cpuidle_lock(cluster, core); 190 hisi_set_cpuidle_flag(cluster, core); 191 hisi_cpuidle_unlock(cluster, core); 192 193 mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core), 194 hikey960_sec_entrypoint >> 2); 195 196 hisi_enter_core_idle(cluster, core); 197 } 198 199 /* Perform the common cluster specific operations */ 200 if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { 201 hisi_cpuidle_lock(cluster, core); 202 hisi_disable_pdc(cluster); 203 204 /* check if any core is powered up */ 205 if (hisi_test_pwrdn_allcores(cluster, core)) { 206 207 cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr)); 208 209 isb(); 210 dsbsy(); 211 212 /* mask the pdc wakeup irq, then 213 * enable pdc to power down the core 214 */ 215 hisi_pdc_mask_cluster_wakeirq(cluster); 216 hisi_enable_pdc(cluster); 217 218 hisi_cpuidle_unlock(cluster, core); 219 220 /* check the SR flag bit to determine 221 * CLUSTER_IDLE_IPC or AP_SR_IPC to send 222 */ 223 if (hisi_test_ap_suspend_flag(cluster)) 224 hisi_enter_ap_suspend(cluster, core); 225 else 226 hisi_enter_cluster_idle(cluster, core); 227 } else { 228 /* enable pdc */ 229 hisi_enable_pdc(cluster); 230 hisi_cpuidle_unlock(cluster, core); 231 } 232 } 233 } 234 235 static void hikey960_sr_dma_reinit(void) 236 { 237 unsigned int ctr = 0; 238 239 mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3); 240 241 /* 1~15 channel is set non_secure */ 242 for (ctr = 1; ctr <= 15; ctr++) 243 mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40), 244 (1 << 6) | (1 << 18)); 245 } 246 247 static void 248 hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 249 { 250 unsigned long mpidr = read_mpidr_el1(); 251 unsigned int core = mpidr & MPIDR_CPU_MASK; 252 unsigned int cluster = 253 (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS; 254 255 /* Nothing to be done on waking up from retention from CPU level */ 256 if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) 257 return; 258 259 hisi_cpuidle_lock(cluster, core); 260 hisi_clear_cpuidle_flag(cluster, core); 261 hisi_cpuidle_unlock(cluster, core); 262 263 if (hisi_test_ap_suspend_flag(cluster)) { 264 hikey960_sr_dma_reinit(); 265 gicv2_cpuif_enable(); 266 console_init(PL011_UART6_BASE, PL011_UART_CLK_IN_HZ, 267 PL011_BAUDRATE); 268 } 269 270 hikey960_pwr_domain_on_finish(target_state); 271 } 272 273 static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state) 274 { 275 int i; 276 277 for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) 278 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 279 } 280 281 static const plat_psci_ops_t hikey960_psci_ops = { 282 .cpu_standby = hikey960_pwr_domain_standby, 283 .pwr_domain_on = hikey960_pwr_domain_on, 284 .pwr_domain_on_finish = hikey960_pwr_domain_on_finish, 285 .pwr_domain_off = hikey960_pwr_domain_off, 286 .pwr_domain_suspend = hikey960_pwr_domain_suspend, 287 .pwr_domain_suspend_finish = hikey960_pwr_domain_suspend_finish, 288 .system_off = NULL, 289 .system_reset = hikey960_system_reset, 290 .validate_power_state = hikey960_validate_power_state, 291 .validate_ns_entrypoint = hikey960_validate_ns_entrypoint, 292 .get_sys_suspend_power_state = hikey960_get_sys_suspend_power_state, 293 }; 294 295 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 296 const plat_psci_ops_t **psci_ops) 297 { 298 hikey960_sec_entrypoint = sec_entrypoint; 299 300 INFO("%s: sec_entrypoint=0x%lx\n", __func__, 301 (unsigned long)hikey960_sec_entrypoint); 302 303 /* 304 * Initialize PSCI ops struct 305 */ 306 *psci_ops = &hikey960_psci_ops; 307 return 0; 308 } 309