215 lines
7.1 KiB
Diff
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
|
|
|