xref: /rk3399_ARM-atf/drivers/nxp/scmi/vendor/scmi_imx9.c (revision c42aefd3eb1b5888ee6f3d1f8645b62ec850cdcc)
1 /*
2  * Copyright 2023-2025 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 
9 #include <arch_helpers.h>
10 #include <common/debug.h>
11 #include <drivers/arm/css/scmi.h>
12 #include "scmi_imx9.h"
13 #include <scmi_private.h>
14 
15 /*
16  * API to set the SCMI AP core reset address and attributes
17  */
18 int scmi_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t cpu_id,
19 			     uint32_t attr)
20 {
21 	mailbox_mem_t *mbx_mem;
22 	unsigned int token = 0U;
23 	int ret;
24 	scmi_channel_t *ch = (scmi_channel_t *)p;
25 
26 	validate_scmi_channel(ch);
27 
28 	scmi_get_channel(ch);
29 
30 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
31 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
32 			IMX9_SCMI_CORE_RESET_ADDR_SET_MSG, token);
33 	mbx_mem->len = IMX9_SCMI_CORE_RESET_ADDR_SET_MSG_LEN;
34 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
35 	SCMI_PAYLOAD_ARG4(mbx_mem->payload, cpu_id, attr,
36 			  reset_addr & 0xffffffff, reset_addr >> 32);
37 
38 	scmi_send_sync_command(ch);
39 
40 	/* Get the return values */
41 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
42 	assert(mbx_mem->len == IMX9_SCMI_CORE_RESET_ADDR_SET_RESP_LEN);
43 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
44 
45 	scmi_put_channel(ch);
46 
47 	return ret;
48 }
49 
50 int scmi_core_start(void *p, uint32_t cpu_id)
51 {
52 	mailbox_mem_t *mbx_mem;
53 	unsigned int token = 0U;
54 	int ret;
55 	scmi_channel_t *ch = (scmi_channel_t *)p;
56 
57 	validate_scmi_channel(ch);
58 
59 	scmi_get_channel(ch);
60 
61 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
62 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
63 			IMX9_SCMI_CORE_START_MSG, token);
64 	mbx_mem->len = IMX9_SCMI_CORE_START_MSG_LEN;
65 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
66 	SCMI_PAYLOAD_ARG1(mbx_mem->payload, cpu_id);
67 
68 	scmi_send_sync_command(ch);
69 
70 	/* Get the return values */
71 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
72 	assert(mbx_mem->len == IMX9_SCMI_CORE_START_RESP_LEN);
73 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
74 
75 	scmi_put_channel(ch);
76 
77 	return ret;
78 }
79 
80 int scmi_core_stop(void *p, uint32_t cpu_id)
81 {
82 	mailbox_mem_t *mbx_mem;
83 	unsigned int token = 0U;
84 	int ret;
85 	scmi_channel_t *ch = (scmi_channel_t *)p;
86 
87 	validate_scmi_channel(ch);
88 
89 	scmi_get_channel(ch);
90 
91 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
92 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
93 			IMX9_SCMI_CORE_STOP_MSG, token);
94 	mbx_mem->len = IMX9_SCMI_CORE_STOP_MSG_LEN;
95 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
96 	SCMI_PAYLOAD_ARG1(mbx_mem->payload, cpu_id);
97 
98 	scmi_send_sync_command(ch);
99 
100 	/* Get the return values */
101 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
102 	assert(mbx_mem->len == IMX9_SCMI_CORE_STOP_RESP_LEN);
103 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
104 
105 	scmi_put_channel(ch);
106 
107 	return ret;
108 }
109 
110 int scmi_core_set_sleep_mode(void *p, uint32_t cpu_id, uint32_t wakeup,
111 			     uint32_t mode)
112 {
113 	mailbox_mem_t *mbx_mem;
114 	unsigned int token = 0U;
115 	int ret;
116 	scmi_channel_t *ch = (scmi_channel_t *)p;
117 
118 	validate_scmi_channel(ch);
119 
120 	scmi_get_channel(ch);
121 
122 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
123 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
124 			IMX9_SCMI_CORE_SETSLEEPMODE_MSG, token);
125 	mbx_mem->len = IMX9_SCMI_CORE_SETSLEEPMODE_MSG_LEN;
126 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
127 	SCMI_PAYLOAD_ARG3(mbx_mem->payload, cpu_id, wakeup, mode);
128 
129 	scmi_send_sync_command(ch);
130 
131 	/* Get the return values */
132 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
133 	assert(mbx_mem->len == IMX9_SCMI_CORE_SETSLEEPMODE_RESP_LEN);
134 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
135 
136 	scmi_put_channel(ch);
137 
138 	return ret;
139 }
140 
141 int scmi_core_Irq_wake_set(void *p, uint32_t cpu_id, uint32_t mask_idx,
142 		uint32_t num_mask, uint32_t *mask)
143 {
144 	mailbox_mem_t *mbx_mem;
145 	unsigned int token = 0U;
146 	int ret;
147 	scmi_channel_t *ch = (scmi_channel_t *)p;
148 
149 	validate_scmi_channel(ch);
150 
151 	scmi_get_channel(ch);
152 
153 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
154 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
155 			IMX9_SCMI_CORE_SETIRQWAKESET_MSG, token);
156 	mbx_mem->len = IMX9_SCMI_CORE_SETIRQWAKESET_MSG_LEN;
157 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
158 	SCMI_PAYLOAD_ARG3(mbx_mem->payload, cpu_id, mask_idx, num_mask);
159 
160 	for (unsigned int i = 0U; i < num_mask; i++) {
161 		mbx_mem->payload[3U + i] = mask[i];
162 	}
163 
164 	scmi_send_sync_command(ch);
165 
166 	/* Get the return values */
167 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
168 	assert(mbx_mem->len == IMX9_SCMI_CORE_SETIRQWAKESET_RESP_LEN);
169 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
170 
171 	scmi_put_channel(ch);
172 
173 	return ret;
174 }
175 
176 int scmi_core_nonIrq_wake_set(void *p, uint32_t cpu_id, uint32_t mask_idx,
177 		uint32_t num_mask, uint32_t mask)
178 {
179 	mailbox_mem_t *mbx_mem;
180 	unsigned int token = 0U;
181 	int ret;
182 	scmi_channel_t *ch = (scmi_channel_t *)p;
183 
184 	validate_scmi_channel(ch);
185 	scmi_get_channel(ch);
186 
187 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
188 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
189 			IMX9_SCMI_CORE_NONIRQWAKESET_MSG, token);
190 	mbx_mem->len = IMX9_SCMI_CORE_NONIRQWAKESET_MSG_LEN;
191 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
192 	SCMI_PAYLOAD_ARG4(mbx_mem->payload, cpu_id, mask_idx, num_mask, mask);
193 
194 	scmi_send_sync_command(ch);
195 
196 	/* Get the return values */
197 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
198 	assert(mbx_mem->len == IMX9_SCMI_CORE_NONIRQWAKESET_RESP_LEN);
199 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
200 
201 	scmi_put_channel(ch);
202 
203 	return ret;
204 }
205 
206 int scmi_core_lpm_mode_set(void *p, uint32_t cpu_id,
207 			   uint32_t num_configs,
208 			   struct scmi_lpm_config *cfg)
209 {
210 	mailbox_mem_t *mbx_mem;
211 	unsigned int token = 0U;
212 	int ret;
213 	scmi_channel_t *ch = (scmi_channel_t *)p;
214 
215 	validate_scmi_channel(ch);
216 
217 	scmi_get_channel(ch);
218 
219 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
220 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
221 			IMX9_SCMI_CORE_LPMMODESET_MSG, token);
222 	mbx_mem->len = IMX9_SCMI_CORE_LPMMODESET_MSG_LEN +
223 		       (num_configs * sizeof(struct scmi_lpm_config));
224 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
225 	SCMI_PAYLOAD_ARG2(mbx_mem->payload, cpu_id, num_configs);
226 
227 	/* The lpm config starts from byte 2 in the payload memory */
228 	unsigned int j = 2U;
229 
230 	for (unsigned int i = 0U; i < num_configs; i++) {
231 		mmio_write_32((uintptr_t)&mbx_mem->payload[j++],
232 			      cfg[i].power_domain);
233 		mmio_write_32((uintptr_t)&mbx_mem->payload[j++],
234 			      cfg[i].lpmsetting);
235 		mmio_write_32((uintptr_t)&mbx_mem->payload[j++],
236 			      cfg[i].retentionmask);
237 	}
238 	scmi_send_sync_command(ch);
239 
240 	/* Get the return values */
241 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
242 	assert(mbx_mem->len == IMX9_SCMI_CORE_LPMMODESET_RESP_LEN);
243 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
244 
245 	scmi_put_channel(ch);
246 
247 	return ret;
248 }
249 
250 int scmi_per_lpm_mode_set(void *p, uint32_t cpu_id, uint32_t num_configs,
251 		struct scmi_per_lpm_config *cfg)
252 {
253 	mailbox_mem_t *mbx_mem;
254 	unsigned int token = 0U;
255 	int ret;
256 	scmi_channel_t *ch = (scmi_channel_t *)p;
257 	struct scmi_per_lpm_config *tmp = cfg;
258 
259 	validate_scmi_channel(ch);
260 
261 	scmi_get_channel(ch);
262 
263 	do {
264 		mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
265 		mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
266 				IMX9_SCMI_PER_LPMMODESET_MSG, token);
267 		mbx_mem->len = IMX9_SCMI_PER_LPMMODESET_MSG_LEN +
268 			       (num_configs * sizeof(struct scmi_per_lpm_config));
269 		mbx_mem->flags = SCMI_FLAG_RESP_POLL;
270 		SCMI_PAYLOAD_ARG2(mbx_mem->payload, cpu_id, num_configs);
271 
272 		/* The lpm config starts from byte 2 in the payload memory */
273 		unsigned int j = 2U;
274 
275 		for (unsigned int i = 0U; i < num_configs; i++) {
276 			mmio_write_32((uintptr_t)&mbx_mem->payload[j++],
277 				      cfg[i].perId);
278 			mmio_write_32((uintptr_t)&mbx_mem->payload[j++],
279 				      cfg[i].lpmSetting);
280 		}
281 		scmi_send_sync_command(ch);
282 
283 		/* Get the return values */
284 		SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
285 		assert(mbx_mem->len == IMX9_SCMI_PER_LPMMODESET_RESP_LEN);
286 		assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
287 
288 		if (num_configs > MAX_PER_LPI_CONFIGS_PER_CMD) {
289 			num_configs -= MAX_PER_LPI_CONFIGS_PER_CMD;
290 			tmp += MAX_PER_LPI_CONFIGS_PER_CMD;
291 		} else {
292 			break;
293 		}
294 	} while (num_configs);
295 
296 	scmi_put_channel(ch);
297 
298 	return ret;
299 }
300 
301 int scmi_perf_mode_set(void *p, uint32_t domain_id, uint32_t perf_level)
302 {
303 	mailbox_mem_t *mbx_mem;
304 	unsigned int token = 0U;
305 	int ret;
306 	scmi_channel_t *ch = (scmi_channel_t *)p;
307 
308 	validate_scmi_channel(ch);
309 
310 	scmi_get_channel(ch);
311 
312 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
313 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_PERF_PROTO_ID,
314 			IMX9_SCMI_CORE_PERFLEVELSET_MSG, token);
315 	mbx_mem->len = IMX9_SCMI_CORE_PERFLEVELSET_MSG_LEN;
316 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
317 	SCMI_PAYLOAD_ARG2(mbx_mem->payload, domain_id, perf_level);
318 
319 	scmi_send_sync_command(ch);
320 
321 	/* Get the return values */
322 	SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
323 	assert(mbx_mem->len == IMX9_SCMI_CORE_PERFLEVELSET_RESP_LEN);
324 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
325 
326 	scmi_put_channel(ch);
327 
328 	return ret;
329 
330 }
331 
332 int scmi_core_info_get(void *p, uint32_t cpu_id, uint32_t *runmode,
333 		       uint32_t *sleepmode, uint64_t *vector)
334 {
335 	mailbox_mem_t *mbx_mem;
336 	unsigned int token = 0U;
337 	int ret;
338 	scmi_channel_t *ch = (scmi_channel_t *)p;
339 	uint32_t lo_addr, hi_addr;
340 
341 	validate_scmi_channel(ch);
342 
343 	scmi_get_channel(ch);
344 
345 	mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
346 	mbx_mem->msg_header = SCMI_MSG_CREATE(IMX9_SCMI_CORE_PROTO_ID,
347 			IMX9_SCMI_CORE_GETINFO_MSG, token);
348 	mbx_mem->len = IMX9_SCMI_CORE_GETINFO_MSG_LEN;
349 	mbx_mem->flags = SCMI_FLAG_RESP_POLL;
350 	SCMI_PAYLOAD_ARG1(mbx_mem->payload, cpu_id);
351 
352 	scmi_send_sync_command(ch);
353 
354 	/* Get the return values */
355 	SCMI_PAYLOAD_RET_VAL5(mbx_mem->payload, ret, *runmode, *sleepmode,
356 			      lo_addr, hi_addr);
357 	*vector = lo_addr | (uint64_t)hi_addr << 32;
358 	assert(mbx_mem->len == IMX9_SCMI_CORE_START_RESP_LEN);
359 	assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
360 
361 	scmi_put_channel(ch);
362 
363 	return ret;
364 }
365