summaryrefslogtreecommitdiff
path: root/drivers/core/device.c
diff options
context:
space:
mode:
authorNicolas Saenz Julienne <nsaenzjulienne@suse.de>2021-01-12 13:55:24 +0100
committerMatthias Brugger <mbrugger@suse.com>2021-02-18 11:56:25 +0100
commit4abf68d57d495674e521b693191be1dcada46ecd (patch)
tree6471b542fbfc4730c539778640611cb5c96c2b15 /drivers/core/device.c
parent283628c412a2b98bdb22093a732aef4d5668e106 (diff)
dm: Introduce DMA constraints into the core device model
Calculating the DMA offset between a bus address space and CPU's every time we call phys_to_bus() and bus_to_phys() isn't ideal performance wise, as it implies traversing the device tree from the device's node up to the root. Since this information is static and available before the device's initialization, parse it before the probe call an provide the DMA offset in 'struct udevice' for the address translation code to use it. Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> Reviewed-by: Simon Glass <sjg@chromium.org> Tested-by: Peter Robinson <pbrobinson@gmail.com> Signed-off-by: Matthias Brugger <mbrugger@suse.com>
Diffstat (limited to 'drivers/core/device.c')
-rw-r--r--drivers/core/device.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 82a00989604..625134921d6 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -422,6 +422,43 @@ fail:
return ret;
}
+/**
+ * device_get_dma_constraints() - Populate device's DMA constraints
+ *
+ * Gets a device's DMA constraints from firmware. This information is later
+ * used by drivers to translate physcal addresses to the device's bus address
+ * space. For now only device-tree is supported.
+ *
+ * @dev: Pointer to target device
+ * Return: 0 if OK or if no DMA constraints were found, error otherwise
+ */
+static int device_get_dma_constraints(struct udevice *dev)
+{
+ struct udevice *parent = dev->parent;
+ phys_addr_t cpu = 0;
+ dma_addr_t bus = 0;
+ u64 size = 0;
+ int ret;
+
+ if (!CONFIG_IS_ENABLED(DM_DMA) || !parent || !dev_has_ofnode(parent))
+ return 0;
+
+ /*
+ * We start parsing for dma-ranges from the device's bus node. This is
+ * specially important on nested buses.
+ */
+ ret = dev_get_dma_range(parent, &cpu, &bus, &size);
+ /* Don't return an error if no 'dma-ranges' were found */
+ if (ret && ret != -ENOENT) {
+ dm_warn("%s: failed to get DMA range, %d\n", dev->name, ret);
+ return ret;
+ }
+
+ dev_set_dma_offset(dev, cpu - bus);
+
+ return 0;
+}
+
int device_probe(struct udevice *dev)
{
const struct driver *drv;
@@ -484,6 +521,10 @@ int device_probe(struct udevice *dev)
goto fail;
}
+ ret = device_get_dma_constraints(dev);
+ if (ret)
+ goto fail;
+
ret = uclass_pre_probe_device(dev);
if (ret)
goto fail;