SHA256
1
0
forked from pool/u-boot

Accepting request 858525 from hardware👢staging

OBS-URL: https://build.opensuse.org/request/show/858525
OBS-URL: https://build.opensuse.org/package/show/hardware:boot/u-boot?expand=0&rev=118
This commit is contained in:
Matthias Brugger 2020-12-24 16:44:52 +00:00 committed by Git OBS Bridge
parent 3dbf44f330
commit 723943821b
16 changed files with 1577 additions and 0 deletions

View File

@ -0,0 +1,36 @@
From 2fc18b303627de11d9c397a9cc3f6c678dc063a8 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Mon, 16 Nov 2020 11:25:11 +0100
Subject: [PATCH] rpi: Add identifier for the new RPi400
The Raspberry Pi Foundation released the new RPi400 which we want to
detect, so we can enable Ethernet on it and know the correct device tree
file name.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
---
Changes since v1:
- The RPi Foundation introduced a RPi400 specific device tree, so use
that file name instead of the fallback (RPi4b).
---
board/raspberrypi/rpi/rpi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 6b1fa5fc14..b66698e4a9 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -157,6 +157,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-4-b.dtb",
true,
},
+ [0x13] = {
+ "400",
+ DTB_DIR "bcm2711-rpi-400.dtb",
+ true,
+ },
};
static const struct rpi_model rpi_models_old_scheme[] = {

View File

@ -0,0 +1,34 @@
From 16c55dcf5b5f757f7847204e010c1fbbde1c9875 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Wed, 18 Nov 2020 16:48:39 +0100
Subject: [PATCH] rpi: Add identifier for the new CM4
The Raspberry Pi Foundation released the new Compute Module 4 which we
want to detect, so we can enable Ethernet on it and know the correct
device tree file name.
Note that this sets the Ethernet option to true since the official CM4
IO board has an Ethernet port. But that might not be the case when using
custom ones.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
---
board/raspberrypi/rpi/rpi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index b66698e4a9..abcf41a5a8 100644
--- a/board/raspberrypi/rpi/rpi.c
+++ b/board/raspberrypi/rpi/rpi.c
@@ -162,6 +162,11 @@ static const struct rpi_model rpi_models_new_scheme[] = {
DTB_DIR "bcm2711-rpi-400.dtb",
true,
},
+ [0x14] = {
+ "Compute Module 4",
+ DTB_DIR "bcm2711-rpi-cm4.dtb",
+ true,
+ },
};
static const struct rpi_model rpi_models_old_scheme[] = {

View File

@ -0,0 +1,53 @@
From 79de6d0785678f2f7c14566ee4e526ef180634a5 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Tue, 17 Nov 2020 17:50:33 +0100
Subject: [PATCH] pci: pcie-brcmstb: Fix inbound window configurations
So far we've assumed a fixed configuration for inbound windows as we had
a single user for this controller. But the controller's DMA constraints
were improved starting with BCM2711's B1 revision of the SoC, notably
available in CM4 and Pi400. They allow for wider inbound windows. We can
now cover the whole address space, whereas before we where limited to
the lower 3GB.
This information is passed to us through DT's 'dma-ranges' property and
it's specially important for us to honor it since some interactions with
the board's co-processor assume we're doing so (specifically the XHCI
firmware load operation, which is handled by the co-processor after
u-boot has correctly configured the PCIe controller).
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
---
drivers/pci/pcie_brcmstb.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index dade79e9c8..f6e8ad0d0a 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -432,6 +432,7 @@ static int brcm_pcie_probe(struct udevice *dev)
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
+ struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
u64 rc_bar2_offset, rc_bar2_size;
@@ -468,13 +469,10 @@ static int brcm_pcie_probe(struct udevice *dev)
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
MISC_CTRL_MAX_BURST_SIZE_128);
- /*
- * TODO: When support for other SoCs than BCM2711 is added we may
- * need to use the base address and size(s) provided in the dma-ranges
- * property.
- */
- rc_bar2_offset = 0;
- rc_bar2_size = 0xc0000000;
+
+ pci_get_dma_regions(dev, &region, 0);
+ rc_bar2_offset = region.bus_start - region.phys_start;
+ rc_bar2_size = 1ULL << fls64(region.size - 1);
tmp = lower_32_bits(rc_bar2_offset);
u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),

View File

@ -0,0 +1,367 @@
From 7b53f3bae226443173c035d99c2fb67d994be285 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Tue, 17 Nov 2020 17:49:54 +0100
Subject: [PATCH] dm: Introduce xxx_get_dma_range()
Add the following functions to get a specific device's DMA ranges:
- dev_get_dma_range()
- ofnode_get_dma_range()
- of_get_dma_range()
- fdt_get_dma_range()
They are specially useful in oder to be able validate a physical address
space range into a bus's and to convert addresses from and to address
spaces.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes since v2:
- Return ENOENT instead of ENODEV
- Refcount of nodes
Changes since v1:
- Fix wrong arguments in of_get_dma_range()'s call to of_translate_dma_address()
- Fix build in SPL/TPL and no LIBFDT supprt
- Add missing declaration in 'core/read.c'
- Address Matthias' comments
---
common/fdt_support.c | 73 +++++++++++++++++++++++++++++++++++++++
drivers/core/of_addr.c | 78 ++++++++++++++++++++++++++++++++++++++++++
drivers/core/ofnode.c | 9 +++++
drivers/core/read.c | 6 ++++
include/dm/of_addr.h | 17 +++++++++
include/dm/ofnode.h | 16 +++++++++
include/dm/read.h | 21 ++++++++++++
include/fdt_support.h | 14 ++++++++
8 files changed, 234 insertions(+)
diff --git a/common/fdt_support.c b/common/fdt_support.c
index a565b470f8..023757bd0e 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -1347,6 +1347,79 @@ u64 fdt_translate_dma_address(const void *blob, int node_offset,
return __of_translate_address(blob, node_offset, in_addr, "dma-ranges");
}
+int fdt_get_dma_range(const void *blob, int node, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+ bool found_dma_ranges = false;
+ struct of_bus *bus_node;
+ const fdt32_t *ranges;
+ int na, ns, pna, pns;
+ int parent = node;
+ int ret = 0;
+ int len;
+
+ /* Find the closest dma-ranges property */
+ while (parent >= 0) {
+ ranges = fdt_getprop(blob, parent, "dma-ranges", &len);
+
+ /* Ignore empty ranges, they imply no translation required */
+ if (ranges && len > 0)
+ break;
+
+ /* Once we find 'dma-ranges', then a missing one is an error */
+ if (found_dma_ranges && !ranges) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ranges)
+ found_dma_ranges = true;
+
+ parent = fdt_parent_offset(blob, parent);
+ }
+
+ if (!ranges || parent < 0) {
+ debug("no dma-ranges found for node %s\n",
+ fdt_get_name(blob, node, NULL));
+ ret = -ENOENT;
+ goto out;
+ }
+
+ /* switch to that node */
+ node = parent;
+ parent = fdt_parent_offset(blob, node);
+ if (parent < 0) {
+ printf("Found dma-ranges in root node, shoudln't happen\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Get the address sizes both for the bus and its parent */
+ bus_node = of_match_bus(blob, node);
+ bus_node->count_cells(blob, node, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ printf("%s: Bad cell count for %s\n", __FUNCTION__,
+ fdt_get_name(blob, node, NULL));
+ return -EINVAL;
+ goto out;
+ }
+
+ bus_node = of_match_bus(blob, parent);
+ bus_node->count_cells(blob, parent, &pna, &pns);
+ if (!OF_CHECK_COUNTS(pna, pns)) {
+ printf("%s: Bad cell count for %s\n", __FUNCTION__,
+ fdt_get_name(blob, parent, NULL));
+ return -EINVAL;
+ goto out;
+ }
+
+ *bus = fdt_read_number(ranges, na);
+ *cpu = fdt_translate_dma_address(blob, node, ranges + na);
+ *size = fdt_read_number(ranges + na + pna, ns);
+out:
+ return ret;
+}
+
/**
* fdt_node_offset_by_compat_reg: Find a node that matches compatiable and
* who's reg property matches a physical cpu address
diff --git a/drivers/core/of_addr.c b/drivers/core/of_addr.c
index ca34d84922..703bc3e3f5 100644
--- a/drivers/core/of_addr.c
+++ b/drivers/core/of_addr.c
@@ -325,6 +325,84 @@ u64 of_translate_dma_address(const struct device_node *dev, const __be32 *in_add
return __of_translate_address(dev, in_addr, "dma-ranges");
}
+int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+ bool found_dma_ranges = false;
+ struct device_node *parent;
+ struct of_bus *bus_node;
+ int na, ns, pna, pns;
+ const __be32 *ranges;
+ int ret = 0;
+ int len;
+
+ /* Find the closest dma-ranges property */
+ dev = of_node_get(dev);
+ while (dev) {
+ ranges = of_get_property(dev, "dma-ranges", &len);
+
+ /* Ignore empty ranges, they imply no translation required */
+ if (ranges && len > 0)
+ break;
+
+ /* Once we find 'dma-ranges', then a missing one is an error */
+ if (found_dma_ranges && !ranges) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ranges)
+ found_dma_ranges = true;
+
+ parent = of_get_parent(dev);
+ of_node_put(dev);
+ dev = parent;
+ }
+
+ if (!dev || !ranges) {
+ debug("no dma-ranges found for node %s\n",
+ of_node_full_name(dev));
+ ret = -ENOENT;
+ goto out;
+ }
+
+ /* switch to that node */
+ parent = of_get_parent(dev);
+ if (!parent) {
+ printf("Found dma-ranges in root node, shoudln't happen\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Get the address sizes both for the bus and its parent */
+ bus_node = of_match_bus((struct device_node*)dev);
+ bus_node->count_cells(dev, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ printf("Bad cell count for %s\n", of_node_full_name(dev));
+ return -EINVAL;
+ goto out_parent;
+ }
+
+ bus_node = of_match_bus(parent);
+ bus_node->count_cells(parent, &pna, &pns);
+ if (!OF_CHECK_COUNTS(pna, pns)) {
+ printf("Bad cell count for %s\n", of_node_full_name(parent));
+ return -EINVAL;
+ goto out_parent;
+ }
+
+ *bus = of_read_number(ranges, na);
+ *cpu = of_translate_dma_address(dev, ranges + na);
+ *size = of_read_number(ranges + na + pna, ns);
+
+out_parent:
+ of_node_put(parent);
+out:
+ of_node_put(dev);
+ return ret;
+}
+
+
static int __of_address_to_resource(const struct device_node *dev,
const __be32 *addrp, u64 size, unsigned int flags,
const char *name, struct resource *r)
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index d02d8d33fe..d4e69b0074 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -888,6 +888,15 @@ u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
}
+int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
+{
+ if (ofnode_is_np(node))
+ return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
+ else
+ return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node),
+ cpu, bus, size);
+}
+
int ofnode_device_is_compatible(ofnode node, const char *compat)
{
if (ofnode_is_np(node))
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 86f3f88170..333e011fef 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -337,6 +337,12 @@ u64 dev_translate_dma_address(const struct udevice *dev, const fdt32_t *in_addr)
return ofnode_translate_dma_address(dev_ofnode(dev), in_addr);
}
+int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+ return ofnode_get_dma_range(dev_ofnode(dev), cpu, bus, size);
+}
+
int dev_read_alias_highest_id(const char *stem)
{
if (of_live_active())
diff --git a/include/dm/of_addr.h b/include/dm/of_addr.h
index 3fa1ffce81..ee21d5cf4f 100644
--- a/include/dm/of_addr.h
+++ b/include/dm/of_addr.h
@@ -44,6 +44,23 @@ u64 of_translate_address(const struct device_node *no, const __be32 *in_addr);
*/
u64 of_translate_dma_address(const struct device_node *no, const __be32 *in_addr);
+
+/**
+ * of_get_dma_range() - get dma-ranges for a specific DT node
+ *
+ * Get DMA ranges for a specifc node, this is useful to perform bus->cpu and
+ * cpu->bus address translations
+ *
+ * @param blob Pointer to device tree blob
+ * @param node_offset Node DT offset
+ * @param cpu Pointer to variable storing the range's cpu address
+ * @param bus Pointer to variable storing the range's bus address
+ * @param size Pointer to variable storing the range's size
+ * @return translated DMA address or OF_BAD_ADDR on error
+ */
+int of_get_dma_range(const struct device_node *dev, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size);
+
/**
* of_get_address() - obtain an address from a node
*
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 8df2facf99..d1be553b37 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -915,6 +915,22 @@ u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr);
*/
u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr);
+/**
+ * ofnode_get_dma_range() - get dma-ranges for a specific DT node
+ *
+ * Get DMA ranges for a specifc node, this is useful to perform bus->cpu and
+ * cpu->bus address translations
+ *
+ * @param blob Pointer to device tree blob
+ * @param node_offset Node DT offset
+ * @param cpu Pointer to variable storing the range's cpu address
+ * @param bus Pointer to variable storing the range's bus address
+ * @param size Pointer to variable storing the range's size
+ * @return translated DMA address or OF_BAD_ADDR on error
+ */
+int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus,
+ u64 *size);
+
/**
* ofnode_device_is_compatible() - check if the node is compatible with compat
*
diff --git a/include/dm/read.h b/include/dm/read.h
index 67db94adfc..6ee7099bd4 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -662,6 +662,21 @@ u64 dev_translate_address(const struct udevice *dev, const fdt32_t *in_addr);
u64 dev_translate_dma_address(const struct udevice *dev,
const fdt32_t *in_addr);
+/**
+ * dev_get_dma_range() - Get a device's DMA constraints
+ *
+ * Provide the address bases and size of the linear mapping between the CPU and
+ * a device's BUS address space.
+ *
+ * @dev: device giving the context in which to translate the DMA address
+ * @cpu: base address for CPU's view of memory
+ * @bus: base address for BUS's view of memory
+ * @size: size of the address space
+ * @return 0 if ok, negative on error
+ */
+int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size);
+
/**
* dev_read_alias_highest_id - Get highest alias id for the given stem
* @stem: Alias stem to be examined
@@ -1002,6 +1017,12 @@ static inline u64 dev_translate_dma_address(const struct udevice *dev,
return ofnode_translate_dma_address(dev_ofnode(dev), in_addr);
}
+static inline int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size)
+{
+ return ofnode_get_dma_range(dev_ofnode(dev), cpu, bus, size);
+}
+
static inline int dev_read_alias_highest_id(const char *stem)
{
if (!CONFIG_IS_ENABLED(OF_LIBFDT))
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 9684cffe80..963c917445 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -260,6 +260,20 @@ u64 fdt_translate_address(const void *blob, int node_offset,
u64 fdt_translate_dma_address(const void *blob, int node_offset,
const __be32 *in_addr);
+/**
+ * Get DMA ranges for a specifc node, this is useful to perform bus->cpu and
+ * cpu->bus address translations
+ *
+ * @param blob Pointer to device tree blob
+ * @param node_offset Node DT offset
+ * @param cpu Pointer to variable storing the range's cpu address
+ * @param bus Pointer to variable storing the range's bus address
+ * @param size Pointer to variable storing the range's size
+ * @return translated DMA address or OF_BAD_ADDR on error
+ */
+int fdt_get_dma_range(const void *blob, int node_offset, phys_addr_t *cpu,
+ dma_addr_t *bus, u64 *size);
+
int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
phys_addr_t compat_off);
int fdt_alloc_phandle(void *blob);

View File

@ -0,0 +1,116 @@
From 8cc51dc21c710f48692ba6fa1b51f9da3f7de9ca Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Tue, 15 Dec 2020 13:51:16 +0100
Subject: [PATCH] dm: test: Add test case for dev_get_dma_ranges()
Introduce some new nodes in sandbox's test device-tree and dm tests in
order to validate dev_get_dma_range().
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes since v3:
- Use ut_assertok() instead of ut_assert(!func())
---
arch/sandbox/dts/test.dts | 17 ++++++++++++++
test/dm/Makefile | 1 +
test/dm/read.c | 49 +++++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
create mode 100644 test/dm/read.c
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9f45c48e4e..c0ac4a793c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -270,6 +270,23 @@
compatible = "denx,u-boot-devres-test";
};
+ mmio-bus@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "denx,u-boot-test-bus";
+ dma-ranges = <0x10000000 0x00000000 0x00040000>;
+
+ subnode@0 {
+ compatible = "denx,u-boot-fdt-test";
+ };
+ };
+
+ mmio-bus@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "denx,u-boot-test-bus";
+ };
+
acpi_test1: acpi-test {
compatible = "denx,u-boot-acpi-test";
acpi-ssdt-test-data = "ab";
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 864c8d0b4c..3cf5c0f2ca 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
# Tests for particular subsystems - when enabling driver model for a new
# subsystem you must add sandbox tests here.
obj-$(CONFIG_UT_DM) += core.o
+obj-$(CONFIG_UT_DM) += read.o
ifneq ($(CONFIG_SANDBOX),)
obj-$(CONFIG_ACPIGEN) += acpi.o
obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/read.c b/test/dm/read.c
new file mode 100644
index 0000000000..7768aa2968
--- /dev/null
+++ b/test/dm/read.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/ofnode.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/ut.h>
+
+static int dm_test_dma_ranges(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ phys_addr_t cpu;
+ dma_addr_t bus;
+ ofnode node;
+ u64 size;
+
+ /* dma-ranges are on the device's node */
+ node = ofnode_path("/mmio-bus@0");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+ ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+ ut_asserteq_64(0x40000, size);
+ ut_asserteq_64(0x0, cpu);
+ ut_asserteq_64(0x10000000, bus);
+
+ /* dma-ranges are on the bus' node */
+ node = ofnode_path("/mmio-bus@0/subnode@0");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+ ut_assertok(dev_get_dma_range(dev, &cpu, &bus, &size));
+ ut_asserteq_64(0x40000, size);
+ ut_asserteq_64(0x0, cpu);
+ ut_asserteq_64(0x10000000, bus);
+
+ /* No dma-ranges available */
+ node = ofnode_path("/mmio-bus@1");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+ ut_asserteq(-ENOENT, dev_get_dma_range(dev, &cpu, &bus, &size));
+
+ return 0;
+}
+DM_TEST(dm_test_dma_ranges, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);

View File

@ -0,0 +1,156 @@
From 8d35d23d658c1a50b591f67951a5c24890687fea Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Thu, 19 Nov 2020 17:17: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>
---
Changes since v4:
- Use macros to access dma_offset
Changes since v3:
- Comment functions and struct variables
- Correct typos
Changes since v2:
- Return/Fail on error
- Add config option
- use ulong instead for u64 for dev->dma_offset
Changes since v1:
- Update commit message so as to explain better the reasoning behind
this
---
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 00d1d80dc3..ea90cecc86 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -99,6 +99,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 355dbd147a..d41dab88da 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -402,6 +402,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_of_valid(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;
@@ -463,6 +500,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 953706cf52..9d4670424b 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);

View File

@ -0,0 +1,123 @@
From 612c8faa01d20895eff45b9681c6406b6daf7035 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Mon, 14 Dec 2020 20:45:19 +0100
Subject: [PATCH] dm: test: Add test case for dev->dma_offset
Add test to validate dev->dma_offset is properly set on devices.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes since v3:
- Use ut_assertok() instead of ut_assert(!func())
---
arch/sandbox/dts/test.dts | 4 ++++
configs/sandbox64_defconfig | 1 +
configs/sandbox_defconfig | 1 +
configs/sandbox_flattree_defconfig | 1 +
configs/sandbox_spl_defconfig | 1 +
test/dm/core.c | 30 ++++++++++++++++++++++++++++++
6 files changed, 38 insertions(+)
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c0ac4a793c..ff5d65a522 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -285,6 +285,10 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "denx,u-boot-test-bus";
+
+ subnode@0 {
+ compatible = "denx,u-boot-fdt-test";
+ };
};
acpi_test1: acpi-test {
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 9c102948c0..6cd0c3b19e 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -91,6 +91,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_DEVRES=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 92ffe48432..10132088c6 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -104,6 +104,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_DEVRES=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index dd93167e1b..528e6d4ff0 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -75,6 +75,7 @@ CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_DEVRES=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 6d8e827aeb..c8b62eba21 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -93,6 +93,7 @@ CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
CONFIG_SPL_DM=y
+CONFIG_DM_DMA=y
CONFIG_REGMAP=y
CONFIG_SPL_REGMAP=y
CONFIG_SYSCON=y
diff --git a/test/dm/core.c b/test/dm/core.c
index 8ed5bf7370..c079655b4d 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -906,3 +906,33 @@ static int dm_test_inactive_child(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_inactive_child, UT_TESTF_SCAN_PDATA);
+
+static int dm_test_dma_offset(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ ofnode node;
+
+ /* Make sure the bus's dma-ranges aren't taken into account here */
+ node = ofnode_path("/mmio-bus@0");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+ ut_asserteq_64(0, dev->dma_offset);
+
+ /* Device behind a bus with dma-ranges */
+ node = ofnode_path("/mmio-bus@0/subnode@0");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+ ut_asserteq_64(-0x10000000ULL, dev->dma_offset);
+
+ /* This one has no dma-ranges */
+ node = ofnode_path("/mmio-bus@1");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+ node = ofnode_path("/mmio-bus@1/subnode@0");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+ ut_asserteq_64(0, dev->dma_offset);
+
+ return 0;
+}
+DM_TEST(dm_test_dma_offset, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);

View File

@ -0,0 +1,53 @@
From 71105045bc57b3fa5a9970d98c59f56ab06cbf80 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Thu, 19 Nov 2020 17:15:31 +0100
Subject: [PATCH] dm: Introduce dev_phys_to_bus()/dev_bus_to_phys()
These functions, instead of relying on hard-coded platform-specific
address translations, make use of the DMA constraints provided by the DM
core. This allows for per-device translations.
We can't yet get rid of the legacy phys_to_bus()/bus_to_phys()
implementations as some of its users are not integrated into the
device model.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Stefan Roese <sr@denx.de>
---
Changes since v4:
- Introduce macros for !DM case to make API usage cleaner
Changes since v2:
- Use CONFIG_DM_DMA
---
include/phys2bus.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/include/phys2bus.h b/include/phys2bus.h
index dc9b8e5a25..866b8b51a8 100644
--- a/include/phys2bus.h
+++ b/include/phys2bus.h
@@ -21,4 +21,21 @@ static inline unsigned long bus_to_phys(unsigned long bus)
}
#endif
+#if CONFIG_IS_ENABLED(DM)
+#include <dm/device.h>
+
+static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, phys_addr_t phys)
+{
+ return phys - dev_get_dma_offset(dev);
+}
+
+static inline phys_addr_t dev_bus_to_phys(struct udevice *dev, dma_addr_t bus)
+{
+ return bus + dev_get_dma_offset(dev);
+}
+#else
+#define dev_phys_to_bus(_, _addr) _addr
+#define dev_bus_to_phys(_, _addr) _addr
+#endif
+
#endif

View File

@ -0,0 +1,77 @@
From 1c7fb1ce2ac1c98d3a0747020751b6062530bfce Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Mon, 14 Dec 2020 21:04:04 +0100
Subject: [PATCH] dm: test: Add test case for
dev_phys_to_bus()/dev_bus_to_phys()
By reusing DT nodes already available in sandbox's test DT introduce a
test to validate dev_phys_to_bus()/dev_bus_to_phys().
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes since v3:
- Use ut_assertok() instead of ut_assert(!func())
- Use ut_assert_addr()
---
test/dm/Makefile | 1 +
test/dm/phys2bus.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
create mode 100644 test/dm/phys2bus.c
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 3cf5c0f2ca..bc955ad291 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
# subsystem you must add sandbox tests here.
obj-$(CONFIG_UT_DM) += core.o
obj-$(CONFIG_UT_DM) += read.o
+obj-$(CONFIG_UT_DM) += phys2bus.o
ifneq ($(CONFIG_SANDBOX),)
obj-$(CONFIG_ACPIGEN) += acpi.o
obj-$(CONFIG_ACPIGEN) += acpigen.o
diff --git a/test/dm/phys2bus.c b/test/dm/phys2bus.c
new file mode 100644
index 0000000000..342f2fa8eb
--- /dev/null
+++ b/test/dm/phys2bus.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <phys2bus.h>
+#include <dm/device.h>
+#include <dm/ofnode.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/uclass-internal.h>
+#include <test/ut.h>
+
+static int dm_test_phys_to_bus(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ ofnode node;
+
+ node = ofnode_path("/mmio-bus@0");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_BUS, node, &dev));
+ /* In this case it should be transparent, no dma-ranges in parent bus */
+ ut_asserteq_addr((void*)0xfffffULL, (void*)dev_phys_to_bus(dev, 0xfffff));
+ ut_asserteq_addr((void*)0xfffffULL, (void*)(ulong)dev_bus_to_phys(dev, 0xfffff));
+
+ node = ofnode_path("/mmio-bus@0/subnode@0");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(uclass_get_device_by_ofnode(UCLASS_TEST_FDT, node, &dev));
+ ut_asserteq_addr((void*)0x100fffffULL, (void*)dev_phys_to_bus(dev, 0xfffff));
+ ut_asserteq_addr((void*)0xfffffULL, (void*)(ulong)dev_bus_to_phys(dev, 0x100fffff));
+
+ return 0;
+}
+DM_TEST(dm_test_phys_to_bus, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);

View File

@ -0,0 +1,320 @@
From 16bb2e3d352e5be135ef9ec30c86042f18f2fb0f Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Tue, 17 Nov 2020 17:52:02 +0100
Subject: [PATCH] xhci: translate virtual addresses into the bus's address
space
So far we've been content with passing physical addresses when
configuring memory addresses into XHCI controllers, but not all
platforms have buses with transparent mappings. Specifically the
Raspberry Pi 4 might introduce an offset to memory accesses incoming
from its PCIe port.
Introduce xhci_virt_to_bus() and xhci_bus_to_virt() to cater with these
limitations, and make sure we don't break non DM users.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Stefan Roese <sr@denx.de>
---
Changes since v5:
- Fix bulk transfers
Changes since v4:
- Introduce macro to access ctrl->dev
- No need to make code conditional on DM_DMA with new macros
Changes since v3:
- Don't call phys_to_bus()/bus_to_phys(), we only support DM
---
drivers/usb/host/xhci-mem.c | 45 +++++++++++++++++++-----------------
drivers/usb/host/xhci-ring.c | 11 +++++----
drivers/usb/host/xhci.c | 4 ++--
include/usb/xhci.h | 20 +++++++++++++++-
4 files changed, 52 insertions(+), 28 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 1da0524aa0..e01b943f22 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
ctrl->dcbaa->dev_context_ptrs[0] = 0;
- free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0]));
+ free(xhci_bus_to_virt(ctrl, le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@@ -216,8 +216,8 @@ static void *xhci_malloc(unsigned int size)
* @param link_trbs flag to indicate whether to link the trbs or NOT
* @return none
*/
-static void xhci_link_segments(struct xhci_segment *prev,
- struct xhci_segment *next, bool link_trbs)
+static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment *prev,
+ struct xhci_segment *next, bool link_trbs)
{
u32 val;
u64 val_64 = 0;
@@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
- val_64 = virt_to_phys(next->trbs);
+ val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
@@ -305,7 +305,8 @@ static struct xhci_segment *xhci_segment_alloc(void)
* @param link_trbs flag to indicate whether to link the trbs or NOT
* @return pointer to the newly created RING
*/
-struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
+struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
+ bool link_trbs)
{
struct xhci_ring *ring;
struct xhci_segment *prev;
@@ -328,12 +329,12 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs)
next = xhci_segment_alloc();
BUG_ON(!next);
- xhci_link_segments(prev, next, link_trbs);
+ xhci_link_segments(ctrl, prev, next, link_trbs);
prev = next;
num_segs--;
}
- xhci_link_segments(prev, ring->first_seg, link_trbs);
+ xhci_link_segments(ctrl, prev, ring->first_seg, link_trbs);
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
@@ -355,6 +356,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
struct xhci_hccr *hccr = ctrl->hccr;
struct xhci_hcor *hcor = ctrl->hcor;
struct xhci_scratchpad *scratchpad;
+ uint64_t val_64;
int num_sp;
uint32_t page_size;
void *buf;
@@ -372,8 +374,9 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64));
if (!scratchpad->sp_array)
goto fail_sp2;
- ctrl->dcbaa->dev_context_ptrs[0] =
- cpu_to_le64((uintptr_t)scratchpad->sp_array);
+
+ val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
+ ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
sizeof(ctrl->dcbaa->dev_context_ptrs[0]));
@@ -394,8 +397,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
for (i = 0; i < num_sp; i++) {
- uintptr_t ptr = (uintptr_t)buf + i * page_size;
- scratchpad->sp_array[i] = cpu_to_le64(ptr);
+ val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
+ scratchpad->sp_array[i] = cpu_to_le64(val_64);
}
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@@ -487,9 +490,9 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id)
}
/* Allocate endpoint 0 ring */
- virt_dev->eps[0].ring = xhci_ring_alloc(1, true);
+ virt_dev->eps[0].ring = xhci_ring_alloc(ctrl, 1, true);
- byte_64 = virt_to_phys(virt_dev->out_ctx->bytes);
+ byte_64 = xhci_virt_to_bus(ctrl, virt_dev->out_ctx->bytes);
/* Point to output device context in dcbaa. */
ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64);
@@ -526,15 +529,15 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
return -ENOMEM;
}
- val_64 = virt_to_phys(ctrl->dcbaa);
+ val_64 = xhci_virt_to_bus(ctrl, ctrl->dcbaa);
/* Set the pointer in DCBAA register */
xhci_writeq(&hcor->or_dcbaap, val_64);
/* Command ring control pointer register initialization */
- ctrl->cmd_ring = xhci_ring_alloc(1, true);
+ ctrl->cmd_ring = xhci_ring_alloc(ctrl, 1, true);
/* Set the address in the Command Ring Control register */
- trb_64 = virt_to_phys(ctrl->cmd_ring->first_seg->trbs);
+ trb_64 = xhci_virt_to_bus(ctrl, ctrl->cmd_ring->first_seg->trbs);
val_64 = xhci_readq(&hcor->or_crcr);
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(trb_64 & (u64) ~CMD_RING_RSVD_BITS) |
@@ -555,7 +558,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
ctrl->ir_set = &ctrl->run_regs->ir_set[0];
/* Event ring does not maintain link TRB */
- ctrl->event_ring = xhci_ring_alloc(ERST_NUM_SEGS, false);
+ ctrl->event_ring = xhci_ring_alloc(ctrl, ERST_NUM_SEGS, false);
ctrl->erst.entries = (struct xhci_erst_entry *)
xhci_malloc(sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS);
@@ -564,8 +567,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
for (val = 0, seg = ctrl->event_ring->first_seg;
val < ERST_NUM_SEGS;
val++) {
- trb_64 = virt_to_phys(seg->trbs);
struct xhci_erst_entry *entry = &ctrl->erst.entries[val];
+ trb_64 = xhci_virt_to_bus(ctrl, seg->trbs);
entry->seg_addr = cpu_to_le64(trb_64);
entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
entry->rsvd = 0;
@@ -574,7 +577,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
xhci_flush_cache((uintptr_t)ctrl->erst.entries,
ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
- deq = virt_to_phys(ctrl->event_ring->dequeue);
+ deq = xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue);
/* Update HC event ring dequeue pointer */
xhci_writeq(&ctrl->ir_set->erst_dequeue,
@@ -589,7 +592,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
/* this is the event ring segment table pointer */
val_64 = xhci_readq(&ctrl->ir_set->erst_base);
val_64 &= ERST_PTR_MASK;
- val_64 |= virt_to_phys(ctrl->erst.entries) & ~ERST_PTR_MASK;
+ val_64 |= xhci_virt_to_bus(ctrl, ctrl->erst.entries) & ~ERST_PTR_MASK;
xhci_writeq(&ctrl->ir_set->erst_base, val_64);
@@ -857,7 +860,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) |
((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT));
- trb_64 = virt_to_phys(virt_dev->eps[0].ring->first_seg->trbs);
+ trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[0].ring->first_seg->trbs);
ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state);
/*
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 092ed6eaf1..27e7a39571 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -275,10 +275,13 @@ void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id,
u32 ep_index, trb_type cmd)
{
u32 fields[4];
- u64 val_64 = virt_to_phys(ptr);
+ u64 val_64 = 0;
BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING));
+ if (ptr)
+ val_64 = xhci_virt_to_bus(ctrl, ptr);
+
fields[0] = lower_32_bits(val_64);
fields[1] = upper_32_bits(val_64);
fields[2] = 0;
@@ -399,7 +402,7 @@ void xhci_acknowledge_event(struct xhci_ctrl *ctrl)
/* Inform the hardware */
xhci_writeq(&ctrl->ir_set->erst_dequeue,
- virt_to_phys(ctrl->event_ring->dequeue) | ERST_EHB);
+ xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue) | ERST_EHB);
}
/**
@@ -577,7 +580,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
u64 addr;
int ret;
u32 trb_fields[4];
- u64 val_64 = virt_to_phys(buffer);
+ u64 val_64 = xhci_virt_to_bus(ctrl, buffer);
debug("dev=%p, pipe=%lx, buffer=%p, length=%d\n",
udev, pipe, buffer, length);
@@ -876,7 +879,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
if (length > 0) {
if (req->requesttype & USB_DIR_IN)
field |= TRB_DIR_IN;
- buf_64 = virt_to_phys(buffer);
+ buf_64 = xhci_virt_to_bus(ctrl, buffer);
trb_fields[0] = lower_32_bits(buf_64);
trb_fields[1] = upper_32_bits(buf_64);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 126dabc11b..6b4dce9bca 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -606,7 +606,7 @@ static int xhci_set_configuration(struct usb_device *udev)
ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index);
/* Allocate the ep rings */
- virt_dev->eps[ep_index].ring = xhci_ring_alloc(1, true);
+ virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true);
if (!virt_dev->eps[ep_index].ring)
return -ENOMEM;
@@ -631,7 +631,7 @@ static int xhci_set_configuration(struct usb_device *udev)
cpu_to_le32(MAX_BURST(max_burst) |
ERROR_COUNT(err_count));
- trb_64 = virt_to_phys(virt_dev->eps[ep_index].ring->enqueue);
+ trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[ep_index].ring->enqueue);
ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 |
virt_dev->eps[ep_index].ring->cycle_state);
diff --git a/include/usb/xhci.h b/include/usb/xhci.h
index 7d34103fd5..048149fb11 100644
--- a/include/usb/xhci.h
+++ b/include/usb/xhci.h
@@ -16,6 +16,7 @@
#ifndef HOST_XHCI_H_
#define HOST_XHCI_H_
+#include <phys2bus.h>
#include <reset.h>
#include <asm/types.h>
#include <asm/cache.h>
@@ -1229,6 +1230,12 @@ struct xhci_ctrl {
int rootdev;
};
+#if CONFIG_IS_ENABLED(DM_USB)
+#define xhci_to_dev(_ctrl) _ctrl->dev
+#else
+#define xhci_to_dev(_ctrl) NULL
+#endif
+
unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb);
struct xhci_input_control_ctx
*xhci_get_input_control_ctx(struct xhci_container_ctx *ctx);
@@ -1258,7 +1265,8 @@ int xhci_check_maxpacket(struct usb_device *udev);
void xhci_flush_cache(uintptr_t addr, u32 type_len);
void xhci_inval_cache(uintptr_t addr, u32 type_len);
void xhci_cleanup(struct xhci_ctrl *ctrl);
-struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs);
+struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
+ bool link_trbs);
int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id);
int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
struct xhci_hcor *hcor);
@@ -1286,4 +1294,14 @@ extern struct dm_usb_ops xhci_usb_ops;
struct xhci_ctrl *xhci_get_ctrl(struct usb_device *udev);
+static inline dma_addr_t xhci_virt_to_bus(struct xhci_ctrl *ctrl, void *addr)
+{
+ return dev_phys_to_bus(xhci_to_dev(ctrl), virt_to_phys(addr));
+}
+
+static inline void *xhci_bus_to_virt(struct xhci_ctrl *ctrl, dma_addr_t addr)
+{
+ return phys_to_virt(dev_bus_to_phys(xhci_to_dev(ctrl), addr));
+}
+
#endif /* HOST_XHCI_H_ */

View File

@ -0,0 +1,89 @@
From 9d5e73021a5778a29855140e50aa5309e7611618 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Thu, 19 Nov 2020 16:39:00 +0100
Subject: [PATCH] mmc: Introduce mmc_phys_to_bus()/mmc_bus_to_phys()
This will allow us to use DM variants of phys_to_bus()/bus_to_phys()
when relevant.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes since v4:
- Introduce mmc->dev access macros to avoid ifdefs
- No need to create mmc_phys_to_bus()
Changes since v3:
- Don't call phys_to_bus()/bus_to_phys(), we only support DM
---
drivers/mmc/sdhci.c | 12 +++++++-----
include/mmc.h | 6 ++++++
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 7673219fb3..874b686750 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -14,12 +14,12 @@
#include <log.h>
#include <malloc.h>
#include <mmc.h>
+#include <phys2bus.h>
#include <sdhci.h>
#include <asm/cache.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
-#include <phys2bus.h>
static void sdhci_reset(struct sdhci_host *host, u8 mask)
{
@@ -124,6 +124,7 @@ static void sdhci_prepare_adma_table(struct sdhci_host *host,
static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
int *is_aligned, int trans_bytes)
{
+ dma_addr_t dma_addr;
unsigned char ctrl;
void *buf;
@@ -154,8 +155,8 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
mmc_get_dma_dir(data));
if (host->flags & USE_SDMA) {
- sdhci_writel(host, phys_to_bus((ulong)host->start_addr),
- SDHCI_DMA_ADDRESS);
+ dma_addr = dev_phys_to_bus(mmc_to_dev(host->mmc), host->start_addr);
+ sdhci_writel(host, dma_addr, SDHCI_DMA_ADDRESS);
} else if (host->flags & (USE_ADMA | USE_ADMA64)) {
sdhci_prepare_adma_table(host, data);
@@ -209,8 +210,9 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data)
start_addr &=
~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1);
start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE;
- sdhci_writel(host, phys_to_bus((ulong)start_addr),
- SDHCI_DMA_ADDRESS);
+ start_addr = dev_phys_to_bus(mmc_to_dev(host->mmc),
+ start_addr);
+ sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
}
}
if (timeout-- > 0)
diff --git a/include/mmc.h b/include/mmc.h
index 82562193cc..d3f6c955d6 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -699,6 +699,12 @@ struct mmc {
u32 quirks;
};
+#if CONFIG_IS_ENABLED(DM_MMC)
+#define mmc_to_dev(_mmc) _mmc->dev
+#else
+#define mmc_to_dev(_mmc) NULL
+#endif
+
struct mmc_hwpart_conf {
struct {
uint enh_start; /* in 512-byte sectors */

View File

@ -0,0 +1,52 @@
From b8247b786c889b0141854d8a745409b7dd131d81 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Tue, 15 Dec 2020 13:35:34 +0100
Subject: [PATCH] configs: rpi4: Enable DM_DMA across all RPi4 configurations
The DM_DMA option is needed in order to translate physical address into
bus addresses on a per-device basis.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
configs/rpi_4_32b_defconfig | 1 +
configs/rpi_4_defconfig | 1 +
configs/rpi_arm64_defconfig | 1 +
3 files changed, 3 insertions(+)
diff --git a/configs/rpi_4_32b_defconfig b/configs/rpi_4_32b_defconfig
index 4a88448e9d..e6c038e750 100644
--- a/configs/rpi_4_32b_defconfig
+++ b/configs/rpi_4_32b_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
CONFIG_DFU_MMC=y
CONFIG_DM_KEYBOARD=y
CONFIG_DM_MMC=y
diff --git a/configs/rpi_4_defconfig b/configs/rpi_4_defconfig
index 71f95ed8f7..e8d6fb7e85 100644
--- a/configs/rpi_4_defconfig
+++ b/configs/rpi_4_defconfig
@@ -22,6 +22,7 @@ CONFIG_OF_BOARD=y
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
CONFIG_DFU_MMC=y
CONFIG_DM_KEYBOARD=y
CONFIG_DM_MMC=y
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index 4ce8469f43..7d837a9e93 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_FS_UUID=y
CONFIG_OF_BOARD=y
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_DM_DMA=y
CONFIG_DM_KEYBOARD=y
CONFIG_DM_MMC=y
CONFIG_MMC_SDHCI=y

View File

@ -0,0 +1,31 @@
From 83e81b4e04c3ef65402f161283a4b3faa50748c7 Mon Sep 17 00:00:00 2001
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Date: Mon, 21 Dec 2020 13:41:08 +0100
Subject: [PATCH] video: arm: rpi: Add brcm,bcm2711-hdmi0 compatible
The 'brcm,bcm2711-hdmi0' compatible string is used on RPi4 instead of
'brcm,bcm2835-hdmi' since the IP core was upgraded (now called VC6
instead of VC4). This has no functional change as far as u-boot driver
is concerned. So simply add the compatible string.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
---
Changes since v3:
- Add this patch
---
drivers/video/bcm2835.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c
index 0888cb0019..51941c4f53 100644
--- a/drivers/video/bcm2835.c
+++ b/drivers/video/bcm2835.c
@@ -52,6 +52,7 @@ static int bcm2835_video_probe(struct udevice *dev)
static const struct udevice_id bcm2835_video_ids[] = {
{ .compatible = "brcm,bcm2835-hdmi" },
+ { .compatible = "brcm,bcm2711-hdmi0" },
{ .compatible = "brcm,bcm2708-fb" },
{ }
};

View File

@ -0,0 +1,33 @@
From 09332b4c60063e0f0f975f80211d2554eb18389f Mon Sep 17 00:00:00 2001
From: Stefan Roese <sr@denx.de>
Date: Mon, 24 Aug 2020 13:04:37 +0200
Subject: [PATCH] usb: xhci: xhci_bulk_tx: Don't "BUG" when comparing addresses
Octeon uses mapped addresses for virtual and physical memory. It's not
that easy to calculate the resulting addresses here. So let's remove
this BUG_ON() completely, as it's not really helpful.
Please also note, that BUG_ON() is not recommended any more in the Linux
kernel.
Signed-off-by: Stefan Roese <sr@denx.de>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Marek Vasut <marex@denx.de>
---
drivers/usb/host/xhci-ring.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 27e7a39571..af8a12fc21 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -729,8 +729,6 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
BUG_ON(TRB_TO_SLOT_ID(field) != slot_id);
BUG_ON(TRB_TO_EP_INDEX(field) != ep_index);
- BUG_ON(*(void **)(uintptr_t)le64_to_cpu(event->trans_event.buffer) -
- buffer > (size_t)length);
record_transfer_result(udev, event, length);
xhci_acknowledge_event(ctrl);

View File

@ -1,3 +1,26 @@
-------------------------------------------------------------------
Thu Dec 24 16:17:08 UTC 2020 - Matthias Brugger <mbrugger@suse.com>
Enable RPi 4 Compute Module (jsc#SLE-16895).
Fix problems with DMA offset after FW update (bsc#1180338)
Patch queue updated from git://github.com/openSUSE/u-boot.git tumbleweed-2020.10
* Patches added:
0015-rpi-Add-identifier-for-the-new-RPi4.patch
0016-rpi-Add-identifier-for-the-new-CM4.patch
0017-pci-pcie-brcmstb-Fix-inbound-window.patch
0018-dm-Introduce-xxx_get_dma_range.patch
0019-dm-test-Add-test-case-for-dev_get_d.patch
0020-dm-Introduce-DMA-constraints-into-t.patch
0021-dm-test-Add-test-case-for-dev-dma_o.patch
0022-dm-Introduce-dev_phys_to_bus-dev_bu.patch
0023-dm-test-Add-test-case-for-dev_phys_.patch
0024-xhci-translate-virtual-addresses-in.patch
0025-mmc-Introduce-mmc_phys_to_bus-mmc_b.patch
0026-configs-rpi4-Enable-DM_DMA-across-a.patch
0027-video-arm-rpi-Add-brcm-bcm2711-hdmi.patch
0028-usb-xhci-xhci_bulk_tx-Don-t-BUG-whe.patch
-------------------------------------------------------------------
Fri Dec 11 13:18:00 UTC 2020 - Guillaume GARDET <guillaume.gardet@opensuse.org>

View File

@ -229,6 +229,20 @@ Patch0011: 0011-sunxi-dts-OrangePi-Zero-Add-SPI-ali.patch
Patch0012: 0012-sunxi-dts-OrangePi-Zero-Enable-SPI-.patch
Patch0013: 0013-sunxi-Enable-SPI-support-on-Orange-.patch
Patch0014: 0014-Disable-CONFIG_CMD_BTRFS-in-xilinx_.patch
Patch0015: 0015-rpi-Add-identifier-for-the-new-RPi4.patch
Patch0016: 0016-rpi-Add-identifier-for-the-new-CM4.patch
Patch0017: 0017-pci-pcie-brcmstb-Fix-inbound-window.patch
Patch0018: 0018-dm-Introduce-xxx_get_dma_range.patch
Patch0019: 0019-dm-test-Add-test-case-for-dev_get_d.patch
Patch0020: 0020-dm-Introduce-DMA-constraints-into-t.patch
Patch0021: 0021-dm-test-Add-test-case-for-dev-dma_o.patch
Patch0022: 0022-dm-Introduce-dev_phys_to_bus-dev_bu.patch
Patch0023: 0023-dm-test-Add-test-case-for-dev_phys_.patch
Patch0024: 0024-xhci-translate-virtual-addresses-in.patch
Patch0025: 0025-mmc-Introduce-mmc_phys_to_bus-mmc_b.patch
Patch0026: 0026-configs-rpi4-Enable-DM_DMA-across-a.patch
Patch0027: 0027-video-arm-rpi-Add-brcm-bcm2711-hdmi.patch
Patch0028: 0028-usb-xhci-xhci_bulk_tx-Don-t-BUG-whe.patch
# Patches: end
BuildRequires: bc
BuildRequires: bison