1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2022, Linaro Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <fwk_element.h>
9 #include <fwk_id.h>
10 #include <fwk_module.h>
11 #include <fwk_module_idx.h>
12
13 #include <mod_clock.h>
14 #include <mod_optee_clock.h>
15 #include <mod_scmi_clock.h>
16 #include <scmi_agents.h>
17
18 #include <assert.h>
19 #include <stddef.h>
20 #include <stdint.h>
21
22 #include <dt-bindings/clock/stm32mp1-clks.h>
23 #include <stm32_util.h>
24 #include <util.h>
25
26 /*
27 * Indices of clock elements exposed through a SCMI agent.
28 * As all exposed SCMI clocks relate to a single backend dirver
29 * these indices are used as indices for fwk elements for modules
30 * CLOCK and STM32_CLOCK. Note these are not the clock ID values
31 * exposed through SCMI.
32 */
33 enum clock_elt_idx {
34 /* Clocks exposed to agent SCMI */
35 CLK_IDX_SCMI_HSE,
36 CLK_IDX_SCMI_HSI,
37 CLK_IDX_SCMI_CSI,
38 CLK_IDX_SCMI_LSE,
39 CLK_IDX_SCMI_LSI,
40 CLK_IDX_SCMI_PLL2_Q,
41 CLK_IDX_SCMI_PLL2_R,
42 CLK_IDX_SCMI_MPU,
43 CLK_IDX_SCMI_AXI,
44 CLK_IDX_SCMI_BSEC,
45 CLK_IDX_SCMI_CRYP1,
46 CLK_IDX_SCMI_GPIOZ,
47 CLK_IDX_SCMI_HASH1,
48 CLK_IDX_SCMI_I2C4,
49 CLK_IDX_SCMI_I2C6,
50 CLK_IDX_SCMI_IWDG1,
51 CLK_IDX_SCMI_RNG1,
52 CLK_IDX_SCMI_RTC,
53 CLK_IDX_SCMI_RTCAPB,
54 CLK_IDX_SCMI_SPI6,
55 CLK_IDX_SCMI_USART1,
56 /* Count indices */
57 CLK_IDX_COUNT
58 };
59
60 struct mod_stm32_clock_dev_config {
61 const char *name;
62 unsigned long rcc_clk_id;
63 bool default_enabled;
64 };
65
66 /*
67 * stm32_clock_cfg - Common configuration for exposed SCMI clocks
68 *
69 * Clock name defined here is used for all CLOCK and STM32_CLOCK
70 * fwk elements names.
71 */
72 #define STM32_CLOCK_CFG(_idx, _rcc_clk_id, _name, _default_enabled) \
73 [(_idx)] = { \
74 .rcc_clk_id = (_rcc_clk_id), \
75 .name = (_name), \
76 .default_enabled = (_default_enabled), \
77 }
78
79 static const struct mod_stm32_clock_dev_config stm32_clock_cfg[] = {
80 STM32_CLOCK_CFG(CLK_IDX_SCMI_HSE, CK_HSE, "ck_hse", true),
81 STM32_CLOCK_CFG(CLK_IDX_SCMI_HSI, CK_HSI, "ck_hsi", true),
82 STM32_CLOCK_CFG(CLK_IDX_SCMI_CSI, CK_CSI, "ck_csi", true),
83 STM32_CLOCK_CFG(CLK_IDX_SCMI_LSE, CK_LSE, "ck_lse", true),
84 STM32_CLOCK_CFG(CLK_IDX_SCMI_LSI, CK_LSI, "ck_lsi", true),
85 STM32_CLOCK_CFG(CLK_IDX_SCMI_PLL2_Q, PLL2_Q, "pll2_q", true),
86 STM32_CLOCK_CFG(CLK_IDX_SCMI_PLL2_R, PLL2_R, "pll2_r", true),
87 STM32_CLOCK_CFG(CLK_IDX_SCMI_MPU, CK_MCU, "ck_mpu", true),
88 STM32_CLOCK_CFG(CLK_IDX_SCMI_AXI, CK_AXI, "ck_axi", true),
89 STM32_CLOCK_CFG(CLK_IDX_SCMI_BSEC, BSEC, "bsec", false),
90 STM32_CLOCK_CFG(CLK_IDX_SCMI_CRYP1, CRYP1, "cryp1", false),
91 STM32_CLOCK_CFG(CLK_IDX_SCMI_GPIOZ, GPIOZ, "gpioz", false),
92 STM32_CLOCK_CFG(CLK_IDX_SCMI_HASH1, HASH1, "hash1", false),
93 STM32_CLOCK_CFG(CLK_IDX_SCMI_I2C4, I2C4_K, "i2c4_k", false),
94 STM32_CLOCK_CFG(CLK_IDX_SCMI_I2C6, I2C6_K, "i2c6_k", false),
95 STM32_CLOCK_CFG(CLK_IDX_SCMI_IWDG1, IWDG1, "iwdg1", false),
96 STM32_CLOCK_CFG(CLK_IDX_SCMI_RNG1, RNG1_K, "rng1_k", true),
97 STM32_CLOCK_CFG(CLK_IDX_SCMI_RTC, RTC, "ck_rtc", true),
98 STM32_CLOCK_CFG(CLK_IDX_SCMI_RTCAPB, RTCAPB, "rtcapb", true),
99 STM32_CLOCK_CFG(CLK_IDX_SCMI_SPI6, SPI6_K, "spi6_k", false),
100 STM32_CLOCK_CFG(CLK_IDX_SCMI_USART1, USART1_K, "usart1_k", false),
101 };
102
103 /*
104 * Bindgins between SCMI clock_id value and clock module element in fwk
105 */
106 #define SCMI_CLOCK_ELT_ID(_idx) \
107 { .element_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_CLOCK, (_idx)) }
108
109 static struct mod_scmi_clock_device scmi_clock_device[] = {
110 [CK_SCMI_HSE] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_HSE),
111 [CK_SCMI_HSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_HSI),
112 [CK_SCMI_CSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_CSI),
113 [CK_SCMI_LSE] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_LSE),
114 [CK_SCMI_LSI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_LSI),
115 [CK_SCMI_PLL2_Q] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_PLL2_Q),
116 [CK_SCMI_PLL2_R] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_PLL2_R),
117 [CK_SCMI_MPU] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_MPU),
118 [CK_SCMI_AXI] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_AXI),
119 [CK_SCMI_BSEC] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_BSEC),
120 [CK_SCMI_CRYP1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_CRYP1),
121 [CK_SCMI_GPIOZ] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_GPIOZ),
122 [CK_SCMI_HASH1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_HASH1),
123 [CK_SCMI_I2C4] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_I2C4),
124 [CK_SCMI_I2C6] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_I2C6),
125 [CK_SCMI_IWDG1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_IWDG1),
126 [CK_SCMI_RNG1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_RNG1),
127 [CK_SCMI_RTC] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_RTC),
128 [CK_SCMI_RTCAPB] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_RTCAPB),
129 [CK_SCMI_SPI6] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_SPI6),
130 [CK_SCMI_USART1] = SCMI_CLOCK_ELT_ID(CLK_IDX_SCMI_USART1),
131 };
132
133 /* Agents and clocks references */
134 static const struct mod_scmi_clock_agent clk_agent_tbl[SCMI_AGENT_ID_COUNT] = {
135 [SCMI_AGENT_ID_NSEC0] = {
136 .device_table = (void *)scmi_clock_device,
137 .device_count = FWK_ARRAY_SIZE(scmi_clock_device),
138 },
139 };
140
141 /* Exported configuration data for module SCMI_CLOCK */
142 struct fwk_module_config config_scmi_clock = {
143 .data = &((struct mod_scmi_clock_config){
144 .agent_table = clk_agent_tbl,
145 .agent_count = FWK_ARRAY_SIZE(clk_agent_tbl),
146 }),
147 };
148
149 /*
150 * Clock backend driver configuration
151 * STM32_CLOCK element index is the related CLOCK element index.
152 */
153 #define CLOCK_DATA(_idx) ((struct mod_clock_dev_config){ \
154 .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_CLOCK, \
155 (_idx)), \
156 .api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_CLOCK, 0), \
157 })
158
159 #define CLOCK_ELT(_idx) [(_idx)] = { \
160 .name = stm32_clock_cfg[(_idx)].name, \
161 .data = &CLOCK_DATA((_idx)), \
162 }
163
164 /* Element names are the clock names exposed by the SCMI service */
165 static struct fwk_element clock_elt[] = {
166 /* Clocks exposed to agent SCMI */
167 CLOCK_ELT(CLK_IDX_SCMI_HSE),
168 CLOCK_ELT(CLK_IDX_SCMI_HSI),
169 CLOCK_ELT(CLK_IDX_SCMI_CSI),
170 CLOCK_ELT(CLK_IDX_SCMI_LSE),
171 CLOCK_ELT(CLK_IDX_SCMI_LSI),
172 CLOCK_ELT(CLK_IDX_SCMI_PLL2_Q),
173 CLOCK_ELT(CLK_IDX_SCMI_PLL2_R),
174 CLOCK_ELT(CLK_IDX_SCMI_MPU),
175 CLOCK_ELT(CLK_IDX_SCMI_AXI),
176 CLOCK_ELT(CLK_IDX_SCMI_BSEC),
177 CLOCK_ELT(CLK_IDX_SCMI_CRYP1),
178 CLOCK_ELT(CLK_IDX_SCMI_GPIOZ),
179 CLOCK_ELT(CLK_IDX_SCMI_HASH1),
180 CLOCK_ELT(CLK_IDX_SCMI_I2C4),
181 CLOCK_ELT(CLK_IDX_SCMI_I2C6),
182 CLOCK_ELT(CLK_IDX_SCMI_IWDG1),
183 CLOCK_ELT(CLK_IDX_SCMI_RNG1),
184 CLOCK_ELT(CLK_IDX_SCMI_RTC),
185 CLOCK_ELT(CLK_IDX_SCMI_RTCAPB),
186 CLOCK_ELT(CLK_IDX_SCMI_SPI6),
187 CLOCK_ELT(CLK_IDX_SCMI_USART1),
188 /* Termination entry */
189 [CLK_IDX_COUNT] = { 0 }
190 };
191
192 static_assert(FWK_ARRAY_SIZE(clock_elt) == CLK_IDX_COUNT + 1,
193 "Invalid range for CLOCK and STM32_CLOCK indices");
194
195 /* Exported configuration data for module VOLTAGE_DOMAIN */
196 const struct fwk_module_config config_clock = {
197 .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(clock_elt),
198 };
199
200 #define CLOCK_COUNT FWK_ARRAY_SIZE(stm32_clock_cfg)
201 static struct mod_optee_clock_config optee_clock_cfg[CLOCK_COUNT];
202
203 #define OPTEE_CLOCK_ELT(_idx) \
204 [(_idx)] = { \
205 .name = stm32_clock_cfg[(_idx)].name, \
206 .data = &optee_clock_cfg[(_idx)], \
207 }
208
209 static const struct fwk_element optee_clock_elt[] = {
210 /* Clocks exposed to agent SCMI */
211 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_HSE),
212 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_HSI),
213 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_CSI),
214 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_LSE),
215 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_LSI),
216 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_PLL2_Q),
217 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_PLL2_R),
218 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_MPU),
219 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_AXI),
220 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_BSEC),
221 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_CRYP1),
222 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_GPIOZ),
223 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_HASH1),
224 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_I2C4),
225 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_I2C6),
226 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_IWDG1),
227 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_RNG1),
228 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_RTC),
229 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_RTCAPB),
230 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_SPI6),
231 OPTEE_CLOCK_ELT(CLK_IDX_SCMI_USART1),
232 /* Termination entry */
233 [CLK_IDX_COUNT] = { 0 }
234 };
235
236 static_assert(FWK_ARRAY_SIZE(optee_clock_elt) == CLK_IDX_COUNT + 1,
237 "Invalid range for CLOCK and STM32_CLOCK indices");
238
optee_clock_get_elt_table(fwk_id_t module_id)239 static const struct fwk_element *optee_clock_get_elt_table(fwk_id_t module_id)
240 {
241 size_t n;
242
243 for (n = 0; n < FWK_ARRAY_SIZE(optee_clock_cfg); n++) {
244 optee_clock_cfg[n].clk =
245 stm32mp_rcc_clock_id_to_clk(stm32_clock_cfg[n].rcc_clk_id);
246 optee_clock_cfg[n].default_enabled = stm32_clock_cfg[n].default_enabled;
247 }
248
249 return optee_clock_elt;
250 }
251
252 struct fwk_module_config config_optee_clock = {
253 .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_clock_get_elt_table),
254 };
255