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