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