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