xref: /optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c (revision d658309647eb2ea592263a956999db54bd517fc5)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2019, STMicroelectronics
4  */
5 #include <assert.h>
6 #include <compiler.h>
7 #include <drivers/scmi-msg.h>
8 #include <drivers/scmi.h>
9 #include <dt-bindings/clock/stm32mp1-clks.h>
10 #include <dt-bindings/reset/stm32mp1-resets.h>
11 #include <initcall.h>
12 #include <mm/core_memprot.h>
13 #include <mm/core_mmu.h>
14 #include <platform_config.h>
15 #include <stdint.h>
16 #include <speculation_barrier.h>
17 #include <stm32_util.h>
18 #include <string.h>
19 #include <tee_api_defines.h>
20 #include <util.h>
21 
22 #define TIMEOUT_US_1MS		1000
23 
24 #define SCMI_CLOCK_NAME_SIZE	16
25 #define SCMI_RD_NAME_SIZE	16
26 
27 /*
28  * struct stm32_scmi_clk - Data for the exposed clock
29  * @clock_id: Clock identifier in RCC clock driver
30  * @name: Clock string ID exposed to agent
31  * @enabled: State of the SCMI clock
32  */
33 struct stm32_scmi_clk {
34 	unsigned long clock_id;
35 	const char *name;
36 	bool enabled;
37 };
38 
39 /*
40  * struct stm32_scmi_rd - Data for the exposed reset controller
41  * @reset_id: Reset identifier in RCC reset driver
42  * @name: Reset string ID exposed to agent
43  */
44 struct stm32_scmi_rd {
45 	unsigned long reset_id;
46 	const char *name;
47 };
48 
49 /* Locate all non-secure SMT message buffers in last page of SYSRAM */
50 #define SMT_BUFFER_BASE		CFG_STM32MP1_SCMI_SHM_BASE
51 #define SMT_BUFFER0_BASE	SMT_BUFFER_BASE
52 #define SMT_BUFFER1_BASE	(SMT_BUFFER_BASE + 0x200)
53 
54 #if (SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE > \
55 	CFG_STM32MP1_SCMI_SHM_BASE + CFG_STM32MP1_SCMI_SHM_SIZE)
56 #error "SCMI shared memory mismatch"
57 #endif
58 
59 register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE,
60 		  CFG_STM32MP1_SCMI_SHM_SIZE);
61 
62 static struct scmi_msg_channel scmi_channel[] = {
63 	[0] = {
64 		.agent_name = "stm32mp1-agent-0",
65 		.shm_addr = { .pa = SMT_BUFFER0_BASE, },
66 		.shm_size = SMT_BUF_SLOT_SIZE,
67 	},
68 	[1] = {
69 		.agent_name = "stm32mp1-agent-1",
70 		.shm_addr =  { .pa = SMT_BUFFER1_BASE, },
71 		.shm_size = SMT_BUF_SLOT_SIZE,
72 	},
73 };
74 
75 struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
76 {
77 	assert(agent_id < ARRAY_SIZE(scmi_channel));
78 
79 	return &scmi_channel[agent_id];
80 }
81 
82 #define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
83 	[_scmi_id] = { \
84 		.clock_id = _id, \
85 		.name = _name, \
86 		.enabled = _init_enabled, \
87 	}
88 
89 struct stm32_scmi_clk stm32_scmi0_clock[] = {
90 	CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true),
91 	CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true),
92 	CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true),
93 	CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true),
94 	CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true),
95 	CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true),
96 	CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true),
97 	CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true),
98 	CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true),
99 	CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true),
100 	CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false),
101 	CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false),
102 	CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false),
103 	CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false),
104 	CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false),
105 	CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false),
106 	CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true),
107 	CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true),
108 	CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true),
109 	CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false),
110 	CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false),
111 };
112 
113 struct stm32_scmi_clk stm32_scmi1_clock[] = {
114 	CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true),
115 	CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true),
116 	CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false),
117 };
118 
119 #define RESET_CELL(_scmi_id, _id, _name) \
120 	[_scmi_id] = { \
121 		.reset_id = _id, \
122 		.name = _name, \
123 	}
124 
125 struct stm32_scmi_rd stm32_scmi0_reset_domain[] = {
126 	RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"),
127 	RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"),
128 	RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"),
129 	RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"),
130 	RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"),
131 	RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"),
132 	RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"),
133 	RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"),
134 	RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
135 	RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
136 	RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
137 	RESET_CELL(RST_SCMI0_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"),
138 };
139 
140 struct scmi_agent_resources {
141 	struct stm32_scmi_clk *clock;
142 	size_t clock_count;
143 	struct stm32_scmi_rd *rd;
144 	size_t rd_count;
145 	struct stm32_scmi_pd *pd;
146 	size_t pd_count;
147 	struct stm32_scmi_perfs *perfs;
148 	size_t perfs_count;
149 };
150 
151 const struct scmi_agent_resources agent_resources[] = {
152 	[0] = {
153 		.clock = stm32_scmi0_clock,
154 		.clock_count = ARRAY_SIZE(stm32_scmi0_clock),
155 		.rd = stm32_scmi0_reset_domain,
156 		.rd_count = ARRAY_SIZE(stm32_scmi0_reset_domain),
157 	},
158 	[1] = {
159 		.clock = stm32_scmi1_clock,
160 		.clock_count = ARRAY_SIZE(stm32_scmi1_clock),
161 	},
162 };
163 
164 static const struct scmi_agent_resources *find_resource(unsigned int agent_id)
165 {
166 	assert(agent_id < ARRAY_SIZE(agent_resources));
167 
168 	return &agent_resources[agent_id];
169 }
170 
171 static size_t __maybe_unused plat_scmi_protocol_count_paranoid(void)
172 {
173 	unsigned int n = 0;
174 	unsigned int count = 0;
175 	const size_t agent_count = ARRAY_SIZE(agent_resources);
176 
177 	for (n = 0; n < agent_count; n++)
178 		if (agent_resources[n].clock_count)
179 			break;
180 	if (n < agent_count)
181 		count++;
182 
183 	for (n = 0; n < agent_count; n++)
184 		if (agent_resources[n].rd_count)
185 			break;
186 	if (n < agent_count)
187 		count++;
188 
189 	for (n = 0; n < agent_count; n++)
190 		if (agent_resources[n].pd_count)
191 			break;
192 	if (n < agent_count)
193 		count++;
194 
195 	for (n = 0; n < agent_count; n++)
196 		if (agent_resources[n].perfs_count)
197 			break;
198 	if (n < agent_count)
199 		count++;
200 
201 	return count;
202 }
203 
204 static const char vendor[] = "ST";
205 static const char sub_vendor[] = "";
206 
207 const char *plat_scmi_vendor_name(void)
208 {
209 	return vendor;
210 }
211 
212 const char *plat_scmi_sub_vendor_name(void)
213 {
214 	return sub_vendor;
215 }
216 
217 /* Currently supporting Clocks and Reset Domains */
218 static const uint8_t plat_protocol_list[] = {
219 	SCMI_PROTOCOL_ID_CLOCK,
220 	SCMI_PROTOCOL_ID_RESET_DOMAIN,
221 	0 /* Null termination */
222 };
223 
224 size_t plat_scmi_protocol_count(void)
225 {
226 	const size_t count = ARRAY_SIZE(plat_protocol_list) - 1;
227 
228 	assert(count == plat_scmi_protocol_count_paranoid());
229 
230 	return count;
231 }
232 
233 const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
234 {
235 	assert(plat_scmi_protocol_count_paranoid() ==
236 	       (ARRAY_SIZE(plat_protocol_list) - 1));
237 
238 	return plat_protocol_list;
239 }
240 
241 /*
242  * Platform SCMI clocks
243  */
244 static struct stm32_scmi_clk *find_clock(unsigned int agent_id,
245 					 unsigned int scmi_id)
246 {
247 	const struct scmi_agent_resources *resource = find_resource(agent_id);
248 	size_t n = 0;
249 
250 	if (resource) {
251 		for (n = 0U; n < resource->clock_count; n++)
252 			if (n == scmi_id)
253 				return &resource->clock[n];
254 	}
255 
256 	return NULL;
257 }
258 
259 size_t plat_scmi_clock_count(unsigned int agent_id)
260 {
261 	const struct scmi_agent_resources *resource = find_resource(agent_id);
262 
263 	if (!resource)
264 		return 0;
265 
266 	return resource->clock_count;
267 }
268 
269 const char *plat_scmi_clock_get_name(unsigned int agent_id,
270 				     unsigned int scmi_id)
271 {
272 	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
273 
274 	if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id))
275 		return NULL;
276 
277 	return clock->name;
278 }
279 
280 int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
281 				    size_t start_index, unsigned long *array,
282 				    size_t *nb_elts)
283 {
284 	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
285 
286 	if (!clock)
287 		return SCMI_NOT_FOUND;
288 
289 	if (!stm32mp_nsec_can_access_clock(clock->clock_id))
290 		return SCMI_DENIED;
291 
292 	/* Exposed clocks are currently fixed rate clocks */
293 	if (start_index)
294 		return SCMI_INVALID_PARAMETERS;
295 
296 	if (!array)
297 		*nb_elts = 1;
298 	else if (*nb_elts == 1)
299 		*array = stm32_clock_get_rate(clock->clock_id);
300 	else
301 		return SCMI_GENERIC_ERROR;
302 
303 	return SCMI_SUCCESS;
304 }
305 
306 unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
307 				       unsigned int scmi_id)
308 {
309 	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
310 
311 	if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id))
312 		return 0;
313 
314 	return stm32_clock_get_rate(clock->clock_id);
315 }
316 
317 int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
318 {
319 	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
320 
321 	if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id))
322 		return 0;
323 
324 	return (int32_t)clock->enabled;
325 }
326 
327 int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
328 				  bool enable_not_disable)
329 {
330 	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
331 
332 	if (!clock)
333 		return SCMI_NOT_FOUND;
334 
335 	if (!stm32mp_nsec_can_access_clock(clock->clock_id))
336 		return SCMI_DENIED;
337 
338 	if (enable_not_disable) {
339 		if (!clock->enabled) {
340 			DMSG("SCMI clock %u enable", scmi_id);
341 			stm32_clock_enable(clock->clock_id);
342 			clock->enabled = true;
343 		}
344 	} else {
345 		if (clock->enabled) {
346 			DMSG("SCMI clock %u disable", scmi_id);
347 			stm32_clock_disable(clock->clock_id);
348 			clock->enabled = false;
349 		}
350 	}
351 
352 	return SCMI_SUCCESS;
353 }
354 
355 /*
356  * Platform SCMI reset domains
357  */
358 static struct stm32_scmi_rd *find_rd(unsigned int agent_id,
359 				     unsigned int scmi_id)
360 {
361 	const struct scmi_agent_resources *resource = find_resource(agent_id);
362 	size_t n = 0;
363 
364 	if (resource) {
365 		for (n = 0; n < resource->rd_count; n++)
366 			if (n == scmi_id)
367 				return &resource->rd[n];
368 	}
369 
370 	return NULL;
371 }
372 
373 const char *plat_scmi_rd_get_name(unsigned int agent_id, unsigned int scmi_id)
374 {
375 	const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id);
376 
377 	if (!rd)
378 		return NULL;
379 
380 	return rd->name;
381 }
382 
383 size_t plat_scmi_rd_count(unsigned int agent_id)
384 {
385 	const struct scmi_agent_resources *resource = find_resource(agent_id);
386 
387 	if (!resource)
388 		return 0;
389 
390 	return resource->rd_count;
391 }
392 
393 int32_t plat_scmi_rd_autonomous(unsigned int agent_id, unsigned int scmi_id,
394 				uint32_t state)
395 {
396 	const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id);
397 
398 	if (!rd)
399 		return SCMI_NOT_FOUND;
400 
401 	if (!stm32mp_nsec_can_access_reset(rd->reset_id))
402 		return SCMI_DENIED;
403 
404 	if (rd->reset_id == MCU_HOLD_BOOT_R)
405 		return SCMI_NOT_SUPPORTED;
406 
407 	/* Supports only reset with context loss */
408 	if (state)
409 		return SCMI_NOT_SUPPORTED;
410 
411 	DMSG("SCMI reset %u cycle", scmi_id);
412 
413 	if (stm32_reset_assert(rd->reset_id, TIMEOUT_US_1MS))
414 		return SCMI_HARDWARE_ERROR;
415 
416 	if (stm32_reset_deassert(rd->reset_id, TIMEOUT_US_1MS))
417 		return SCMI_HARDWARE_ERROR;
418 
419 	return SCMI_SUCCESS;
420 }
421 
422 int32_t plat_scmi_rd_set_state(unsigned int agent_id, unsigned int scmi_id,
423 			       bool assert_not_deassert)
424 {
425 	const struct stm32_scmi_rd *rd = find_rd(agent_id, scmi_id);
426 
427 	if (!rd)
428 		return SCMI_NOT_FOUND;
429 
430 	if (!stm32mp_nsec_can_access_reset(rd->reset_id))
431 		return SCMI_DENIED;
432 
433 	if (rd->reset_id == MCU_HOLD_BOOT_R) {
434 		DMSG("SCMI MCU hold boot %s",
435 		     assert_not_deassert ? "set" : "release");
436 		stm32_reset_assert_deassert_mcu(assert_not_deassert);
437 		return SCMI_SUCCESS;
438 	}
439 
440 	if (assert_not_deassert) {
441 		DMSG("SCMI reset %u set", scmi_id);
442 		stm32_reset_set(rd->reset_id);
443 	} else {
444 		DMSG("SCMI reset %u release", scmi_id);
445 		stm32_reset_release(rd->reset_id);
446 	}
447 
448 	return SCMI_SUCCESS;
449 }
450 
451 /*
452  * Initialize platform SCMI resources
453  */
454 static TEE_Result stm32mp1_init_scmi_server(void)
455 {
456 	size_t i = 0;
457 	size_t j = 0;
458 
459 	for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) {
460 		struct scmi_msg_channel *chan = &scmi_channel[i];
461 
462 		/* Enforce non-secure shm mapped as device memory */
463 		chan->shm_addr.va = (vaddr_t)phys_to_virt(chan->shm_addr.pa,
464 							  MEM_AREA_IO_NSEC);
465 		assert(chan->shm_addr.va);
466 
467 		scmi_smt_init_agent_channel(chan);
468 	}
469 
470 	for (i = 0; i < ARRAY_SIZE(agent_resources); i++) {
471 		const struct scmi_agent_resources *res = &agent_resources[i];
472 
473 		for (j = 0; j < res->clock_count; j++) {
474 			struct stm32_scmi_clk *clk = &res->clock[j];
475 
476 			if (!clk->name ||
477 			    strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)
478 				panic("SCMI clock name invalid");
479 
480 			/* Sync SCMI clocks with their targeted initial state */
481 			if (clk->enabled &&
482 			    stm32mp_nsec_can_access_clock(clk->clock_id))
483 				stm32_clock_enable(clk->clock_id);
484 		}
485 
486 		for (j = 0; j < res->rd_count; j++) {
487 			struct stm32_scmi_rd *rd = &res->rd[j];
488 
489 			if (!rd->name ||
490 			    strlen(rd->name) >= SCMI_RD_NAME_SIZE)
491 				panic("SCMI reset domain name invalid");
492 		}
493 	}
494 
495 	return TEE_SUCCESS;
496 }
497 
498 driver_init_late(stm32mp1_init_scmi_server);
499