111c122751
- Add qemu-riscv64spl Patch queue updated from git://github.com/openSUSE/u-boot.git tumbleweed-2021.01 * Patches added: 0031-efi_loader-Avoid-emitting-efi_var_b.patch - Drop pcm051rev3 for Phytec Wega board - Fix binary extension for sunxi based boards - Add Pinephone - Fix documentation location Update to v2021.01. Patch queue updated from git://github.com/openSUSE/u-boot.git tumbleweed-2021.01 * Patches dropped: 0028-usb-xhci-xhci_bulk_tx-Don-t-BUG-whe.patch 0029-Revert-Fix-data-abort-caused-by-mis.patch 0030-usb-xhci-pci-Add-DM_FLAG_OS_PREPARE.patch 0031-pci-brcmstb-Cleanup-controller-stat.patch * Patches added: 0028-usb-xhci-pci-Add-DM_FLAG_OS_PREPARE.patch 0029-pci-brcmstb-Cleanup-controller-stat.patch 0030-fs-btrfs-Select-SHA256-in-Kconfig.patch OBS-URL: https://build.opensuse.org/request/show/872955 OBS-URL: https://build.opensuse.org/package/show/hardware:boot/u-boot?expand=0&rev=127
141 lines
4.4 KiB
Diff
141 lines
4.4 KiB
Diff
From d327db89d06e0532645a2ec5151aaca7299939fd Mon Sep 17 00:00:00 2001
|
|
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
|
|
Date: Tue, 12 Jan 2021 13:55:24 +0100
|
|
Subject: [PATCH] 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>
|
|
---
|
|
drivers/core/Kconfig | 10 ++++++++++
|
|
drivers/core/device.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
|
include/dm/device.h | 13 +++++++++++++
|
|
3 files changed, 64 insertions(+)
|
|
|
|
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
|
|
index ffae6f9795..295cf2dd00 100644
|
|
--- a/drivers/core/Kconfig
|
|
+++ b/drivers/core/Kconfig
|
|
@@ -113,6 +113,16 @@ config SPL_DM_SEQ_ALIAS
|
|
numbered devices (e.g. serial0 = &serial0). This feature can be
|
|
disabled if it is not required, to save code space in SPL.
|
|
|
|
+config DM_DMA
|
|
+ bool "Support per-device DMA constraints"
|
|
+ depends on DM
|
|
+ default n
|
|
+ help
|
|
+ Enable this to extract per-device DMA constraints, only supported on
|
|
+ device-tree systems for now. This is needed in order translate
|
|
+ addresses on systems where different buses have different views of
|
|
+ the physical address space.
|
|
+
|
|
config REGMAP
|
|
bool "Support register maps"
|
|
depends on DM
|
|
diff --git a/drivers/core/device.c b/drivers/core/device.c
|
|
index 4b3dcb3b37..788ce6046a 100644
|
|
--- a/drivers/core/device.c
|
|
+++ b/drivers/core/device.c
|
|
@@ -421,6 +421,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_of_node(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;
|
|
@@ -482,6 +519,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;
|
|
diff --git a/include/dm/device.h b/include/dm/device.h
|
|
index 5bef484247..b27889af01 100644
|
|
--- a/include/dm/device.h
|
|
+++ b/include/dm/device.h
|
|
@@ -138,6 +138,8 @@ enum {
|
|
* When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will
|
|
* add to this list. Memory so-allocated will be freed
|
|
* automatically when the device is removed / unbound
|
|
+ * @dma_offset: Offset between the physical address space (CPU's) and the
|
|
+ * device's bus address space
|
|
*/
|
|
struct udevice {
|
|
const struct driver *driver;
|
|
@@ -161,6 +163,9 @@ struct udevice {
|
|
#ifdef CONFIG_DEVRES
|
|
struct list_head devres_head;
|
|
#endif
|
|
+#if CONFIG_IS_ENABLED(DM_DMA)
|
|
+ ulong dma_offset;
|
|
+#endif
|
|
};
|
|
|
|
/* Maximum sequence number supported */
|
|
@@ -172,6 +177,14 @@ struct udevice {
|
|
/* Returns non-zero if the device is active (probed and not removed) */
|
|
#define device_active(dev) ((dev)->flags & DM_FLAG_ACTIVATED)
|
|
|
|
+#if CONFIG_IS_ENABLED(DM_DMA)
|
|
+#define dev_set_dma_offset(_dev, _offset) _dev->dma_offset = _offset
|
|
+#define dev_get_dma_offset(_dev) _dev->dma_offset
|
|
+#else
|
|
+#define dev_set_dma_offset(_dev, _offset)
|
|
+#define dev_get_dma_offset(_dev) 0
|
|
+#endif
|
|
+
|
|
static inline int dev_of_offset(const struct udevice *dev)
|
|
{
|
|
return ofnode_to_offset(dev->node);
|