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