.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * ST's Remote Processor Control Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2015 STMicroelectronics - All Rights Reserved |
---|
5 | 6 | * |
---|
6 | 7 | * Author: Ludovic Barre <ludovic.barre@st.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | 8 | */ |
---|
12 | 9 | |
---|
13 | 10 | #include <linux/clk.h> |
---|
.. | .. |
---|
19 | 16 | #include <linux/mfd/syscon.h> |
---|
20 | 17 | #include <linux/module.h> |
---|
21 | 18 | #include <linux/of.h> |
---|
| 19 | +#include <linux/of_address.h> |
---|
22 | 20 | #include <linux/of_device.h> |
---|
23 | 21 | #include <linux/of_reserved_mem.h> |
---|
24 | 22 | #include <linux/platform_device.h> |
---|
.. | .. |
---|
91 | 89 | dev_err(dev, "failed to send message via mbox: %d\n", ret); |
---|
92 | 90 | } |
---|
93 | 91 | |
---|
| 92 | +static int st_rproc_mem_alloc(struct rproc *rproc, |
---|
| 93 | + struct rproc_mem_entry *mem) |
---|
| 94 | +{ |
---|
| 95 | + struct device *dev = rproc->dev.parent; |
---|
| 96 | + void *va; |
---|
| 97 | + |
---|
| 98 | + va = ioremap_wc(mem->dma, mem->len); |
---|
| 99 | + if (!va) { |
---|
| 100 | + dev_err(dev, "Unable to map memory region: %pa+%zx\n", |
---|
| 101 | + &mem->dma, mem->len); |
---|
| 102 | + return -ENOMEM; |
---|
| 103 | + } |
---|
| 104 | + |
---|
| 105 | + /* Update memory entry va */ |
---|
| 106 | + mem->va = va; |
---|
| 107 | + |
---|
| 108 | + return 0; |
---|
| 109 | +} |
---|
| 110 | + |
---|
| 111 | +static int st_rproc_mem_release(struct rproc *rproc, |
---|
| 112 | + struct rproc_mem_entry *mem) |
---|
| 113 | +{ |
---|
| 114 | + iounmap(mem->va); |
---|
| 115 | + |
---|
| 116 | + return 0; |
---|
| 117 | +} |
---|
| 118 | + |
---|
| 119 | +static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) |
---|
| 120 | +{ |
---|
| 121 | + struct device *dev = rproc->dev.parent; |
---|
| 122 | + struct device_node *np = dev->of_node; |
---|
| 123 | + struct rproc_mem_entry *mem; |
---|
| 124 | + struct reserved_mem *rmem; |
---|
| 125 | + struct of_phandle_iterator it; |
---|
| 126 | + int index = 0; |
---|
| 127 | + |
---|
| 128 | + of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); |
---|
| 129 | + while (of_phandle_iterator_next(&it) == 0) { |
---|
| 130 | + rmem = of_reserved_mem_lookup(it.node); |
---|
| 131 | + if (!rmem) { |
---|
| 132 | + dev_err(dev, "unable to acquire memory-region\n"); |
---|
| 133 | + return -EINVAL; |
---|
| 134 | + } |
---|
| 135 | + |
---|
| 136 | + /* No need to map vdev buffer */ |
---|
| 137 | + if (strcmp(it.node->name, "vdev0buffer")) { |
---|
| 138 | + /* Register memory region */ |
---|
| 139 | + mem = rproc_mem_entry_init(dev, NULL, |
---|
| 140 | + (dma_addr_t)rmem->base, |
---|
| 141 | + rmem->size, rmem->base, |
---|
| 142 | + st_rproc_mem_alloc, |
---|
| 143 | + st_rproc_mem_release, |
---|
| 144 | + it.node->name); |
---|
| 145 | + } else { |
---|
| 146 | + /* Register reserved memory for vdev buffer allocation */ |
---|
| 147 | + mem = rproc_of_resm_mem_entry_init(dev, index, |
---|
| 148 | + rmem->size, |
---|
| 149 | + rmem->base, |
---|
| 150 | + it.node->name); |
---|
| 151 | + } |
---|
| 152 | + |
---|
| 153 | + if (!mem) |
---|
| 154 | + return -ENOMEM; |
---|
| 155 | + |
---|
| 156 | + rproc_add_carveout(rproc, mem); |
---|
| 157 | + index++; |
---|
| 158 | + } |
---|
| 159 | + |
---|
| 160 | + return rproc_elf_load_rsc_table(rproc, fw); |
---|
| 161 | +} |
---|
| 162 | + |
---|
94 | 163 | static int st_rproc_start(struct rproc *rproc) |
---|
95 | 164 | { |
---|
96 | 165 | struct st_rproc *ddata = rproc->priv; |
---|
.. | .. |
---|
121 | 190 | } |
---|
122 | 191 | } |
---|
123 | 192 | |
---|
124 | | - dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr); |
---|
| 193 | + dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr); |
---|
125 | 194 | |
---|
126 | 195 | return 0; |
---|
127 | 196 | |
---|
.. | .. |
---|
158 | 227 | } |
---|
159 | 228 | |
---|
160 | 229 | static const struct rproc_ops st_rproc_ops = { |
---|
161 | | - .kick = st_rproc_kick, |
---|
162 | | - .start = st_rproc_start, |
---|
163 | | - .stop = st_rproc_stop, |
---|
| 230 | + .kick = st_rproc_kick, |
---|
| 231 | + .start = st_rproc_start, |
---|
| 232 | + .stop = st_rproc_stop, |
---|
| 233 | + .parse_fw = st_rproc_parse_fw, |
---|
| 234 | + .load = rproc_elf_load_segments, |
---|
| 235 | + .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, |
---|
| 236 | + .sanity_check = rproc_elf_sanity_check, |
---|
| 237 | + .get_boot_addr = rproc_elf_get_boot_addr, |
---|
164 | 238 | }; |
---|
165 | 239 | |
---|
166 | 240 | /* |
---|
.. | .. |
---|
252 | 326 | if (err) { |
---|
253 | 327 | dev_err(dev, "Boot offset not found\n"); |
---|
254 | 328 | return -EINVAL; |
---|
255 | | - } |
---|
256 | | - |
---|
257 | | - err = of_reserved_mem_device_init(dev); |
---|
258 | | - if (err) { |
---|
259 | | - dev_err(dev, "Failed to obtain shared memory\n"); |
---|
260 | | - return err; |
---|
261 | 329 | } |
---|
262 | 330 | |
---|
263 | 331 | err = clk_prepare(ddata->clk); |
---|
.. | .. |
---|
386 | 454 | rproc_del(rproc); |
---|
387 | 455 | |
---|
388 | 456 | clk_disable_unprepare(ddata->clk); |
---|
389 | | - |
---|
390 | | - of_reserved_mem_device_release(&pdev->dev); |
---|
391 | 457 | |
---|
392 | 458 | for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++) |
---|
393 | 459 | mbox_free_channel(ddata->mbox_chan[i]); |
---|