1c76d4239SHadi Asyrafi /* 2c76d4239SHadi Asyrafi * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3c76d4239SHadi Asyrafi * 4c76d4239SHadi Asyrafi * SPDX-License-Identifier: BSD-3-Clause 5c76d4239SHadi Asyrafi */ 6c76d4239SHadi Asyrafi 7c76d4239SHadi Asyrafi #include <arch_helpers.h> 8c76d4239SHadi Asyrafi #include <common/debug.h> 9c76d4239SHadi Asyrafi #include <drivers/arm/gicv2.h> 10c76d4239SHadi Asyrafi #include <lib/mmio.h> 11c76d4239SHadi Asyrafi #include <lib/psci/psci.h> 12c76d4239SHadi Asyrafi #include <plat/common/platform.h> 13c76d4239SHadi Asyrafi 14c76d4239SHadi Asyrafi #include "socfpga_mailbox.h" 15c76d4239SHadi Asyrafi #include "socfpga_plat_def.h" 16*32cf34acSHadi Asyrafi #include "socfpga_reset_manager.h" 17c76d4239SHadi Asyrafi 18c76d4239SHadi Asyrafi 19c76d4239SHadi Asyrafi 20c76d4239SHadi Asyrafi /******************************************************************************* 21c76d4239SHadi Asyrafi * plat handler called when a CPU is about to enter standby. 22c76d4239SHadi Asyrafi ******************************************************************************/ 23c76d4239SHadi Asyrafi void socfpga_cpu_standby(plat_local_state_t cpu_state) 24c76d4239SHadi Asyrafi { 25c76d4239SHadi Asyrafi /* 26c76d4239SHadi Asyrafi * Enter standby state 27c76d4239SHadi Asyrafi * dsb is good practice before using wfi to enter low power states 28c76d4239SHadi Asyrafi */ 29c76d4239SHadi Asyrafi VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state); 30c76d4239SHadi Asyrafi dsb(); 31c76d4239SHadi Asyrafi wfi(); 32c76d4239SHadi Asyrafi } 33c76d4239SHadi Asyrafi 34c76d4239SHadi Asyrafi /******************************************************************************* 35c76d4239SHadi Asyrafi * plat handler called when a power domain is about to be turned on. The 36c76d4239SHadi Asyrafi * mpidr determines the CPU to be turned on. 37c76d4239SHadi Asyrafi ******************************************************************************/ 38c76d4239SHadi Asyrafi int socfpga_pwr_domain_on(u_register_t mpidr) 39c76d4239SHadi Asyrafi { 40c76d4239SHadi Asyrafi unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); 41c76d4239SHadi Asyrafi 42c76d4239SHadi Asyrafi VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); 43c76d4239SHadi Asyrafi 44c76d4239SHadi Asyrafi if (cpu_id == -1) 45c76d4239SHadi Asyrafi return PSCI_E_INTERN_FAIL; 46c76d4239SHadi Asyrafi 47cf82aff0SHadi Asyrafi mmio_write_64(PLAT_CPUID_RELEASE, cpu_id); 48c76d4239SHadi Asyrafi 49c76d4239SHadi Asyrafi /* release core reset */ 50c76d4239SHadi Asyrafi mmio_setbits_32(SOCFPGA_RSTMGR_MPUMODRST_OFST, 1 << cpu_id); 51c76d4239SHadi Asyrafi return PSCI_E_SUCCESS; 52c76d4239SHadi Asyrafi } 53c76d4239SHadi Asyrafi 54c76d4239SHadi Asyrafi /******************************************************************************* 55c76d4239SHadi Asyrafi * plat handler called when a power domain is about to be turned off. The 56c76d4239SHadi Asyrafi * target_state encodes the power state that each level should transition to. 57c76d4239SHadi Asyrafi ******************************************************************************/ 58c76d4239SHadi Asyrafi void socfpga_pwr_domain_off(const psci_power_state_t *target_state) 59c76d4239SHadi Asyrafi { 60c76d4239SHadi Asyrafi for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) 61c76d4239SHadi Asyrafi VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", 62c76d4239SHadi Asyrafi __func__, i, target_state->pwr_domain_state[i]); 63c76d4239SHadi Asyrafi 64c76d4239SHadi Asyrafi /* Prevent interrupts from spuriously waking up this cpu */ 65c76d4239SHadi Asyrafi gicv2_cpuif_disable(); 66c76d4239SHadi Asyrafi } 67c76d4239SHadi Asyrafi 68c76d4239SHadi Asyrafi /******************************************************************************* 69c76d4239SHadi Asyrafi * plat handler called when a power domain is about to be suspended. The 70c76d4239SHadi Asyrafi * target_state encodes the power state that each level should transition to. 71c76d4239SHadi Asyrafi ******************************************************************************/ 72c76d4239SHadi Asyrafi void socfpga_pwr_domain_suspend(const psci_power_state_t *target_state) 73c76d4239SHadi Asyrafi { 74c76d4239SHadi Asyrafi unsigned int cpu_id = plat_my_core_pos(); 75c76d4239SHadi Asyrafi 76c76d4239SHadi Asyrafi for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) 77c76d4239SHadi Asyrafi VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", 78c76d4239SHadi Asyrafi __func__, i, target_state->pwr_domain_state[i]); 79*32cf34acSHadi Asyrafi 80c76d4239SHadi Asyrafi /* assert core reset */ 81c76d4239SHadi Asyrafi mmio_setbits_32(SOCFPGA_RSTMGR_MPUMODRST_OFST, 1 << cpu_id); 82c76d4239SHadi Asyrafi 83c76d4239SHadi Asyrafi } 84c76d4239SHadi Asyrafi 85c76d4239SHadi Asyrafi /******************************************************************************* 86c76d4239SHadi Asyrafi * plat handler called when a power domain has just been powered on after 87c76d4239SHadi Asyrafi * being turned off earlier. The target_state encodes the low power state that 88c76d4239SHadi Asyrafi * each level has woken up from. 89c76d4239SHadi Asyrafi ******************************************************************************/ 90c76d4239SHadi Asyrafi void socfpga_pwr_domain_on_finish(const psci_power_state_t *target_state) 91c76d4239SHadi Asyrafi { 92c76d4239SHadi Asyrafi for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) 93c76d4239SHadi Asyrafi VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", 94c76d4239SHadi Asyrafi __func__, i, target_state->pwr_domain_state[i]); 95c76d4239SHadi Asyrafi 96c76d4239SHadi Asyrafi /* Program the gic per-cpu distributor or re-distributor interface */ 97c76d4239SHadi Asyrafi gicv2_pcpu_distif_init(); 98c76d4239SHadi Asyrafi gicv2_set_pe_target_mask(plat_my_core_pos()); 99c76d4239SHadi Asyrafi 100c76d4239SHadi Asyrafi /* Enable the gic cpu interface */ 101c76d4239SHadi Asyrafi gicv2_cpuif_enable(); 102c76d4239SHadi Asyrafi } 103c76d4239SHadi Asyrafi 104c76d4239SHadi Asyrafi /******************************************************************************* 105c76d4239SHadi Asyrafi * plat handler called when a power domain has just been powered on after 106c76d4239SHadi Asyrafi * having been suspended earlier. The target_state encodes the low power state 107c76d4239SHadi Asyrafi * that each level has woken up from. 108c76d4239SHadi Asyrafi * TODO: At the moment we reuse the on finisher and reinitialize the secure 109c76d4239SHadi Asyrafi * context. Need to implement a separate suspend finisher. 110c76d4239SHadi Asyrafi ******************************************************************************/ 111c76d4239SHadi Asyrafi void socfpga_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 112c76d4239SHadi Asyrafi { 113c76d4239SHadi Asyrafi unsigned int cpu_id = plat_my_core_pos(); 114c76d4239SHadi Asyrafi 115c76d4239SHadi Asyrafi for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) 116c76d4239SHadi Asyrafi VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", 117c76d4239SHadi Asyrafi __func__, i, target_state->pwr_domain_state[i]); 118c76d4239SHadi Asyrafi 119c76d4239SHadi Asyrafi /* release core reset */ 120c76d4239SHadi Asyrafi mmio_clrbits_32(SOCFPGA_RSTMGR_MPUMODRST_OFST, 1 << cpu_id); 121c76d4239SHadi Asyrafi } 122c76d4239SHadi Asyrafi 123c76d4239SHadi Asyrafi /******************************************************************************* 124c76d4239SHadi Asyrafi * plat handlers to shutdown/reboot the system 125c76d4239SHadi Asyrafi ******************************************************************************/ 126c76d4239SHadi Asyrafi static void __dead2 socfpga_system_off(void) 127c76d4239SHadi Asyrafi { 128c76d4239SHadi Asyrafi wfi(); 129c76d4239SHadi Asyrafi ERROR("System Off: operation not handled.\n"); 130c76d4239SHadi Asyrafi panic(); 131c76d4239SHadi Asyrafi } 132c76d4239SHadi Asyrafi 133c76d4239SHadi Asyrafi static void __dead2 socfpga_system_reset(void) 134c76d4239SHadi Asyrafi { 135c76d4239SHadi Asyrafi mailbox_reset_cold(); 136c76d4239SHadi Asyrafi 137c76d4239SHadi Asyrafi while (1) 138c76d4239SHadi Asyrafi wfi(); 139c76d4239SHadi Asyrafi } 140c76d4239SHadi Asyrafi 141*32cf34acSHadi Asyrafi static int socfpga_system_reset2(int is_vendor, int reset_type, 142*32cf34acSHadi Asyrafi u_register_t cookie) 143*32cf34acSHadi Asyrafi { 144*32cf34acSHadi Asyrafi /* disable cpuif */ 145*32cf34acSHadi Asyrafi gicv2_cpuif_disable(); 146*32cf34acSHadi Asyrafi 147*32cf34acSHadi Asyrafi /* Store magic number */ 148*32cf34acSHadi Asyrafi mmio_write_32(L2_RESET_DONE_REG, L2_RESET_DONE_STATUS); 149*32cf34acSHadi Asyrafi 150*32cf34acSHadi Asyrafi /* Increase timeout */ 151*32cf34acSHadi Asyrafi mmio_write_32(SOCFPGA_RSTMGR_HDSKTIMEOUT, 0xffffff); 152*32cf34acSHadi Asyrafi 153*32cf34acSHadi Asyrafi /* Enable handshakes */ 154*32cf34acSHadi Asyrafi mmio_setbits_32(SOCFPGA_RSTMGR_HDSKEN, SOCFPGA_RSTMGR_HDSKEN_SET); 155*32cf34acSHadi Asyrafi 156*32cf34acSHadi Asyrafi /* Reset L2 module */ 157*32cf34acSHadi Asyrafi mmio_setbits_32(SOCFPGA_RSTMGR_COLDMODRST, 0x100); 158*32cf34acSHadi Asyrafi 159*32cf34acSHadi Asyrafi while (1) 160*32cf34acSHadi Asyrafi wfi(); 161*32cf34acSHadi Asyrafi 162*32cf34acSHadi Asyrafi /* Should not reach here */ 163*32cf34acSHadi Asyrafi return 0; 164*32cf34acSHadi Asyrafi } 165*32cf34acSHadi Asyrafi 166c76d4239SHadi Asyrafi int socfpga_validate_power_state(unsigned int power_state, 167c76d4239SHadi Asyrafi psci_power_state_t *req_state) 168c76d4239SHadi Asyrafi { 169c76d4239SHadi Asyrafi VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); 170c76d4239SHadi Asyrafi 171c76d4239SHadi Asyrafi return PSCI_E_SUCCESS; 172c76d4239SHadi Asyrafi } 173c76d4239SHadi Asyrafi 174c76d4239SHadi Asyrafi int socfpga_validate_ns_entrypoint(unsigned long ns_entrypoint) 175c76d4239SHadi Asyrafi { 176c76d4239SHadi Asyrafi VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint); 177c76d4239SHadi Asyrafi return PSCI_E_SUCCESS; 178c76d4239SHadi Asyrafi } 179c76d4239SHadi Asyrafi 180c76d4239SHadi Asyrafi void socfpga_get_sys_suspend_power_state(psci_power_state_t *req_state) 181c76d4239SHadi Asyrafi { 182c76d4239SHadi Asyrafi req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE; 183c76d4239SHadi Asyrafi req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE; 184c76d4239SHadi Asyrafi } 185c76d4239SHadi Asyrafi 186c76d4239SHadi Asyrafi /******************************************************************************* 187c76d4239SHadi Asyrafi * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard 188c76d4239SHadi Asyrafi * platform layer will take care of registering the handlers with PSCI. 189c76d4239SHadi Asyrafi ******************************************************************************/ 190c76d4239SHadi Asyrafi const plat_psci_ops_t socfpga_psci_pm_ops = { 191c76d4239SHadi Asyrafi .cpu_standby = socfpga_cpu_standby, 192c76d4239SHadi Asyrafi .pwr_domain_on = socfpga_pwr_domain_on, 193c76d4239SHadi Asyrafi .pwr_domain_off = socfpga_pwr_domain_off, 194c76d4239SHadi Asyrafi .pwr_domain_suspend = socfpga_pwr_domain_suspend, 195c76d4239SHadi Asyrafi .pwr_domain_on_finish = socfpga_pwr_domain_on_finish, 196c76d4239SHadi Asyrafi .pwr_domain_suspend_finish = socfpga_pwr_domain_suspend_finish, 197c76d4239SHadi Asyrafi .system_off = socfpga_system_off, 198c76d4239SHadi Asyrafi .system_reset = socfpga_system_reset, 199*32cf34acSHadi Asyrafi .system_reset2 = socfpga_system_reset2, 200c76d4239SHadi Asyrafi .validate_power_state = socfpga_validate_power_state, 201c76d4239SHadi Asyrafi .validate_ns_entrypoint = socfpga_validate_ns_entrypoint, 202c76d4239SHadi Asyrafi .get_sys_suspend_power_state = socfpga_get_sys_suspend_power_state 203c76d4239SHadi Asyrafi }; 204c76d4239SHadi Asyrafi 205c76d4239SHadi Asyrafi /******************************************************************************* 206c76d4239SHadi Asyrafi * Export the platform specific power ops. 207c76d4239SHadi Asyrafi ******************************************************************************/ 208c76d4239SHadi Asyrafi int plat_setup_psci_ops(uintptr_t sec_entrypoint, 209c76d4239SHadi Asyrafi const struct plat_psci_ops **psci_ops) 210c76d4239SHadi Asyrafi { 211c76d4239SHadi Asyrafi /* Save warm boot entrypoint.*/ 212cf82aff0SHadi Asyrafi mmio_write_64(PLAT_SEC_ENTRY, sec_entrypoint); 213c76d4239SHadi Asyrafi *psci_ops = &socfpga_psci_pm_ops; 214cf82aff0SHadi Asyrafi 215c76d4239SHadi Asyrafi return 0; 216c76d4239SHadi Asyrafi } 217