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