From bf1eaf44d5a4721371f1a532f0439e58e74d2c71 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Thu, 26 Nov 2020 23:13:57 +0100 Subject: [PATCH] Raspberry Pi: Add RPi400 and CM4 support (#1025) Backport patches for RPi400 and CM4 support. Tested on a RPi400 which seems to successfully boot and run Home Assistant OS with this. --- ...FIG_OF_BOARD-instead-of-CONFIG_EMBED.patch | 4 +- ...i-Disable-simple-framebuffer-support.patch | 8 +- ...rpi-force-a-smaller-amount-of-memory.patch | 8 +- .../0004-usb-xhci-convert-to-TRB_TYPE.patch | 91 +++++ ...cros-with-parameter-to-fill-ep_info2.patch | 121 +++++++ ...b-xhci-avoid-type-conversion-of-void.patch | 95 +++++ ...he-ADMA2-table-handling-into-own-mod.patch | 281 +++++++++++++++ ...pi-Add-identifier-for-the-new-RPi400.patch | 40 +++ ...9-rpi-Add-identifier-for-the-new-CM4.patch | 40 +++ ...tb-Fix-inbound-window-configurations.patch | 59 ++++ .../0011-dm-Introduce-xxx_get_dma_range.patch | 327 ++++++++++++++++++ ...-constraints-into-the-core-device-mo.patch | 78 +++++ ...duce-dev_phys_to_bus-dev_bus_to_phys.patch | 45 +++ ...irtual-addresses-into-the-bus-s-addr.patch | 308 +++++++++++++++++ ...duce-mmc_phys_to_bus-mmc_bus_to_phys.patch | 78 +++++ 15 files changed, 1573 insertions(+), 10 deletions(-) create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0004-usb-xhci-convert-to-TRB_TYPE.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0005-usb-xhci-use-macros-with-parameter-to-fill-ep_info2.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0006-usb-xhci-avoid-type-conversion-of-void.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0007-mmc-sdhci-move-the-ADMA2-table-handling-into-own-mod.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0008-rpi-Add-identifier-for-the-new-RPi400.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0009-rpi-Add-identifier-for-the-new-CM4.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0010-pci-pcie-brcmstb-Fix-inbound-window-configurations.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0011-dm-Introduce-xxx_get_dma_range.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0012-dm-Introduce-DMA-constraints-into-the-core-device-mo.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0013-dm-Introduce-dev_phys_to_bus-dev_bus_to_phys.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0014-xhci-translate-virtual-addresses-into-the-bus-s-addr.patch create mode 100644 buildroot-external/board/raspberrypi/patches/uboot/0015-mmc-Introduce-mmc_phys_to_bus-mmc_bus_to_phys.patch 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 4497e5794..9435c5378 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 a04331a6ba7334282836bbaa76e979c4e6be3900 Mon Sep 17 00:00:00 2001 -Message-Id: +Message-Id: From: Pascal Vizeli Date: Tue, 10 Dec 2019 09:48:46 +0000 -Subject: [PATCH 1/3] rpi: Use CONFIG_OF_BOARD instead of CONFIG_EMBED +Subject: [PATCH 01/15] rpi: Use CONFIG_OF_BOARD instead of CONFIG_EMBED Signed-off-by: Pascal Vizeli --- diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0002-raspberrypi-Disable-simple-framebuffer-support.patch b/buildroot-external/board/raspberrypi/patches/uboot/0002-raspberrypi-Disable-simple-framebuffer-support.patch index aa2d98535..09a78954f 100644 --- a/buildroot-external/board/raspberrypi/patches/uboot/0002-raspberrypi-Disable-simple-framebuffer-support.patch +++ b/buildroot-external/board/raspberrypi/patches/uboot/0002-raspberrypi-Disable-simple-framebuffer-support.patch @@ -1,10 +1,10 @@ From cc40a554b003df9b07f8a55f69a94d7393d81cbc Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: -References: +Message-Id: +In-Reply-To: +References: From: Florin Sarbu Date: Thu, 12 Sep 2019 12:31:31 +0200 -Subject: [PATCH 2/3] raspberrypi: Disable simple framebuffer support +Subject: [PATCH 02/15] raspberrypi: Disable simple framebuffer support On 4.19 kernels this u-boot driver clashes with bcm2708_fb. So let's disable it from here so that we have bcm2708_fb diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0003-rpi-force-a-smaller-amount-of-memory.patch b/buildroot-external/board/raspberrypi/patches/uboot/0003-rpi-force-a-smaller-amount-of-memory.patch index 5e73f4636..dbef8a146 100644 --- a/buildroot-external/board/raspberrypi/patches/uboot/0003-rpi-force-a-smaller-amount-of-memory.patch +++ b/buildroot-external/board/raspberrypi/patches/uboot/0003-rpi-force-a-smaller-amount-of-memory.patch @@ -1,10 +1,10 @@ From b0895f2384712f3d0d89405c06519da195e9ccc9 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: -References: +Message-Id: +In-Reply-To: +References: From: Stefan Agner Date: Thu, 26 Nov 2020 17:56:01 +0100 -Subject: [PATCH 3/3] rpi: force a smaller amount of memory +Subject: [PATCH 03/15] rpi: force a smaller amount of memory This fixes booting from USB on 32-bit installations. It seems not to affect the detected memory or SD card boot negatively. diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0004-usb-xhci-convert-to-TRB_TYPE.patch b/buildroot-external/board/raspberrypi/patches/uboot/0004-usb-xhci-convert-to-TRB_TYPE.patch new file mode 100644 index 000000000..ecc2a7b9b --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0004-usb-xhci-convert-to-TRB_TYPE.patch @@ -0,0 +1,91 @@ +From 000f636c9ea4909a23119ba65d3a3847687c8c6b Mon Sep 17 00:00:00 2001 +Message-Id: <000f636c9ea4909a23119ba65d3a3847687c8c6b.1606428503.git.stefan@agner.ch> +In-Reply-To: +References: +From: Chunfeng Yun +Date: Tue, 8 Sep 2020 18:59:59 +0200 +Subject: [PATCH 04/15] usb: xhci: convert to TRB_TYPE() + +Use TRB_TYPE(p) instead of ((p) << TRB_TYPE_SHIFT) + +Signed-off-by: Chunfeng Yun +Reviewed-by: Bin Meng +--- + drivers/usb/host/xhci-mem.c | 3 +-- + drivers/usb/host/xhci-ring.c | 11 +++++------ + include/usb/xhci.h | 1 - + 3 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 1da0524aa0..d627aa5555 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -236,8 +236,7 @@ static void xhci_link_segments(struct xhci_segment *prev, + */ + val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control); + val &= ~TRB_TYPE_BITMASK; +- val |= (TRB_LINK << TRB_TYPE_SHIFT); +- ++ val |= TRB_TYPE(TRB_LINK); + prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); + } + } +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 092ed6eaf1..a893277c75 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -699,7 +699,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, + trb_fields[0] = lower_32_bits(addr); + trb_fields[1] = upper_32_bits(addr); + trb_fields[2] = length_field; +- trb_fields[3] = field | (TRB_NORMAL << TRB_TYPE_SHIFT); ++ trb_fields[3] = field | TRB_TYPE(TRB_NORMAL); + + queue_trb(ctrl, ring, (num_trbs > 1), trb_fields); + +@@ -825,7 +825,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, + /* Queue setup TRB - see section 6.4.1.2.1 */ + /* FIXME better way to translate setup_packet into two u32 fields? */ + field = 0; +- field |= TRB_IDT | (TRB_SETUP << TRB_TYPE_SHIFT); ++ field |= TRB_IDT | TRB_TYPE(TRB_SETUP); + if (start_cycle == 0) + field |= 0x1; + +@@ -862,9 +862,9 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, + /* If there's data, queue data TRBs */ + /* Only set interrupt on short packet for IN endpoints */ + if (usb_pipein(pipe)) +- field = TRB_ISP | (TRB_DATA << TRB_TYPE_SHIFT); ++ field = TRB_ISP | TRB_TYPE(TRB_DATA); + else +- field = (TRB_DATA << TRB_TYPE_SHIFT); ++ field = TRB_TYPE(TRB_DATA); + + length_field = (length & TRB_LEN_MASK) | xhci_td_remainder(length) | + ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); +@@ -904,8 +904,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, + trb_fields[2] = ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); + /* Event on completion */ + trb_fields[3] = field | TRB_IOC | +- (TRB_STATUS << TRB_TYPE_SHIFT) | +- ep_ring->cycle_state; ++ TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state; + + queue_trb(ctrl, ep_ring, false, trb_fields); + +diff --git a/include/usb/xhci.h b/include/usb/xhci.h +index 7d34103fd5..6e7a040379 100644 +--- a/include/usb/xhci.h ++++ b/include/usb/xhci.h +@@ -903,7 +903,6 @@ union xhci_trb { + /* TRB bit mask */ + #define TRB_TYPE_BITMASK (0xfc00) + #define TRB_TYPE(p) ((p) << 10) +-#define TRB_TYPE_SHIFT (10) + #define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) + + /* TRB type IDs */ +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0005-usb-xhci-use-macros-with-parameter-to-fill-ep_info2.patch b/buildroot-external/board/raspberrypi/patches/uboot/0005-usb-xhci-use-macros-with-parameter-to-fill-ep_info2.patch new file mode 100644 index 000000000..df75b05a7 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0005-usb-xhci-use-macros-with-parameter-to-fill-ep_info2.patch @@ -0,0 +1,121 @@ +From bab3fd38c8eec5f3d12e41e706c02c79b4c4a21e Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Chunfeng Yun +Date: Tue, 8 Sep 2020 19:00:02 +0200 +Subject: [PATCH 05/15] usb: xhci: use macros with parameter to fill ep_info2 + +Use macros with parameter to fill ep_info2, then some macros +for MASK and SHIFT can be removed + +Signed-off-by: Chunfeng Yun +Reviewed-by: Bin Meng +--- + drivers/usb/host/xhci-mem.c | 15 +++++---------- + drivers/usb/host/xhci.c | 6 ++---- + include/usb/xhci.h | 6 ------ + 3 files changed, 7 insertions(+), 20 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index d627aa5555..0b49614995 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -825,25 +825,22 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, + + /* Step 4 - ring already allocated */ + /* Step 5 */ +- ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); ++ ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP)); + debug("SPEED = %d\n", speed); + + switch (speed) { + case USB_SPEED_SUPER: +- ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << +- MAX_PACKET_SHIFT)); ++ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(512)); + debug("Setting Packet size = 512bytes\n"); + break; + case USB_SPEED_HIGH: + /* USB core guesses at a 64-byte max packet first for FS devices */ + case USB_SPEED_FULL: +- ep0_ctx->ep_info2 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << +- MAX_PACKET_SHIFT)); ++ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(64)); + debug("Setting Packet size = 64bytes\n"); + break; + case USB_SPEED_LOW: +- ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << +- MAX_PACKET_SHIFT)); ++ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(8)); + debug("Setting Packet size = 8bytes\n"); + break; + default: +@@ -852,9 +849,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, + } + + /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ +- ep0_ctx->ep_info2 |= +- cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | +- ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); ++ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3)); + + trb_64 = virt_to_phys(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.c b/drivers/usb/host/xhci.c +index 126dabc11b..999ef79173 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -618,8 +618,7 @@ static int xhci_set_configuration(struct usb_device *udev) + cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) | + EP_INTERVAL(interval) | EP_MULT(mult)); + +- ep_ctx[ep_index]->ep_info2 = +- cpu_to_le32(ep_type << EP_TYPE_SHIFT); ++ ep_ctx[ep_index]->ep_info2 = cpu_to_le32(EP_TYPE(ep_type)); + ep_ctx[ep_index]->ep_info2 |= + cpu_to_le32(MAX_PACKET + (get_unaligned(&endpt_desc->wMaxPacketSize))); +@@ -832,8 +831,7 @@ int xhci_check_maxpacket(struct usb_device *udev) + ctrl->devs[slot_id]->out_ctx, ep_index); + in_ctx = ctrl->devs[slot_id]->in_ctx; + ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); +- ep_ctx->ep_info2 &= cpu_to_le32(~((0xffff & MAX_PACKET_MASK) +- << MAX_PACKET_SHIFT)); ++ ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET(MAX_PACKET_MASK)); + ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); + + /* +diff --git a/include/usb/xhci.h b/include/usb/xhci.h +index 6e7a040379..2e201bcbfa 100644 +--- a/include/usb/xhci.h ++++ b/include/usb/xhci.h +@@ -634,11 +634,8 @@ struct xhci_ep_ctx { + */ + #define FORCE_EVENT (0x1) + #define ERROR_COUNT(p) (((p) & 0x3) << 1) +-#define ERROR_COUNT_SHIFT (1) +-#define ERROR_COUNT_MASK (0x3) + #define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7) + #define EP_TYPE(p) ((p) << 3) +-#define EP_TYPE_SHIFT (3) + #define ISOC_OUT_EP 1 + #define BULK_OUT_EP 2 + #define INT_OUT_EP 3 +@@ -649,13 +646,10 @@ struct xhci_ep_ctx { + /* bit 6 reserved */ + /* bit 7 is Host Initiate Disable - for disabling stream selection */ + #define MAX_BURST(p) (((p)&0xff) << 8) +-#define MAX_BURST_MASK (0xff) +-#define MAX_BURST_SHIFT (8) + #define CTX_TO_MAX_BURST(p) (((p) >> 8) & 0xff) + #define MAX_PACKET(p) (((p)&0xffff) << 16) + #define MAX_PACKET_MASK (0xffff) + #define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) +-#define MAX_PACKET_SHIFT (16) + + /* Get max packet size from ep desc. Bit 10..0 specify the max packet size. + * USB2.0 spec 9.6.6. +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0006-usb-xhci-avoid-type-conversion-of-void.patch b/buildroot-external/board/raspberrypi/patches/uboot/0006-usb-xhci-avoid-type-conversion-of-void.patch new file mode 100644 index 000000000..1e6b7b30c --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0006-usb-xhci-avoid-type-conversion-of-void.patch @@ -0,0 +1,95 @@ +From 8591faf0da31be68ea45fdc8a0485c0163a3eb52 Mon Sep 17 00:00:00 2001 +Message-Id: <8591faf0da31be68ea45fdc8a0485c0163a3eb52.1606428503.git.stefan@agner.ch> +In-Reply-To: +References: +From: Heinrich Schuchardt +Date: Tue, 29 Sep 2020 22:03:01 +0200 +Subject: [PATCH 06/15] usb: xhci: avoid type conversion of void * + +void * can be assigned to any pointer variable. Avoid unnecessary +conversions. + +Signed-off-by: Heinrich Schuchardt +--- + drivers/usb/host/xhci-mem.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 0b49614995..b002d6f166 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -279,10 +279,10 @@ static struct xhci_segment *xhci_segment_alloc(void) + { + struct xhci_segment *seg; + +- seg = (struct xhci_segment *)malloc(sizeof(struct xhci_segment)); ++ seg = malloc(sizeof(struct xhci_segment)); + BUG_ON(!seg); + +- seg->trbs = (union xhci_trb *)xhci_malloc(SEGMENT_SIZE); ++ seg->trbs = xhci_malloc(SEGMENT_SIZE); + + seg->next = NULL; + +@@ -309,7 +309,7 @@ struct xhci_ring *xhci_ring_alloc(unsigned int num_segs, bool link_trbs) + struct xhci_ring *ring; + struct xhci_segment *prev; + +- ring = (struct xhci_ring *)malloc(sizeof(struct xhci_ring)); ++ ring = malloc(sizeof(struct xhci_ring)); + BUG_ON(!ring); + + if (num_segs == 0) +@@ -425,8 +425,7 @@ static struct xhci_container_ctx + { + struct xhci_container_ctx *ctx; + +- ctx = (struct xhci_container_ctx *) +- malloc(sizeof(struct xhci_container_ctx)); ++ ctx = malloc(sizeof(struct xhci_container_ctx)); + BUG_ON(!ctx); + + BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)); +@@ -436,7 +435,7 @@ static struct xhci_container_ctx + if (type == XHCI_CTX_TYPE_INPUT) + ctx->size += CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); + +- ctx->bytes = (u8 *)xhci_malloc(ctx->size); ++ ctx->bytes = xhci_malloc(ctx->size); + + return ctx; + } +@@ -458,8 +457,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) + return -EEXIST; + } + +- ctrl->devs[slot_id] = (struct xhci_virt_device *) +- malloc(sizeof(struct xhci_virt_device)); ++ ctrl->devs[slot_id] = malloc(sizeof(struct xhci_virt_device)); + + if (!ctrl->devs[slot_id]) { + puts("Failed to allocate virtual device\n"); +@@ -518,8 +516,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, + struct xhci_segment *seg; + + /* DCBAA initialization */ +- ctrl->dcbaa = (struct xhci_device_context_array *) +- xhci_malloc(sizeof(struct xhci_device_context_array)); ++ ctrl->dcbaa = xhci_malloc(sizeof(struct xhci_device_context_array)); + if (ctrl->dcbaa == NULL) { + puts("unable to allocate DCBA\n"); + return -ENOMEM; +@@ -555,8 +552,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, + + /* Event ring does not maintain link TRB */ + ctrl->event_ring = xhci_ring_alloc(ERST_NUM_SEGS, false); +- ctrl->erst.entries = (struct xhci_erst_entry *) +- xhci_malloc(sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS); ++ ctrl->erst.entries = xhci_malloc(sizeof(struct xhci_erst_entry) * ++ ERST_NUM_SEGS); + + ctrl->erst.num_entries = ERST_NUM_SEGS; + +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0007-mmc-sdhci-move-the-ADMA2-table-handling-into-own-mod.patch b/buildroot-external/board/raspberrypi/patches/uboot/0007-mmc-sdhci-move-the-ADMA2-table-handling-into-own-mod.patch new file mode 100644 index 000000000..9eba7daea --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0007-mmc-sdhci-move-the-ADMA2-table-handling-into-own-mod.patch @@ -0,0 +1,281 @@ +From f12d0a67a79679641299b1b923883e62332ee6d4 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Michael Walle +Date: Wed, 23 Sep 2020 12:42:51 +0200 +Subject: [PATCH 07/15] mmc: sdhci: move the ADMA2 table handling into own + module + +There are other (non-SDHCI) controllers which supports ADMA2 descriptor +tables, namely the Freescale eSDHC. Instead of copying the code, move it +into an own module. + +Signed-off-by: Michael Walle +--- + drivers/mmc/Kconfig | 5 +++ + drivers/mmc/Makefile | 1 + + drivers/mmc/sdhci-adma.c | 73 ++++++++++++++++++++++++++++++++++++++++ + drivers/mmc/sdhci.c | 63 +++++----------------------------- + include/sdhci.h | 8 +++-- + 5 files changed, 92 insertions(+), 58 deletions(-) + create mode 100644 drivers/mmc/sdhci-adma.c + +diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig +index 0c252e34c7..88582db58c 100644 +--- a/drivers/mmc/Kconfig ++++ b/drivers/mmc/Kconfig +@@ -46,6 +46,9 @@ config SPL_DM_MMC + + if MMC + ++config MMC_SDHCI_ADMA_HELPERS ++ bool ++ + config MMC_SPI + bool "Support for SPI-based MMC controller" + depends on DM_MMC && DM_SPI +@@ -445,6 +448,7 @@ config MMC_SDHCI_SDMA + config MMC_SDHCI_ADMA + bool "Support SDHCI ADMA2" + depends on MMC_SDHCI ++ select MMC_SDHCI_ADMA_HELPERS + help + This enables support for the ADMA (Advanced DMA) defined + in the SD Host Controller Standard Specification Version 3.00 +@@ -452,6 +456,7 @@ config MMC_SDHCI_ADMA + config SPL_MMC_SDHCI_ADMA + bool "Support SDHCI ADMA2 in SPL" + depends on MMC_SDHCI ++ select MMC_SDHCI_ADMA_HELPERS + help + This enables support for the ADMA (Advanced DMA) defined + in the SD Host Controller Standard Specification Version 3.00 in SPL. +diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile +index 22266ec8ec..1c849cbab2 100644 +--- a/drivers/mmc/Makefile ++++ b/drivers/mmc/Makefile +@@ -6,6 +6,7 @@ + obj-y += mmc.o + obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o + obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o ++obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o + + ifndef CONFIG_$(SPL_)BLK + obj-y += mmc_legacy.o +diff --git a/drivers/mmc/sdhci-adma.c b/drivers/mmc/sdhci-adma.c +new file mode 100644 +index 0000000000..2ec057fbb1 +--- /dev/null ++++ b/drivers/mmc/sdhci-adma.c +@@ -0,0 +1,73 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * SDHCI ADMA2 helper functions. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void sdhci_adma_desc(struct sdhci_adma_desc *desc, ++ dma_addr_t addr, u16 len, bool end) ++{ ++ u8 attr; ++ ++ attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA; ++ if (end) ++ attr |= ADMA_DESC_ATTR_END; ++ ++ desc->attr = attr; ++ desc->len = len; ++ desc->reserved = 0; ++ desc->addr_lo = lower_32_bits(addr); ++#ifdef CONFIG_DMA_ADDR_T_64BIT ++ desc->addr_hi = upper_32_bits(addr); ++#endif ++} ++ ++/** ++ * sdhci_prepare_adma_table() - Populate the ADMA table ++ * ++ * @table: Pointer to the ADMA table ++ * @data: Pointer to MMC data ++ * @addr: DMA address to write to or read from ++ * ++ * Fill the ADMA table according to the MMC data to read from or write to the ++ * given DMA address. ++ * Please note, that the table size depends on CONFIG_SYS_MMC_MAX_BLK_COUNT and ++ * we don't have to check for overflow. ++ */ ++void sdhci_prepare_adma_table(struct sdhci_adma_desc *table, ++ struct mmc_data *data, dma_addr_t addr) ++{ ++ uint trans_bytes = data->blocksize * data->blocks; ++ uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN); ++ struct sdhci_adma_desc *desc = table; ++ int i = desc_count; ++ ++ while (--i) { ++ sdhci_adma_desc(desc, addr, ADMA_MAX_LEN, false); ++ addr += ADMA_MAX_LEN; ++ trans_bytes -= ADMA_MAX_LEN; ++ desc++; ++ } ++ ++ sdhci_adma_desc(desc, addr, trans_bytes, true); ++ ++ flush_cache((dma_addr_t)table, ++ ROUND(desc_count * sizeof(struct sdhci_adma_desc), ++ ARCH_DMA_MINALIGN)); ++} ++ ++/** ++ * sdhci_adma_init() - initialize the ADMA descriptor table ++ * ++ * @return pointer to the allocated descriptor table or NULL in case of an ++ * error. ++ */ ++struct sdhci_adma_desc *sdhci_adma_init(void) ++{ ++ return memalign(ARCH_DMA_MINALIGN, ADMA_TABLE_SZ); ++} +diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c +index 7673219fb3..d549a264d7 100644 +--- a/drivers/mmc/sdhci.c ++++ b/drivers/mmc/sdhci.c +@@ -69,57 +69,6 @@ static void sdhci_transfer_pio(struct sdhci_host *host, struct mmc_data *data) + } + } + +-#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) +-static void sdhci_adma_desc(struct sdhci_host *host, dma_addr_t dma_addr, +- u16 len, bool end) +-{ +- struct sdhci_adma_desc *desc; +- u8 attr; +- +- desc = &host->adma_desc_table[host->desc_slot]; +- +- attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA; +- if (!end) +- host->desc_slot++; +- else +- attr |= ADMA_DESC_ATTR_END; +- +- desc->attr = attr; +- desc->len = len; +- desc->reserved = 0; +- desc->addr_lo = lower_32_bits(dma_addr); +-#ifdef CONFIG_DMA_ADDR_T_64BIT +- desc->addr_hi = upper_32_bits(dma_addr); +-#endif +-} +- +-static void sdhci_prepare_adma_table(struct sdhci_host *host, +- struct mmc_data *data) +-{ +- uint trans_bytes = data->blocksize * data->blocks; +- uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN); +- int i = desc_count; +- dma_addr_t dma_addr = host->start_addr; +- +- host->desc_slot = 0; +- +- while (--i) { +- sdhci_adma_desc(host, dma_addr, ADMA_MAX_LEN, false); +- dma_addr += ADMA_MAX_LEN; +- trans_bytes -= ADMA_MAX_LEN; +- } +- +- sdhci_adma_desc(host, dma_addr, trans_bytes, true); +- +- flush_cache((dma_addr_t)host->adma_desc_table, +- ROUND(desc_count * sizeof(struct sdhci_adma_desc), +- ARCH_DMA_MINALIGN)); +-} +-#elif defined(CONFIG_MMC_SDHCI_SDMA) +-static void sdhci_prepare_adma_table(struct sdhci_host *host, +- struct mmc_data *data) +-{} +-#endif + #if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)) + static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, + int *is_aligned, int trans_bytes) +@@ -156,8 +105,11 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, + if (host->flags & USE_SDMA) { + sdhci_writel(host, phys_to_bus((ulong)host->start_addr), + SDHCI_DMA_ADDRESS); +- } else if (host->flags & (USE_ADMA | USE_ADMA64)) { +- sdhci_prepare_adma_table(host, data); ++ } ++#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) ++ else if (host->flags & (USE_ADMA | USE_ADMA64)) { ++ sdhci_prepare_adma_table(host->adma_desc_table, data, ++ host->start_addr); + + sdhci_writel(host, lower_32_bits(host->adma_addr), + SDHCI_ADMA_ADDRESS); +@@ -165,6 +117,7 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, + sdhci_writel(host, upper_32_bits(host->adma_addr), + SDHCI_ADMA_ADDRESS_HI); + } ++#endif + } + #else + static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, +@@ -770,9 +723,9 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, + __func__); + return -EINVAL; + } +- host->adma_desc_table = memalign(ARCH_DMA_MINALIGN, ADMA_TABLE_SZ); +- ++ host->adma_desc_table = sdhci_adma_init(); + host->adma_addr = (dma_addr_t)host->adma_desc_table; ++ + #ifdef CONFIG_DMA_ADDR_T_64BIT + host->flags |= USE_ADMA64; + #else +diff --git a/include/sdhci.h b/include/sdhci.h +index 94fc3ed56a..f69d5f81fb 100644 +--- a/include/sdhci.h ++++ b/include/sdhci.h +@@ -271,7 +271,6 @@ struct sdhci_ops { + int (*deferred_probe)(struct sdhci_host *host); + }; + +-#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) + #define ADMA_MAX_LEN 65532 + #ifdef CONFIG_DMA_ADDR_T_64BIT + #define ADMA_DESC_LEN 16 +@@ -302,7 +301,7 @@ struct sdhci_adma_desc { + u32 addr_hi; + #endif + } __packed; +-#endif ++ + struct sdhci_host { + const char *name; + void *ioaddr; +@@ -334,7 +333,6 @@ struct sdhci_host { + dma_addr_t adma_addr; + #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) + struct sdhci_adma_desc *adma_desc_table; +- uint desc_slot; + #endif + }; + +@@ -496,4 +494,8 @@ extern const struct dm_mmc_ops sdhci_ops; + #else + #endif + ++struct sdhci_adma_desc *sdhci_adma_init(void); ++void sdhci_prepare_adma_table(struct sdhci_adma_desc *table, ++ struct mmc_data *data, dma_addr_t addr); ++ + #endif /* __SDHCI_HW_H */ +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0008-rpi-Add-identifier-for-the-new-RPi400.patch b/buildroot-external/board/raspberrypi/patches/uboot/0008-rpi-Add-identifier-for-the-new-RPi400.patch new file mode 100644 index 000000000..171ff4677 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0008-rpi-Add-identifier-for-the-new-RPi400.patch @@ -0,0 +1,40 @@ +From 0ad1fdab7a52554d1da758b36917c09965495dd9 Mon Sep 17 00:00:00 2001 +Message-Id: <0ad1fdab7a52554d1da758b36917c09965495dd9.1606428503.git.stefan@agner.ch> +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:15 +0100 +Subject: [PATCH 08/15] 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. + +So far the Raspberry Pi foundation is using the RPi4b device-tree file +to boot RPi400. I see no reason not to do the same as they are +completely compatible. + +Signed-off-by: Nicolas Saenz Julienne +--- + 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 18e60e76cc..e36bee3a34 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-4-b.dtb", ++ true, ++ }, + }; + + static const struct rpi_model rpi_models_old_scheme[] = { +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0009-rpi-Add-identifier-for-the-new-CM4.patch b/buildroot-external/board/raspberrypi/patches/uboot/0009-rpi-Add-identifier-for-the-new-CM4.patch new file mode 100644 index 000000000..2aa1eec54 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0009-rpi-Add-identifier-for-the-new-CM4.patch @@ -0,0 +1,40 @@ +From f9cb12f4cf902797987fea885fa186ba7d676aa0 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:16 +0100 +Subject: [PATCH 09/15] rpi: Add identifier for the new CM4 + +The Raspberry Pi Foundation released the new Compute Module 4which 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 +--- + 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 e36bee3a34..20311e90fe 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-4-b.dtb", + true, + }, ++ [0x14] = { ++ "Compute Modue 4", ++ DTB_DIR "bcm2711-rpi-cm4.dtb", ++ true, ++ }, + }; + + static const struct rpi_model rpi_models_old_scheme[] = { +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0010-pci-pcie-brcmstb-Fix-inbound-window-configurations.patch b/buildroot-external/board/raspberrypi/patches/uboot/0010-pci-pcie-brcmstb-Fix-inbound-window-configurations.patch new file mode 100644 index 000000000..c007f53f0 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0010-pci-pcie-brcmstb-Fix-inbound-window-configurations.patch @@ -0,0 +1,59 @@ +From c576988161912dfcb1bcd8b87640f5f998a87bf3 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:17 +0100 +Subject: [PATCH 10/15] 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 them 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 +--- + 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, ®ion, 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), +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0011-dm-Introduce-xxx_get_dma_range.patch b/buildroot-external/board/raspberrypi/patches/uboot/0011-dm-Introduce-xxx_get_dma_range.patch new file mode 100644 index 000000000..73b7b5bc7 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0011-dm-Introduce-xxx_get_dma_range.patch @@ -0,0 +1,327 @@ +From a2052b8361818ec5acb04e5d0c1d229083dfbeb6 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:18 +0100 +Subject: [PATCH 11/15] dm: Introduce xxx_get_dma_range() + +Add the follwing 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 +--- + common/fdt_support.c | 72 ++++++++++++++++++++++++++++++++++++++++++ + drivers/core/of_addr.c | 68 +++++++++++++++++++++++++++++++++++++++ + drivers/core/ofnode.c | 9 ++++++ + drivers/core/read.c | 5 +++ + include/dm/of_addr.h | 17 ++++++++++ + include/dm/ofnode.h | 16 ++++++++++ + include/dm/read.h | 6 ++++ + include/fdt_support.h | 14 ++++++++ + 8 files changed, 207 insertions(+) + +diff --git a/common/fdt_support.c b/common/fdt_support.c +index a565b470f8..ffc8f8b6b5 100644 +--- a/common/fdt_support.c ++++ b/common/fdt_support.c +@@ -1347,6 +1347,78 @@ 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; ++ const fdt32_t *ranges; ++ int na, ns, pna, pns; ++ int parent = node; ++ u64 cpu_addr; ++ 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 = -ENODEV; ++ 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 = -ENODEV; ++ 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 */ ++ of_match_bus(blob, 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; ++ } ++ ++ of_match_bus(blob, parent)->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_addr = fdt_read_number(ranges + na, pna); ++ *cpu = fdt_translate_dma_address(blob, node, (const fdt32_t*)&cpu_addr); ++ *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..8457e04a25 100644 +--- a/drivers/core/of_addr.c ++++ b/drivers/core/of_addr.c +@@ -325,6 +325,74 @@ 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; ++ int na, ns, pna, pns; ++ const __be32 *ranges; ++ int ret = 0; ++ int len; ++ ++ /* Find the closest dma-ranges property */ ++ 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 = -ENODEV; ++ goto out; ++ } ++ ++ if (ranges) ++ found_dma_ranges = true; ++ ++ dev = of_get_parent(dev); ++ } ++ ++ if (!dev || !ranges) { ++ debug("no dma-ranges found for node %s\n", ++ of_node_full_name(dev)); ++ ret = -ENODEV ++ 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 */ ++ of_match_bus(dev)->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; ++ } ++ ++ of_match_bus(parent)->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; ++ } ++ ++ *bus = of_read_number(ranges, na); ++ *cpu = of_translate_dma_address(dev, of_read_number(ranges + na, pna)); ++ *size = of_read_number(ranges + na + pna, ns); ++out: ++ 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..09b58a40db 100644 +--- a/drivers/core/read.c ++++ b/drivers/core/read.c +@@ -337,6 +337,11 @@ u64 dev_translate_dma_address(const struct udevice *dev, const fdt32_t *in_addr) + return ofnode_translate_dma_address(dev_ofnode(dev), in_addr); + } + ++u64 dev_translate_cpu_address(const struct udevice *dev, const fdt32_t *in_addr) ++{ ++ return ofnode_translate_cpu_address(dev_ofnode(dev), in_addr); ++} ++ + 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..f4b17bf026 100644 +--- a/include/dm/read.h ++++ b/include/dm/read.h +@@ -1002,6 +1002,12 @@ static inline u64 dev_translate_dma_address(const struct udevice *dev, + return ofnode_translate_dma_address(dev_ofnode(dev), in_addr); + } + ++static inline u64 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); +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0012-dm-Introduce-DMA-constraints-into-the-core-device-mo.patch b/buildroot-external/board/raspberrypi/patches/uboot/0012-dm-Introduce-DMA-constraints-into-the-core-device-mo.patch new file mode 100644 index 000000000..0f7f79f4d --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0012-dm-Introduce-DMA-constraints-into-the-core-device-mo.patch @@ -0,0 +1,78 @@ +From ea24a497a84cf0d1efb9c4f285d4d29bd69f3ebb Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:19 +0100 +Subject: [PATCH 12/15] 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. This information is static and available before initializing the +devices so parse it before the probe call an provide the DMA offset it +in 'struct udevice' for the DMA code to use it. + +Signed-off-by: Nicolas Saenz Julienne +--- + drivers/core/device.c | 24 ++++++++++++++++++++++++ + include/dm/device.h | 1 + + 2 files changed, 25 insertions(+) + +diff --git a/drivers/core/device.c b/drivers/core/device.c +index 355dbd147a..484852b2ac 100644 +--- a/drivers/core/device.c ++++ b/drivers/core/device.c +@@ -402,6 +402,28 @@ fail: + return ret; + } + ++void device_get_dma_constraints(struct udevice *dev) ++{ ++ phys_addr_t cpu; ++ dma_addr_t bus; ++ u64 size; ++ int ret; ++ ++ if (!dev_of_valid(dev)) ++ return; ++ ++ ret = dev_get_dma_range(dev, &cpu, &bus, &size); ++ if (ret) { ++ /* Don't complain if no 'dma-ranges' were found */ ++ if (ret != -ENODEV) ++ dm_warn("%s: failed to get DMA range, %d\n", ++ dev->name, ret); ++ return; ++ } ++ ++ dev->dma_offset = cpu - bus; ++} ++ + int device_probe(struct udevice *dev) + { + const struct driver *drv; +@@ -463,6 +485,8 @@ int device_probe(struct udevice *dev) + goto fail; + } + ++ device_get_dma_constraints(dev); ++ + ret = uclass_pre_probe_device(dev); + if (ret) + goto fail; +diff --git a/include/dm/device.h b/include/dm/device.h +index 953706cf52..6489f7ae61 100644 +--- a/include/dm/device.h ++++ b/include/dm/device.h +@@ -161,6 +161,7 @@ struct udevice { + #ifdef CONFIG_DEVRES + struct list_head devres_head; + #endif ++ u64 dma_offset; + }; + + /* Maximum sequence number supported */ +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0013-dm-Introduce-dev_phys_to_bus-dev_bus_to_phys.patch b/buildroot-external/board/raspberrypi/patches/uboot/0013-dm-Introduce-dev_phys_to_bus-dev_bus_to_phys.patch new file mode 100644 index 000000000..01dc4c9c1 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0013-dm-Introduce-dev_phys_to_bus-dev_bus_to_phys.patch @@ -0,0 +1,45 @@ +From 3f75e2303ddb7fa6eed6dc288880f613329ce3bb Mon Sep 17 00:00:00 2001 +Message-Id: <3f75e2303ddb7fa6eed6dc288880f613329ce3bb.1606428503.git.stefan@agner.ch> +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:20 +0100 +Subject: [PATCH 13/15] 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. + +Signed-off-by: Nicolas Saenz Julienne +--- + include/phys2bus.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/include/phys2bus.h b/include/phys2bus.h +index dc9b8e5a25..a380063af4 100644 +--- a/include/phys2bus.h ++++ b/include/phys2bus.h +@@ -21,4 +21,20 @@ static inline unsigned long bus_to_phys(unsigned long bus) + } + #endif + ++#if CONFIG_IS_ENABLED(DM) ++#include ++ ++static inline dma_addr_t dev_phys_to_bus(struct udevice *dev, ++ phys_addr_t phys) ++{ ++ return phys - dev->dma_offset; ++} ++ ++static inline phys_addr_t dev_bus_to_phys(struct udevice *dev, ++ dma_addr_t bus) ++{ ++ return bus + dev->dma_offset; ++} ++#endif ++ + #endif +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0014-xhci-translate-virtual-addresses-into-the-bus-s-addr.patch b/buildroot-external/board/raspberrypi/patches/uboot/0014-xhci-translate-virtual-addresses-into-the-bus-s-addr.patch new file mode 100644 index 000000000..e1e9efe85 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0014-xhci-translate-virtual-addresses-into-the-bus-s-addr.patch @@ -0,0 +1,308 @@ +From e3c96fd50787aa9ea2e5136593166cc49696d7ea Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:21 +0100 +Subject: [PATCH 14/15] 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 +--- + drivers/usb/host/xhci-mem.c | 45 +++++++++++++++++++----------------- + drivers/usb/host/xhci-ring.c | 11 +++++---- + drivers/usb/host/xhci.c | 4 ++-- + include/usb/xhci.h | 22 +++++++++++++++++- + 4 files changed, 54 insertions(+), 28 deletions(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index b002d6f166..e8d435d644 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); + +@@ -304,7 +304,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; +@@ -327,12 +328,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 |= +@@ -354,6 +355,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; +@@ -371,8 +373,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((uintptr_t)val_64); + + xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0], + sizeof(ctrl->dcbaa->dev_context_ptrs[0])); +@@ -393,8 +396,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, +@@ -484,9 +487,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); +@@ -522,15 +525,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) | +@@ -551,7 +554,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 = xhci_malloc(sizeof(struct xhci_erst_entry) * + ERST_NUM_SEGS); + +@@ -560,8 +563,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; +@@ -570,7 +573,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, +@@ -585,7 +588,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); + +@@ -848,7 +851,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, + /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3)); + +- 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 a893277c75..74deaabb9b 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 999ef79173..de2c83c64f 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; + +@@ -630,7 +630,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 2e201bcbfa..12e2b3ba80 100644 +--- a/include/usb/xhci.h ++++ b/include/usb/xhci.h +@@ -16,6 +16,7 @@ + #ifndef HOST_XHCI_H_ + #define HOST_XHCI_H_ + ++#include + #include + #include + #include +@@ -1251,7 +1252,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); +@@ -1279,4 +1281,22 @@ 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) ++{ ++#if CONFIG_IS_ENABLED(DM_USB) ++ return dev_phys_to_bus(ctrl->dev, virt_to_phys(addr)); ++#else ++ return phys_to_bus(virt_to_phys(addr)); ++#endif ++} ++ ++static inline void *xhci_bus_to_virt(struct xhci_ctrl *ctrl, dma_addr_t addr) ++{ ++#if CONFIG_IS_ENABLED(DM_USB) ++ return phys_to_virt(dev_bus_to_phys(ctrl->dev, addr)); ++#else ++ return phys_to_virt(bus_to_phys(addr)); ++#endif ++} ++ + #endif /* HOST_XHCI_H_ */ +-- +2.29.2 + diff --git a/buildroot-external/board/raspberrypi/patches/uboot/0015-mmc-Introduce-mmc_phys_to_bus-mmc_bus_to_phys.patch b/buildroot-external/board/raspberrypi/patches/uboot/0015-mmc-Introduce-mmc_phys_to_bus-mmc_bus_to_phys.patch new file mode 100644 index 000000000..59d656588 --- /dev/null +++ b/buildroot-external/board/raspberrypi/patches/uboot/0015-mmc-Introduce-mmc_phys_to_bus-mmc_bus_to_phys.patch @@ -0,0 +1,78 @@ +From de9f878b9cc4ab665c6aa4e6bb14193c66f78816 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: +References: +From: Nicolas Saenz Julienne +Date: Thu, 19 Nov 2020 18:48:22 +0100 +Subject: [PATCH 15/15] 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 +--- + drivers/mmc/sdhci.c | 7 ++++--- + include/mmc.h | 10 ++++++++++ + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c +index d549a264d7..a5a6c751e3 100644 +--- a/drivers/mmc/sdhci.c ++++ b/drivers/mmc/sdhci.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + static void sdhci_reset(struct sdhci_host *host, u8 mask) + { +@@ -103,7 +102,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_writel(host, ++ mmc_phys_to_bus(host->mmc, (ulong)host->start_addr), + SDHCI_DMA_ADDRESS); + } + #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) +@@ -162,7 +162,8 @@ 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_writel(host, ++ mmc_phys_to_bus(host->mmc, (ulong)start_addr), + SDHCI_DMA_ADDRESS); + } + } +diff --git a/include/mmc.h b/include/mmc.h +index 82562193cc..1d5b1f986e 100644 +--- a/include/mmc.h ++++ b/include/mmc.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + struct bd_info; + +@@ -938,4 +939,13 @@ static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) + return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + } + ++static inline dma_addr_t mmc_phys_to_bus(struct mmc *mmc, phys_addr_t addr) ++{ ++#if CONFIG_IS_ENABLED(DM_MMC) ++ return dev_phys_to_bus(mmc->dev, addr); ++#else ++ return phys_to_bus(addr); ++#endif ++} ++ + #endif /* _MMC_H_ */ +-- +2.29.2 +