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