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