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.
This commit is contained in:
Stefan Agner 2020-11-26 23:13:57 +01:00 committed by GitHub
parent c94f7933ef
commit bf1eaf44d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1573 additions and 10 deletions

View File

@ -1,8 +1,8 @@
From a04331a6ba7334282836bbaa76e979c4e6be3900 Mon Sep 17 00:00:00 2001 From a04331a6ba7334282836bbaa76e979c4e6be3900 Mon Sep 17 00:00:00 2001
Message-Id: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch> Message-Id: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Pascal Vizeli <pvizeli@syshack.ch> From: Pascal Vizeli <pvizeli@syshack.ch>
Date: Tue, 10 Dec 2019 09:48:46 +0000 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 <pvizeli@syshack.ch> Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
--- ---

View File

@ -1,10 +1,10 @@
From cc40a554b003df9b07f8a55f69a94d7393d81cbc Mon Sep 17 00:00:00 2001 From cc40a554b003df9b07f8a55f69a94d7393d81cbc Mon Sep 17 00:00:00 2001
Message-Id: <cc40a554b003df9b07f8a55f69a94d7393d81cbc.1606418463.git.stefan@agner.ch> Message-Id: <cc40a554b003df9b07f8a55f69a94d7393d81cbc.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch> In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch> References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Florin Sarbu <florin@balena.io> From: Florin Sarbu <florin@balena.io>
Date: Thu, 12 Sep 2019 12:31:31 +0200 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. 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 So let's disable it from here so that we have bcm2708_fb

View File

@ -1,10 +1,10 @@
From b0895f2384712f3d0d89405c06519da195e9ccc9 Mon Sep 17 00:00:00 2001 From b0895f2384712f3d0d89405c06519da195e9ccc9 Mon Sep 17 00:00:00 2001
Message-Id: <b0895f2384712f3d0d89405c06519da195e9ccc9.1606418463.git.stefan@agner.ch> Message-Id: <b0895f2384712f3d0d89405c06519da195e9ccc9.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch> In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch> References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Stefan Agner <stefan@agner.ch> From: Stefan Agner <stefan@agner.ch>
Date: Thu, 26 Nov 2020 17:56:01 +0100 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 This fixes booting from USB on 32-bit installations. It seems not to
affect the detected memory or SD card boot negatively. affect the detected memory or SD card boot negatively.

View File

@ -0,0 +1,91 @@
From 000f636c9ea4909a23119ba65d3a3847687c8c6b Mon Sep 17 00:00:00 2001
Message-Id: <000f636c9ea4909a23119ba65d3a3847687c8c6b.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Chunfeng Yun <chunfeng.yun@mediatek.com>
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 <chunfeng.yun@mediatek.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
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

View File

@ -0,0 +1,121 @@
From bab3fd38c8eec5f3d12e41e706c02c79b4c4a21e Mon Sep 17 00:00:00 2001
Message-Id: <bab3fd38c8eec5f3d12e41e706c02c79b4c4a21e.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Chunfeng Yun <chunfeng.yun@mediatek.com>
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 <chunfeng.yun@mediatek.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
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

View File

@ -0,0 +1,95 @@
From 8591faf0da31be68ea45fdc8a0485c0163a3eb52 Mon Sep 17 00:00:00 2001
Message-Id: <8591faf0da31be68ea45fdc8a0485c0163a3eb52.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
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 <xypron.glpk@gmx.de>
---
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

View File

@ -0,0 +1,281 @@
From f12d0a67a79679641299b1b923883e62332ee6d4 Mon Sep 17 00:00:00 2001
Message-Id: <f12d0a67a79679641299b1b923883e62332ee6d4.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Michael Walle <michael@walle.cc>
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 <michael@walle.cc>
---
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 <common.h>
+#include <cpu_func.h>
+#include <sdhci.h>
+#include <malloc.h>
+#include <asm/cache.h>
+
+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

View File

@ -0,0 +1,40 @@
From 0ad1fdab7a52554d1da758b36917c09965495dd9 Mon Sep 17 00:00:00 2001
Message-Id: <0ad1fdab7a52554d1da758b36917c09965495dd9.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
board/raspberrypi/rpi/rpi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 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

View File

@ -0,0 +1,40 @@
From f9cb12f4cf902797987fea885fa186ba7d676aa0 Mon Sep 17 00:00:00 2001
Message-Id: <f9cb12f4cf902797987fea885fa186ba7d676aa0.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
board/raspberrypi/rpi/rpi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
index 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

View File

@ -0,0 +1,59 @@
From c576988161912dfcb1bcd8b87640f5f998a87bf3 Mon Sep 17 00:00:00 2001
Message-Id: <c576988161912dfcb1bcd8b87640f5f998a87bf3.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
drivers/pci/pcie_brcmstb.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index dade79e9c8..f6e8ad0d0a 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -432,6 +432,7 @@ static int brcm_pcie_probe(struct udevice *dev)
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct brcm_pcie *pcie = dev_get_priv(dev);
void __iomem *base = pcie->base;
+ struct pci_region region;
bool ssc_good = false;
int num_out_wins = 0;
u64 rc_bar2_offset, rc_bar2_size;
@@ -468,13 +469,10 @@ static int brcm_pcie_probe(struct udevice *dev)
MISC_CTRL_SCB_ACCESS_EN_MASK |
MISC_CTRL_CFG_READ_UR_MODE_MASK |
MISC_CTRL_MAX_BURST_SIZE_128);
- /*
- * TODO: When support for other SoCs than BCM2711 is added we may
- * need to use the base address and size(s) provided in the dma-ranges
- * property.
- */
- rc_bar2_offset = 0;
- rc_bar2_size = 0xc0000000;
+
+ pci_get_dma_regions(dev, &region, 0);
+ rc_bar2_offset = region.bus_start - region.phys_start;
+ rc_bar2_size = 1ULL << fls64(region.size - 1);
tmp = lower_32_bits(rc_bar2_offset);
u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
--
2.29.2

View File

@ -0,0 +1,327 @@
From a2052b8361818ec5acb04e5d0c1d229083dfbeb6 Mon Sep 17 00:00:00 2001
Message-Id: <a2052b8361818ec5acb04e5d0c1d229083dfbeb6.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
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

View File

@ -0,0 +1,78 @@
From ea24a497a84cf0d1efb9c4f285d4d29bd69f3ebb Mon Sep 17 00:00:00 2001
Message-Id: <ea24a497a84cf0d1efb9c4f285d4d29bd69f3ebb.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
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

View File

@ -0,0 +1,45 @@
From 3f75e2303ddb7fa6eed6dc288880f613329ce3bb Mon Sep 17 00:00:00 2001
Message-Id: <3f75e2303ddb7fa6eed6dc288880f613329ce3bb.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
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 <dm/device.h>
+
+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

View File

@ -0,0 +1,308 @@
From e3c96fd50787aa9ea2e5136593166cc49696d7ea Mon Sep 17 00:00:00 2001
Message-Id: <e3c96fd50787aa9ea2e5136593166cc49696d7ea.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
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 <phys2bus.h>
#include <reset.h>
#include <asm/types.h>
#include <asm/cache.h>
@@ -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

View File

@ -0,0 +1,78 @@
From de9f878b9cc4ab665c6aa4e6bb14193c66f78816 Mon Sep 17 00:00:00 2001
Message-Id: <de9f878b9cc4ab665c6aa4e6bb14193c66f78816.1606428503.git.stefan@agner.ch>
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
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 <nsaenzjulienne@suse.de>
---
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 <linux/bitops.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
-#include <phys2bus.h>
static void sdhci_reset(struct sdhci_host *host, u8 mask)
{
@@ -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 <linux/compiler.h>
#include <linux/dma-direction.h>
#include <part.h>
+#include <phys2bus.h>
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