1fdaaaeb4SEtienne Carriere /*
233667d29SYann 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
1133667d29SYann 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
plat_scmi_get_channel(unsigned int agent_id)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
find_resource(unsigned int agent_id)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
plat_scmi_protocol_count_paranoid(void)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
plat_scmi_vendor_name(void)184fdaaaeb4SEtienne Carriere const char *plat_scmi_vendor_name(void)
185fdaaaeb4SEtienne Carriere {
186fdaaaeb4SEtienne Carriere return vendor;
187fdaaaeb4SEtienne Carriere }
188fdaaaeb4SEtienne Carriere
plat_scmi_sub_vendor_name(void)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
plat_scmi_protocol_count(void)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
plat_scmi_protocol_list(unsigned int agent_id __unused)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 */
find_clock(unsigned int agent_id,unsigned int scmi_id)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
plat_scmi_clock_count(unsigned int agent_id)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
plat_scmi_clock_get_name(unsigned int agent_id,unsigned int scmi_id)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
plat_scmi_clock_rates_array(unsigned int agent_id,unsigned int scmi_id,unsigned long * array,size_t * nb_elts,uint32_t start_idx)262fdaaaeb4SEtienne Carriere int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
263*ca9d6edcSXiaoDong Huang unsigned long *array, size_t *nb_elts,
264*ca9d6edcSXiaoDong Huang uint32_t start_idx)
265fdaaaeb4SEtienne Carriere {
266fdaaaeb4SEtienne Carriere struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
267fdaaaeb4SEtienne Carriere
268fdaaaeb4SEtienne Carriere if (clock == NULL) {
269fdaaaeb4SEtienne Carriere return SCMI_NOT_FOUND;
270fdaaaeb4SEtienne Carriere }
271fdaaaeb4SEtienne Carriere
272fdaaaeb4SEtienne Carriere if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
273fdaaaeb4SEtienne Carriere return SCMI_DENIED;
274fdaaaeb4SEtienne Carriere }
275fdaaaeb4SEtienne Carriere
276*ca9d6edcSXiaoDong Huang if (start_idx > 0) {
277*ca9d6edcSXiaoDong Huang return SCMI_OUT_OF_RANGE;
278*ca9d6edcSXiaoDong Huang }
279*ca9d6edcSXiaoDong Huang
280fdaaaeb4SEtienne Carriere if (array == NULL) {
281fdaaaeb4SEtienne Carriere *nb_elts = 1U;
282fdaaaeb4SEtienne Carriere } else if (*nb_elts == 1U) {
28333667d29SYann Gautier *array = clk_get_rate(clock->clock_id);
284fdaaaeb4SEtienne Carriere } else {
285fdaaaeb4SEtienne Carriere return SCMI_GENERIC_ERROR;
286fdaaaeb4SEtienne Carriere }
287fdaaaeb4SEtienne Carriere
288fdaaaeb4SEtienne Carriere return SCMI_SUCCESS;
289fdaaaeb4SEtienne Carriere }
290fdaaaeb4SEtienne Carriere
plat_scmi_clock_get_rate(unsigned int agent_id,unsigned int scmi_id)291fdaaaeb4SEtienne Carriere unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
292fdaaaeb4SEtienne Carriere unsigned int scmi_id)
293fdaaaeb4SEtienne Carriere {
294fdaaaeb4SEtienne Carriere struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
295fdaaaeb4SEtienne Carriere
296fdaaaeb4SEtienne Carriere if ((clock == NULL) ||
297fdaaaeb4SEtienne Carriere !stm32mp_nsec_can_access_clock(clock->clock_id)) {
298fdaaaeb4SEtienne Carriere return 0U;
299fdaaaeb4SEtienne Carriere }
300fdaaaeb4SEtienne Carriere
30133667d29SYann Gautier return clk_get_rate(clock->clock_id);
302fdaaaeb4SEtienne Carriere }
303fdaaaeb4SEtienne Carriere
plat_scmi_clock_get_state(unsigned int agent_id,unsigned int scmi_id)304fdaaaeb4SEtienne Carriere int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
305fdaaaeb4SEtienne Carriere {
306fdaaaeb4SEtienne Carriere struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
307fdaaaeb4SEtienne Carriere
308fdaaaeb4SEtienne Carriere if ((clock == NULL) ||
309fdaaaeb4SEtienne Carriere !stm32mp_nsec_can_access_clock(clock->clock_id)) {
310fdaaaeb4SEtienne Carriere return 0U;
311fdaaaeb4SEtienne Carriere }
312fdaaaeb4SEtienne Carriere
313fdaaaeb4SEtienne Carriere return (int32_t)clock->enabled;
314fdaaaeb4SEtienne Carriere }
315fdaaaeb4SEtienne Carriere
plat_scmi_clock_set_state(unsigned int agent_id,unsigned int scmi_id,bool enable_not_disable)316fdaaaeb4SEtienne Carriere int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
317fdaaaeb4SEtienne Carriere bool enable_not_disable)
318fdaaaeb4SEtienne Carriere {
319fdaaaeb4SEtienne Carriere struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
320fdaaaeb4SEtienne Carriere
321fdaaaeb4SEtienne Carriere if (clock == NULL) {
322fdaaaeb4SEtienne Carriere return SCMI_NOT_FOUND;
323fdaaaeb4SEtienne Carriere }
324fdaaaeb4SEtienne Carriere
325fdaaaeb4SEtienne Carriere if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
326fdaaaeb4SEtienne Carriere return SCMI_DENIED;
327fdaaaeb4SEtienne Carriere }
328fdaaaeb4SEtienne Carriere
329fdaaaeb4SEtienne Carriere if (enable_not_disable) {
330fdaaaeb4SEtienne Carriere if (!clock->enabled) {
331fdaaaeb4SEtienne Carriere VERBOSE("SCMI clock %u enable\n", scmi_id);
33233667d29SYann Gautier clk_enable(clock->clock_id);
333fdaaaeb4SEtienne Carriere clock->enabled = true;
334fdaaaeb4SEtienne Carriere }
335fdaaaeb4SEtienne Carriere } else {
336fdaaaeb4SEtienne Carriere if (clock->enabled) {
337fdaaaeb4SEtienne Carriere VERBOSE("SCMI clock %u disable\n", scmi_id);
33833667d29SYann Gautier clk_disable(clock->clock_id);
339fdaaaeb4SEtienne Carriere clock->enabled = false;
340fdaaaeb4SEtienne Carriere }
341fdaaaeb4SEtienne Carriere }
342fdaaaeb4SEtienne Carriere
343fdaaaeb4SEtienne Carriere return SCMI_SUCCESS;
344fdaaaeb4SEtienne Carriere }
345fdaaaeb4SEtienne Carriere
346fdaaaeb4SEtienne Carriere /*
347fdaaaeb4SEtienne Carriere * Platform SCMI reset domains
348fdaaaeb4SEtienne Carriere */
find_rstd(unsigned int agent_id,unsigned int scmi_id)349fdaaaeb4SEtienne Carriere static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id,
350fdaaaeb4SEtienne Carriere unsigned int scmi_id)
351fdaaaeb4SEtienne Carriere {
352fdaaaeb4SEtienne Carriere const struct scmi_agent_resources *resource = find_resource(agent_id);
353fdaaaeb4SEtienne Carriere size_t n;
354fdaaaeb4SEtienne Carriere
355fdaaaeb4SEtienne Carriere if (resource != NULL) {
356fdaaaeb4SEtienne Carriere for (n = 0U; n < resource->rstd_count; n++) {
357fdaaaeb4SEtienne Carriere if (n == scmi_id) {
358fdaaaeb4SEtienne Carriere return &resource->rstd[n];
359fdaaaeb4SEtienne Carriere }
360fdaaaeb4SEtienne Carriere }
361fdaaaeb4SEtienne Carriere }
362fdaaaeb4SEtienne Carriere
363fdaaaeb4SEtienne Carriere return NULL;
364fdaaaeb4SEtienne Carriere }
365fdaaaeb4SEtienne Carriere
plat_scmi_rstd_get_name(unsigned int agent_id,unsigned int scmi_id)366fdaaaeb4SEtienne Carriere const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
367fdaaaeb4SEtienne Carriere {
368fdaaaeb4SEtienne Carriere const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
369fdaaaeb4SEtienne Carriere
370fdaaaeb4SEtienne Carriere if (rstd == NULL) {
371fdaaaeb4SEtienne Carriere return NULL;
372fdaaaeb4SEtienne Carriere }
373fdaaaeb4SEtienne Carriere
374fdaaaeb4SEtienne Carriere return rstd->name;
375fdaaaeb4SEtienne Carriere }
376fdaaaeb4SEtienne Carriere
plat_scmi_rstd_count(unsigned int agent_id)377fdaaaeb4SEtienne Carriere size_t plat_scmi_rstd_count(unsigned int agent_id)
378fdaaaeb4SEtienne Carriere {
379fdaaaeb4SEtienne Carriere const struct scmi_agent_resources *resource = find_resource(agent_id);
380fdaaaeb4SEtienne Carriere
381fdaaaeb4SEtienne Carriere if (resource == NULL) {
382fdaaaeb4SEtienne Carriere return 0U;
383fdaaaeb4SEtienne Carriere }
384fdaaaeb4SEtienne Carriere
385fdaaaeb4SEtienne Carriere return resource->rstd_count;
386fdaaaeb4SEtienne Carriere }
387fdaaaeb4SEtienne Carriere
plat_scmi_rstd_autonomous(unsigned int agent_id,unsigned int scmi_id,uint32_t state)388fdaaaeb4SEtienne Carriere int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
389fdaaaeb4SEtienne Carriere uint32_t state)
390fdaaaeb4SEtienne Carriere {
391fdaaaeb4SEtienne Carriere const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
392fdaaaeb4SEtienne Carriere
393fdaaaeb4SEtienne Carriere if (rstd == NULL) {
394fdaaaeb4SEtienne Carriere return SCMI_NOT_FOUND;
395fdaaaeb4SEtienne Carriere }
396fdaaaeb4SEtienne Carriere
397fdaaaeb4SEtienne Carriere if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
398fdaaaeb4SEtienne Carriere return SCMI_DENIED;
399fdaaaeb4SEtienne Carriere }
400fdaaaeb4SEtienne Carriere
401fdaaaeb4SEtienne Carriere /* Supports only reset with context loss */
402fdaaaeb4SEtienne Carriere if (state != 0U) {
403fdaaaeb4SEtienne Carriere return SCMI_NOT_SUPPORTED;
404fdaaaeb4SEtienne Carriere }
405fdaaaeb4SEtienne Carriere
406fdaaaeb4SEtienne Carriere VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id);
407fdaaaeb4SEtienne Carriere
408fdaaaeb4SEtienne Carriere if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) {
409fdaaaeb4SEtienne Carriere return SCMI_HARDWARE_ERROR;
410fdaaaeb4SEtienne Carriere }
411fdaaaeb4SEtienne Carriere
412fdaaaeb4SEtienne Carriere if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) {
413fdaaaeb4SEtienne Carriere return SCMI_HARDWARE_ERROR;
414fdaaaeb4SEtienne Carriere }
415fdaaaeb4SEtienne Carriere
416fdaaaeb4SEtienne Carriere return SCMI_SUCCESS;
417fdaaaeb4SEtienne Carriere }
418fdaaaeb4SEtienne Carriere
plat_scmi_rstd_set_state(unsigned int agent_id,unsigned int scmi_id,bool assert_not_deassert)419fdaaaeb4SEtienne Carriere int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
420fdaaaeb4SEtienne Carriere bool assert_not_deassert)
421fdaaaeb4SEtienne Carriere {
422fdaaaeb4SEtienne Carriere const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
423fdaaaeb4SEtienne Carriere
424fdaaaeb4SEtienne Carriere if (rstd == NULL) {
425fdaaaeb4SEtienne Carriere return SCMI_NOT_FOUND;
426fdaaaeb4SEtienne Carriere }
427fdaaaeb4SEtienne Carriere
428fdaaaeb4SEtienne Carriere if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
429fdaaaeb4SEtienne Carriere return SCMI_DENIED;
430fdaaaeb4SEtienne Carriere }
431fdaaaeb4SEtienne Carriere
432fdaaaeb4SEtienne Carriere if (assert_not_deassert) {
433fdaaaeb4SEtienne Carriere VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
434fdaaaeb4SEtienne Carriere stm32mp_reset_set(rstd->reset_id);
435fdaaaeb4SEtienne Carriere } else {
436fdaaaeb4SEtienne Carriere VERBOSE("SCMI reset %lu release\n", rstd->reset_id);
437fdaaaeb4SEtienne Carriere stm32mp_reset_release(rstd->reset_id);
438fdaaaeb4SEtienne Carriere }
439fdaaaeb4SEtienne Carriere
440fdaaaeb4SEtienne Carriere return SCMI_SUCCESS;
441fdaaaeb4SEtienne Carriere }
442fdaaaeb4SEtienne Carriere
443fdaaaeb4SEtienne Carriere /*
444fdaaaeb4SEtienne Carriere * Initialize platform SCMI resources
445fdaaaeb4SEtienne Carriere */
stm32mp1_init_scmi_server(void)446fdaaaeb4SEtienne Carriere void stm32mp1_init_scmi_server(void)
447fdaaaeb4SEtienne Carriere {
448fdaaaeb4SEtienne Carriere size_t i;
449fdaaaeb4SEtienne Carriere
450fdaaaeb4SEtienne Carriere for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
451fdaaaeb4SEtienne Carriere scmi_smt_init_agent_channel(&scmi_channel[i]);
452fdaaaeb4SEtienne Carriere }
453fdaaaeb4SEtienne Carriere
454fdaaaeb4SEtienne Carriere for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) {
455fdaaaeb4SEtienne Carriere const struct scmi_agent_resources *res = &agent_resources[i];
456fdaaaeb4SEtienne Carriere size_t j;
457fdaaaeb4SEtienne Carriere
458fdaaaeb4SEtienne Carriere for (j = 0U; j < res->clock_count; j++) {
459fdaaaeb4SEtienne Carriere struct stm32_scmi_clk *clk = &res->clock[j];
460fdaaaeb4SEtienne Carriere
461fdaaaeb4SEtienne Carriere if ((clk->name == NULL) ||
462fdaaaeb4SEtienne Carriere (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) {
463fdaaaeb4SEtienne Carriere ERROR("Invalid SCMI clock name\n");
464fdaaaeb4SEtienne Carriere panic();
465fdaaaeb4SEtienne Carriere }
466fdaaaeb4SEtienne Carriere
467fdaaaeb4SEtienne Carriere /* Sync SCMI clocks with their targeted initial state */
468fdaaaeb4SEtienne Carriere if (clk->enabled &&
469fdaaaeb4SEtienne Carriere stm32mp_nsec_can_access_clock(clk->clock_id)) {
47033667d29SYann Gautier clk_enable(clk->clock_id);
471fdaaaeb4SEtienne Carriere }
472fdaaaeb4SEtienne Carriere }
473fdaaaeb4SEtienne Carriere
474fdaaaeb4SEtienne Carriere for (j = 0U; j < res->rstd_count; j++) {
475fdaaaeb4SEtienne Carriere struct stm32_scmi_rstd *rstd = &res->rstd[j];
476fdaaaeb4SEtienne Carriere
477fdaaaeb4SEtienne Carriere if ((rstd->name == NULL) ||
478fdaaaeb4SEtienne Carriere (strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) {
479fdaaaeb4SEtienne Carriere ERROR("Invalid SCMI reset domain name\n");
480fdaaaeb4SEtienne Carriere panic();
481fdaaaeb4SEtienne Carriere }
482fdaaaeb4SEtienne Carriere }
483fdaaaeb4SEtienne Carriere }
484fdaaaeb4SEtienne Carriere }
485