1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2023, STMicroelectronics 4 */ 5 6 #include <assert.h> 7 #include <config.h> 8 #include <drivers/rstctrl.h> 9 #include <drivers/stm32_remoteproc.h> 10 #include <kernel/cache_helpers.h> 11 #include <kernel/dt_driver.h> 12 #include <kernel/tee_misc.h> 13 #include <libfdt.h> 14 #include <mm/core_memprot.h> 15 #include <mm/core_mmu.h> 16 17 #define TIMEOUT_US_1MS U(1000) 18 19 /** 20 * struct stm32_rproc_mem - Memory regions used by the remote processor 21 * 22 * @addr: physical base address from the CPU space perspective 23 * @da: device address corresponding to the physical base address 24 * from remote processor space perspective 25 * @size: size of the region 26 */ 27 struct stm32_rproc_mem { 28 paddr_t addr; 29 paddr_t da; 30 size_t size; 31 }; 32 33 /** 34 * struct stm32_rproc_instance - rproc instance context 35 * 36 * @cdata: pointer to the device compatible data 37 * @link: the node in the rproc_list 38 * @n_regions: number of memory regions 39 * @regions: memory regions used 40 * @mcu_rst: remote processor reset control 41 * @hold_boot: remote processor hold boot control 42 */ 43 struct stm32_rproc_instance { 44 const struct stm32_rproc_compat_data *cdata; 45 SLIST_ENTRY(stm32_rproc_instance) link; 46 size_t n_regions; 47 struct stm32_rproc_mem *regions; 48 struct rstctrl *mcu_rst; 49 struct rstctrl *hold_boot; 50 }; 51 52 /** 53 * struct stm32_rproc_compat_data - rproc associated data for compatible list 54 * 55 * @rproc_id: identifies the remote processor 56 */ 57 struct stm32_rproc_compat_data { 58 uint32_t rproc_id; 59 }; 60 61 static SLIST_HEAD(, stm32_rproc_instance) rproc_list = 62 SLIST_HEAD_INITIALIZER(rproc_list); 63 64 void *stm32_rproc_get(uint32_t rproc_id) 65 { 66 struct stm32_rproc_instance *rproc = NULL; 67 68 SLIST_FOREACH(rproc, &rproc_list, link) 69 if (rproc->cdata->rproc_id == rproc_id) 70 break; 71 72 return rproc; 73 } 74 75 TEE_Result stm32_rproc_start(uint32_t rproc_id) 76 { 77 struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); 78 TEE_Result res = TEE_ERROR_GENERIC; 79 80 if (!rproc || !rproc->hold_boot) 81 return TEE_ERROR_GENERIC; 82 83 /* 84 * The firmware is started by de-asserting the hold boot and 85 * asserting it back to avoid auto restart on a crash. 86 * No need to release the MCU reset as it is automatically released by 87 * the hardware. 88 */ 89 res = rstctrl_deassert_to(rproc->hold_boot, TIMEOUT_US_1MS); 90 if (!res) 91 res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); 92 93 return res; 94 } 95 96 static TEE_Result rproc_stop(struct stm32_rproc_instance *rproc) 97 { 98 TEE_Result res = TEE_ERROR_GENERIC; 99 100 if (!rproc->hold_boot || !rproc->mcu_rst) 101 return TEE_ERROR_GENERIC; 102 103 res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); 104 if (!res) 105 res = rstctrl_assert_to(rproc->mcu_rst, TIMEOUT_US_1MS); 106 107 return res; 108 } 109 110 TEE_Result stm32_rproc_stop(uint32_t rproc_id) 111 { 112 struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); 113 114 if (!rproc) 115 return TEE_ERROR_BAD_PARAMETERS; 116 117 return rproc_stop(rproc); 118 } 119 120 TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size, 121 paddr_t *pa) 122 { 123 struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); 124 struct stm32_rproc_mem *mems = NULL; 125 unsigned int i = 0; 126 127 if (!rproc) 128 return TEE_ERROR_BAD_PARAMETERS; 129 130 mems = rproc->regions; 131 132 for (i = 0; i < rproc->n_regions; i++) { 133 if (core_is_buffer_inside(da, size, mems[i].da, mems[i].size)) { 134 /* 135 * A match between the requested DA memory area and the 136 * registered regions has been found. 137 * The PA is the reserved-memory PA address plus the 138 * delta between the requested DA and the 139 * reserved-memory DA address. 140 */ 141 *pa = mems[i].addr + da - mems[i].da; 142 return TEE_SUCCESS; 143 } 144 } 145 146 return TEE_ERROR_ACCESS_DENIED; 147 } 148 149 TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size, 150 void **va) 151 { 152 struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); 153 struct stm32_rproc_mem *mems = NULL; 154 unsigned int i = 0; 155 156 if (!rproc) 157 return TEE_ERROR_BAD_PARAMETERS; 158 159 mems = rproc->regions; 160 161 for (i = 0; i < rproc->n_regions; i++) { 162 if (!core_is_buffer_inside(pa, size, mems[i].addr, 163 mems[i].size)) 164 continue; 165 *va = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, pa, size); 166 if (!*va) { 167 EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); 168 return TEE_ERROR_GENERIC; 169 } 170 171 return TEE_SUCCESS; 172 } 173 174 return TEE_ERROR_ACCESS_DENIED; 175 } 176 177 TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size) 178 { 179 struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); 180 struct stm32_rproc_mem *mems = NULL; 181 paddr_t pa = virt_to_phys(va); 182 unsigned int i = 0; 183 184 if (!rproc || !pa) 185 return TEE_ERROR_BAD_PARAMETERS; 186 187 mems = rproc->regions; 188 189 for (i = 0; i < rproc->n_regions; i++) { 190 if (!core_is_buffer_inside(pa, size, mems[i].addr, 191 mems[i].size)) 192 continue; 193 194 /* Flush the cache before unmapping the memory */ 195 dcache_clean_range(va, size); 196 197 if (core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, va, size)) { 198 EMSG("Can't unmap region %#"PRIxPA" size %zu", 199 pa, size); 200 return TEE_ERROR_GENERIC; 201 } 202 203 return TEE_SUCCESS; 204 } 205 206 return TEE_ERROR_ACCESS_DENIED; 207 } 208 209 static TEE_Result stm32_rproc_get_dma_range(struct stm32_rproc_mem *region, 210 const void *fdt, int node) 211 { 212 const fdt32_t *list = NULL; 213 int ahb_node = 0; 214 int len = 0; 215 int nranges = 0; 216 int i = 0; 217 218 /* 219 * The match between local and remote processor memory mapping is 220 * described in the dma-ranges defined by the bus parent node. 221 */ 222 ahb_node = fdt_parent_offset(fdt, node); 223 224 list = fdt_getprop(fdt, ahb_node, "dma-ranges", &len); 225 if (!list) { 226 if (len != -FDT_ERR_NOTFOUND) 227 return TEE_ERROR_GENERIC; 228 /* Same memory mapping */ 229 DMSG("No dma-ranges found in DT"); 230 region->da = region->addr; 231 return TEE_SUCCESS; 232 } 233 234 if ((len % (sizeof(uint32_t) * 3))) 235 return TEE_ERROR_GENERIC; 236 237 nranges = len / sizeof(uint32_t); 238 239 for (i = 0; i < nranges; i += 3) { 240 uint32_t da = fdt32_to_cpu(list[i]); 241 uint32_t pa = fdt32_to_cpu(list[i + 1]); 242 uint32_t size = fdt32_to_cpu(list[i + 2]); 243 244 if (core_is_buffer_inside(region->addr, region->size, 245 pa, size)) { 246 region->da = da + (region->addr - pa); 247 return TEE_SUCCESS; 248 } 249 } 250 251 return TEE_ERROR_BAD_PARAMETERS; 252 } 253 254 /* Get device tree memory regions reserved for the Cortex-M and the IPC */ 255 static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc, 256 const void *fdt, int node) 257 { 258 const fdt32_t *list = NULL; 259 TEE_Result res = TEE_ERROR_GENERIC; 260 struct stm32_rproc_mem *regions = NULL; 261 int len = 0; 262 int n_regions = 0; 263 int i = 0; 264 265 list = fdt_getprop(fdt, node, "memory-region", &len); 266 if (!list) { 267 EMSG("No memory regions found in DT"); 268 return TEE_ERROR_GENERIC; 269 } 270 271 n_regions = len / sizeof(uint32_t); 272 273 regions = calloc(n_regions, sizeof(*regions)); 274 if (!regions) 275 return TEE_ERROR_OUT_OF_MEMORY; 276 277 for (i = 0; i < n_regions; i++) { 278 int pnode = 0; 279 280 pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(list[i])); 281 if (pnode < 0) { 282 res = TEE_ERROR_GENERIC; 283 goto err; 284 } 285 286 regions[i].addr = fdt_reg_base_address(fdt, pnode); 287 regions[i].size = fdt_reg_size(fdt, pnode); 288 289 if (regions[i].addr <= 0 || regions[i].size <= 0) { 290 res = TEE_ERROR_GENERIC; 291 goto err; 292 } 293 294 res = stm32_rproc_get_dma_range(®ions[i], fdt, node); 295 if (res) 296 goto err; 297 298 if (!regions[i].addr || !regions[i].size) { 299 res = TEE_ERROR_BAD_PARAMETERS; 300 goto err; 301 } 302 303 DMSG("register region %#"PRIxPA" size %#zx", 304 regions[i].addr, regions[i].size); 305 } 306 307 rproc->n_regions = n_regions; 308 rproc->regions = regions; 309 310 return TEE_SUCCESS; 311 312 err: 313 free(regions); 314 315 return res; 316 } 317 318 static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc) 319 { 320 free(rproc->regions); 321 free(rproc); 322 } 323 324 static TEE_Result stm32_rproc_probe(const void *fdt, int node, 325 const void *comp_data) 326 { 327 struct stm32_rproc_instance *rproc = NULL; 328 TEE_Result res = TEE_ERROR_GENERIC; 329 330 rproc = calloc(1, sizeof(*rproc)); 331 if (!rproc) 332 return TEE_ERROR_OUT_OF_MEMORY; 333 334 rproc->cdata = comp_data; 335 336 res = stm32_rproc_parse_mems(rproc, fdt, node); 337 if (res) 338 goto err; 339 340 res = rstctrl_dt_get_by_name(fdt, node, "mcu_rst", &rproc->mcu_rst); 341 if (res) 342 goto err; 343 344 res = rstctrl_dt_get_by_name(fdt, node, "hold_boot", &rproc->hold_boot); 345 if (res) 346 goto err; 347 348 /* Ensure that the MCU is HOLD */ 349 if (rproc->mcu_rst) { 350 res = rproc_stop(rproc); 351 if (res) 352 goto err; 353 } 354 355 /* 356 * The memory management should be enhance with firewall 357 * mechanism to map the memory in secure area for the firmware 358 * loading and then to give exclusive access right to the 359 * coprocessor (except for the shared memory). 360 */ 361 IMSG("Warning: the remoteproc memories are not protected by firewall"); 362 363 SLIST_INSERT_HEAD(&rproc_list, rproc, link); 364 365 return TEE_SUCCESS; 366 367 err: 368 stm32_rproc_cleanup(rproc); 369 return res; 370 } 371 372 static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = { 373 .rproc_id = STM32_M4_RPROC_ID, 374 }; 375 376 static const struct dt_device_match stm32_rproc_match_table[] = { 377 { 378 .compatible = "st,stm32mp1-m4-tee", 379 .compat_data = &stm32_rproc_m4_compat, 380 }, 381 { } 382 }; 383 384 DEFINE_DT_DRIVER(stm32_rproc_dt_driver) = { 385 .name = "stm32-rproc", 386 .match_table = stm32_rproc_match_table, 387 .probe = &stm32_rproc_probe, 388 }; 389