diff --git a/buildroot-external/board/raspberrypi/kernel.config b/buildroot-external/board/raspberrypi/kernel.config index ec7a7bd9d..2f7e1795d 100644 --- a/buildroot-external/board/raspberrypi/kernel.config +++ b/buildroot-external/board/raspberrypi/kernel.config @@ -1,3 +1,6 @@ # CONFIG_AUTOFS4_FS is not set # CONFIG_AUTOFS_FS is not set # CONFIG_PGTABLE_MAPPING is not set + +CONFIG_NVME_CORE=y +CONFIG_BLK_DEV_NVME=y diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0001-rpi-Use-CONFIG_OF_BOARD-instead-of-CONFIG_EMBED.patch b/buildroot-external/board/raspberrypi/patches/uboot/0001-rpi-Use-CONFIG_OF_BOARD-instead-of-CONFIG_EMBED.patch index 11193d704..3135e0d39 100644 --- a/buildroot-external/board/raspberrypi/patches/uboot/0001-rpi-Use-CONFIG_OF_BOARD-instead-of-CONFIG_EMBED.patch +++ b/buildroot-external/board/raspberrypi/patches/uboot/0001-rpi-Use-CONFIG_OF_BOARD-instead-of-CONFIG_EMBED.patch @@ -1,8 +1,8 @@ -From fe8e09815b4ae3ef12937f81cfb08e50f972f7b0 Mon Sep 17 00:00:00 2001 -Message-Id: +From cb3001355d465fa4a2f80cd186700a7bd27ca354 Mon Sep 17 00:00:00 2001 +Message-Id: From: Pascal Vizeli Date: Tue, 10 Dec 2019 09:48:46 +0000 -Subject: [PATCH 1/2] rpi: Use CONFIG_OF_BOARD instead of CONFIG_EMBED +Subject: [PATCH 1/8] rpi: Use CONFIG_OF_BOARD instead of CONFIG_EMBED Signed-off-by: Pascal Vizeli --- diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0002-usb-xhci-reset-endpoint-on-USB-stall.patch b/buildroot-external/board/raspberrypi/patches/uboot/0002-usb-xhci-reset-endpoint-on-USB-stall.patch index 009950843..08d8759a0 100644 --- a/buildroot-external/board/raspberrypi/patches/uboot/0002-usb-xhci-reset-endpoint-on-USB-stall.patch +++ b/buildroot-external/board/raspberrypi/patches/uboot/0002-usb-xhci-reset-endpoint-on-USB-stall.patch @@ -1,10 +1,10 @@ -From b9f62d571a79e9ea7be3c8327733bc5964336bae Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: -References: +From e89cc9ab5b404645bc19f149401b6ac97b35069d Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: From: Stefan Agner Date: Mon, 27 Sep 2021 12:28:04 +0200 -Subject: [PATCH 2/2] usb: xhci: reset endpoint on USB stall +Subject: [PATCH 2/8] usb: xhci: reset endpoint on USB stall There are devices which cause a USB stall when trying to read strings. Specifically Arduino Mega R3 stalls when trying to read the product diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0003-rpi-add-NVMe-to-boot-order.patch b/buildroot-external/board/raspberrypi/patches/uboot/0003-rpi-add-NVMe-to-boot-order.patch new file mode 100644 index 000000000..ece870431 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0003-rpi-add-NVMe-to-boot-order.patch @@ -0,0 +1,44 @@ +From 130b939a3176abdd483bd30cbed9783d96e68819 Mon Sep 17 00:00:00 2001 +Message-Id: <130b939a3176abdd483bd30cbed9783d96e68819.1632816160.git.stefan@agner.ch> +In-Reply-To: +References: +From: Stefan Agner +Date: Tue, 29 Dec 2020 23:34:52 +0100 +Subject: [PATCH 3/8] rpi: add NVMe to boot order + +The Compute Module 4 I/O Board can support a NVMe. Add NVMe to the boot +order. + +Signed-off-by: Stefan Agner +--- + include/configs/rpi.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/include/configs/rpi.h b/include/configs/rpi.h +index 522b41c02d..9b46203b5b 100644 +--- a/include/configs/rpi.h ++++ b/include/configs/rpi.h +@@ -169,6 +169,12 @@ + #define BOOT_TARGET_MMC(func) + #endif + ++#if CONFIG_IS_ENABLED(CMD_NVME) ++ #define BOOT_TARGET_NVME(func) func(NVME, nvme, 0) ++#else ++ #define BOOT_TARGET_NVME(func) ++#endif ++ + #if CONFIG_IS_ENABLED(CMD_USB) + #define BOOT_TARGET_USB(func) func(USB, usb, 0) + #else +@@ -189,6 +195,7 @@ + + #define BOOT_TARGET_DEVICES(func) \ + BOOT_TARGET_MMC(func) \ ++ BOOT_TARGET_NVME(func) \ + BOOT_TARGET_USB(func) \ + BOOT_TARGET_PXE(func) \ + BOOT_TARGET_DHCP(func) +-- +2.33.0 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0004-Revert-nvme-Correct-the-prps-per-page-calculation-me.patch b/buildroot-external/board/raspberrypi/patches/uboot/0004-Revert-nvme-Correct-the-prps-per-page-calculation-me.patch new file mode 100644 index 000000000..60b97a34e --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0004-Revert-nvme-Correct-the-prps-per-page-calculation-me.patch @@ -0,0 +1,44 @@ +From bb7d531f80d676a26f85982fc2bbb2a0939fd3bf Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Stefan Agner +Date: Thu, 23 Sep 2021 23:43:31 +0200 +Subject: [PATCH 4/8] Revert "nvme: Correct the prps per page calculation + method" + +This reverts commit 859b33c948945f7904f60a2c12a3792d356d51ad. + +If there is more than one PRP List the last entry is a pointer to +the next list. From the NVM Express specification: + +"The last entry within a memory page, as indicated by the memory page +size in the CC.MPS field, shall be a PRP List pointer if there is more +than a single memory page of data to be transferred." + +For the purpose of calculating the number of pages required for PRP +lists we should always assume that the last entry is required for +the next PRP list. + +Signed-off-by: Stefan Agner +Cc: Wesley Sheng +--- + drivers/nvme/nvme.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c +index f6465ea7f4..1ae3001a90 100644 +--- a/drivers/nvme/nvme.c ++++ b/drivers/nvme/nvme.c +@@ -81,7 +81,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, + u64 *prp_pool; + int length = total_len; + int i, nprps; +- u32 prps_per_page = page_size >> 3; ++ u32 prps_per_page = (page_size >> 3) - 1; + u32 num_pages; + + length -= (page_size - offset); +-- +2.33.0 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0005-nvme-improve-readability-of-nvme_setup_prps.patch b/buildroot-external/board/raspberrypi/patches/uboot/0005-nvme-improve-readability-of-nvme_setup_prps.patch new file mode 100644 index 000000000..730f1368a --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0005-nvme-improve-readability-of-nvme_setup_prps.patch @@ -0,0 +1,51 @@ +From a09d03397cad903a7a5925d5a0e9e5262ab9b13e Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Stefan Agner +Date: Thu, 23 Sep 2021 23:52:44 +0200 +Subject: [PATCH 5/8] nvme: improve readability of nvme_setup_prps() + +Improve readability by introducing consts, reuse consts where +appropriate and adding variables with discriptive name. + +Signed-off-by: Stefan Agner +--- + drivers/nvme/nvme.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c +index 1ae3001a90..677e66b1bb 100644 +--- a/drivers/nvme/nvme.c ++++ b/drivers/nvme/nvme.c +@@ -76,12 +76,12 @@ static int nvme_wait_ready(struct nvme_dev *dev, bool enabled) + static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, + int total_len, u64 dma_addr) + { +- u32 page_size = dev->page_size; ++ const u32 page_size = dev->page_size; ++ const u32 prps_per_page = (page_size >> 3) - 1; + int offset = dma_addr & (page_size - 1); + u64 *prp_pool; + int length = total_len; + int i, nprps; +- u32 prps_per_page = (page_size >> 3) - 1; + u32 num_pages; + + length -= (page_size - offset); +@@ -119,9 +119,9 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, + prp_pool = dev->prp_pool; + i = 0; + while (nprps) { +- if (i == ((page_size >> 3) - 1)) { +- *(prp_pool + i) = cpu_to_le64((ulong)prp_pool + +- page_size); ++ if (i == prps_per_page) { ++ u64 next_prp_list = (u64)prp_pool + page_size; ++ *(prp_pool + i) = cpu_to_le64(next_prp_list); + i = 0; + prp_pool += page_size; + } +-- +2.33.0 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0006-nvme-Use-pointer-for-CPU-addressed-buffers.patch b/buildroot-external/board/raspberrypi/patches/uboot/0006-nvme-Use-pointer-for-CPU-addressed-buffers.patch new file mode 100644 index 000000000..b1993033e --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0006-nvme-Use-pointer-for-CPU-addressed-buffers.patch @@ -0,0 +1,263 @@ +From 7e71ddff9abedfda11fa6c8cc1ba2b5729af9a95 Mon Sep 17 00:00:00 2001 +Message-Id: <7e71ddff9abedfda11fa6c8cc1ba2b5729af9a95.1632816160.git.stefan@agner.ch> +In-Reply-To: +References: +From: Stefan Agner +Date: Thu, 23 Sep 2021 23:58:35 +0200 +Subject: [PATCH 6/8] nvme: Use pointer for CPU addressed buffers + +Pass buffers which use CPU addressing as void pointers. This aligns with +DMA APIs which use void pointers as argument. It will avoid unnecessary +type casts when adding support bus address translations. + +Signed-off-by: Stefan Agner +--- + drivers/nvme/nvme.c | 50 ++++++++++++++++++++-------------------- + drivers/nvme/nvme_show.c | 4 ++-- + include/nvme.h | 12 +++++----- + 3 files changed, 33 insertions(+), 33 deletions(-) + +diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c +index 677e66b1bb..4c4dc7cc4d 100644 +--- a/drivers/nvme/nvme.c ++++ b/drivers/nvme/nvme.c +@@ -74,11 +74,11 @@ static int nvme_wait_ready(struct nvme_dev *dev, bool enabled) + } + + static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, +- int total_len, u64 dma_addr) ++ int total_len, void *buffer) + { + const u32 page_size = dev->page_size; + const u32 prps_per_page = (page_size >> 3) - 1; +- int offset = dma_addr & (page_size - 1); ++ int offset = (uintptr_t)buffer & (page_size - 1); + u64 *prp_pool; + int length = total_len; + int i, nprps; +@@ -92,10 +92,10 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, + } + + if (length) +- dma_addr += (page_size - offset); ++ buffer += (page_size - offset); + + if (length <= page_size) { +- *prp2 = dma_addr; ++ *prp2 = (u64)buffer; + return 0; + } + +@@ -125,11 +125,11 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, + i = 0; + prp_pool += page_size; + } +- *(prp_pool + i++) = cpu_to_le64(dma_addr); +- dma_addr += page_size; ++ *(prp_pool + i++) = cpu_to_le64((u64)buffer); ++ buffer += page_size; + nprps--; + } +- *prp2 = (ulong)dev->prp_pool; ++ *prp2 = (u64)dev->prp_pool; + + flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool + + dev->prp_entry_num * sizeof(u64)); +@@ -450,42 +450,42 @@ static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid, + } + + int nvme_identify(struct nvme_dev *dev, unsigned nsid, +- unsigned cns, dma_addr_t dma_addr) ++ unsigned int cns, void *buffer) + { + struct nvme_command c; + u32 page_size = dev->page_size; +- int offset = dma_addr & (page_size - 1); ++ int offset = (uintptr_t)buffer & (page_size - 1); + int length = sizeof(struct nvme_id_ctrl); + int ret; + + 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((u64)buffer); + + 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); ++ buffer += (page_size - offset); ++ c.identify.prp2 = cpu_to_le64((u64)buffer); + } + + c.identify.cns = cpu_to_le32(cns); + +- invalidate_dcache_range(dma_addr, +- dma_addr + sizeof(struct nvme_id_ctrl)); ++ invalidate_dcache_range((uintptr_t)buffer, ++ (uintptr_t)buffer + sizeof(struct nvme_id_ctrl)); + + ret = nvme_submit_admin_cmd(dev, &c, NULL); + if (!ret) +- invalidate_dcache_range(dma_addr, +- dma_addr + sizeof(struct nvme_id_ctrl)); ++ invalidate_dcache_range((uintptr_t)buffer, ++ (uintptr_t)buffer + sizeof(struct nvme_id_ctrl)); + + return ret; + } + + int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, +- dma_addr_t dma_addr, u32 *result) ++ void *buffer, u32 *result) + { + struct nvme_command c; + int ret; +@@ -493,7 +493,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((u64)buffer); + c.features.fid = cpu_to_le32(fid); + + ret = nvme_submit_admin_cmd(dev, &c, result); +@@ -513,13 +513,13 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, + } + + int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11, +- dma_addr_t dma_addr, u32 *result) ++ void *buffer, u32 *result) + { + struct nvme_command c; + + 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((u64)buffer); + c.features.fid = cpu_to_le32(fid); + c.features.dword11 = cpu_to_le32(dword11); + +@@ -570,7 +570,7 @@ static int nvme_set_queue_count(struct nvme_dev *dev, int count) + u32 q_count = (count - 1) | ((count - 1) << 16); + + status = nvme_set_features(dev, NVME_FEAT_NUM_QUEUES, +- q_count, 0, &result); ++ q_count, NULL, &result); + + if (status < 0) + return status; +@@ -622,7 +622,7 @@ static int nvme_get_info_from_identify(struct nvme_dev *dev) + if (!ctrl) + return -ENOMEM; + +- ret = nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl); ++ ret = nvme_identify(dev, 0, 1, ctrl); + if (ret) { + free(ctrl); + return -EIO; +@@ -708,7 +708,7 @@ static int nvme_blk_probe(struct udevice *udev) + ns->dev = ndev; + /* extract the namespace id from the block device name */ + ns->ns_id = trailing_strtol(udev->name); +- if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id)) { ++ if (nvme_identify(ndev, ns->ns_id, 0, id)) { + free(id); + return -EIO; + } +@@ -770,7 +770,7 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr, + } + + if (nvme_setup_prps(dev, &prp2, +- lbas << ns->lba_shift, (ulong)buffer)) ++ lbas << ns->lba_shift, buffer)) + return -EIO; + c.rw.slba = cpu_to_le64(slba); + slba += lbas; +@@ -889,7 +889,7 @@ static int nvme_probe(struct udevice *udev) + char name[20]; + + memset(id, 0, sizeof(*id)); +- if (nvme_identify(ndev, i, 0, (dma_addr_t)(long)id)) { ++ if (nvme_identify(ndev, i, 0, id)) { + ret = -EIO; + goto free_id; + } +diff --git a/drivers/nvme/nvme_show.c b/drivers/nvme/nvme_show.c +index 15e459da1a..c30adfada5 100644 +--- a/drivers/nvme/nvme_show.c ++++ b/drivers/nvme/nvme_show.c +@@ -111,14 +111,14 @@ int nvme_print_info(struct udevice *udev) + ALLOC_CACHE_ALIGN_BUFFER(char, buf_ctrl, sizeof(struct nvme_id_ctrl)); + struct nvme_id_ctrl *ctrl = (struct nvme_id_ctrl *)buf_ctrl; + +- if (nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl)) ++ if (nvme_identify(dev, 0, 1, ctrl)) + return -EIO; + + print_optional_admin_cmd(le16_to_cpu(ctrl->oacs), ns->devnum); + print_optional_nvm_cmd(le16_to_cpu(ctrl->oncs), ns->devnum); + print_format_nvme_attributes(ctrl->fna, ns->devnum); + +- if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)(long)id)) ++ if (nvme_identify(dev, ns->ns_id, 0, id)) + return -EIO; + + print_formats(id, ns); +diff --git a/include/nvme.h b/include/nvme.h +index 2cdf8ce320..8ff823cd81 100644 +--- a/include/nvme.h ++++ b/include/nvme.h +@@ -18,12 +18,12 @@ struct nvme_dev; + * @dev: NVMe controller device + * @nsid: 0 for controller, namespace id for namespace to identify + * @cns: 1 for controller, 0 for namespace +- * @dma_addr: dma buffer address to store the identify result ++ * @buffer: dma buffer address to store the identify result + * @return: 0 on success, -ETIMEDOUT on command execution timeout, + * -EIO on command execution fails + */ + int nvme_identify(struct nvme_dev *dev, unsigned nsid, +- unsigned cns, dma_addr_t dma_addr); ++ unsigned int cns, void *buffer); + + /** + * nvme_get_features - retrieve the attributes of the feature specified +@@ -33,13 +33,13 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid, + * @dev: NVMe controller device + * @fid: feature id to provide data + * @nsid: namespace id the command applies to +- * @dma_addr: data structure used as part of the specified feature ++ * @buffer: data structure used as part of the specified feature + * @result: command-specific result in the completion queue entry + * @return: 0 on success, -ETIMEDOUT on command execution timeout, + * -EIO on command execution fails + */ + int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, +- dma_addr_t dma_addr, u32 *result); ++ void *buffer, u32 *result); + + /** + * nvme_set_features - specify the attributes of the feature indicated +@@ -49,13 +49,13 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, + * @dev: NVMe controller device + * @fid: feature id to provide data + * @dword11: command-specific input parameter +- * @dma_addr: data structure used as part of the specified feature ++ * @buffer: data structure used as part of the specified feature + * @result: command-specific result in the completion queue entry + * @return: 0 on success, -ETIMEDOUT on command execution timeout, + * -EIO on command execution fails + */ + int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11, +- dma_addr_t dma_addr, u32 *result); ++ void *buffer, u32 *result); + + /** + * nvme_scan_namespace - scan all namespaces attached to NVMe controllers +-- +2.33.0 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0007-nvme-translate-virtual-addresses-into-the-bus-s-addr.patch b/buildroot-external/board/raspberrypi/patches/uboot/0007-nvme-translate-virtual-addresses-into-the-bus-s-addr.patch new file mode 100644 index 000000000..7e022659e --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0007-nvme-translate-virtual-addresses-into-the-bus-s-addr.patch @@ -0,0 +1,201 @@ +From 9e8a4fc39549069ff5a81119755586efe9002cab Mon Sep 17 00:00:00 2001 +Message-Id: <9e8a4fc39549069ff5a81119755586efe9002cab.1632816160.git.stefan@agner.ch> +In-Reply-To: +References: +From: Stefan Agner +Date: Fri, 24 Sep 2021 00:27:39 +0200 +Subject: [PATCH 7/8] nvme: translate virtual addresses into the bus's address + space + +So far we've been content with passing physical/CPU addresses when +configuring memory addresses into NVMe 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 nvme_virt_to_bus() and nvme_bus_to_virt() to cater with these +limitations, and make sure we don't break non DM users. +For devices where PCIe's view of host memory doesn't match the memory +as seen by the CPU. + +A similar change has been introduced for XHCI controller with +commit 1a474559d90a ("xhci: translate virtual addresses into the bus's +address space"). + +Signed-off-by: Stefan Agner +Series-to: bmeng.cn@gmail.com +Series-cc: u-boot@lists.denx.de, nsaenz@kernel.org, m.szyprowski@samsung.com, mbrugger@suse.com, s.nawrocki@samsung.com +Series-prefix: RFC +--- + drivers/nvme/nvme.c | 32 ++++++++++++++++++-------------- + drivers/nvme/nvme.h | 15 +++++++++++++++ + 2 files changed, 33 insertions(+), 14 deletions(-) + +diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c +index 4c4dc7cc4d..0b7082d71b 100644 +--- a/drivers/nvme/nvme.c ++++ b/drivers/nvme/nvme.c +@@ -95,7 +95,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, + buffer += (page_size - offset); + + if (length <= page_size) { +- *prp2 = (u64)buffer; ++ *prp2 = nvme_virt_to_bus(dev, buffer); + return 0; + } + +@@ -120,16 +120,16 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2, + i = 0; + while (nprps) { + if (i == prps_per_page) { +- u64 next_prp_list = (u64)prp_pool + page_size; +- *(prp_pool + i) = cpu_to_le64(next_prp_list); ++ u64 next = nvme_virt_to_bus(dev, prp_pool + page_size); ++ *(prp_pool + i) = cpu_to_le64(next); + i = 0; + prp_pool += page_size; + } +- *(prp_pool + i++) = cpu_to_le64((u64)buffer); ++ *(prp_pool + i++) = cpu_to_le64(nvme_virt_to_bus(dev, buffer)); + buffer += page_size; + nprps--; + } +- *prp2 = (u64)dev->prp_pool; ++ *prp2 = nvme_virt_to_bus(dev, dev->prp_pool); + + flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool + + dev->prp_entry_num * sizeof(u64)); +@@ -356,6 +356,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev) + int result; + u32 aqa; + u64 cap = dev->cap; ++ u64 dma_addr; + struct nvme_queue *nvmeq; + /* most architectures use 4KB as the page size */ + unsigned page_shift = 12; +@@ -396,8 +397,10 @@ 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); ++ dma_addr = nvme_virt_to_bus(dev, nvmeq->sq_cmds); ++ nvme_writeq(dma_addr, &dev->bar->asq); ++ dma_addr = nvme_virt_to_bus(dev, nvmeq->cqes); ++ nvme_writeq(dma_addr, &dev->bar->acq); + + result = nvme_enable_ctrl(dev); + if (result) +@@ -423,7 +426,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(nvme_virt_to_bus(dev, 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 +443,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(nvme_virt_to_bus(dev, 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 +464,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((u64)buffer); ++ c.identify.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, buffer)); + + length -= (page_size - offset); + if (length <= 0) { + c.identify.prp2 = 0; + } else { + buffer += (page_size - offset); +- c.identify.prp2 = cpu_to_le64((u64)buffer); ++ c.identify.prp2 = cpu_to_le64(nvme_virt_to_bus(dev, buffer)); + } + + c.identify.cns = cpu_to_le32(cns); +@@ -493,7 +496,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((u64)buffer); ++ c.features.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, buffer)); + c.features.fid = cpu_to_le32(fid); + + ret = nvme_submit_admin_cmd(dev, &c, result); +@@ -519,7 +522,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((u64)buffer); ++ c.features.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, buffer)); + c.features.fid = cpu_to_le32(fid); + c.features.dword11 = cpu_to_le32(dword11); + +@@ -775,7 +778,7 @@ 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((ulong)buffer); ++ c.rw.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, buffer)); + c.rw.prp2 = cpu_to_le64(prp2); + status = nvme_submit_sync_cmd(dev->queues[NVME_IO_Q], + &c, NULL, IO_TIMEOUT); +@@ -834,6 +837,7 @@ static int nvme_probe(struct udevice *udev) + struct nvme_id_ns *id; + + ndev->instance = trailing_strtol(udev->name); ++ ndev->dev = udev->parent; + + INIT_LIST_HEAD(&ndev->namespaces); + ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, +diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h +index c6aae4da5d..31e6899bca 100644 +--- a/drivers/nvme/nvme.h ++++ b/drivers/nvme/nvme.h +@@ -7,8 +7,15 @@ + #ifndef __DRIVER_NVME_H__ + #define __DRIVER_NVME_H__ + ++#include + #include + ++#if CONFIG_IS_ENABLED(DM_USB) ++#define nvme_to_dev(_dev) _dev->dev ++#else ++#define nvme_to_dev(_dev) NULL ++#endif ++ + struct nvme_id_power_state { + __le16 max_power; /* centiwatts */ + __u8 rsvd2; +@@ -596,6 +603,9 @@ enum { + + /* Represents an NVM Express device. Each nvme_dev is a PCI function. */ + struct nvme_dev { ++#if CONFIG_IS_ENABLED(DM_USB) ++ struct udevice *dev; ++#endif + struct list_head node; + struct nvme_queue **queues; + u32 __iomem *dbs; +@@ -635,4 +645,9 @@ struct nvme_ns { + u8 flbas; + }; + ++static inline dma_addr_t nvme_virt_to_bus(struct nvme_dev *dev, void *addr) ++{ ++ return dev_phys_to_bus(nvme_to_dev(dev), virt_to_phys(addr)); ++} ++ + #endif /* __DRIVER_NVME_H__ */ +-- +2.33.0 + diff --git a/buildroot-external/board/raspberrypi/rpi4-64/uboot.config b/buildroot-external/board/raspberrypi/rpi4-64/uboot.config new file mode 100644 index 000000000..82b4d3388 --- /dev/null +++ b/buildroot-external/board/raspberrypi/rpi4-64/uboot.config @@ -0,0 +1,2 @@ +CONFIG_CMD_NVME=y +CONFIG_NVME=y diff --git a/buildroot-external/board/raspberrypi/rpi4/uboot.config b/buildroot-external/board/raspberrypi/rpi4/uboot.config new file mode 100644 index 000000000..82b4d3388 --- /dev/null +++ b/buildroot-external/board/raspberrypi/rpi4/uboot.config @@ -0,0 +1,2 @@ +CONFIG_CMD_NVME=y +CONFIG_NVME=y diff --git a/buildroot-external/configs/rpi4_64_defconfig b/buildroot-external/configs/rpi4_64_defconfig index 1ba29b4f1..b98fbe6e4 100644 --- a/buildroot-external/configs/rpi4_64_defconfig +++ b/buildroot-external/configs/rpi4_64_defconfig @@ -97,7 +97,7 @@ BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y BR2_TARGET_UBOOT_CUSTOM_VERSION=y BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2021.10-rc5" BR2_TARGET_UBOOT_BOARD_DEFCONFIG="rpi_4" -BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/bootloader/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/uboot.config" +BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/bootloader/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/rpi4-64/uboot.config" BR2_PACKAGE_HOST_UBOOT_TOOLS=y BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="$(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/uboot-boot64.ush" diff --git a/buildroot-external/configs/rpi4_defconfig b/buildroot-external/configs/rpi4_defconfig index f1d017817..77b99bec8 100644 --- a/buildroot-external/configs/rpi4_defconfig +++ b/buildroot-external/configs/rpi4_defconfig @@ -95,7 +95,7 @@ BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y BR2_TARGET_UBOOT_CUSTOM_VERSION=y BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2021.10-rc5" BR2_TARGET_UBOOT_BOARD_DEFCONFIG="rpi_4_32b" -BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/bootloader/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/uboot.config" +BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/bootloader/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/rpi4/uboot.config" BR2_PACKAGE_HOST_UBOOT_TOOLS=y BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="$(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/uboot-boot.ush"