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