1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2022-2024, STMicroelectronics
4 */
5 #include <drivers/stm32_rif.h>
6 #include <io.h>
7 #include <kernel/boot.h>
8 #include <kernel/dt.h>
9 #include <kernel/interrupt.h>
10 #include <kernel/panic.h>
11 #include <libfdt.h>
12 #include <mm/core_memprot.h>
13 #include <tee_api_defines.h>
14 #include <trace.h>
15 #include <util.h>
16
17 /* IAC offset register */
18 #define _IAC_IER0 U(0x000)
19 #define _IAC_ISR0 U(0x080)
20 #define _IAC_ICR0 U(0x100)
21 #define _IAC_IISR0 U(0x36C)
22
23 #define _IAC_HWCFGR2 U(0x3EC)
24 #define _IAC_HWCFGR1 U(0x3F0)
25 #define _IAC_VERR U(0x3F4)
26
27 /* IAC_HWCFGR2 register fields */
28 #define _IAC_HWCFGR2_CFG1_MASK GENMASK_32(3, 0)
29 #define _IAC_HWCFGR2_CFG1_SHIFT 0
30 #define _IAC_HWCFGR2_CFG2_MASK GENMASK_32(7, 4)
31 #define _IAC_HWCFGR2_CFG2_SHIFT 4
32
33 /* IAC_HWCFGR1 register fields */
34 #define _IAC_HWCFGR1_CFG1_MASK GENMASK_32(3, 0)
35 #define _IAC_HWCFGR1_CFG1_SHIFT 0
36 #define _IAC_HWCFGR1_CFG2_MASK GENMASK_32(7, 4)
37 #define _IAC_HWCFGR1_CFG2_SHIFT 4
38 #define _IAC_HWCFGR1_CFG3_MASK GENMASK_32(11, 8)
39 #define _IAC_HWCFGR1_CFG3_SHIFT 8
40 #define _IAC_HWCFGR1_CFG4_MASK GENMASK_32(15, 12)
41 #define _IAC_HWCFGR1_CFG4_SHIFT 12
42 #define _IAC_HWCFGR1_CFG5_MASK GENMASK_32(24, 16)
43 #define _IAC_HWCFGR1_CFG5_SHIFT 16
44
45 /* IAC_VERR register fields */
46 #define _IAC_VERR_MINREV_MASK GENMASK_32(3, 0)
47 #define _IAC_VERR_MINREV_SHIFT 0
48 #define _IAC_VERR_MAJREV_MASK GENMASK_32(7, 4)
49 #define _IAC_VERR_MAJREV_SHIFT 4
50
51 /* Periph ID per register */
52 #define _PERIPH_IDS_PER_REG 32
53
54 #define _IAC_FLD_PREP(field, value) (SHIFT_U32((value), \
55 (field ## _SHIFT)) & \
56 (field ## _MASK))
57 #define _IAC_FLD_GET(field, value) (((uint32_t)(value) & \
58 (field ## _MASK)) >> \
59 (field ## _SHIFT))
60
61 #define IAC_EXCEPT_MSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG + \
62 _PERIPH_IDS_PER_REG - 1)
63 #define IAC_EXCEPT_LSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG)
64 #define IAC_FIRST_ILAC_IN_REG(x) (__builtin_ffs((x)) - 1)
65 #define IAC_ILAC_ID(reg_val, offset) (IAC_FIRST_ILAC_IN_REG(reg_val) + \
66 IAC_EXCEPT_LSB_BIT(offset))
67
68 /**
69 * struct iac_driver_data - Hardware information on the IAC peripheral
70 *
71 * @version: Peripheral version number
72 * @num_ilac: Number of IAC lines
73 */
74 struct iac_driver_data {
75 uint32_t version;
76 uint8_t num_ilac;
77 };
78
79 /**
80 * struct stm32_iac_platdata - Platform data for the IAC driver
81 *
82 * @irq_chip: Reference to the main IRQ chip of the platform
83 * @base: Virtual base address of the IAC peripheral
84 * @irq: ID of the IAC interrupt
85 */
86 struct stm32_iac_platdata {
87 struct itr_chip *irq_chip;
88 vaddr_t base;
89 size_t irq;
90 };
91
92 /**
93 * struct iac_device - IAC device private data
94 * @pdata: Platform data read from the DT
95 * @ddata: Device data read from the hardware
96 * @itr: Interrupt handler reference
97 */
98 struct iac_device {
99 struct stm32_iac_platdata pdata;
100 struct iac_driver_data *ddata;
101 struct itr_handler *itr;
102 };
103
104 static struct iac_device iac_dev;
105
stm32_iac_get_hwdata(void)106 static void stm32_iac_get_hwdata(void)
107 {
108 struct iac_driver_data *ddata = iac_dev.ddata;
109 vaddr_t base = iac_dev.pdata.base;
110 uint32_t regval = 0;
111
112 regval = io_read32(base + _IAC_HWCFGR1);
113 ddata->num_ilac = _IAC_FLD_GET(_IAC_HWCFGR1_CFG5, regval);
114
115 ddata->version = io_read32(base + _IAC_VERR);
116
117 DMSG("IAC version %"PRIu32".%"PRIu32,
118 _IAC_FLD_GET(_IAC_VERR_MAJREV, ddata->version),
119 _IAC_FLD_GET(_IAC_VERR_MINREV, ddata->version));
120
121 DMSG("HW cap: enabled, num ilac:[%"PRIu8"]", ddata->num_ilac);
122 }
123
stm32_iac_parse_fdt(const void * fdt,int node)124 static TEE_Result stm32_iac_parse_fdt(const void *fdt, int node)
125 {
126 struct stm32_iac_platdata *pdata = &iac_dev.pdata;
127 TEE_Result res = TEE_ERROR_GENERIC;
128 struct dt_node_info dt_info = { };
129 struct io_pa_va base = { };
130
131 fdt_fill_device_info(fdt, &dt_info, node);
132 if (dt_info.reg == DT_INFO_INVALID_REG)
133 return TEE_ERROR_BAD_PARAMETERS;
134
135 res = interrupt_dt_get(fdt, node, &pdata->irq_chip, &pdata->irq);
136 if (res)
137 return res;
138
139 base.pa = dt_info.reg;
140 pdata->base = io_pa_or_va_secure(&base, dt_info.reg_size);
141
142 return TEE_SUCCESS;
143 }
144
stm32_iac_itr(struct itr_handler * h __unused)145 static enum itr_return stm32_iac_itr(struct itr_handler *h __unused)
146 {
147 struct iac_driver_data *ddata = iac_dev.ddata;
148 vaddr_t base = iac_dev.pdata.base;
149 unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
150 unsigned int i = 0;
151 uint32_t isr = 0;
152
153 for (i = 0; i < nreg; i++) {
154 uint32_t offset = sizeof(uint32_t) * i;
155 unsigned int j = 0;
156
157 isr = io_read32(base + _IAC_ISR0 + offset);
158 isr &= io_read32(base + _IAC_IER0 + offset);
159
160 if (!isr)
161 continue;
162
163 EMSG("IAC exceptions [%d:%d]: %#"PRIx32, IAC_EXCEPT_MSB_BIT(i),
164 IAC_EXCEPT_LSB_BIT(i), isr);
165
166 for (j = 0; j < _PERIPH_IDS_PER_REG; j++) {
167 EMSG("IAC exception ID: %d", IAC_ILAC_ID(isr, i));
168
169 io_write32(base + _IAC_ICR0 + offset,
170 BIT(IAC_FIRST_ILAC_IN_REG(isr)));
171
172 isr = io_read32(base + _IAC_ISR0 + offset);
173 isr &= io_read32(base + _IAC_IER0 + offset);
174
175 if (!isr)
176 break;
177 }
178 }
179
180 stm32_rif_access_violation_action();
181 if (IS_ENABLED(CFG_STM32_PANIC_ON_IAC_EVENT))
182 panic();
183
184 return ITRR_HANDLED;
185 }
186
stm32_iac_setup(void)187 static void stm32_iac_setup(void)
188 {
189 struct iac_driver_data *ddata = iac_dev.ddata;
190 vaddr_t base = iac_dev.pdata.base;
191 unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
192 unsigned int i = 0;
193
194 for (i = 0; i < nreg; i++) {
195 vaddr_t reg_ofst = base + sizeof(uint32_t) * i;
196
197 /* Clear status flags */
198 io_write32(reg_ofst + _IAC_ICR0, ~0x0);
199 /* Enable all peripherals of nreg */
200 io_write32(reg_ofst + _IAC_IER0, ~0x0);
201 }
202 }
203
probe_iac_device(const void * fdt,int node)204 static TEE_Result probe_iac_device(const void *fdt, int node)
205 {
206 TEE_Result res = TEE_ERROR_GENERIC;
207 bool is_tdcid = false;
208
209 res = stm32_rifsc_check_tdcid(&is_tdcid);
210 if (res)
211 return res;
212
213 /* IAC must be managed by the trusted domain CID */
214 if (!is_tdcid)
215 return TEE_ERROR_ACCESS_DENIED;
216
217 res = stm32_iac_parse_fdt(fdt, node);
218 if (res)
219 return res;
220
221 stm32_iac_get_hwdata();
222 stm32_iac_setup();
223
224 res = interrupt_alloc_add_handler(iac_dev.pdata.irq_chip,
225 iac_dev.pdata.irq, stm32_iac_itr,
226 ITRF_TRIGGER_LEVEL, NULL,
227 &iac_dev.itr);
228 if (res)
229 panic();
230
231 interrupt_enable(iac_dev.pdata.irq_chip, iac_dev.itr->it);
232
233 return TEE_SUCCESS;
234 }
235
stm32_iac_probe(const void * fdt,int node,const void * compat_data __unused)236 static TEE_Result stm32_iac_probe(const void *fdt, int node,
237 const void *compat_data __unused)
238 {
239 TEE_Result res = TEE_ERROR_GENERIC;
240
241 iac_dev.ddata = calloc(1, sizeof(*iac_dev.ddata));
242 if (!iac_dev.ddata)
243 return TEE_ERROR_OUT_OF_MEMORY;
244
245 res = probe_iac_device(fdt, node);
246 if (res)
247 free(iac_dev.ddata);
248
249 return res;
250 }
251
252 static const struct dt_device_match stm32_iac_match_table[] = {
253 { .compatible = "st,stm32mp25-iac" },
254 { }
255 };
256
257 DEFINE_DT_DRIVER(stm32_iac_dt_driver) = {
258 .name = "stm32-iac",
259 .match_table = stm32_iac_match_table,
260 .probe = stm32_iac_probe,
261 };
262