blob: 761d30f50708fa732348e73abaf7d19ad5a2bcd3 [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);
35 ret = PSCI_E_INTERN_FAIL;
36 }
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);
44 ret = PSCI_E_INTERN_FAIL;
45 }
46
47 if (ret != PSCI_E_INTERN_FAIL) {
48 ret = ti_sci_proc_set_boot_cfg(proc_id, am62l_sec_entrypoint, 0, 0);
49 if (ret != 0) {
50 ERROR("Request to set core boot address failed: %d\n", ret);
51 ret = PSCI_E_INTERN_FAIL;
52 }
53 }
54
55 if (ret != PSCI_E_INTERN_FAIL) {
56 /* sanity check these are off before starting a core */
57 ret = ti_sci_proc_set_boot_ctrl(proc_id,
58 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ |
59 PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS |
60 PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM);
61 if (ret != 0) {
62 ERROR("Request to clear boot config failed: %d\n", ret);
63 ret = PSCI_E_INTERN_FAIL;
64 }
65 }
66
67 if (ret != PSCI_E_INTERN_FAIL) {
68 /*
69 * TODO: Add the actual PM operation call
70 * to turn on the core here
71 */
72 ret = PSCI_E_SUCCESS;
73 }
74
75 return ret;
76}
77
78static void am62l_pwr_domain_off(const psci_power_state_t *target_state)
79{
80 /* At very least the local core should be powering down */
81 assert(((target_state)->pwr_domain_state[MPIDR_AFFLVL0]) == PLAT_MAX_OFF_STATE);
82
83 /* Prevent interrupts from spuriously waking up this cpu */
84 k3_gic_cpuif_disable();
85
86}
87
88static void am62l_pwr_down_domain(const psci_power_state_t *target_state)
89{
90 /* TODO: Add the actual pm operation call to turn off the core */
91}
92
93void am62l_pwr_domain_on_finish(const psci_power_state_t *target_state)
94{
95 k3_gic_pcpu_init();
96 k3_gic_cpuif_enable();
97}
98
99static void am62l_system_reset(void)
100{
101 mmio_write_32(WKUP_CTRL_MMR0_DEVICE_MANAGEMENT_BASE + WKUP_CTRL_MMR0_DEVICE_RESET_OFFSET,
102 0x6);
103
104 /* Wait for reset to complete for 500ms before printing error */
105 mdelay(500);
106
107 /* Ideally we should not reach here */
108 ERROR("%s: Failed to reset device\n", __func__);
109}
110
111static plat_psci_ops_t am62l_plat_psci_ops = {
112 .pwr_domain_on = am62l_pwr_domain_on,
113 .pwr_domain_off = am62l_pwr_domain_off,
114 .pwr_domain_pwr_down = am62l_pwr_down_domain,
115 .pwr_domain_on_finish = am62l_pwr_domain_on_finish,
116 .system_reset = am62l_system_reset,
117};
118
119void __aligned(16) jump_to_atf_func(void *unused)
120{
121 /*
122 * MISRA Deviation observed:
123 * Rule 11.1 (MISRA C:2012) Prohibits conversion performed between a
124 * pointer to a function and another incompatible type.
125 * This conversion is required for handling secure boot entry points.
126 * The conversion is safe as the address is verified before execution.
127 */
128 void (*bl31_loc_warm_entry)(void) = (void *)am62l_sec_entrypoint_glob;
129
130 bl31_loc_warm_entry();
131}
132
133int plat_setup_psci_ops(uintptr_t sec_entrypoint,
134 const plat_psci_ops_t **psci_ops)
135{
136 am62l_sec_entrypoint_glob = sec_entrypoint;
137 /* Note that boot vector reg in sec mmr requires 16B aligned start address */
138 am62l_sec_entrypoint = (uint64_t)(void *)&jump_to_atf_func;
139 VERBOSE("am62l_sec_entrypoint = 0x%lx\n", am62l_sec_entrypoint);
140
141 *psci_ops = &am62l_plat_psci_ops;
142
143 return 0;
144}