1 /* 2 * Copyright (c) 2017-2018, 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 <bl_common.h> 10 #include <console.h> 11 #include <context.h> 12 #include <context_mgmt.h> 13 #include <debug.h> 14 #include <mmio.h> 15 #include <platform.h> 16 #include <platform_def.h> 17 #include <psci.h> 18 #include "hi3798cv200.h" 19 #include "plat_private.h" 20 21 #define REG_PERI_CPU_RVBARADDR 0xF8A80034 22 #define REG_PERI_CPU_AARCH_MODE 0xF8A80030 23 24 #define REG_CPU_LP_CPU_SW_BEGIN 10 25 #define CPU_REG_COREPO_SRST 12 26 #define CPU_REG_CORE_SRST 8 27 28 static void poplar_cpu_standby(plat_local_state_t cpu_state) 29 { 30 dsb(); 31 wfi(); 32 } 33 34 static int poplar_pwr_domain_on(u_register_t mpidr) 35 { 36 unsigned int cpu = plat_core_pos_by_mpidr(mpidr); 37 unsigned int regval, regval_bak; 38 39 /* Select 400MHz before start slave cores */ 40 regval_bak = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP)); 41 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x206); 42 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x606); 43 44 /* Clear the slave cpu arm_por_srst_req reset */ 45 regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST)); 46 regval &= ~(1 << (cpu + CPU_REG_COREPO_SRST)); 47 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval); 48 49 /* Clear the slave cpu reset */ 50 regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST)); 51 regval &= ~(1 << (cpu + CPU_REG_CORE_SRST)); 52 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval); 53 54 /* Restore cpu frequency */ 55 regval = regval_bak & (~(1 << REG_CPU_LP_CPU_SW_BEGIN)); 56 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval); 57 mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval_bak); 58 59 return PSCI_E_SUCCESS; 60 } 61 62 static void poplar_pwr_domain_off(const psci_power_state_t *target_state) 63 { 64 assert(0); 65 } 66 67 static void poplar_pwr_domain_suspend(const psci_power_state_t *target_state) 68 { 69 assert(0); 70 } 71 72 static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state) 73 { 74 assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == 75 PLAT_MAX_OFF_STATE); 76 77 /* Enable the gic cpu interface */ 78 poplar_gic_pcpu_init(); 79 80 /* Program the gic per-cpu distributor or re-distributor interface */ 81 poplar_gic_cpuif_enable(); 82 } 83 84 static void poplar_pwr_domain_suspend_finish( 85 const psci_power_state_t *target_state) 86 { 87 assert(0); 88 } 89 90 static void __dead2 poplar_system_off(void) 91 { 92 ERROR("Poplar System Off: operation not handled.\n"); 93 panic(); 94 } 95 96 static void __dead2 poplar_system_reset(void) 97 { 98 mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551); 99 mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0), 0x00000100); 100 mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000003); 101 102 wfi(); 103 ERROR("Poplar System Reset: operation not handled.\n"); 104 panic(); 105 } 106 107 static int32_t poplar_validate_power_state(unsigned int power_state, 108 psci_power_state_t *req_state) 109 { 110 VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); 111 112 int pstate = psci_get_pstate_type(power_state); 113 114 assert(req_state); 115 116 /* Sanity check the requested state */ 117 if (pstate == PSTATE_TYPE_STANDBY) 118 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; 119 else 120 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; 121 122 /* We expect the 'state id' to be zero */ 123 if (psci_get_pstate_id(power_state)) 124 return PSCI_E_INVALID_PARAMS; 125 126 return PSCI_E_SUCCESS; 127 } 128 129 static int poplar_validate_ns_entrypoint(uintptr_t entrypoint) 130 { 131 /* 132 * Check if the non secure entrypoint lies within the non 133 * secure DRAM. 134 */ 135 if ((entrypoint >= DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE))) 136 return PSCI_E_SUCCESS; 137 138 return PSCI_E_INVALID_ADDRESS; 139 } 140 141 static void poplar_get_sys_suspend_power_state(psci_power_state_t *req_state) 142 { 143 int i; 144 145 for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) 146 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 147 } 148 149 static const plat_psci_ops_t poplar_plat_psci_ops = { 150 .cpu_standby = poplar_cpu_standby, 151 .pwr_domain_on = poplar_pwr_domain_on, 152 .pwr_domain_off = poplar_pwr_domain_off, 153 .pwr_domain_suspend = poplar_pwr_domain_suspend, 154 .pwr_domain_on_finish = poplar_pwr_domain_on_finish, 155 .pwr_domain_suspend_finish = poplar_pwr_domain_suspend_finish, 156 .system_off = poplar_system_off, 157 .system_reset = poplar_system_reset, 158 .validate_power_state = poplar_validate_power_state, 159 .validate_ns_entrypoint = poplar_validate_ns_entrypoint, 160 .get_sys_suspend_power_state = poplar_get_sys_suspend_power_state, 161 }; 162 163 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 164 const plat_psci_ops_t **psci_ops) 165 { 166 *psci_ops = &poplar_plat_psci_ops; 167 168 mmio_write_32((uintptr_t)REG_PERI_CPU_AARCH_MODE, 0xF); 169 mmio_write_32((uintptr_t)REG_PERI_CPU_RVBARADDR, sec_entrypoint); 170 return 0; 171 } 172