mirror of
https://github.com/home-assistant/operating-system.git
synced 2025-07-28 07:26:28 +00:00
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:
parent
c94f7933ef
commit
bf1eaf44d5
@ -1,8 +1,8 @@
|
||||
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>
|
||||
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>
|
||||
---
|
||||
|
@ -1,10 +1,10 @@
|
||||
From cc40a554b003df9b07f8a55f69a94d7393d81cbc Mon Sep 17 00:00:00 2001
|
||||
Message-Id: <cc40a554b003df9b07f8a55f69a94d7393d81cbc.1606418463.git.stefan@agner.ch>
|
||||
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch>
|
||||
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch>
|
||||
Message-Id: <cc40a554b003df9b07f8a55f69a94d7393d81cbc.1606428503.git.stefan@agner.ch>
|
||||
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
|
||||
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
|
||||
From: Florin Sarbu <florin@balena.io>
|
||||
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
|
||||
|
@ -1,10 +1,10 @@
|
||||
From b0895f2384712f3d0d89405c06519da195e9ccc9 Mon Sep 17 00:00:00 2001
|
||||
Message-Id: <b0895f2384712f3d0d89405c06519da195e9ccc9.1606418463.git.stefan@agner.ch>
|
||||
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch>
|
||||
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606418463.git.stefan@agner.ch>
|
||||
Message-Id: <b0895f2384712f3d0d89405c06519da195e9ccc9.1606428503.git.stefan@agner.ch>
|
||||
In-Reply-To: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
|
||||
References: <a04331a6ba7334282836bbaa76e979c4e6be3900.1606428503.git.stefan@agner.ch>
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ®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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user