1baa7650bSAnson Huang /* 2baa7650bSAnson Huang * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3baa7650bSAnson Huang * 4baa7650bSAnson Huang * SPDX-License-Identifier: BSD-3-Clause 5baa7650bSAnson Huang */ 6baa7650bSAnson Huang 7baa7650bSAnson Huang #include <arch.h> 8baa7650bSAnson Huang #include <arch_helpers.h> 9baa7650bSAnson Huang #include <cci.h> 10baa7650bSAnson Huang #include <debug.h> 11baa7650bSAnson Huang #include <gicv3.h> 12baa7650bSAnson Huang #include <mmio.h> 13baa7650bSAnson Huang #include <plat_imx8.h> 14baa7650bSAnson Huang #include <psci.h> 15baa7650bSAnson Huang #include <sci/sci.h> 16baa7650bSAnson Huang #include <stdbool.h> 17baa7650bSAnson Huang 18baa7650bSAnson Huang const static int ap_core_index[PLATFORM_CORE_COUNT] = { 19baa7650bSAnson Huang SC_R_A53_0, SC_R_A53_1, SC_R_A53_2, 20baa7650bSAnson Huang SC_R_A53_3, SC_R_A72_0, SC_R_A72_1, 21baa7650bSAnson Huang }; 22baa7650bSAnson Huang 23baa7650bSAnson Huang /* need to enable USE_COHERENT_MEM to avoid coherence issue */ 24baa7650bSAnson Huang #if USE_COHERENT_MEM 25baa7650bSAnson Huang static unsigned int a53_cpu_on_number __section("tzfw_coherent_mem"); 26baa7650bSAnson Huang static unsigned int a72_cpu_on_number __section("tzfw_coherent_mem"); 27baa7650bSAnson Huang #endif 28baa7650bSAnson Huang 29baa7650bSAnson Huang int imx_pwr_domain_on(u_register_t mpidr) 30baa7650bSAnson Huang { 31baa7650bSAnson Huang int ret = PSCI_E_SUCCESS; 32baa7650bSAnson Huang unsigned int cluster_id, cpu_id; 33baa7650bSAnson Huang 34baa7650bSAnson Huang cluster_id = MPIDR_AFFLVL1_VAL(mpidr); 35baa7650bSAnson Huang cpu_id = MPIDR_AFFLVL0_VAL(mpidr); 36baa7650bSAnson Huang 37baa7650bSAnson Huang tf_printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id); 38baa7650bSAnson Huang 39baa7650bSAnson Huang if (cluster_id == 0) { 40baa7650bSAnson Huang if (a53_cpu_on_number == 0) 41baa7650bSAnson Huang sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON); 42baa7650bSAnson Huang 43baa7650bSAnson Huang if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id], 44baa7650bSAnson Huang SC_PM_PW_MODE_ON) != SC_ERR_NONE) { 45baa7650bSAnson Huang ERROR("cluster0 core %d power on failed!\n", cpu_id); 46baa7650bSAnson Huang ret = PSCI_E_INTERN_FAIL; 47baa7650bSAnson Huang } 48baa7650bSAnson Huang 49baa7650bSAnson Huang if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id], 50baa7650bSAnson Huang true, BL31_BASE) != SC_ERR_NONE) { 51baa7650bSAnson Huang ERROR("boot cluster0 core %d failed!\n", cpu_id); 52baa7650bSAnson Huang ret = PSCI_E_INTERN_FAIL; 53baa7650bSAnson Huang } 54baa7650bSAnson Huang } else { 55baa7650bSAnson Huang if (a72_cpu_on_number == 0) 56baa7650bSAnson Huang sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON); 57baa7650bSAnson Huang 58baa7650bSAnson Huang if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4], 59baa7650bSAnson Huang SC_PM_PW_MODE_ON) != SC_ERR_NONE) { 60baa7650bSAnson Huang ERROR(" cluster1 core %d power on failed!\n", cpu_id); 61baa7650bSAnson Huang ret = PSCI_E_INTERN_FAIL; 62baa7650bSAnson Huang } 63baa7650bSAnson Huang 64baa7650bSAnson Huang if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id + 4], 65baa7650bSAnson Huang true, BL31_BASE) != SC_ERR_NONE) { 66baa7650bSAnson Huang ERROR("boot cluster1 core %d failed!\n", cpu_id); 67baa7650bSAnson Huang ret = PSCI_E_INTERN_FAIL; 68baa7650bSAnson Huang } 69baa7650bSAnson Huang } 70baa7650bSAnson Huang 71baa7650bSAnson Huang return ret; 72baa7650bSAnson Huang } 73baa7650bSAnson Huang 74baa7650bSAnson Huang void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) 75baa7650bSAnson Huang { 76baa7650bSAnson Huang uint64_t mpidr = read_mpidr_el1(); 77baa7650bSAnson Huang unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); 78baa7650bSAnson Huang 79baa7650bSAnson Huang if (cluster_id == 0 && a53_cpu_on_number++ == 0) 80baa7650bSAnson Huang cci_enable_snoop_dvm_reqs(0); 81baa7650bSAnson Huang if (cluster_id == 1 && a72_cpu_on_number++ == 0) 82baa7650bSAnson Huang cci_enable_snoop_dvm_reqs(1); 83baa7650bSAnson Huang 84baa7650bSAnson Huang plat_gic_pcpu_init(); 85baa7650bSAnson Huang plat_gic_cpuif_enable(); 86baa7650bSAnson Huang } 87baa7650bSAnson Huang 88*0f53bca0SAnson Huang void imx_pwr_domain_off(const psci_power_state_t *target_state) 89*0f53bca0SAnson Huang { 90*0f53bca0SAnson Huang u_register_t mpidr = read_mpidr_el1(); 91*0f53bca0SAnson Huang unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); 92*0f53bca0SAnson Huang unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr); 93*0f53bca0SAnson Huang 94*0f53bca0SAnson Huang plat_gic_cpuif_disable(); 95*0f53bca0SAnson Huang if (cluster_id == 0) { 96*0f53bca0SAnson Huang sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id], 97*0f53bca0SAnson Huang SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE); 98*0f53bca0SAnson Huang if (--a53_cpu_on_number == 0) 99*0f53bca0SAnson Huang cci_disable_snoop_dvm_reqs(0); 100*0f53bca0SAnson Huang } else { 101*0f53bca0SAnson Huang sc_pm_req_cpu_low_power_mode(ipc_handle, 102*0f53bca0SAnson Huang ap_core_index[cpu_id + 4], 103*0f53bca0SAnson Huang SC_PM_PW_MODE_OFF, 104*0f53bca0SAnson Huang SC_PM_WAKE_SRC_NONE); 105*0f53bca0SAnson Huang if (--a72_cpu_on_number == 0) 106*0f53bca0SAnson Huang cci_disable_snoop_dvm_reqs(1); 107*0f53bca0SAnson Huang } 108*0f53bca0SAnson Huang tf_printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id); 109*0f53bca0SAnson Huang } 110*0f53bca0SAnson Huang 111baa7650bSAnson Huang int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) 112baa7650bSAnson Huang { 113baa7650bSAnson Huang return PSCI_E_SUCCESS; 114baa7650bSAnson Huang } 115baa7650bSAnson Huang 116baa7650bSAnson Huang static const plat_psci_ops_t imx_plat_psci_ops = { 117baa7650bSAnson Huang .pwr_domain_on = imx_pwr_domain_on, 118baa7650bSAnson Huang .pwr_domain_on_finish = imx_pwr_domain_on_finish, 119*0f53bca0SAnson Huang .pwr_domain_off = imx_pwr_domain_off, 120baa7650bSAnson Huang .validate_ns_entrypoint = imx_validate_ns_entrypoint, 121db81c592SAnson Huang .system_off = imx_system_off, 122d31ffcf0SAnson Huang .system_reset = imx_system_reset, 123baa7650bSAnson Huang }; 124baa7650bSAnson Huang 125baa7650bSAnson Huang int plat_setup_psci_ops(uintptr_t sec_entrypoint, 126baa7650bSAnson Huang const plat_psci_ops_t **psci_ops) 127baa7650bSAnson Huang { 128baa7650bSAnson Huang uint64_t mpidr = read_mpidr_el1(); 129baa7650bSAnson Huang unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr); 130baa7650bSAnson Huang 131baa7650bSAnson Huang imx_mailbox_init(sec_entrypoint); 132baa7650bSAnson Huang *psci_ops = &imx_plat_psci_ops; 133baa7650bSAnson Huang 134baa7650bSAnson Huang if (cluster_id == 0) 135baa7650bSAnson Huang a53_cpu_on_number++; 136baa7650bSAnson Huang else 137baa7650bSAnson Huang a72_cpu_on_number++; 138baa7650bSAnson Huang 139baa7650bSAnson Huang return 0; 140baa7650bSAnson Huang } 141