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