uboot-tools/Fix-NVMe-not-only-on-Raspberry-Pi-5.patch
Peter Robinson a1afa6b9d7 2026.07 RC3
2026-05-29 14:14:46 +01:00

215 lines
7.1 KiB
Diff

From 06179e084181cbbc1e20121dc525621b77733bbc Mon Sep 17 00:00:00 2001
From: Torsten Duwe <duwe@suse.de>
Date: Fri, 8 May 2026 17:42:39 +0200
Subject: [PATCH 1/3] core: Skip parent device nodes without a DT reference
when looking for dma-ranges
If a device node got created dynamically, there is no guarantee that the
parent node has an associated device tree node which could specify dma
constraints. Especially PCI(e) enumeration adds intermediate "bus nodes",
also dynamically.
Try harder to find the correct configuration by walking up the tree until
a DT association is found.
Suggested-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Torsten Duwe <duwe@suse.de>
Reviewed-by: Peter Robinson <pbrobinson@gmail.com>
Tested-by: Peter Robinson <pbrobinson@gmail.com>
---
drivers/core/device.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c
index d365204ba11..b6d00cf4714 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -459,7 +459,19 @@ static int device_get_dma_constraints(struct udevice *dev)
u64 size = 0;
int ret;
- if (!CONFIG_IS_ENABLED(DM_DMA) || !parent || !dev_has_ofnode(parent))
+ if (!CONFIG_IS_ENABLED(DM_DMA) || !parent)
+ return 0;
+
+ /* Look for the first node in the parent chain */
+ while (parent) {
+ if (dev_has_ofnode(parent))
+ break;
+
+ parent = dev_get_parent(parent);
+ }
+
+ /* No parents have a node, bail out */
+ if (!parent)
return 0;
/*
--
2.54.0
From 38978e38c1246972a318479a1e833d66f06e41be Mon Sep 17 00:00:00 2001
From: Peter Robinson <pbrobinson@gmail.com>
Date: Fri, 29 May 2026 13:38:27 +0100
Subject: [PATCH 2/3] nvme: Fix missing address translation for PCIe inbound
access
U-Boot currently does not account for PCIe bridges with a non-zero
inbound access offset when talking NVMe, it only works on platforms
where this offset happens to be zero.
This patch enhances the NVMe driver with the ability to also handle
these cases.
Signed-off-by: Torsten Duwe <duwe@suse.de>
Reviewed-by: Peter Robinson <pbrobinson@gmail.com>
Tested-by: Peter Robinson <pbrobinson@gmail.com>
Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
---
drivers/nvme/nvme.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 0631b190b97..713f2b0b713 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -12,6 +12,7 @@
#include <log.h>
#include <malloc.h>
#include <memalign.h>
+#include <phys2bus.h>
#include <time.h>
#include <dm/device-internal.h>
#include <linux/compat.h>
@@ -27,6 +28,13 @@
#define IO_TIMEOUT 30
#define MAX_PRP_POOL 512
+/*
+ * Convert a memory address to the value needed by the PCI device to
+ * access the given location, taking into account inbound window
+ * translations of PCI bridges:
+ */
+#define DEV_ADDR(a) dev_phys_to_bus(dev->udev, (a))
+
static int nvme_wait_csts(struct nvme_dev *dev, u32 mask, u32 val)
{
int timeout;
@@ -91,8 +99,8 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
i = 0;
while (nprps) {
if ((i == (prps_per_page - 1)) && nprps > 1) {
- *(prp_pool + i) = cpu_to_le64((ulong)prp_pool +
- page_size);
+ *(prp_pool + i) = cpu_to_le64(DEV_ADDR((ulong)prp_pool +
+ page_size));
i = 0;
prp_pool = (u64 *)((uintptr_t)prp_pool + page_size);
}
@@ -396,8 +404,8 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
writel(aqa, &dev->bar->aqa);
- nvme_writeq((ulong)nvmeq->sq_cmds, &dev->bar->asq);
- nvme_writeq((ulong)nvmeq->cqes, &dev->bar->acq);
+ nvme_writeq(DEV_ADDR((ulong)nvmeq->sq_cmds), &dev->bar->asq);
+ nvme_writeq(DEV_ADDR((ulong)nvmeq->cqes), &dev->bar->acq);
result = nvme_enable_ctrl(dev);
if (result)
@@ -423,7 +431,7 @@ static int nvme_alloc_cq(struct nvme_dev *dev, u16 qid,
memset(&c, 0, sizeof(c));
c.create_cq.opcode = nvme_admin_create_cq;
- c.create_cq.prp1 = cpu_to_le64((ulong)nvmeq->cqes);
+ c.create_cq.prp1 = cpu_to_le64(DEV_ADDR((ulong)nvmeq->cqes));
c.create_cq.cqid = cpu_to_le16(qid);
c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
c.create_cq.cq_flags = cpu_to_le16(flags);
@@ -440,7 +448,7 @@ static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid,
memset(&c, 0, sizeof(c));
c.create_sq.opcode = nvme_admin_create_sq;
- c.create_sq.prp1 = cpu_to_le64((ulong)nvmeq->sq_cmds);
+ c.create_sq.prp1 = cpu_to_le64(DEV_ADDR((ulong)nvmeq->sq_cmds));
c.create_sq.sqid = cpu_to_le16(qid);
c.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
c.create_sq.sq_flags = cpu_to_le16(flags);
@@ -461,14 +469,14 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid,
memset(&c, 0, sizeof(c));
c.identify.opcode = nvme_admin_identify;
c.identify.nsid = cpu_to_le32(nsid);
- c.identify.prp1 = cpu_to_le64(dma_addr);
+ c.identify.prp1 = cpu_to_le64(DEV_ADDR(dma_addr));
length -= (page_size - offset);
if (length <= 0) {
c.identify.prp2 = 0;
} else {
dma_addr += (page_size - offset);
- c.identify.prp2 = cpu_to_le64(dma_addr);
+ c.identify.prp2 = cpu_to_le64(DEV_ADDR(dma_addr));
}
c.identify.cns = cpu_to_le32(cns);
@@ -493,7 +501,7 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
memset(&c, 0, sizeof(c));
c.features.opcode = nvme_admin_get_features;
c.features.nsid = cpu_to_le32(nsid);
- c.features.prp1 = cpu_to_le64(dma_addr);
+ c.features.prp1 = cpu_to_le64(DEV_ADDR(dma_addr));
c.features.fid = cpu_to_le32(fid);
ret = nvme_submit_admin_cmd(dev, &c, result);
@@ -519,7 +527,7 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
memset(&c, 0, sizeof(c));
c.features.opcode = nvme_admin_set_features;
- c.features.prp1 = cpu_to_le64(dma_addr);
+ c.features.prp1 = cpu_to_le64(DEV_ADDR(dma_addr));
c.features.fid = cpu_to_le32(fid);
c.features.dword11 = cpu_to_le32(dword11);
@@ -788,8 +796,8 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,
c.rw.slba = cpu_to_le64(slba);
slba += lbas;
c.rw.length = cpu_to_le16(lbas - 1);
- c.rw.prp1 = cpu_to_le64(temp_buffer);
- c.rw.prp2 = cpu_to_le64(prp2);
+ c.rw.prp1 = cpu_to_le64(DEV_ADDR(temp_buffer));
+ c.rw.prp2 = cpu_to_le64(DEV_ADDR(prp2));
status = nvme_submit_sync_cmd(dev->queues[NVME_IO_Q],
&c, NULL, IO_TIMEOUT);
if (status)
--
2.54.0
From 0e9d37b398f25bcb05525910d515559c9090c0aa Mon Sep 17 00:00:00 2001
From: Torsten Duwe <duwe@suse.de>
Date: Fri, 8 May 2026 17:42:48 +0200
Subject: [PATCH 3/3] configs: enable NVMe
Enable NVMe in the Raspberry Pi 64-Bit default config
Signed-off-by: Torsten Duwe <duwe@suse.de>
Reviewed-by: Peter Robinson <pbrobinson@gmail.com>
Tested-by: Peter Robinson <pbrobinson@gmail.com>
---
configs/rpi_arm64_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/configs/rpi_arm64_defconfig b/configs/rpi_arm64_defconfig
index 69e8e72c5d7..acf44f44fc5 100644
--- a/configs/rpi_arm64_defconfig
+++ b/configs/rpi_arm64_defconfig
@@ -41,6 +41,7 @@ CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_BCM2835=y
CONFIG_MMC_SDHCI_BCMSTB=y
CONFIG_BCMGENET=y
+CONFIG_NVME_PCI=y
CONFIG_PCI_BRCMSTB=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
--
2.54.0