1 /*
2 * Copyright 2019 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <arch.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <services/std_svc.h>
11 #include <string.h>
12 #include <platform_def.h>
13 #include <common/debug.h>
14 #include <common/runtime_svc.h>
15 #include <imx_sip_svc.h>
16 #include <lib/el3_runtime/context_mgmt.h>
17 #include <lib/mmio.h>
18 #include <sci/sci.h>
19
20 #if defined(PLAT_imx8qm) || defined(PLAT_imx8qx)
21
22 #ifdef PLAT_imx8qm
23 static const int ap_cluster_index[PLATFORM_CLUSTER_COUNT] = {
24 SC_R_A53, SC_R_A72,
25 };
26 #endif
27
imx_srtc_set_time(uint32_t year_mon,unsigned long day_hour,unsigned long min_sec)28 static 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
imx_srtc_handler(uint32_t smc_fid,void * handle,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4)38 int 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 }
57
imx_cpufreq_set_target(uint32_t cluster_id,unsigned long freq)58 static 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
62 #ifdef PLAT_imx8qm
63 sc_pm_set_clock_rate(ipc_handle, ap_cluster_index[cluster_id], SC_PM_CLK_CPU, &rate);
64 #endif
65 #ifdef PLAT_imx8qx
66 sc_pm_set_clock_rate(ipc_handle, SC_R_A35, SC_PM_CLK_CPU, &rate);
67 #endif
68 }
69
imx_cpufreq_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3)70 int 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 }
85
86 static bool wakeup_src_irqsteer;
87
imx_is_wakeup_src_irqsteer(void)88 bool imx_is_wakeup_src_irqsteer(void)
89 {
90 return wakeup_src_irqsteer;
91 }
92
imx_wakeup_src_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3)93 int 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 }
111
imx_otp_handler(uint32_t smc_fid,void * handle,u_register_t x1,u_register_t x2)112 int 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 }
137
imx_misc_set_temp_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4)138 int 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 }
146
147 #endif /* defined(PLAT_imx8qm) || defined(PLAT_imx8qx) */
148
149 #if defined(PLAT_imx8mm) || defined(PLAT_imx8mq)
imx_src_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,void * handle)150 int 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
imx_get_commit_hash(u_register_t x2,u_register_t x3,u_register_t x4)180 static 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
imx_buildinfo_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4)204 uint64_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 }
222
imx_kernel_entry_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4)223 int 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 }
256