| /* |
| * Copyright (c) 2025, Texas Instruments Incorporated - https://www.ti.com/ |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include <assert.h> |
| #include <stdbool.h> |
| |
| #include <arch_helpers.h> |
| #include <common/debug.h> |
| #include <drivers/delay_timer.h> |
| #include <lib/el3_runtime/cpu_data.h> |
| #include <lib/mmio.h> |
| #include <lib/psci/psci.h> |
| #include <plat/common/platform.h> |
| #include <ti_sci.h> |
| #include <ti_sci_protocol.h> |
| |
| #include <k3_gicv3.h> |
| #include <platform_def.h> |
| |
| uintptr_t am62l_sec_entrypoint; |
| uintptr_t am62l_sec_entrypoint_glob; |
| void __aligned(16) jump_to_atf_func(void *unused); |
| |
| static int am62l_pwr_domain_on(u_register_t mpidr) |
| { |
| int32_t core, ret; |
| uint8_t proc_id; |
| |
| core = plat_core_pos_by_mpidr(mpidr); |
| if (core < 0) { |
| ERROR("Could not get target core id: %d\n", core); |
| return PSCI_E_INTERN_FAIL; |
| } |
| |
| proc_id = (uint8_t)(PLAT_PROC_START_ID + (uint32_t)core); |
| |
| ret = ti_sci_proc_request(proc_id); |
| if (ret != 0) { |
| ERROR("Request for processor ID 0x%x failed: %d\n", |
| proc_id, ret); |
| return PSCI_E_INTERN_FAIL; |
| } |
| |
| ret = ti_sci_proc_set_boot_cfg(proc_id, am62l_sec_entrypoint, 0, 0); |
| if (ret != 0) { |
| ERROR("Request to set core boot address failed: %d\n", ret); |
| return PSCI_E_INTERN_FAIL; |
| } |
| |
| /* sanity check these are off before starting a core */ |
| ret = ti_sci_proc_set_boot_ctrl(proc_id, |
| 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ | |
| PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS | |
| PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM); |
| if (ret != 0) { |
| ERROR("Request to clear boot config failed: %d\n", ret); |
| return PSCI_E_INTERN_FAIL; |
| } |
| |
| /* |
| * TODO: Add the actual PM operation call |
| * to turn on the core here |
| */ |
| return PSCI_E_SUCCESS; |
| } |
| |
| static void am62l_pwr_domain_off(const psci_power_state_t *target_state) |
| { |
| /* At very least the local core should be powering down */ |
| assert(((target_state)->pwr_domain_state[MPIDR_AFFLVL0]) == PLAT_MAX_OFF_STATE); |
| |
| /* Prevent interrupts from spuriously waking up this cpu */ |
| k3_gic_cpuif_disable(); |
| |
| } |
| |
| static void am62l_pwr_down_domain(const psci_power_state_t *target_state) |
| { |
| /* TODO: Add the actual pm operation call to turn off the core */ |
| } |
| |
| void am62l_pwr_domain_on_finish(const psci_power_state_t *target_state) |
| { |
| k3_gic_pcpu_init(); |
| k3_gic_cpuif_enable(); |
| } |
| |
| static void am62l_system_reset(void) |
| { |
| mmio_write_32(WKUP_CTRL_MMR0_DEVICE_MANAGEMENT_BASE + WKUP_CTRL_MMR0_DEVICE_RESET_OFFSET, |
| 0x6); |
| |
| /* Wait for reset to complete for 500ms before printing error */ |
| mdelay(500); |
| |
| /* Ideally we should not reach here */ |
| ERROR("%s: Failed to reset device\n", __func__); |
| } |
| |
| static plat_psci_ops_t am62l_plat_psci_ops = { |
| .pwr_domain_on = am62l_pwr_domain_on, |
| .pwr_domain_off = am62l_pwr_domain_off, |
| .pwr_domain_pwr_down = am62l_pwr_down_domain, |
| .pwr_domain_on_finish = am62l_pwr_domain_on_finish, |
| .system_reset = am62l_system_reset, |
| }; |
| |
| void __aligned(16) jump_to_atf_func(void *unused) |
| { |
| /* |
| * MISRA Deviation observed: |
| * Rule 11.1 (MISRA C:2012) Prohibits conversion performed between a |
| * pointer to a function and another incompatible type. |
| * This conversion is required for handling secure boot entry points. |
| * The conversion is safe as the address is verified before execution. |
| */ |
| void (*bl31_loc_warm_entry)(void) = (void *)am62l_sec_entrypoint_glob; |
| |
| bl31_loc_warm_entry(); |
| } |
| |
| int plat_setup_psci_ops(uintptr_t sec_entrypoint, |
| const plat_psci_ops_t **psci_ops) |
| { |
| am62l_sec_entrypoint_glob = sec_entrypoint; |
| /* Note that boot vector reg in sec mmr requires 16B aligned start address */ |
| am62l_sec_entrypoint = (uint64_t)(void *)&jump_to_atf_func; |
| VERBOSE("am62l_sec_entrypoint = 0x%lx\n", am62l_sec_entrypoint); |
| |
| *psci_ops = &am62l_plat_psci_ops; |
| |
| return 0; |
| } |