1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. 4 * Copyright (c) 2017-2024, 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 13 #include <assert.h> 14 #include <drivers/clk_dt.h> 15 #include <drivers/stm32_etzpc.h> 16 #include <drivers/stm32mp_dt_bindings.h> 17 #include <initcall.h> 18 #include <io.h> 19 #include <keep.h> 20 #include <kernel/boot.h> 21 #include <kernel/dt.h> 22 #include <kernel/panic.h> 23 #include <kernel/pm.h> 24 #include <kernel/spinlock.h> 25 #include <libfdt.h> 26 #include <mm/core_memprot.h> 27 #include <stm32_util.h> 28 #include <util.h> 29 30 /* ID Registers */ 31 #define ETZPC_TZMA0_SIZE U(0x000) 32 #define ETZPC_DECPROT0 U(0x010) 33 #define ETZPC_DECPROT_LOCK0 U(0x030) 34 #define ETZPC_HWCFGR U(0x3F0) 35 #define ETZPC_VERR U(0x3F4) 36 37 /* ID Registers fields */ 38 #define ETZPC_TZMA0_SIZE_LOCK BIT(31) 39 #define ETZPC_DECPROT0_MASK GENMASK_32(1, 0) 40 #define ETZPC_HWCFGR_NUM_TZMA_MASK GENMASK_32(7, 0) 41 #define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0 42 #define ETZPC_HWCFGR_NUM_PER_SEC_MASK GENMASK_32(15, 8) 43 #define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8 44 #define ETZPC_HWCFGR_NUM_AHB_SEC_MASK GENMASK_32(23, 16) 45 #define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16 46 #define ETZPC_HWCFGR_CHUNKS1N4_MASK GENMASK_32(31, 24) 47 #define ETZPC_HWCFGR_CHUNKS1N4_SHIFT 24 48 49 #define DECPROT_SHIFT 1 50 #define IDS_PER_DECPROT_REGS U(16) 51 #define IDS_PER_DECPROT_LOCK_REGS U(32) 52 53 /* 54 * Implementation uses uint8_t to store each securable DECPROT configuration 55 * and uint16_t to store each securable TZMA configuration. When resuming 56 * from deep suspend, the DECPROT configurations are restored. 57 */ 58 #define PERIPH_PM_LOCK_BIT BIT(7) 59 #define PERIPH_PM_ATTR_MASK GENMASK_32(2, 0) 60 #define TZMA_PM_LOCK_BIT BIT(15) 61 #define TZMA_PM_VALUE_MASK GENMASK_32(9, 0) 62 63 /* 64 * struct stm32_etzpc_platdata - Driver data set at initialization 65 * 66 * @name: Name of the peripheral 67 * @clk: ETZPC clock 68 * @periph_cfg: Peripheral DECPROT configuration 69 * @tzma_cfg: TZMA configuration 70 * @base: ETZPC IOMEM base address 71 */ 72 struct stm32_etzpc_platdata { 73 char *name; 74 struct clk *clk; 75 uint8_t *periph_cfg; 76 uint16_t *tzma_cfg; 77 struct io_pa_va base; 78 }; 79 80 /* 81 * struct stm32_etzpc_driver_data - configuration data from the hardware 82 * 83 * @num_tzma: Number of TZMA zones, read from the hardware 84 * @num_per_sec: Number of securable AHB & APB periphs, read from the hardware 85 * @num_ahb_sec: Number of securable AHB master zones, read from the hardware 86 */ 87 struct stm32_etzpc_driver_data { 88 unsigned int num_tzma; 89 unsigned int num_per_sec; 90 unsigned int num_ahb_sec; 91 }; 92 93 /* 94 * struct etzpc_device - ETZPC device driver instance 95 * @pdata: Platform data set during initialization 96 * @ddata: Device configuration data from the hardware 97 * @lock: Access contention 98 */ 99 struct etzpc_device { 100 struct stm32_etzpc_platdata pdata; 101 struct stm32_etzpc_driver_data ddata; 102 unsigned int lock; 103 }; 104 105 static struct etzpc_device *etzpc_device; 106 107 static uint32_t etzpc_lock(void) 108 { 109 return cpu_spin_lock_xsave(&etzpc_device->lock); 110 } 111 112 static void etzpc_unlock(uint32_t exceptions) 113 { 114 cpu_spin_unlock_xrestore(&etzpc_device->lock, exceptions); 115 } 116 117 static bool valid_decprot_id(unsigned int id) 118 { 119 return id < etzpc_device->ddata.num_per_sec; 120 } 121 122 static bool __maybe_unused valid_tzma_id(unsigned int id) 123 { 124 return id < etzpc_device->ddata.num_tzma; 125 } 126 127 static enum etzpc_decprot_attributes etzpc_binding2decprot(uint32_t mode) 128 { 129 switch (mode) { 130 case DECPROT_S_RW: 131 return ETZPC_DECPROT_S_RW; 132 case DECPROT_NS_R_S_W: 133 return ETZPC_DECPROT_NS_R_S_W; 134 #ifdef CFG_STM32MP15 135 case DECPROT_MCU_ISOLATION: 136 return ETZPC_DECPROT_MCU_ISOLATION; 137 #endif 138 case DECPROT_NS_RW: 139 return ETZPC_DECPROT_NS_RW; 140 default: 141 panic(); 142 } 143 } 144 145 static void etzpc_configure_decprot(uint32_t decprot_id, 146 enum etzpc_decprot_attributes attr) 147 { 148 size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_REGS); 149 uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; 150 uint32_t masked_decprot = (uint32_t)attr & ETZPC_DECPROT0_MASK; 151 vaddr_t base = etzpc_device->pdata.base.va; 152 unsigned int exceptions = 0; 153 154 assert(valid_decprot_id(decprot_id)); 155 156 DMSG("ID : %"PRIu32", CONF %d", decprot_id, attr); 157 158 exceptions = etzpc_lock(); 159 160 io_clrsetbits32(base + ETZPC_DECPROT0 + offset, 161 ETZPC_DECPROT0_MASK << shift, 162 masked_decprot << shift); 163 164 etzpc_unlock(exceptions); 165 } 166 167 enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id) 168 { 169 size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_REGS); 170 uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; 171 vaddr_t base = etzpc_device->pdata.base.va; 172 uint32_t value = 0; 173 174 assert(valid_decprot_id(decprot_id)); 175 176 value = (io_read32(base + ETZPC_DECPROT0 + offset) >> shift) & 177 ETZPC_DECPROT0_MASK; 178 179 return (enum etzpc_decprot_attributes)value; 180 } 181 182 static void etzpc_lock_decprot(uint32_t decprot_id) 183 { 184 size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); 185 uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); 186 vaddr_t base = etzpc_device->pdata.base.va; 187 uint32_t exceptions = 0; 188 189 assert(valid_decprot_id(decprot_id)); 190 191 exceptions = etzpc_lock(); 192 193 io_write32(base + offset + ETZPC_DECPROT_LOCK0, mask); 194 195 etzpc_unlock(exceptions); 196 } 197 198 static bool decprot_is_locked(uint32_t decprot_id) 199 { 200 size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); 201 uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); 202 vaddr_t base = etzpc_device->pdata.base.va; 203 204 assert(valid_decprot_id(decprot_id)); 205 206 return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask; 207 } 208 209 void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value) 210 { 211 size_t offset = sizeof(uint32_t) * tzma_id; 212 vaddr_t base = etzpc_device->pdata.base.va; 213 uint32_t exceptions = 0; 214 215 assert(valid_tzma_id(tzma_id)); 216 217 exceptions = etzpc_lock(); 218 219 io_write32(base + ETZPC_TZMA0_SIZE + offset, tzma_value); 220 221 etzpc_unlock(exceptions); 222 } 223 224 static uint16_t etzpc_get_tzma(uint32_t tzma_id) 225 { 226 size_t offset = sizeof(uint32_t) * tzma_id; 227 vaddr_t base = etzpc_device->pdata.base.va; 228 229 assert(valid_tzma_id(tzma_id)); 230 231 return io_read32(base + ETZPC_TZMA0_SIZE + offset); 232 } 233 234 static void etzpc_lock_tzma(uint32_t tzma_id) 235 { 236 size_t offset = sizeof(uint32_t) * tzma_id; 237 vaddr_t base = etzpc_device->pdata.base.va; 238 uint32_t exceptions = 0; 239 240 assert(valid_tzma_id(tzma_id)); 241 242 exceptions = etzpc_lock(); 243 244 io_setbits32(base + ETZPC_TZMA0_SIZE + offset, ETZPC_TZMA0_SIZE_LOCK); 245 246 etzpc_unlock(exceptions); 247 } 248 249 static bool tzma_is_locked(uint32_t tzma_id) 250 { 251 size_t offset = sizeof(uint32_t) * tzma_id; 252 vaddr_t base = etzpc_device->pdata.base.va; 253 254 assert(valid_tzma_id(tzma_id)); 255 256 return io_read32(base + ETZPC_TZMA0_SIZE + offset) & 257 ETZPC_TZMA0_SIZE_LOCK; 258 } 259 260 static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused, 261 const struct pm_callback_handle *pm_handle __unused) 262 { 263 struct stm32_etzpc_driver_data *ddata = &etzpc_device->ddata; 264 struct stm32_etzpc_platdata *pdata = &etzpc_device->pdata; 265 unsigned int n = 0; 266 267 if (op == PM_OP_SUSPEND) { 268 for (n = 0; n < ddata->num_per_sec; n++) { 269 pdata->periph_cfg[n] = 270 (uint8_t)etzpc_get_decprot(n); 271 if (decprot_is_locked(n)) 272 pdata->periph_cfg[n] |= PERIPH_PM_LOCK_BIT; 273 } 274 275 for (n = 0; n < ddata->num_tzma; n++) { 276 pdata->tzma_cfg[n] = 277 (uint8_t)etzpc_get_tzma(n); 278 if (tzma_is_locked(n)) 279 pdata->tzma_cfg[n] |= TZMA_PM_LOCK_BIT; 280 } 281 282 return TEE_SUCCESS; 283 } 284 285 /* PM_OP_RESUME */ 286 for (n = 0; n < ddata->num_per_sec; n++) { 287 unsigned int attr = pdata->periph_cfg[n] & PERIPH_PM_ATTR_MASK; 288 289 etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr); 290 291 if (pdata->periph_cfg[n] & PERIPH_PM_LOCK_BIT) 292 etzpc_lock_decprot(n); 293 } 294 295 for (n = 0; n < ddata->num_tzma; n++) { 296 uint16_t value = pdata->tzma_cfg[n] & TZMA_PM_VALUE_MASK; 297 298 etzpc_configure_tzma(n, value); 299 300 if (pdata->tzma_cfg[n] & TZMA_PM_LOCK_BIT) 301 etzpc_lock_tzma(n); 302 } 303 304 return TEE_SUCCESS; 305 } 306 DECLARE_KEEP_PAGER(etzpc_pm); 307 308 static void stm32_etzpc_set_driverdata(void) 309 { 310 struct stm32_etzpc_driver_data *ddata = &etzpc_device->ddata; 311 vaddr_t base = etzpc_device->pdata.base.va; 312 uint32_t reg = io_read32(base + ETZPC_HWCFGR); 313 314 ddata->num_tzma = (reg & ETZPC_HWCFGR_NUM_TZMA_MASK) >> 315 ETZPC_HWCFGR_NUM_TZMA_SHIFT; 316 ddata->num_per_sec = (reg & ETZPC_HWCFGR_NUM_PER_SEC_MASK) >> 317 ETZPC_HWCFGR_NUM_PER_SEC_SHIFT; 318 ddata->num_ahb_sec = (reg & ETZPC_HWCFGR_NUM_AHB_SEC_MASK) >> 319 ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT; 320 321 DMSG("ETZPC revision 0x%02"PRIx8", per_sec %u, ahb_sec %u, tzma %u", 322 io_read8(base + ETZPC_VERR), 323 ddata->num_per_sec, ddata->num_ahb_sec, ddata->num_tzma); 324 } 325 326 static void fdt_etzpc_conf_decprot(const void *fdt, int node) 327 { 328 const fdt32_t *cuint = NULL; 329 size_t i = 0; 330 int len = 0; 331 332 cuint = fdt_getprop(fdt, node, "st,decprot", &len); 333 if (!cuint) { 334 DMSG("No ETZPC DECPROT configuration in DT"); 335 return; 336 } 337 338 clk_enable(etzpc_device->pdata.clk); 339 340 for (i = 0; i < len / sizeof(uint32_t); i++) { 341 uint32_t value = fdt32_to_cpu(cuint[i]); 342 uint32_t id = value & ETZPC_ID_MASK; 343 uint32_t mode = (value & ETZPC_MODE_MASK) >> ETZPC_MODE_SHIFT; 344 bool lock = value & ETZPC_LOCK_MASK; 345 enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX; 346 347 if (!valid_decprot_id(id)) { 348 DMSG("Invalid DECPROT %"PRIu32, id); 349 panic(); 350 } 351 352 attr = etzpc_binding2decprot(mode); 353 etzpc_configure_decprot(id, attr); 354 355 if (lock) 356 etzpc_lock_decprot(id); 357 } 358 359 clk_disable(etzpc_device->pdata.clk); 360 } 361 362 static TEE_Result init_etzpc_from_dt(const void *fdt, int node) 363 { 364 TEE_Result res = TEE_ERROR_GENERIC; 365 struct dt_node_info etzpc_info = { }; 366 int len = 0; 367 368 fdt_fill_device_info(fdt, &etzpc_info, node); 369 if (etzpc_info.reg == DT_INFO_INVALID_REG || 370 etzpc_info.reg_size == DT_INFO_INVALID_REG_SIZE) 371 return TEE_ERROR_ITEM_NOT_FOUND; 372 373 etzpc_device->pdata.base.pa = etzpc_info.reg; 374 etzpc_device->pdata.name = strdup(fdt_get_name(fdt, node, &len)); 375 io_pa_or_va_secure(&etzpc_device->pdata.base, etzpc_info.reg_size); 376 res = clk_dt_get_by_index(fdt, node, 0, &etzpc_device->pdata.clk); 377 if (res) 378 return res; 379 380 stm32_etzpc_set_driverdata(); 381 382 etzpc_device->pdata.periph_cfg = 383 calloc(etzpc_device->ddata.num_per_sec, 384 sizeof(*etzpc_device->pdata.periph_cfg)); 385 386 etzpc_device->pdata.tzma_cfg = 387 calloc(etzpc_device->ddata.num_tzma, 388 sizeof(*etzpc_device->pdata.tzma_cfg)); 389 if (!etzpc_device->pdata.periph_cfg || !etzpc_device->pdata.tzma_cfg) 390 return TEE_ERROR_OUT_OF_MEMORY; 391 392 fdt_etzpc_conf_decprot(fdt, node); 393 394 return TEE_SUCCESS; 395 } 396 397 static TEE_Result stm32_etzpc_probe(const void *fdt, int node, 398 const void *compat_data __unused) 399 { 400 TEE_Result res = TEE_ERROR_GENERIC; 401 int subnode = 0; 402 403 etzpc_device = calloc(1, sizeof(*etzpc_device)); 404 if (!etzpc_device) 405 panic("ETZPC probe failed"); 406 407 res = init_etzpc_from_dt(fdt, node); 408 if (res) { 409 free(etzpc_device->pdata.periph_cfg); 410 free(etzpc_device->pdata.tzma_cfg); 411 free(etzpc_device->pdata.name); 412 free(etzpc_device); 413 return res; 414 } 415 416 fdt_for_each_subnode(subnode, fdt, node) { 417 res = dt_driver_maybe_add_probe_node(fdt, subnode); 418 if (res) { 419 EMSG("Failed to add node %s to probe list: %#"PRIx32, 420 fdt_get_name(fdt, subnode, NULL), res); 421 panic(); 422 } 423 } 424 425 register_pm_core_service_cb(etzpc_pm, NULL, "stm32-etzpc"); 426 427 return TEE_SUCCESS; 428 } 429 430 static const struct dt_device_match etzpc_match_table[] = { 431 { .compatible = "st,stm32-etzpc" }, 432 { } 433 }; 434 435 DEFINE_DT_DRIVER(etzpc_dt_driver) = { 436 .name = "stm32-etzpc", 437 .match_table = etzpc_match_table, 438 .probe = stm32_etzpc_probe, 439 }; 440