|
10 | 10 | #include <linux/mfd/syscon.h> |
11 | 11 | #include <linux/module.h> |
12 | 12 | #include <linux/of_address.h> |
| 13 | +#include <linux/of_reserved_mem.h> |
13 | 14 | #include <linux/of_device.h> |
14 | 15 | #include <linux/platform_device.h> |
15 | 16 | #include <linux/regmap.h> |
@@ -241,10 +242,102 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i |
241 | 242 | return va; |
242 | 243 | } |
243 | 244 |
|
| 245 | +static int imx_rproc_mem_alloc(struct rproc *rproc, |
| 246 | + struct rproc_mem_entry *mem) |
| 247 | +{ |
| 248 | + struct device *dev = rproc->dev.parent; |
| 249 | + void *va; |
| 250 | + |
| 251 | + dev_dbg(dev, "map memory: %p+%zx\n", &mem->dma, mem->len); |
| 252 | + va = ioremap_wc(mem->dma, mem->len); |
| 253 | + if (IS_ERR_OR_NULL(va)) { |
| 254 | + dev_err(dev, "Unable to map memory region: %p+%zx\n", |
| 255 | + &mem->dma, mem->len); |
| 256 | + return -ENOMEM; |
| 257 | + } |
| 258 | + |
| 259 | + /* Update memory entry va */ |
| 260 | + mem->va = va; |
| 261 | + |
| 262 | + return 0; |
| 263 | +} |
| 264 | + |
| 265 | +static int imx_rproc_mem_release(struct rproc *rproc, |
| 266 | + struct rproc_mem_entry *mem) |
| 267 | +{ |
| 268 | + dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma); |
| 269 | + iounmap(mem->va); |
| 270 | + |
| 271 | + return 0; |
| 272 | +} |
| 273 | + |
| 274 | +static int imx_rproc_parse_memory_regions(struct rproc *rproc) |
| 275 | +{ |
| 276 | + struct imx_rproc *priv = rproc->priv; |
| 277 | + struct device_node *np = priv->dev->of_node; |
| 278 | + struct of_phandle_iterator it; |
| 279 | + struct rproc_mem_entry *mem; |
| 280 | + struct reserved_mem *rmem; |
| 281 | + u32 da; |
| 282 | + |
| 283 | + /* Register associated reserved memory regions */ |
| 284 | + of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); |
| 285 | + while (of_phandle_iterator_next(&it) == 0) { |
| 286 | + /* |
| 287 | + * Ignore the first memory region which will be used vdev buffer. |
| 288 | + * No need to do extra handlings, rproc_add_virtio_dev will handle it. |
| 289 | + */ |
| 290 | + if (!strcmp(it.node->name, "vdev0buffer")) |
| 291 | + continue; |
| 292 | + |
| 293 | + rmem = of_reserved_mem_lookup(it.node); |
| 294 | + if (!rmem) { |
| 295 | + dev_err(priv->dev, "unable to acquire memory-region\n"); |
| 296 | + return -EINVAL; |
| 297 | + } |
| 298 | + |
| 299 | + /* No need to translate pa to da, i.MX use same map */ |
| 300 | + da = rmem->base; |
| 301 | + |
| 302 | + /* Register memory region */ |
| 303 | + mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)rmem->base, rmem->size, da, |
| 304 | + imx_rproc_mem_alloc, imx_rproc_mem_release, |
| 305 | + it.node->name); |
| 306 | + |
| 307 | + if (mem) |
| 308 | + rproc_coredump_add_segment(rproc, da, rmem->size); |
| 309 | + else |
| 310 | + return -ENOMEM; |
| 311 | + |
| 312 | + rproc_add_carveout(rproc, mem); |
| 313 | + } |
| 314 | + |
| 315 | + return 0; |
| 316 | +} |
| 317 | + |
| 318 | +static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) |
| 319 | +{ |
| 320 | + int ret = imx_rproc_parse_memory_regions(rproc); |
| 321 | + |
| 322 | + if (ret) |
| 323 | + return ret; |
| 324 | + |
| 325 | + ret = rproc_elf_load_rsc_table(rproc, fw); |
| 326 | + if (ret) |
| 327 | + dev_info(&rproc->dev, "No resource table in elf\n"); |
| 328 | + |
| 329 | + return 0; |
| 330 | +} |
| 331 | + |
244 | 332 | static const struct rproc_ops imx_rproc_ops = { |
245 | 333 | .start = imx_rproc_start, |
246 | 334 | .stop = imx_rproc_stop, |
247 | 335 | .da_to_va = imx_rproc_da_to_va, |
| 336 | + .load = rproc_elf_load_segments, |
| 337 | + .parse_fw = imx_rproc_parse_fw, |
| 338 | + .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, |
| 339 | + .sanity_check = rproc_elf_sanity_check, |
| 340 | + .get_boot_addr = rproc_elf_get_boot_addr, |
248 | 341 | }; |
249 | 342 |
|
250 | 343 | static int imx_rproc_addr_init(struct imx_rproc *priv, |
|
0 commit comments