aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md87
-rw-r--r--remoteproc/ethosu_remoteproc.c145
2 files changed, 138 insertions, 94 deletions
diff --git a/README.md b/README.md
index 4bcd34b..1b9a692 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,12 @@ modified to insert an Ethos-U subsystem in one of the M-class slots. Mailbox
communication is based on the Arm MHU v2, and the reset is controlled using a IO
mapped bridge.
+## ethosu
+
+The `ethosu` device represents the Ethos-U subsystem and contains a
+`dma-ranges` entry that specifies how to translate between the Linux kernel
+physical addresses and bus (Cortex-M) addresses.
+
## ethosu-rproc
The [Ethos-U remoteproc driver](remoteproc/ethosu_remoteproc.c) is used to load
@@ -111,20 +117,17 @@ The `memory-region` entry references the shared memory pool. This is the memory
region used to allocate DMA buffers for the virtio rpmsg message queues and
other memory resources.
-The `ethosu,dma-ranges` is specific to the Ethos-U remoteproc driver, and is
-used to translate Linux physical addresses into DMA addresses. The reason for
-not using `dma-range` directly is that `dma-ranges` is not fully supported by
-the
-[virtio_ring.c](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/virtio/virtio_ring.c)
-kernel driver. Buffers sent to the firmware will contain Linux physical
-addresses instead of DMA addresses.
-
The `reset` entry is referencing the driver used to control reset for the
subsystem.
The `mboxes` entry is referencing the MHU v2 driver used for mailbox
communication.
+Note `dma-ranges` is not fully supported by the
+[virtio_ring.c](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/virtio/virtio_ring.c)
+kernel driver. Therefore, buffers sent to the firmware will contain Linux
+physical addresses instead of DMA addresses.
+
## Corstone-1000 DTB
```
@@ -169,38 +172,42 @@ communication.
reg-names = "rstreg", "streg";
};
- /* - compatible : "arm,ethosu-rproc"
- * - reg : Memory regions reserved for firmware binary
- * - ethosu,dma-ranges : Address translation from bus address (Cortex-M)
- * to Linux kernel physical address
- * - bus address (#address-cells)
- * - physical address (#address-cells)
- * - size (#size-cells)
- * - memory-region : Memory region for allocation of DMA buffers
- * - mboxes : Mailbox driver used to raise interrupts on
- * remote CPU
- * - resets : Reset driver used to reset remote CPU
- */
- ethosu-rproc {
- compatible = "arm,ethosu-rproc";
-
- // Address mapping from DMA to physical
- ethosu,dma-ranges = <0x00000000 0x44000000 0x00200000>,
- <0x60000000 0x80000000 0x10000000>;
-
- reg = <0x44000000 0x00200000>,
- <0x84000000 0x01000000>;
- reg-names = "rom", "shared";
-
- // Memory region to allocate buffers from
- memory-region = <&rproc_reserved>;
-
- // Mailbox IRQ communication
- mboxes = <&mbox_es0mhu0 0>, <&mbox_es0mhu0 0>;
- mbox-names = "tx", "rx";
-
- // Reset handler
- resets = <&cs1k_rst_es0 0>;
+
+ ethosu {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ // Address mapping from bus address (Cortex-M) to Linux kernel physical address
+ dma-ranges = <0x00000000 0x44000000 0x00200000>,
+ <0x60000000 0x80000000 0x10000000>;
+
+
+ /* - compatible : "arm,ethosu-rproc"
+ * - reg : Memory regions reserved for firmware binary
+ * - memory-region : Memory region for allocation of DMA buffers
+ * - mboxes : Mailbox driver used to raise interrupts on
+ * remote CPU
+ * - resets : Reset driver used to reset remote CPU
+ */
+ ethosu-rproc {
+ compatible = "arm,ethosu-rproc";
+
+ reg = <0x44000000 0x00200000>,
+ <0x84000000 0x01000000>;
+ reg-names = "rom", "shared";
+
+ // Memory region to allocate buffers from
+ memory-region = <&rproc_reserved>;
+
+ // Mailbox IRQ communication
+ mboxes = <&mbox_es0mhu0 0>, <&mbox_es0mhu0 0>;
+ mbox-names = "tx", "rx";
+
+ // Reset handler
+ resets = <&cs1k_rst_es0 0>;
+ };
};
};
```
diff --git a/remoteproc/ethosu_remoteproc.c b/remoteproc/ethosu_remoteproc.c
index b1f8793..0369156 100644
--- a/remoteproc/ethosu_remoteproc.c
+++ b/remoteproc/ethosu_remoteproc.c
@@ -1,5 +1,6 @@
/*
- * Copyright 2021-2023 Arm Limited and/or its affiliates
+ * SPDX-FileCopyrightText: Copyright 2021-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * SPDX-License-Identifier: GPL-2.0-only
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -14,10 +15,10 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
- *
- * SPDX-License-Identifier: GPL-2.0-only
*/
+
#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <linux/irqreturn.h>
@@ -58,6 +59,35 @@ static bool auto_boot = DEFAULT_AUTO_BOOT;
module_param(auto_boot, bool, 0);
MODULE_PARM_DESC(auto_boot, "Set to one to auto boot at load.");
+#define RSC_MAPPING RSC_VENDOR_START + 1
+
+/**
+ * struct fw_rsc_map_range - memory map range
+ * @da: Start device address of the memory address range
+ * @pa: Start physical address of the memory address range
+ * @len: length of memory address range
+ *
+ * Memory range to translate between physical and device addresses.
+ */
+struct fw_rsc_map_range {
+ uint32_t da;
+ uint32_t pa;
+ uint32_t len;
+} __packed;
+
+/**
+ * struct fw_rsc_mapping - memory map for address translation
+ * @num_ranges: Number of ranges in the memory map
+ * @range: Array of the ranges in the memory map
+ *
+ * This resource entry requests the host to provide information for how to
+ * translate between physical and device addresses.
+ */
+struct fw_rsc_mapping {
+ uint8_t num_ranges;
+ struct fw_rsc_map_range range[0];
+} __packed;
+
struct ethosu_rproc {
struct device *dev;
struct reset_control *rstc;
@@ -92,47 +122,6 @@ static void ethosu_mbox_top(struct mbox_client *client,
queue_work(erproc->wq, &erproc->work);
}
-static dma_addr_t ethosu_of_pa_to_da(struct rproc *rproc,
- const phys_addr_t pa,
- const size_t size)
-{
- static const char of_rproc_ranges[] = "ethosu,dma-ranges";
-
- struct device *dev = rproc->dev.parent;
- struct device_node *np = dev->of_node;
- const __be32 *rproc_ranges = of_get_property(np, of_rproc_ranges, NULL);
- const int addr_cells = of_n_addr_cells(np);
- const int size_cells = of_n_size_cells(np);
- const int ranges_cells = addr_cells + addr_cells + size_cells;
- int ranges_cnt;
- int i;
-
- ranges_cnt = of_property_count_elems_of_size(
- np, of_rproc_ranges, ranges_cells * sizeof(u32));
-
- for (i = 0; i < ranges_cnt; i++) {
- const int offset = i * ranges_cells;
-
- const uint64_t of_da = of_read_number(
- &rproc_ranges[offset], addr_cells);
- const uint64_t of_pa = of_read_number(
- &rproc_ranges[offset + addr_cells], addr_cells);
- const uint64_t of_size = of_read_number(
- &rproc_ranges[offset + addr_cells + addr_cells],
- size_cells);
-
- if (pa >= of_pa && (pa + size) <= (of_pa + of_size)) {
- const dma_addr_t da = of_da + pa - of_pa;
-
- dev_dbg(dev, "PA to DA. pa=0x%llx, da=0x%llx", pa, da);
-
- return da;
- }
- }
-
- return (dma_addr_t)(-1);
-}
-
static int ethosu_add_carveout(struct rproc *rproc,
const phys_addr_t pa,
const size_t size,
@@ -143,9 +132,10 @@ static int ethosu_add_carveout(struct rproc *rproc,
void __iomem *va;
struct rproc_mem_entry *mem;
- da = ethosu_of_pa_to_da(rproc, pa, size);
- if (da == (dma_addr_t)(-1)) {
- dev_err(dev, "No mapping found for PA. pa=%llx, size=%zu", pa,
+ da = translate_phys_to_dma(dev, pa);
+ dev_dbg(dev, "PA to DA. pa=0x%pa, da=0x%pad", &pa, &da);
+ if (da == DMA_MAPPING_ERROR) {
+ dev_err(dev, "No mapping found for PA. pa=%pa, size=%zu", &pa,
size);
return -ENOMEM;
@@ -153,7 +143,7 @@ static int ethosu_add_carveout(struct rproc *rproc,
va = devm_ioremap_wc(dev, pa, size);
if (!va) {
- dev_err(dev, "Failed to remap address. pa=%llx, len=%zu", pa,
+ dev_err(dev, "Failed to remap address. pa=%pa, len=%zu", &pa,
size);
return -ENOMEM;
@@ -163,8 +153,8 @@ static int ethosu_add_carveout(struct rproc *rproc,
if (!mem)
return -ENOMEM;
- dev_info(dev, "Add carveout mapping. dma=%llx, da=%x, va=%p, len=%zu",
- mem->dma, mem->da, mem->va, mem->len);
+ dev_info(dev, "Add carveout mapping. dma=%pad, da=%x, va=%p, len=%zu",
+ &mem->dma, mem->da, mem->va, mem->len);
rproc_add_carveout(rproc, mem);
@@ -247,11 +237,58 @@ static void ethosu_rproc_kick(struct rproc *rproc,
mbox_send_message(erproc->ch_tx, (void *)&vqid);
}
+static int ethosu_rproc_handle_rsc(struct rproc *rproc,
+ u32 rsc_type,
+ void *rsc,
+ int offset,
+ int avail)
+{
+ struct ethosu_rproc *erproc = (struct ethosu_rproc *)rproc->priv;
+ struct device *dev = erproc->dev;
+ struct fw_rsc_mapping *mapping = rsc;
+ const struct bus_dma_region *map;
+ size_t num_ranges = 0U;
+ size_t i;
+
+ if (rsc_type != RSC_MAPPING)
+ return RSC_IGNORED;
+
+ if (struct_size(mapping, range, mapping->num_ranges) > avail) {
+ dev_err(dev, "mapping rsc is truncated\n");
+
+ return -EINVAL;
+ }
+
+ for (map = dev->dma_range_map; map->size; ++map)
+ num_ranges++;
+
+ if (num_ranges > mapping->num_ranges) {
+ dev_err(dev,
+ "Mapping rsc doesn't have enough room for DMA ranges\n");
+
+ return -EINVAL;
+ }
+
+ for (i = 0U; i < num_ranges; ++i) {
+ map = &dev->dma_range_map[i];
+ struct fw_rsc_map_range *range = &mapping->range[i];
+
+ range->da = map->dma_start;
+ range->pa = map->cpu_start;
+ range->len = map->size;
+ }
+
+ dev_dbg(dev, "handle_rsc: Mapping rsc setup");
+
+ return RSC_HANDLED;
+}
+
static const struct rproc_ops ethosu_rproc_ops = {
- .prepare = &ethosu_rproc_prepare,
- .start = &ethosu_rproc_start,
- .stop = &ethosu_rproc_stop,
- .kick = &ethosu_rproc_kick,
+ .prepare = &ethosu_rproc_prepare,
+ .start = &ethosu_rproc_start,
+ .stop = &ethosu_rproc_stop,
+ .kick = &ethosu_rproc_kick,
+ .handle_rsc = &ethosu_rproc_handle_rsc,
};
static int ethosu_mailbox_init(struct ethosu_rproc *erproc)