1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
4 * Copyright (c) 2017-2019, STMicroelectronics
5 */
6
7 /*
8 * STM32 ETPZC acts as a firewall on stm32mp SoC peripheral interfaces and
9 * internal memories. The driver expects a single instance of the controller
10 * in the platform.
11 *
12 * The driver API is defined in header file stm32_etzpc.h.
13 *
14 * Driver registers a PM callback for restoration of the access permissions
15 * when it resumes.
16 */
17
18 #include <assert.h>
19 #include <drivers/stm32_etzpc.h>
20 #include <initcall.h>
21 #include <io.h>
22 #include <keep.h>
23 #include <kernel/dt.h>
24 #include <kernel/boot.h>
25 #include <kernel/panic.h>
26 #include <kernel/pm.h>
27 #include <libfdt.h>
28 #include <mm/core_memprot.h>
29 #include <util.h>
30
31 /* Devicetree compatibility */
32 #define ETZPC_COMPAT "st,stm32-etzpc"
33
34 /* ID Registers */
35 #define ETZPC_TZMA0_SIZE 0x000U
36 #define ETZPC_DECPROT0 0x010U
37 #define ETZPC_DECPROT_LOCK0 0x030U
38 #define ETZPC_HWCFGR 0x3F0U
39 #define ETZPC_VERR 0x3F4U
40
41 /* ID Registers fields */
42 #define ETZPC_TZMA0_SIZE_LOCK BIT(31)
43 #define ETZPC_DECPROT0_MASK GENMASK_32(1, 0)
44 #define ETZPC_HWCFGR_NUM_TZMA_MASK GENMASK_32(7, 0)
45 #define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0
46 #define ETZPC_HWCFGR_NUM_PER_SEC_MASK GENMASK_32(15, 8)
47 #define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8
48 #define ETZPC_HWCFGR_NUM_AHB_SEC_MASK GENMASK_32(23, 16)
49 #define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16
50 #define ETZPC_HWCFGR_CHUNCKS1N4_MASK GENMASK_32(31, 24)
51 #define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24
52
53 #define DECPROT_SHIFT 1
54 #define IDS_PER_DECPROT_REGS 16U
55 #define IDS_PER_DECPROT_LOCK_REGS 32U
56
57 /*
58 * Implementation uses uint8_t to store each securable DECPROT configuration
59 * and uint16_t to store each securable TZMA configuration. When resuming
60 * from deep suspend, the DECPROT configurations are restored.
61 */
62 #define PERIPH_PM_LOCK_BIT BIT(7)
63 #define PERIPH_PM_ATTR_MASK GENMASK_32(2, 0)
64 #define TZMA_PM_LOCK_BIT BIT(15)
65 #define TZMA_PM_VALUE_MASK GENMASK_32(9, 0)
66
67 /*
68 * @base - iobase for interface base address
69 * @num_tzma - number of TZMA zone, read from the hardware
70 * @num_ahb_sec - number of securable AHB master zone, read from the hardware
71 * @num_per_sec - number of securable AHB & APB periphs, read from the hardware
72 * @periph_cfg - Backup for restoring DECPROT when resuming (PERIH_PM_*)
73 * @tzma_cfg - Backup for restoring TZMA when resuming (TZMA_PM_*)
74 */
75 struct etzpc_instance {
76 struct io_pa_va base;
77 unsigned int num_tzma;
78 unsigned int num_per_sec;
79 unsigned int num_ahb_sec;
80 uint8_t *periph_cfg;
81 uint16_t *tzma_cfg;
82 };
83
84 /* Only 1 instance of the ETZPC is expected per platform */
85 static struct etzpc_instance etzpc_dev;
86
etzpc_base(void)87 static vaddr_t etzpc_base(void)
88 {
89 return io_pa_or_va_secure(&etzpc_dev.base, 1);
90 }
91
valid_decprot_id(unsigned int id)92 static bool __maybe_unused valid_decprot_id(unsigned int id)
93 {
94 return id < etzpc_dev.num_per_sec;
95 }
96
valid_tzma_id(unsigned int id)97 static bool __maybe_unused valid_tzma_id(unsigned int id)
98 {
99 return id < etzpc_dev.num_tzma;
100 }
101
etzpc_configure_decprot(uint32_t decprot_id,enum etzpc_decprot_attributes decprot_attr)102 void etzpc_configure_decprot(uint32_t decprot_id,
103 enum etzpc_decprot_attributes decprot_attr)
104 {
105 size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
106 uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
107 uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK;
108 vaddr_t base = etzpc_base();
109
110 assert(valid_decprot_id(decprot_id));
111
112 io_clrsetbits32(base + ETZPC_DECPROT0 + offset,
113 ETZPC_DECPROT0_MASK << shift,
114 masked_decprot << shift);
115
116 /* Save for PM */
117 assert((decprot_attr & ~PERIPH_PM_ATTR_MASK) == 0);
118 COMPILE_TIME_ASSERT(ETZPC_DECPROT_MAX <= UINT8_MAX);
119
120 etzpc_dev.periph_cfg[decprot_id] &= ~PERIPH_PM_ATTR_MASK;
121 etzpc_dev.periph_cfg[decprot_id] |= (uint8_t)decprot_attr;
122 }
123
etzpc_get_decprot(uint32_t decprot_id)124 enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id)
125 {
126 size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
127 uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
128 vaddr_t base = etzpc_base();
129 uint32_t value = 0;
130
131 assert(valid_decprot_id(decprot_id));
132
133 value = (io_read32(base + ETZPC_DECPROT0 + offset) >> shift) &
134 ETZPC_DECPROT0_MASK;
135
136 return (enum etzpc_decprot_attributes)value;
137 }
138
etzpc_lock_decprot(uint32_t decprot_id)139 void etzpc_lock_decprot(uint32_t decprot_id)
140 {
141 size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
142 uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
143 vaddr_t base = etzpc_base();
144
145 assert(valid_decprot_id(decprot_id));
146
147 io_write32(base + offset + ETZPC_DECPROT_LOCK0, mask);
148
149 /* Save for PM */
150 etzpc_dev.periph_cfg[decprot_id] |= PERIPH_PM_LOCK_BIT;
151 }
152
etzpc_get_lock_decprot(uint32_t decprot_id)153 bool etzpc_get_lock_decprot(uint32_t decprot_id)
154 {
155 size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
156 uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
157 vaddr_t base = etzpc_base();
158
159 assert(valid_decprot_id(decprot_id));
160
161 return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask;
162 }
163
etzpc_configure_tzma(uint32_t tzma_id,uint16_t tzma_value)164 void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value)
165 {
166 size_t offset = sizeof(uint32_t) * tzma_id;
167 vaddr_t base = etzpc_base();
168
169 assert(valid_tzma_id(tzma_id));
170
171 io_write32(base + ETZPC_TZMA0_SIZE + offset, tzma_value);
172
173 /* Save for PM */
174 assert((tzma_value & ~TZMA_PM_VALUE_MASK) == 0);
175 etzpc_dev.tzma_cfg[tzma_id] &= ~TZMA_PM_VALUE_MASK;
176 etzpc_dev.tzma_cfg[tzma_id] |= tzma_value;
177 }
178
etzpc_get_tzma(uint32_t tzma_id)179 uint16_t etzpc_get_tzma(uint32_t tzma_id)
180 {
181 size_t offset = sizeof(uint32_t) * tzma_id;
182 vaddr_t base = etzpc_base();
183
184 assert(valid_tzma_id(tzma_id));
185
186 return io_read32(base + ETZPC_TZMA0_SIZE + offset);
187 }
188
etzpc_lock_tzma(uint32_t tzma_id)189 void etzpc_lock_tzma(uint32_t tzma_id)
190 {
191 size_t offset = sizeof(uint32_t) * tzma_id;
192 vaddr_t base = etzpc_base();
193
194 assert(valid_tzma_id(tzma_id));
195
196 io_setbits32(base + ETZPC_TZMA0_SIZE + offset, ETZPC_TZMA0_SIZE_LOCK);
197
198 /* Save for PM */
199 etzpc_dev.tzma_cfg[tzma_id] |= TZMA_PM_LOCK_BIT;
200 }
201
etzpc_get_lock_tzma(uint32_t tzma_id)202 bool etzpc_get_lock_tzma(uint32_t tzma_id)
203 {
204 size_t offset = sizeof(uint32_t) * tzma_id;
205 vaddr_t base = etzpc_base();
206
207 assert(valid_tzma_id(tzma_id));
208
209 return io_read32(base + ETZPC_TZMA0_SIZE + offset) &
210 ETZPC_TZMA0_SIZE_LOCK;
211 }
212
etzpc_pm(enum pm_op op,unsigned int pm_hint __unused,const struct pm_callback_handle * pm_handle)213 static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused,
214 const struct pm_callback_handle *pm_handle)
215 {
216 struct etzpc_instance *dev = NULL;
217 unsigned int n = 0;
218
219 if (op != PM_OP_RESUME)
220 return TEE_SUCCESS;
221
222 dev = (struct etzpc_instance *)PM_CALLBACK_GET_HANDLE(pm_handle);
223
224 for (n = 0; n < dev->num_per_sec; n++) {
225 unsigned int attr = dev->periph_cfg[n] & PERIPH_PM_ATTR_MASK;
226
227 etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr);
228
229 if (dev->periph_cfg[n] & PERIPH_PM_LOCK_BIT)
230 etzpc_lock_decprot(n);
231 }
232
233 for (n = 0; n < dev->num_tzma; n++) {
234 uint16_t value = dev->tzma_cfg[n] & TZMA_PM_VALUE_MASK;
235
236 etzpc_configure_tzma(n, value);
237
238 if (dev->tzma_cfg[n] & TZMA_PM_LOCK_BIT)
239 etzpc_lock_tzma(n);
240 }
241
242 return TEE_SUCCESS;
243 }
244 DECLARE_KEEP_PAGER(etzpc_pm);
245
init_pm(struct etzpc_instance * dev)246 static void init_pm(struct etzpc_instance *dev)
247 {
248 unsigned int n = 0;
249
250 dev->periph_cfg = calloc(dev->num_per_sec, sizeof(*dev->periph_cfg));
251 dev->tzma_cfg = calloc(dev->num_tzma, sizeof(*dev->tzma_cfg));
252 if (!dev->periph_cfg || !dev->tzma_cfg)
253 panic();
254
255 for (n = 0; n < dev->num_per_sec; n++) {
256 dev->periph_cfg[n] = (uint8_t)etzpc_get_decprot(n);
257 if (etzpc_get_lock_decprot(n))
258 dev->periph_cfg[n] |= PERIPH_PM_LOCK_BIT;
259 }
260
261 for (n = 0; n < dev->num_tzma; n++) {
262 dev->tzma_cfg[n] = (uint8_t)etzpc_get_tzma(n);
263 if (etzpc_get_lock_tzma(n))
264 dev->tzma_cfg[n] |= TZMA_PM_LOCK_BIT;
265 }
266
267 register_pm_core_service_cb(etzpc_pm, dev, "stm32-etzpc");
268 }
269
270 struct etzpc_hwcfg {
271 unsigned int num_tzma;
272 unsigned int num_per_sec;
273 unsigned int num_ahb_sec;
274 unsigned int chunk_size;
275 };
276
get_hwcfg(struct etzpc_hwcfg * hwcfg)277 static void get_hwcfg(struct etzpc_hwcfg *hwcfg)
278 {
279 uint32_t reg = io_read32(etzpc_base() + ETZPC_HWCFGR);
280
281 hwcfg->num_tzma = (reg & ETZPC_HWCFGR_NUM_TZMA_MASK) >>
282 ETZPC_HWCFGR_NUM_TZMA_SHIFT;
283 hwcfg->num_per_sec = (reg & ETZPC_HWCFGR_NUM_PER_SEC_MASK) >>
284 ETZPC_HWCFGR_NUM_PER_SEC_SHIFT;
285 hwcfg->num_ahb_sec = (reg & ETZPC_HWCFGR_NUM_AHB_SEC_MASK) >>
286 ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT;
287 hwcfg->chunk_size = (reg & ETZPC_HWCFGR_CHUNCKS1N4_MASK) >>
288 ETZPC_HWCFGR_CHUNCKS1N4_SHIFT;
289 }
290
init_device_from_hw_config(struct etzpc_instance * dev,paddr_t pbase)291 static void init_device_from_hw_config(struct etzpc_instance *dev,
292 paddr_t pbase)
293 {
294 struct etzpc_hwcfg hwcfg = { };
295
296 assert(!dev->base.pa && cpu_mmu_enabled());
297 dev->base.pa = pbase;
298 dev->base.va = (vaddr_t)phys_to_virt(dev->base.pa, MEM_AREA_IO_SEC, 1);
299 assert(etzpc_base());
300
301 get_hwcfg(&hwcfg);
302 dev->num_tzma = hwcfg.num_tzma;
303 dev->num_per_sec = hwcfg.num_per_sec;
304 dev->num_ahb_sec = hwcfg.num_ahb_sec;
305
306 DMSG("ETZPC revison 0x02%" PRIu8 ", per_sec %u, ahb_sec %u, tzma %u",
307 io_read8(etzpc_base() + ETZPC_VERR),
308 hwcfg.num_per_sec, hwcfg.num_ahb_sec, hwcfg.num_tzma);
309
310 init_pm(dev);
311 }
312
stm32_etzpc_init(paddr_t base)313 void stm32_etzpc_init(paddr_t base)
314 {
315 init_device_from_hw_config(&etzpc_dev, base);
316 }
317
318 #ifdef CFG_EMBED_DTB
init_etzpc_from_dt(void)319 static TEE_Result init_etzpc_from_dt(void)
320 {
321 void *fdt = get_embedded_dt();
322 int node = fdt_node_offset_by_compatible(fdt, -1, ETZPC_COMPAT);
323 int status = 0;
324 paddr_t pbase = 0;
325
326 /* When using DT, expect one and only one instance, secure enabled */
327
328 if (node < 0)
329 panic();
330 assert(fdt_node_offset_by_compatible(fdt, node, ETZPC_COMPAT) < 0);
331
332 status = _fdt_get_status(fdt, node);
333 if (!(status & DT_STATUS_OK_SEC))
334 panic();
335
336 pbase = _fdt_reg_base_address(fdt, node);
337 if (pbase == (paddr_t)-1)
338 panic();
339
340 init_device_from_hw_config(&etzpc_dev, pbase);
341
342 return TEE_SUCCESS;
343 }
344
345 service_init(init_etzpc_from_dt);
346 #endif /*CFG_EMBED_DTB*/
347