blob: ec8631a4fee9777b16df80b5bf63ca4535996bd9 [file] [log] [blame]
Anson Huangf753d462019-01-15 10:34:04 +08001/*
2 * Copyright 2019 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Peng Fandd860d12020-07-10 14:18:01 +08007#include <arch.h>
Anson Huangf753d462019-01-15 10:34:04 +08008#include <stdlib.h>
9#include <stdint.h>
Ambroise Vincentffbf32a2019-03-28 09:01:18 +000010#include <services/std_svc.h>
Anson Huang971392d2019-01-18 10:43:59 +080011#include <string.h>
Anson Huangf753d462019-01-15 10:34:04 +080012#include <platform_def.h>
13#include <common/debug.h>
14#include <common/runtime_svc.h>
15#include <imx_sip_svc.h>
Peng Fandd860d12020-07-10 14:18:01 +080016#include <lib/el3_runtime/context_mgmt.h>
Igor Opaniukf2de6812021-03-10 13:42:55 +020017#include <lib/mmio.h>
Anson Huangf753d462019-01-15 10:34:04 +080018#include <sci/sci.h>
19
Leonard Crestezd62c1612019-05-20 11:28:50 +030020#if defined(PLAT_imx8qm) || defined(PLAT_imx8qx)
Leonard Crestez402bd522019-05-08 22:29:21 +030021
Leonard Crestezd62c1612019-05-20 11:28:50 +030022#ifdef PLAT_imx8qm
Boyan Karatotev05e9d4d2022-11-22 14:31:41 +000023static const int ap_cluster_index[PLATFORM_CLUSTER_COUNT] = {
Anson Huang922c45f2019-01-15 10:56:36 +080024 SC_R_A53, SC_R_A72,
25};
26#endif
27
Anson Huangf753d462019-01-15 10:34:04 +080028static int imx_srtc_set_time(uint32_t year_mon,
29 unsigned long day_hour,
30 unsigned long min_sec)
31{
32 return sc_timer_set_rtc_time(ipc_handle,
33 year_mon >> 16, year_mon & 0xffff,
34 day_hour >> 16, day_hour & 0xffff,
35 min_sec >> 16, min_sec & 0xffff);
36}
37
38int imx_srtc_handler(uint32_t smc_fid,
39 void *handle,
40 u_register_t x1,
41 u_register_t x2,
42 u_register_t x3,
43 u_register_t x4)
44{
45 int ret;
46
47 switch (x1) {
48 case IMX_SIP_SRTC_SET_TIME:
49 ret = imx_srtc_set_time(x2, x3, x4);
50 break;
51 default:
52 ret = SMC_UNK;
53 }
54
55 SMC_RET1(handle, ret);
56}
Anson Huang922c45f2019-01-15 10:56:36 +080057
58static void imx_cpufreq_set_target(uint32_t cluster_id, unsigned long freq)
59{
60 sc_pm_clock_rate_t rate = (sc_pm_clock_rate_t)freq;
61
Leonard Crestezd62c1612019-05-20 11:28:50 +030062#ifdef PLAT_imx8qm
Anson Huang922c45f2019-01-15 10:56:36 +080063 sc_pm_set_clock_rate(ipc_handle, ap_cluster_index[cluster_id], SC_PM_CLK_CPU, &rate);
64#endif
Leonard Crestezd62c1612019-05-20 11:28:50 +030065#ifdef PLAT_imx8qx
Anson Huang922c45f2019-01-15 10:56:36 +080066 sc_pm_set_clock_rate(ipc_handle, SC_R_A35, SC_PM_CLK_CPU, &rate);
67#endif
68}
69
70int imx_cpufreq_handler(uint32_t smc_fid,
71 u_register_t x1,
72 u_register_t x2,
73 u_register_t x3)
74{
75 switch (x1) {
76 case IMX_SIP_SET_CPUFREQ:
77 imx_cpufreq_set_target(x2, x3);
78 break;
79 default:
80 return SMC_UNK;
81 }
82
83 return 0;
84}
Anson Huange1d418c2019-01-18 10:01:50 +080085
86static bool wakeup_src_irqsteer;
87
88bool imx_is_wakeup_src_irqsteer(void)
89{
90 return wakeup_src_irqsteer;
91}
92
93int imx_wakeup_src_handler(uint32_t smc_fid,
94 u_register_t x1,
95 u_register_t x2,
96 u_register_t x3)
97{
98 switch (x1) {
99 case IMX_SIP_WAKEUP_SRC_IRQSTEER:
100 wakeup_src_irqsteer = true;
101 break;
102 case IMX_SIP_WAKEUP_SRC_SCU:
103 wakeup_src_irqsteer = false;
104 break;
105 default:
106 return SMC_UNK;
107 }
108
109 return SMC_OK;
110}
Anson Huang6e47de52019-01-18 10:27:48 +0800111
112int imx_otp_handler(uint32_t smc_fid,
113 void *handle,
114 u_register_t x1,
115 u_register_t x2)
116{
117 int ret;
118 uint32_t fuse;
119
120 switch (smc_fid) {
121 case IMX_SIP_OTP_READ:
122 ret = sc_misc_otp_fuse_read(ipc_handle, x1, &fuse);
123 SMC_RET2(handle, ret, fuse);
124 break;
125 case IMX_SIP_OTP_WRITE:
126 ret = sc_misc_otp_fuse_write(ipc_handle, x1, x2);
127 SMC_RET1(handle, ret);
128 break;
129 default:
130 ret = SMC_UNK;
131 SMC_RET1(handle, ret);
132 break;
133 }
134
135 return ret;
136}
Anson Huange708bfb2019-01-18 10:35:54 +0800137
138int imx_misc_set_temp_handler(uint32_t smc_fid,
139 u_register_t x1,
140 u_register_t x2,
141 u_register_t x3,
142 u_register_t x4)
143{
144 return sc_misc_set_temp(ipc_handle, x1, x2, x3, x4);
145}
Anson Huang971392d2019-01-18 10:43:59 +0800146
Leonard Crestezd62c1612019-05-20 11:28:50 +0300147#endif /* defined(PLAT_imx8qm) || defined(PLAT_imx8qx) */
Leonard Crestez402bd522019-05-08 22:29:21 +0300148
Igor Opaniukf2de6812021-03-10 13:42:55 +0200149#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq)
150int imx_src_handler(uint32_t smc_fid,
151 u_register_t x1,
152 u_register_t x2,
153 u_register_t x3,
154 void *handle)
155{
156 uint32_t val;
157
158 switch (x1) {
159 case IMX_SIP_SRC_SET_SECONDARY_BOOT:
160 if (x2 != 0U) {
161 mmio_setbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET,
162 SRC_GPR10_PERSIST_SECONDARY_BOOT);
163 } else {
164 mmio_clrbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET,
165 SRC_GPR10_PERSIST_SECONDARY_BOOT);
166 }
167 break;
168 case IMX_SIP_SRC_IS_SECONDARY_BOOT:
169 val = mmio_read_32(IMX_SRC_BASE + SRC_GPR10_OFFSET);
170 return !!(val & SRC_GPR10_PERSIST_SECONDARY_BOOT);
171 default:
172 return SMC_UNK;
173
174 };
175
176 return 0;
177}
178#endif /* defined(PLAT_imx8mm) || defined(PLAT_imx8mq) */
179
Anson Huang971392d2019-01-18 10:43:59 +0800180static uint64_t imx_get_commit_hash(u_register_t x2,
181 u_register_t x3,
182 u_register_t x4)
183{
184 /* Parse the version_string */
185 char *parse = (char *)version_string;
186 uint64_t hash = 0;
187
188 do {
189 parse = strchr(parse, '-');
190 if (parse) {
191 parse += 1;
192 if (*(parse) == 'g') {
193 /* Default is 7 hexadecimal digits */
194 memcpy((void *)&hash, (void *)(parse + 1), 7);
195 break;
196 }
197 }
198
199 } while (parse != NULL);
200
201 return hash;
202}
203
204uint64_t imx_buildinfo_handler(uint32_t smc_fid,
205 u_register_t x1,
206 u_register_t x2,
207 u_register_t x3,
208 u_register_t x4)
209{
210 uint64_t ret;
211
212 switch (x1) {
213 case IMX_SIP_BUILDINFO_GET_COMMITHASH:
214 ret = imx_get_commit_hash(x2, x3, x4);
215 break;
216 default:
217 return SMC_UNK;
218 }
219
220 return ret;
221}
Peng Fandd860d12020-07-10 14:18:01 +0800222
223int imx_kernel_entry_handler(uint32_t smc_fid,
224 u_register_t x1,
225 u_register_t x2,
226 u_register_t x3,
227 u_register_t x4)
228{
229 static entry_point_info_t bl33_image_ep_info;
230 entry_point_info_t *next_image_info;
231 unsigned int mode;
232
233 if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000))
234 return SMC_UNK;
235
236 mode = MODE32_svc;
237
238 next_image_info = &bl33_image_ep_info;
239
240 next_image_info->pc = x1;
241
242 next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
243 (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
244
245 next_image_info->args.arg0 = 0;
246 next_image_info->args.arg1 = 0;
247 next_image_info->args.arg2 = x3;
248
249 SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
250
251 cm_init_my_context(next_image_info);
252 cm_prepare_el3_exit(NON_SECURE);
253
254 return 0;
255}