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_macros.h>
9 #include <fwk_module.h>
10 #include <fwk_module_idx.h>
11
12 #include <mod_reset_domain.h>
13 #include <mod_scmi_reset_domain.h>
14 #include <mod_optee_reset.h>
15
16 #include <assert.h>
17 #include <dt-bindings/reset/stm32mp1-resets.h>
18 #include <scmi_agents.h>
19 #include <stm32_util.h>
20 #include <util.h>
21
22 /*
23 * Indices of reset domain elements exposed through a SCMI agent.
24 * As all exposed SCMI reset domains relate to a single backend dirver
25 * these indices are used as indices for fwk elements for modules
26 * RESET_DOMAIN and STM32_RESET.
27 */
28 enum resetd_elt_idx {
29 /* Reset domain exposed to agent SCMI */
30 RESETD_IDX_SCMI_SPI6,
31 RESETD_IDX_SCMI_I2C4,
32 RESETD_IDX_SCMI_I2C6,
33 RESETD_IDX_SCMI_USART1,
34 RESETD_IDX_SCMI_STGEN,
35 RESETD_IDX_SCMI_GPIOZ,
36 RESETD_IDX_SCMI_CRYP1,
37 RESETD_IDX_SCMI_HASH1,
38 RESETD_IDX_SCMI_RNG1,
39 RESETD_IDX_SCMI_MDMA,
40 RESETD_IDX_SCMI_MCU,
41 RESETD_IDX_SCMI_MCU_HOLD_BOOT,
42 RESETD_IDX_COUNT
43 };
44
45 struct mod_stm32_reset_dev_config {
46 const char *name;
47 unsigned long rcc_rst_id;
48 };
49
50 /*
51 * stm32_resetd_cfg - Common configuration for exposed SCMI reset domains
52 *
53 * Domain names defined here are used for all RESET_DOMAIN and STM32_RESET
54 * fwk elements names.
55 */
56 #define STM32_RESET_CFG(_idx, _rcc_rst_id, _name) \
57 [(_idx)] = { .rcc_rst_id = (_rcc_rst_id), .name = (_name) }
58
59 static const struct mod_stm32_reset_dev_config stm32_resetd_cfg[] = {
60 STM32_RESET_CFG(RESETD_IDX_SCMI_SPI6, SPI6_R, "spi6"),
61 STM32_RESET_CFG(RESETD_IDX_SCMI_I2C4, I2C4_R, "i2c4"),
62 STM32_RESET_CFG(RESETD_IDX_SCMI_I2C6, I2C6_R, "i2c6"),
63 STM32_RESET_CFG(RESETD_IDX_SCMI_USART1, USART1_R, "usart1"),
64 STM32_RESET_CFG(RESETD_IDX_SCMI_STGEN, STGEN_R, "stgen"),
65 STM32_RESET_CFG(RESETD_IDX_SCMI_GPIOZ, GPIOZ_R, "gpioz"),
66 STM32_RESET_CFG(RESETD_IDX_SCMI_CRYP1, CRYP1_R, "cryp1"),
67 STM32_RESET_CFG(RESETD_IDX_SCMI_HASH1, HASH1_R, "hash1"),
68 STM32_RESET_CFG(RESETD_IDX_SCMI_RNG1, RNG1_R, "rng1"),
69 STM32_RESET_CFG(RESETD_IDX_SCMI_MDMA, MDMA_R, "mdma"),
70 STM32_RESET_CFG(RESETD_IDX_SCMI_MCU, MCU_R, "mcu"),
71 STM32_RESET_CFG(RESETD_IDX_SCMI_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu-hold-boot"),
72 };
73
74 /*
75 * Bindgins between SCMI domain_id value and reset domain module element in fwk
76 */
77 #define SCMI_RESETD_ELT_ID(_idx) \
78 { .element_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_RESET_DOMAIN, (_idx)) }
79
80 static const struct mod_scmi_reset_domain_device scmi_resetd_device[] = {
81 [RST_SCMI_SPI6] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_SPI6),
82 [RST_SCMI_I2C4] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_I2C4),
83 [RST_SCMI_I2C6] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_I2C6),
84 [RST_SCMI_USART1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_USART1),
85 [RST_SCMI_STGEN] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_STGEN),
86 [RST_SCMI_GPIOZ] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_GPIOZ),
87 [RST_SCMI_CRYP1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_CRYP1),
88 [RST_SCMI_HASH1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_HASH1),
89 [RST_SCMI_RNG1] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_RNG1),
90 [RST_SCMI_MDMA] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_MDMA),
91 [RST_SCMI_MCU] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_MCU),
92 [RST_SCMI_MCU_HOLD_BOOT] = SCMI_RESETD_ELT_ID(RESETD_IDX_SCMI_MCU_HOLD_BOOT),
93 };
94
95 /* Agents andreset domains references */
96 static const struct mod_scmi_reset_domain_agent resetd_agent_table[SCMI_AGENT_ID_COUNT] = {
97 [SCMI_AGENT_ID_NSEC0] = {
98 .device_table = (void *)scmi_resetd_device,
99 .agent_domain_count = FWK_ARRAY_SIZE(scmi_resetd_device),
100 },
101 };
102
103 /* Exported configuration data for module SCMI_RESET_DOMAIN */
104 struct fwk_module_config config_scmi_reset_domain = {
105 .data = &((struct mod_scmi_reset_domain_config){
106 .agent_table = resetd_agent_table,
107 .agent_count = FWK_ARRAY_SIZE(resetd_agent_table),
108 }),
109 };
110
111 /*
112 * Reset controller backend driver configuration
113 * STM32_RESET element index is the related RESET_DOMAIN element index.
114 */
115 #define RESETD_DATA(_idx) ((struct mod_reset_domain_dev_config){ \
116 .driver_id = FWK_ID_ELEMENT_INIT(FWK_MODULE_IDX_OPTEE_RESET, (_idx)), \
117 .driver_api_id = FWK_ID_API_INIT(FWK_MODULE_IDX_OPTEE_RESET, 0), \
118 .modes = MOD_RESET_DOMAIN_AUTO_RESET | \
119 MOD_RESET_DOMAIN_MODE_EXPLICIT_ASSERT | \
120 MOD_RESET_DOMAIN_MODE_EXPLICIT_DEASSERT, \
121 .capabilities = 0, /* No notif, no async */ \
122 })
123
124
125 #define RESETD_ELT(_idx) [(_idx)] = { \
126 .name = stm32_resetd_cfg[(_idx)].name, \
127 .data = &RESETD_DATA((_idx)), \
128 }
129
130 /* Element names are the reset domain names exposed by the SCMI service */
131 static const struct fwk_element resetd_elt[] = {
132 /* Reset domains exposed to agent SCMI */
133 RESETD_ELT(RESETD_IDX_SCMI_SPI6),
134 RESETD_ELT(RESETD_IDX_SCMI_I2C4),
135 RESETD_ELT(RESETD_IDX_SCMI_I2C6),
136 RESETD_ELT(RESETD_IDX_SCMI_USART1),
137 RESETD_ELT(RESETD_IDX_SCMI_STGEN),
138 RESETD_ELT(RESETD_IDX_SCMI_GPIOZ),
139 RESETD_ELT(RESETD_IDX_SCMI_CRYP1),
140 RESETD_ELT(RESETD_IDX_SCMI_HASH1),
141 RESETD_ELT(RESETD_IDX_SCMI_RNG1),
142 RESETD_ELT(RESETD_IDX_SCMI_MDMA),
143 RESETD_ELT(RESETD_IDX_SCMI_MCU),
144 RESETD_ELT(RESETD_IDX_SCMI_MCU_HOLD_BOOT),
145 /* Termination entry */
146 [RESETD_IDX_COUNT] = { 0 }
147 };
148
149 static_assert(FWK_ARRAY_SIZE(resetd_elt) == RESETD_IDX_COUNT + 1,
150 "Invalid range for RESET_DOMAIN and STM32_RESET indices");
151
152 /* Exported configuration data for module VOLTAGE_DOMAIN */
153 const struct fwk_module_config config_reset_domain = {
154 .elements = FWK_MODULE_STATIC_ELEMENTS_PTR(resetd_elt),
155 };
156
157 /*
158 * Configuration for module OPTEE_RESET
159 */
160 #define RESET_COUNT FWK_ARRAY_SIZE(stm32_resetd_cfg)
161 static struct mod_optee_reset_dev_config optee_reset_cfg[RESET_COUNT];
162
163 #define OPTEE_RESET_ELT(_idx) \
164 [(_idx)] = { \
165 .name = stm32_resetd_cfg[(_idx)].name, \
166 .data = &optee_reset_cfg[(_idx)], \
167 }
168
169 static const struct fwk_element optee_reset_elt[] = {
170 /* Reset domaines exposed to agent SCMI */
171 OPTEE_RESET_ELT(RESETD_IDX_SCMI_SPI6),
172 OPTEE_RESET_ELT(RESETD_IDX_SCMI_I2C4),
173 OPTEE_RESET_ELT(RESETD_IDX_SCMI_I2C6),
174 OPTEE_RESET_ELT(RESETD_IDX_SCMI_USART1),
175 OPTEE_RESET_ELT(RESETD_IDX_SCMI_STGEN),
176 OPTEE_RESET_ELT(RESETD_IDX_SCMI_GPIOZ),
177 OPTEE_RESET_ELT(RESETD_IDX_SCMI_CRYP1),
178 OPTEE_RESET_ELT(RESETD_IDX_SCMI_HASH1),
179 OPTEE_RESET_ELT(RESETD_IDX_SCMI_RNG1),
180 OPTEE_RESET_ELT(RESETD_IDX_SCMI_MDMA),
181 OPTEE_RESET_ELT(RESETD_IDX_SCMI_MCU),
182 OPTEE_RESET_ELT(RESETD_IDX_SCMI_MCU_HOLD_BOOT),
183 /* Termination entry */
184 [RESETD_IDX_COUNT] = { 0 }
185 };
186
187 static_assert(FWK_ARRAY_SIZE(optee_reset_elt) == RESETD_IDX_COUNT + 1,
188 "Invalid range for RESET and OPTEE_RESET indices");
189
optee_reset_get_elt_table(fwk_id_t module_id)190 static const struct fwk_element *optee_reset_get_elt_table(fwk_id_t module_id)
191 {
192 size_t n;
193
194 for (n = 0; n < FWK_ARRAY_SIZE(optee_reset_cfg); n++) {
195 optee_reset_cfg[n].rstctrl =
196 stm32mp_rcc_reset_id_to_rstctrl(stm32_resetd_cfg[n].rcc_rst_id);
197 }
198
199 return optee_reset_elt;
200 }
201
202 struct fwk_module_config config_optee_reset = {
203 .elements = FWK_MODULE_DYNAMIC_ELEMENTS(optee_reset_get_elt_table),
204 };
205