blob: b14f0f577d221d221452a7f6189731022901e57d [file] [log] [blame]
Dhruva Golef95904f2025-03-24 13:05:23 +05301/*
2 * Copyright (c) 2025, Texas Instruments Incorporated - https://www.ti.com/
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <stdbool.h>
9
10#include <arch_helpers.h>
11#include <common/debug.h>
12#include <drivers/delay_timer.h>
13#include <lib/el3_runtime/cpu_data.h>
14#include <lib/mmio.h>
15#include <lib/psci/psci.h>
16#include <plat/common/platform.h>
17#include <ti_sci.h>
18#include <ti_sci_protocol.h>
19
20#include <k3_gicv3.h>
21#include <platform_def.h>
22
23uintptr_t am62l_sec_entrypoint;
24uintptr_t am62l_sec_entrypoint_glob;
25void __aligned(16) jump_to_atf_func(void *unused);
26
27static int am62l_pwr_domain_on(u_register_t mpidr)
28{
29 int32_t core, ret;
30 uint8_t proc_id;
31
32 core = plat_core_pos_by_mpidr(mpidr);
33 if (core < 0) {
34 ERROR("Could not get target core id: %d\n", core);
Dhruva Golefd0e3692025-03-24 13:05:23 +053035 return PSCI_E_INTERN_FAIL;
Dhruva Golef95904f2025-03-24 13:05:23 +053036 }
37
38 proc_id = (uint8_t)(PLAT_PROC_START_ID + (uint32_t)core);
39
40 ret = ti_sci_proc_request(proc_id);
41 if (ret != 0) {
42 ERROR("Request for processor ID 0x%x failed: %d\n",
43 proc_id, ret);
Dhruva Golefd0e3692025-03-24 13:05:23 +053044 return PSCI_E_INTERN_FAIL;
Dhruva Golef95904f2025-03-24 13:05:23 +053045 }
46
Dhruva Golefd0e3692025-03-24 13:05:23 +053047 ret = ti_sci_proc_set_boot_cfg(proc_id, am62l_sec_entrypoint, 0, 0);
48 if (ret != 0) {
49 ERROR("Request to set core boot address failed: %d\n", ret);
50 return PSCI_E_INTERN_FAIL;
Dhruva Golef95904f2025-03-24 13:05:23 +053051 }
52
Dhruva Golefd0e3692025-03-24 13:05:23 +053053 /* sanity check these are off before starting a core */
54 ret = ti_sci_proc_set_boot_ctrl(proc_id,
55 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ |
56 PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS |
57 PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM);
58 if (ret != 0) {
59 ERROR("Request to clear boot config failed: %d\n", ret);
60 return PSCI_E_INTERN_FAIL;
Dhruva Golef95904f2025-03-24 13:05:23 +053061 }
62
Dhruva Golefd0e3692025-03-24 13:05:23 +053063 /*
64 * TODO: Add the actual PM operation call
65 * to turn on the core here
66 */
67 return PSCI_E_SUCCESS;
Dhruva Golef95904f2025-03-24 13:05:23 +053068}
69
70static void am62l_pwr_domain_off(const psci_power_state_t *target_state)
71{
72 /* At very least the local core should be powering down */
73 assert(((target_state)->pwr_domain_state[MPIDR_AFFLVL0]) == PLAT_MAX_OFF_STATE);
74
75 /* Prevent interrupts from spuriously waking up this cpu */
76 k3_gic_cpuif_disable();
77
78}
79
80static void am62l_pwr_down_domain(const psci_power_state_t *target_state)
81{
82 /* TODO: Add the actual pm operation call to turn off the core */
83}
84
85void am62l_pwr_domain_on_finish(const psci_power_state_t *target_state)
86{
87 k3_gic_pcpu_init();
88 k3_gic_cpuif_enable();
89}
90
91static void am62l_system_reset(void)
92{
93 mmio_write_32(WKUP_CTRL_MMR0_DEVICE_MANAGEMENT_BASE + WKUP_CTRL_MMR0_DEVICE_RESET_OFFSET,
94 0x6);
95
96 /* Wait for reset to complete for 500ms before printing error */
97 mdelay(500);
98
99 /* Ideally we should not reach here */
100 ERROR("%s: Failed to reset device\n", __func__);
101}
102
103static plat_psci_ops_t am62l_plat_psci_ops = {
104 .pwr_domain_on = am62l_pwr_domain_on,
105 .pwr_domain_off = am62l_pwr_domain_off,
106 .pwr_domain_pwr_down = am62l_pwr_down_domain,
107 .pwr_domain_on_finish = am62l_pwr_domain_on_finish,
108 .system_reset = am62l_system_reset,
109};
110
111void __aligned(16) jump_to_atf_func(void *unused)
112{
113 /*
114 * MISRA Deviation observed:
115 * Rule 11.1 (MISRA C:2012) Prohibits conversion performed between a
116 * pointer to a function and another incompatible type.
117 * This conversion is required for handling secure boot entry points.
118 * The conversion is safe as the address is verified before execution.
119 */
120 void (*bl31_loc_warm_entry)(void) = (void *)am62l_sec_entrypoint_glob;
121
122 bl31_loc_warm_entry();
123}
124
125int plat_setup_psci_ops(uintptr_t sec_entrypoint,
126 const plat_psci_ops_t **psci_ops)
127{
128 am62l_sec_entrypoint_glob = sec_entrypoint;
129 /* Note that boot vector reg in sec mmr requires 16B aligned start address */
130 am62l_sec_entrypoint = (uint64_t)(void *)&jump_to_atf_func;
131 VERBOSE("am62l_sec_entrypoint = 0x%lx\n", am62l_sec_entrypoint);
132
133 *psci_ops = &am62l_plat_psci_ops;
134
135 return 0;
136}