mirror of
https://github.com/home-assistant/operating-system.git
synced 2025-07-24 13:36:31 +00:00
Add initial support for Raspberry Pi CM5 on Yellow (#3667)
* Move RPi U-Boot patches to version-specific directory We will need to use different series for 2024.10 which would be used as the base for CM5 support. * Remove common.h include from the fileenv cmd It doesn't seem to be used and common.h has been removed in newer U-Boot. * Use U-Boot 2024.10 with BCM2712 PCIe patches for Yellow Use rebased patchset from v2024.01 with the first patch removed. Add patches needed for PCIe initialization and use rpi_arm64_defconfig as the base config for both CM4 and CM5. * Add device tree for CM5 on HA Yellow and adjust config Add device tree definition based on the CM5 device tree with BCM2712D0 changes applied, and add nodes required for the on-board peripherals of Yellow. Currently the difference in serial numbering still requires either changes in this device tree, or userspace changes to create correct symlinks to make HA configuration directly compatible with CM4 on Yellow. * Add config.txt migration for conditional device_tree options * Fix typos and minor issues found by CodeRabbit
This commit is contained in:
parent
6047770d7f
commit
180c9ada3f
@ -0,0 +1,23 @@
|
||||
From 3d9bd29941ce291e44aab60be1339d4c116ebda5 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Tue, 29 Dec 2020 23:34:52 +0100
|
||||
Subject: [PATCH] rpi: add NVMe to boot order
|
||||
|
||||
The Compute Module 4 I/O Board can support a NVMe. Add NVMe to the boot
|
||||
order.
|
||||
|
||||
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
||||
---
|
||||
board/raspberrypi/rpi/rpi.env | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/board/raspberrypi/rpi/rpi.env b/board/raspberrypi/rpi/rpi.env
|
||||
index 30228285ed..89f6c5a839 100644
|
||||
--- a/board/raspberrypi/rpi/rpi.env
|
||||
+++ b/board/raspberrypi/rpi/rpi.env
|
||||
@@ -74,4 +74,4 @@ pxefile_addr_r=0x02500000
|
||||
fdt_addr_r=0x02600000
|
||||
ramdisk_addr_r=0x02700000
|
||||
|
||||
-boot_targets=mmc usb pxe dhcp
|
||||
+boot_targets=mmc nvme usb pxe dhcp
|
@ -0,0 +1,37 @@
|
||||
From ab13da2df9f86517df45da293ed8002e07a3d5ec Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Thu, 23 Sep 2021 23:43:31 +0200
|
||||
Subject: [PATCH] Revert "nvme: Correct the prps per page calculation method"
|
||||
|
||||
This reverts commit 859b33c948945f7904f60a2c12a3792d356d51ad.
|
||||
|
||||
If there is more than one PRP List the last entry is a pointer to
|
||||
the next list. From the NVM Express specification:
|
||||
|
||||
"The last entry within a memory page, as indicated by the memory page
|
||||
size in the CC.MPS field, shall be a PRP List pointer if there is more
|
||||
than a single memory page of data to be transferred."
|
||||
|
||||
For the purpose of calculating the number of pages required for PRP
|
||||
lists we should always assume that the last entry is required for
|
||||
the next PRP list.
|
||||
|
||||
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
||||
Cc: Wesley Sheng <wesleyshenggit@sina.com>
|
||||
---
|
||||
drivers/nvme/nvme.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
|
||||
index 7c58ceb78f..0b2496cf26 100644
|
||||
--- a/drivers/nvme/nvme.c
|
||||
+++ b/drivers/nvme/nvme.c
|
||||
@@ -52,7 +52,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
u64 *prp_pool;
|
||||
int length = total_len;
|
||||
int i, nprps;
|
||||
- u32 prps_per_page = page_size >> 3;
|
||||
+ u32 prps_per_page = (page_size >> 3) - 1;
|
||||
u32 num_pages;
|
||||
|
||||
length -= (page_size - offset);
|
@ -0,0 +1,27 @@
|
||||
From 9de58838106829b8caa47b6fd6b42ba3435c2ce6 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Thu, 7 Oct 2021 12:02:39 +0200
|
||||
Subject: [PATCH] usb: xhci-brcm: Make driver compatible with downstream device
|
||||
tree
|
||||
|
||||
The downstream device tree uses just "generic-xhci" as compatible
|
||||
string. Use this string to make U-Boot work with the downstream Kernel.
|
||||
|
||||
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
||||
---
|
||||
drivers/usb/host/xhci-brcm.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c
|
||||
index 2ffad148de..2a063ccc9e 100644
|
||||
--- a/drivers/usb/host/xhci-brcm.c
|
||||
+++ b/drivers/usb/host/xhci-brcm.c
|
||||
@@ -81,7 +81,7 @@ static int xhci_brcm_deregister(struct udevice *dev)
|
||||
}
|
||||
|
||||
static const struct udevice_id xhci_brcm_ids[] = {
|
||||
- { .compatible = "brcm,generic-xhci" },
|
||||
+ { .compatible = "generic-xhci" },
|
||||
{ }
|
||||
};
|
||||
|
@ -0,0 +1,43 @@
|
||||
From 8c5910539c7e4e97f233789c2489c800f87ddf81 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Thu, 23 Sep 2021 23:52:44 +0200
|
||||
Subject: [PATCH] nvme: improve readability of nvme_setup_prps()
|
||||
|
||||
Improve readability by introducing consts, reuse consts where
|
||||
appropriate and adding variables with discriptive name.
|
||||
|
||||
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
||||
---
|
||||
drivers/nvme/nvme.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
|
||||
index 0b2496cf26..b1d8eecdca 100644
|
||||
--- a/drivers/nvme/nvme.c
|
||||
+++ b/drivers/nvme/nvme.c
|
||||
@@ -47,12 +47,12 @@ static int nvme_wait_csts(struct nvme_dev *dev, u32 mask, u32 val)
|
||||
static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
int total_len, u64 dma_addr)
|
||||
{
|
||||
- u32 page_size = dev->page_size;
|
||||
+ const u32 page_size = dev->page_size;
|
||||
+ const u32 prps_per_page = (page_size >> 3) - 1;
|
||||
int offset = dma_addr & (page_size - 1);
|
||||
u64 *prp_pool;
|
||||
int length = total_len;
|
||||
int i, nprps;
|
||||
- u32 prps_per_page = (page_size >> 3) - 1;
|
||||
u32 num_pages;
|
||||
|
||||
length -= (page_size - offset);
|
||||
@@ -91,8 +91,8 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
i = 0;
|
||||
while (nprps) {
|
||||
if ((i == (prps_per_page - 1)) && nprps > 1) {
|
||||
- *(prp_pool + i) = cpu_to_le64((ulong)prp_pool +
|
||||
- page_size);
|
||||
+ u64 next_prp_list = (u64)prp_pool + page_size;
|
||||
+ *(prp_pool + i) = cpu_to_le64(next_prp_list);
|
||||
i = 0;
|
||||
prp_pool += page_size;
|
||||
}
|
@ -0,0 +1,258 @@
|
||||
From e3f73d6ddba46f3b4ec8833c11f9ad831e57d394 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Thu, 23 Sep 2021 23:58:35 +0200
|
||||
Subject: [PATCH] nvme: Use pointer for CPU addressed buffers
|
||||
|
||||
Pass buffers which use CPU addressing as void pointers. This aligns with
|
||||
DMA APIs which use void pointers as argument. It will avoid unnecessary
|
||||
type casts when adding support bus address translations.
|
||||
|
||||
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
||||
---
|
||||
drivers/nvme/nvme.c | 50 ++++++++++++++++++++--------------------
|
||||
drivers/nvme/nvme_show.c | 4 ++--
|
||||
include/nvme.h | 12 +++++-----
|
||||
3 files changed, 33 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
|
||||
index b1d8eecdca..f626a472ff 100644
|
||||
--- a/drivers/nvme/nvme.c
|
||||
+++ b/drivers/nvme/nvme.c
|
||||
@@ -45,11 +45,11 @@ static int nvme_wait_csts(struct nvme_dev *dev, u32 mask, u32 val)
|
||||
}
|
||||
|
||||
static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
- int total_len, u64 dma_addr)
|
||||
+ int total_len, void *buffer)
|
||||
{
|
||||
const u32 page_size = dev->page_size;
|
||||
const u32 prps_per_page = (page_size >> 3) - 1;
|
||||
- int offset = dma_addr & (page_size - 1);
|
||||
+ int offset = (uintptr_t)buffer & (page_size - 1);
|
||||
u64 *prp_pool;
|
||||
int length = total_len;
|
||||
int i, nprps;
|
||||
@@ -63,10 +63,10 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
}
|
||||
|
||||
if (length)
|
||||
- dma_addr += (page_size - offset);
|
||||
+ buffer += (page_size - offset);
|
||||
|
||||
if (length <= page_size) {
|
||||
- *prp2 = dma_addr;
|
||||
+ *prp2 = (u64)buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -96,11 +96,11 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
i = 0;
|
||||
prp_pool += page_size;
|
||||
}
|
||||
- *(prp_pool + i++) = cpu_to_le64(dma_addr);
|
||||
- dma_addr += page_size;
|
||||
+ *(prp_pool + i++) = cpu_to_le64((u64)buffer);
|
||||
+ buffer += page_size;
|
||||
nprps--;
|
||||
}
|
||||
- *prp2 = (ulong)dev->prp_pool;
|
||||
+ *prp2 = (u64)dev->prp_pool;
|
||||
|
||||
flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool +
|
||||
num_pages * page_size);
|
||||
@@ -447,42 +447,42 @@ static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid,
|
||||
}
|
||||
|
||||
int nvme_identify(struct nvme_dev *dev, unsigned nsid,
|
||||
- unsigned cns, dma_addr_t dma_addr)
|
||||
+ unsigned int cns, void *buffer)
|
||||
{
|
||||
struct nvme_command c;
|
||||
u32 page_size = dev->page_size;
|
||||
- int offset = dma_addr & (page_size - 1);
|
||||
+ int offset = (uintptr_t)buffer & (page_size - 1);
|
||||
int length = sizeof(struct nvme_id_ctrl);
|
||||
int ret;
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.identify.opcode = nvme_admin_identify;
|
||||
c.identify.nsid = cpu_to_le32(nsid);
|
||||
- c.identify.prp1 = cpu_to_le64(dma_addr);
|
||||
+ c.identify.prp1 = cpu_to_le64((u64)buffer);
|
||||
|
||||
length -= (page_size - offset);
|
||||
if (length <= 0) {
|
||||
c.identify.prp2 = 0;
|
||||
} else {
|
||||
- dma_addr += (page_size - offset);
|
||||
- c.identify.prp2 = cpu_to_le64(dma_addr);
|
||||
+ buffer += (page_size - offset);
|
||||
+ c.identify.prp2 = cpu_to_le64((u64)buffer);
|
||||
}
|
||||
|
||||
c.identify.cns = cpu_to_le32(cns);
|
||||
|
||||
- invalidate_dcache_range(dma_addr,
|
||||
- dma_addr + sizeof(struct nvme_id_ctrl));
|
||||
+ invalidate_dcache_range((uintptr_t)buffer,
|
||||
+ (uintptr_t)buffer + sizeof(struct nvme_id_ctrl));
|
||||
|
||||
ret = nvme_submit_admin_cmd(dev, &c, NULL);
|
||||
if (!ret)
|
||||
- invalidate_dcache_range(dma_addr,
|
||||
- dma_addr + sizeof(struct nvme_id_ctrl));
|
||||
+ invalidate_dcache_range((uintptr_t)buffer,
|
||||
+ (uintptr_t)buffer + sizeof(struct nvme_id_ctrl));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
||||
- dma_addr_t dma_addr, u32 *result)
|
||||
+ void *buffer, u32 *result)
|
||||
{
|
||||
struct nvme_command c;
|
||||
int ret;
|
||||
@@ -490,7 +490,7 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.features.opcode = nvme_admin_get_features;
|
||||
c.features.nsid = cpu_to_le32(nsid);
|
||||
- c.features.prp1 = cpu_to_le64(dma_addr);
|
||||
+ c.features.prp1 = cpu_to_le64((u64)buffer);
|
||||
c.features.fid = cpu_to_le32(fid);
|
||||
|
||||
ret = nvme_submit_admin_cmd(dev, &c, result);
|
||||
@@ -510,13 +510,13 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
||||
}
|
||||
|
||||
int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
|
||||
- dma_addr_t dma_addr, u32 *result)
|
||||
+ void *buffer, u32 *result)
|
||||
{
|
||||
struct nvme_command c;
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.features.opcode = nvme_admin_set_features;
|
||||
- c.features.prp1 = cpu_to_le64(dma_addr);
|
||||
+ c.features.prp1 = cpu_to_le64((u64)buffer);
|
||||
c.features.fid = cpu_to_le32(fid);
|
||||
c.features.dword11 = cpu_to_le32(dword11);
|
||||
|
||||
@@ -567,7 +567,7 @@ static int nvme_set_queue_count(struct nvme_dev *dev, int count)
|
||||
u32 q_count = (count - 1) | ((count - 1) << 16);
|
||||
|
||||
status = nvme_set_features(dev, NVME_FEAT_NUM_QUEUES,
|
||||
- q_count, 0, &result);
|
||||
+ q_count, NULL, &result);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
@@ -628,7 +628,7 @@ static int nvme_get_info_from_identify(struct nvme_dev *dev)
|
||||
if (!ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret = nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl);
|
||||
+ ret = nvme_identify(dev, 0, 1, ctrl);
|
||||
if (ret) {
|
||||
free(ctrl);
|
||||
return -EIO;
|
||||
@@ -718,7 +718,7 @@ static int nvme_blk_probe(struct udevice *udev)
|
||||
ns->dev = ndev;
|
||||
/* extract the namespace id from the block device name */
|
||||
ns->ns_id = trailing_strtol(udev->name);
|
||||
- if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id)) {
|
||||
+ if (nvme_identify(ndev, ns->ns_id, 0, id)) {
|
||||
free(id);
|
||||
return -EIO;
|
||||
}
|
||||
@@ -752,7 +752,7 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,
|
||||
u64 prp2;
|
||||
u64 total_len = blkcnt << desc->log2blksz;
|
||||
u64 temp_len = total_len;
|
||||
- uintptr_t temp_buffer = (uintptr_t)buffer;
|
||||
+ void *temp_buffer = buffer;
|
||||
|
||||
u64 slba = blknr;
|
||||
u16 lbas = 1 << (dev->max_transfer_shift - ns->lba_shift);
|
||||
@@ -890,7 +890,7 @@ int nvme_init(struct udevice *udev)
|
||||
char name[20];
|
||||
|
||||
memset(id, 0, sizeof(*id));
|
||||
- if (nvme_identify(ndev, i, 0, (dma_addr_t)(long)id)) {
|
||||
+ if (nvme_identify(ndev, i, 0, id)) {
|
||||
ret = -EIO;
|
||||
goto free_id;
|
||||
}
|
||||
diff --git a/drivers/nvme/nvme_show.c b/drivers/nvme/nvme_show.c
|
||||
index b06cb5c6d5..ad1a260f9a 100644
|
||||
--- a/drivers/nvme/nvme_show.c
|
||||
+++ b/drivers/nvme/nvme_show.c
|
||||
@@ -113,7 +113,7 @@ int nvme_print_info(struct udevice *udev)
|
||||
if (!ctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
- if (nvme_identify(dev, 0, 1, (dma_addr_t)(long)ctrl)) {
|
||||
+ if (nvme_identify(dev, 0, 1, ctrl)) {
|
||||
ret = -EIO;
|
||||
goto free_ctrl;
|
||||
}
|
||||
@@ -128,7 +128,7 @@ int nvme_print_info(struct udevice *udev)
|
||||
goto free_ctrl;
|
||||
}
|
||||
|
||||
- if (nvme_identify(dev, ns->ns_id, 0, (dma_addr_t)(long)id)) {
|
||||
+ if (nvme_identify(dev, ns->ns_id, 0, id)) {
|
||||
ret = -EIO;
|
||||
goto free_id;
|
||||
}
|
||||
diff --git a/include/nvme.h b/include/nvme.h
|
||||
index 2cdf8ce320..8ff823cd81 100644
|
||||
--- a/include/nvme.h
|
||||
+++ b/include/nvme.h
|
||||
@@ -18,12 +18,12 @@ struct nvme_dev;
|
||||
* @dev: NVMe controller device
|
||||
* @nsid: 0 for controller, namespace id for namespace to identify
|
||||
* @cns: 1 for controller, 0 for namespace
|
||||
- * @dma_addr: dma buffer address to store the identify result
|
||||
+ * @buffer: dma buffer address to store the identify result
|
||||
* @return: 0 on success, -ETIMEDOUT on command execution timeout,
|
||||
* -EIO on command execution fails
|
||||
*/
|
||||
int nvme_identify(struct nvme_dev *dev, unsigned nsid,
|
||||
- unsigned cns, dma_addr_t dma_addr);
|
||||
+ unsigned int cns, void *buffer);
|
||||
|
||||
/**
|
||||
* nvme_get_features - retrieve the attributes of the feature specified
|
||||
@@ -33,13 +33,13 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid,
|
||||
* @dev: NVMe controller device
|
||||
* @fid: feature id to provide data
|
||||
* @nsid: namespace id the command applies to
|
||||
- * @dma_addr: data structure used as part of the specified feature
|
||||
+ * @buffer: data structure used as part of the specified feature
|
||||
* @result: command-specific result in the completion queue entry
|
||||
* @return: 0 on success, -ETIMEDOUT on command execution timeout,
|
||||
* -EIO on command execution fails
|
||||
*/
|
||||
int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
||||
- dma_addr_t dma_addr, u32 *result);
|
||||
+ void *buffer, u32 *result);
|
||||
|
||||
/**
|
||||
* nvme_set_features - specify the attributes of the feature indicated
|
||||
@@ -49,13 +49,13 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
||||
* @dev: NVMe controller device
|
||||
* @fid: feature id to provide data
|
||||
* @dword11: command-specific input parameter
|
||||
- * @dma_addr: data structure used as part of the specified feature
|
||||
+ * @buffer: data structure used as part of the specified feature
|
||||
* @result: command-specific result in the completion queue entry
|
||||
* @return: 0 on success, -ETIMEDOUT on command execution timeout,
|
||||
* -EIO on command execution fails
|
||||
*/
|
||||
int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
|
||||
- dma_addr_t dma_addr, u32 *result);
|
||||
+ void *buffer, u32 *result);
|
||||
|
||||
/**
|
||||
* nvme_scan_namespace - scan all namespaces attached to NVMe controllers
|
@ -0,0 +1,170 @@
|
||||
From 1c9ebd44d5af878719f041d6a2329cc81674134c Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Fri, 24 Sep 2021 00:27:39 +0200
|
||||
Subject: [PATCH] nvme: translate virtual addresses into the bus's address
|
||||
space
|
||||
|
||||
So far we've been content with passing physical/CPU addresses when
|
||||
configuring memory addresses into NVMe controllers, but not all
|
||||
platforms have buses with transparent mappings. Specifically the
|
||||
Raspberry Pi 4 might introduce an offset to memory accesses incoming
|
||||
from its PCIe port.
|
||||
|
||||
Introduce nvme_virt_to_bus() and nvme_bus_to_virt() to cater with these
|
||||
limitations, and make sure we don't break non DM users.
|
||||
For devices where PCIe's view of host memory doesn't match the memory
|
||||
as seen by the CPU.
|
||||
|
||||
A similar change has been introduced for XHCI controller with
|
||||
commit 1a474559d90a ("xhci: translate virtual addresses into the bus's
|
||||
address space").
|
||||
|
||||
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
||||
---
|
||||
drivers/nvme/nvme.c | 31 +++++++++++++++++--------------
|
||||
drivers/nvme/nvme.h | 8 ++++++++
|
||||
2 files changed, 25 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
|
||||
index f626a472ff..70ce63f205 100644
|
||||
--- a/drivers/nvme/nvme.c
|
||||
+++ b/drivers/nvme/nvme.c
|
||||
@@ -66,7 +66,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
buffer += (page_size - offset);
|
||||
|
||||
if (length <= page_size) {
|
||||
- *prp2 = (u64)buffer;
|
||||
+ *prp2 = nvme_virt_to_bus(dev, buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -91,16 +91,16 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
|
||||
i = 0;
|
||||
while (nprps) {
|
||||
if ((i == (prps_per_page - 1)) && nprps > 1) {
|
||||
- u64 next_prp_list = (u64)prp_pool + page_size;
|
||||
- *(prp_pool + i) = cpu_to_le64(next_prp_list);
|
||||
+ u64 next = nvme_virt_to_bus(dev, prp_pool + page_size);
|
||||
+ *(prp_pool + i) = cpu_to_le64(next);
|
||||
i = 0;
|
||||
prp_pool += page_size;
|
||||
}
|
||||
- *(prp_pool + i++) = cpu_to_le64((u64)buffer);
|
||||
+ *(prp_pool + i++) = cpu_to_le64(nvme_virt_to_bus(dev, buffer));
|
||||
buffer += page_size;
|
||||
nprps--;
|
||||
}
|
||||
- *prp2 = (u64)dev->prp_pool;
|
||||
+ *prp2 = nvme_virt_to_bus(dev, dev->prp_pool);
|
||||
|
||||
flush_dcache_range((ulong)dev->prp_pool, (ulong)dev->prp_pool +
|
||||
num_pages * page_size);
|
||||
@@ -353,6 +353,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
|
||||
int result;
|
||||
u32 aqa;
|
||||
u64 cap = dev->cap;
|
||||
+ u64 dma_addr;
|
||||
struct nvme_queue *nvmeq;
|
||||
/* most architectures use 4KB as the page size */
|
||||
unsigned page_shift = 12;
|
||||
@@ -393,8 +394,10 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
|
||||
dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
|
||||
|
||||
writel(aqa, &dev->bar->aqa);
|
||||
- nvme_writeq((ulong)nvmeq->sq_cmds, &dev->bar->asq);
|
||||
- nvme_writeq((ulong)nvmeq->cqes, &dev->bar->acq);
|
||||
+ dma_addr = nvme_virt_to_bus(dev, nvmeq->sq_cmds);
|
||||
+ nvme_writeq(dma_addr, &dev->bar->asq);
|
||||
+ dma_addr = nvme_virt_to_bus(dev, nvmeq->cqes);
|
||||
+ nvme_writeq(dma_addr, &dev->bar->acq);
|
||||
|
||||
result = nvme_enable_ctrl(dev);
|
||||
if (result)
|
||||
@@ -420,7 +423,7 @@ static int nvme_alloc_cq(struct nvme_dev *dev, u16 qid,
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.create_cq.opcode = nvme_admin_create_cq;
|
||||
- c.create_cq.prp1 = cpu_to_le64((ulong)nvmeq->cqes);
|
||||
+ c.create_cq.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, nvmeq->cqes));
|
||||
c.create_cq.cqid = cpu_to_le16(qid);
|
||||
c.create_cq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
|
||||
c.create_cq.cq_flags = cpu_to_le16(flags);
|
||||
@@ -437,7 +440,7 @@ static int nvme_alloc_sq(struct nvme_dev *dev, u16 qid,
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.create_sq.opcode = nvme_admin_create_sq;
|
||||
- c.create_sq.prp1 = cpu_to_le64((ulong)nvmeq->sq_cmds);
|
||||
+ c.create_sq.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, nvmeq->sq_cmds));
|
||||
c.create_sq.sqid = cpu_to_le16(qid);
|
||||
c.create_sq.qsize = cpu_to_le16(nvmeq->q_depth - 1);
|
||||
c.create_sq.sq_flags = cpu_to_le16(flags);
|
||||
@@ -458,14 +461,14 @@ int nvme_identify(struct nvme_dev *dev, unsigned nsid,
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.identify.opcode = nvme_admin_identify;
|
||||
c.identify.nsid = cpu_to_le32(nsid);
|
||||
- c.identify.prp1 = cpu_to_le64((u64)buffer);
|
||||
+ c.identify.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, buffer));
|
||||
|
||||
length -= (page_size - offset);
|
||||
if (length <= 0) {
|
||||
c.identify.prp2 = 0;
|
||||
} else {
|
||||
buffer += (page_size - offset);
|
||||
- c.identify.prp2 = cpu_to_le64((u64)buffer);
|
||||
+ c.identify.prp2 = cpu_to_le64(nvme_virt_to_bus(dev, buffer));
|
||||
}
|
||||
|
||||
c.identify.cns = cpu_to_le32(cns);
|
||||
@@ -490,7 +493,7 @@ int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.features.opcode = nvme_admin_get_features;
|
||||
c.features.nsid = cpu_to_le32(nsid);
|
||||
- c.features.prp1 = cpu_to_le64((u64)buffer);
|
||||
+ c.features.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, buffer));
|
||||
c.features.fid = cpu_to_le32(fid);
|
||||
|
||||
ret = nvme_submit_admin_cmd(dev, &c, result);
|
||||
@@ -516,7 +519,7 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.features.opcode = nvme_admin_set_features;
|
||||
- c.features.prp1 = cpu_to_le64((u64)buffer);
|
||||
+ c.features.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, buffer));
|
||||
c.features.fid = cpu_to_le32(fid);
|
||||
c.features.dword11 = cpu_to_le32(dword11);
|
||||
|
||||
@@ -785,7 +788,7 @@ static ulong nvme_blk_rw(struct udevice *udev, lbaint_t blknr,
|
||||
c.rw.slba = cpu_to_le64(slba);
|
||||
slba += lbas;
|
||||
c.rw.length = cpu_to_le16(lbas - 1);
|
||||
- c.rw.prp1 = cpu_to_le64(temp_buffer);
|
||||
+ c.rw.prp1 = cpu_to_le64(nvme_virt_to_bus(dev, temp_buffer));
|
||||
c.rw.prp2 = cpu_to_le64(prp2);
|
||||
status = nvme_submit_sync_cmd(dev->queues[NVME_IO_Q],
|
||||
&c, NULL, IO_TIMEOUT);
|
||||
diff --git a/drivers/nvme/nvme.h b/drivers/nvme/nvme.h
|
||||
index bc1d612dde..f52103c009 100644
|
||||
--- a/drivers/nvme/nvme.h
|
||||
+++ b/drivers/nvme/nvme.h
|
||||
@@ -7,8 +7,11 @@
|
||||
#ifndef __DRIVER_NVME_H__
|
||||
#define __DRIVER_NVME_H__
|
||||
|
||||
+#include <phys2bus.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
+#define nvme_to_dev(_dev) _dev->udev
|
||||
+
|
||||
struct nvme_id_power_state {
|
||||
__le16 max_power; /* centiwatts */
|
||||
__u8 rsvd2;
|
||||
@@ -705,4 +708,9 @@ int nvme_init(struct udevice *udev);
|
||||
*/
|
||||
int nvme_shutdown(struct udevice *udev);
|
||||
|
||||
+static inline dma_addr_t nvme_virt_to_bus(struct nvme_dev *dev, void *addr)
|
||||
+{
|
||||
+ return dev_phys_to_bus(nvme_to_dev(dev)->parent, virt_to_phys(addr));
|
||||
+}
|
||||
+
|
||||
#endif /* __DRIVER_NVME_H__ */
|
@ -0,0 +1,44 @@
|
||||
From 418664bb1dfa61b8fc1a0292adb00ec93e1a7619 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Agner <stefan@agner.ch>
|
||||
Date: Mon, 24 Apr 2023 15:44:15 +0200
|
||||
Subject: [PATCH] Revert "pci: Check region ranges are addressable"
|
||||
|
||||
This reverts commit ec8eba8c2d4e10e77699c56918d2078210aa1339.
|
||||
|
||||
This commit seems to cause boot hangs when USB via XHCI is enabled on
|
||||
Raspberry Pi 4 32-bit. Reverting the commit fixes USB device detection
|
||||
and makes the devices boot again.
|
||||
|
||||
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
||||
---
|
||||
drivers/pci/pci-uclass.c | 17 +----------------
|
||||
1 file changed, 1 insertion(+), 16 deletions(-)
|
||||
|
||||
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
|
||||
index 6571e65304..803d5c25fc 100644
|
||||
--- a/drivers/pci/pci-uclass.c
|
||||
+++ b/drivers/pci/pci-uclass.c
|
||||
@@ -1038,22 +1038,7 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node,
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SYS_PCI_64BIT) &&
|
||||
type == PCI_REGION_MEM && upper_32_bits(pci_addr)) {
|
||||
- debug(" - pci_addr beyond the 32-bit boundary, ignoring\n");
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (!IS_ENABLED(CONFIG_PHYS_64BIT) && upper_32_bits(addr)) {
|
||||
- debug(" - addr beyond the 32-bit boundary, ignoring\n");
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (~((pci_addr_t)0) - pci_addr < size) {
|
||||
- debug(" - PCI range exceeds max address, ignoring\n");
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (~((phys_addr_t)0) - addr < size) {
|
||||
- debug(" - phys range exceeds max address, ignoring\n");
|
||||
+ debug(" - beyond the 32-bit boundary, ignoring\n");
|
||||
continue;
|
||||
}
|
||||
|
@ -0,0 +1,145 @@
|
||||
From 81100e760c8ed3d697696de5353d51e8e1af2be4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <sairon@sairon.cz>
|
||||
Date: Mon, 30 Sep 2024 17:56:45 +0200
|
||||
Subject: [PATCH] reset: reset-brcmstb: Add Broadcom STB reset controller
|
||||
driver
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add driver for the brcm,brcmstb-reset compatible used on RPi 5 by
|
||||
porting the upstream Linux driver. Assert/deassert functions are adapted
|
||||
to the U-Boot way of handling individual resets' IDs.
|
||||
|
||||
Signed-off-by: Jan Čermák <sairon@sairon.cz>
|
||||
---
|
||||
drivers/reset/Kconfig | 6 +++
|
||||
drivers/reset/Makefile | 1 +
|
||||
drivers/reset/reset-brcmstb.c | 89 +++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 96 insertions(+)
|
||||
create mode 100644 drivers/reset/reset-brcmstb.c
|
||||
|
||||
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
|
||||
index fe5c1214f5..10a364b2a8 100644
|
||||
--- a/drivers/reset/Kconfig
|
||||
+++ b/drivers/reset/Kconfig
|
||||
@@ -63,6 +63,12 @@ config RESET_BCM6345
|
||||
help
|
||||
Support reset controller on BCM6345.
|
||||
|
||||
+config RESET_BRCMSTB
|
||||
+ bool "Broadcom STB reset controller"
|
||||
+ help
|
||||
+ This enables the reset controller driver for Broadcom STB SoCs using
|
||||
+ a SUN_TOP_CTRL_SW_INIT style controller.
|
||||
+
|
||||
config RESET_UNIPHIER
|
||||
bool "Reset controller driver for UniPhier SoCs"
|
||||
depends on ARCH_UNIPHIER
|
||||
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
|
||||
index 2eb639e4a6..d7e9ac1a88 100644
|
||||
--- a/drivers/reset/Makefile
|
||||
+++ b/drivers/reset/Makefile
|
||||
@@ -13,6 +13,7 @@ obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o
|
||||
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
|
||||
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
|
||||
obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
|
||||
+obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
|
||||
obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o
|
||||
obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o
|
||||
diff --git a/drivers/reset/reset-brcmstb.c b/drivers/reset/reset-brcmstb.c
|
||||
new file mode 100644
|
||||
index 0000000000..c0aef5f124
|
||||
--- /dev/null
|
||||
+++ b/drivers/reset/reset-brcmstb.c
|
||||
@@ -0,0 +1,89 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Broadcom STB generic reset controller for SW_INIT style reset controller
|
||||
+ *
|
||||
+ * Based on upstream Linux driver:
|
||||
+ * drivers/reset/reset-brcmstb.c
|
||||
+ * Author: Florian Fainelli <f.fainelli@gmail.com>
|
||||
+ * Copyright (C) 2018 Broadcom
|
||||
+ */
|
||||
+
|
||||
+#include <dm.h>
|
||||
+#include <errno.h>
|
||||
+#include <log.h>
|
||||
+#include <malloc.h>
|
||||
+#include <reset-uclass.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+#define SW_INIT_SET 0x00
|
||||
+#define SW_INIT_CLEAR 0x04
|
||||
+#define SW_INIT_STATUS 0x08
|
||||
+
|
||||
+#define SW_INIT_BIT(id) BIT((id) & 0x1f)
|
||||
+#define SW_INIT_BANK(id) ((id) >> 5)
|
||||
+
|
||||
+/* A full bank contains extra registers that we are not utilizing but still
|
||||
+ * qualify as a single bank.
|
||||
+ */
|
||||
+#define SW_INIT_BANK_SIZE 0x18
|
||||
+
|
||||
+struct brcmstb_reset_priv {
|
||||
+ void __iomem *base;
|
||||
+};
|
||||
+
|
||||
+static int brcmstb_reset_assert(struct reset_ctl *rst)
|
||||
+{
|
||||
+ unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE;
|
||||
+ struct brcmstb_reset_priv *priv = dev_get_priv(rst->dev);
|
||||
+
|
||||
+ writel_relaxed(SW_INIT_BIT(rst->id), priv->base + off + SW_INIT_SET);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int brcmstb_reset_deassert(struct reset_ctl *rst)
|
||||
+{
|
||||
+ unsigned int off = SW_INIT_BANK(rst->id) * SW_INIT_BANK_SIZE;
|
||||
+ struct brcmstb_reset_priv *priv = dev_get_priv(rst->dev);
|
||||
+
|
||||
+ writel_relaxed(SW_INIT_BIT(rst->id), priv->base + off + SW_INIT_CLEAR);
|
||||
+ /* Maximum reset delay after de-asserting a line and seeing block
|
||||
+ * operation is typically 14us for the worst case, build some slack
|
||||
+ * here.
|
||||
+ */
|
||||
+ udelay(200);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+struct reset_ops brcmstb_reset_reset_ops = {
|
||||
+ .rst_assert = brcmstb_reset_assert,
|
||||
+ .rst_deassert = brcmstb_reset_deassert,
|
||||
+};
|
||||
+
|
||||
+static const struct udevice_id brcmstb_reset_ids[] = {
|
||||
+ { .compatible = "brcm,brcmstb-reset" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
+static int brcmstb_reset_probe(struct udevice *dev)
|
||||
+{
|
||||
+ struct brcmstb_reset_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ priv->base = dev_remap_addr(dev);
|
||||
+ if (!priv->base)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+U_BOOT_DRIVER(brcmstb_reset) = {
|
||||
+ .name = "brcmstb-reset",
|
||||
+ .id = UCLASS_RESET,
|
||||
+ .of_match = brcmstb_reset_ids,
|
||||
+ .ops = &brcmstb_reset_reset_ops,
|
||||
+ .probe = brcmstb_reset_probe,
|
||||
+ .priv_auto = sizeof(struct brcmstb_reset_priv),
|
||||
+};
|
@ -0,0 +1,158 @@
|
||||
From eb7dd5b1afa4831e6eca2edb2650bd9db9a6d6eb Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <sairon@sairon.cz>
|
||||
Date: Mon, 30 Sep 2024 18:09:29 +0200
|
||||
Subject: [PATCH] reset: reset-brcmstb-rescal: Add Broadcom RESCAL reset
|
||||
controller driver
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add driver for brcm,bcm7216-pcie-sata-rescal compatible, based on
|
||||
upstream Linux driver. Unlike most of other reset controllers, RESCAL
|
||||
takes no reset IDs, so a custom of_xlate function is used that makes the
|
||||
driver slightly different from the original implementation.
|
||||
|
||||
Signed-off-by: Jan Čermák <sairon@sairon.cz>
|
||||
---
|
||||
drivers/reset/Kconfig | 6 ++
|
||||
drivers/reset/Makefile | 1 +
|
||||
drivers/reset/reset-brcmstb-rescal.c | 101 +++++++++++++++++++++++++++
|
||||
3 files changed, 108 insertions(+)
|
||||
create mode 100644 drivers/reset/reset-brcmstb-rescal.c
|
||||
|
||||
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
|
||||
index 10a364b2a8..fd1eb05a41 100644
|
||||
--- a/drivers/reset/Kconfig
|
||||
+++ b/drivers/reset/Kconfig
|
||||
@@ -69,6 +69,12 @@ config RESET_BRCMSTB
|
||||
This enables the reset controller driver for Broadcom STB SoCs using
|
||||
a SUN_TOP_CTRL_SW_INIT style controller.
|
||||
|
||||
+config RESET_BRCMSTB_RESCAL
|
||||
+ bool "Broadcom STB RESCAL reset controller"
|
||||
+ help
|
||||
+ This enables the RESCAL reset controller found on BCM2712 and some other
|
||||
+ Broadcom STB SoCs (BCM7216).
|
||||
+
|
||||
config RESET_UNIPHIER
|
||||
bool "Reset controller driver for UniPhier SoCs"
|
||||
depends on ARCH_UNIPHIER
|
||||
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
|
||||
index d7e9ac1a88..45cf2f1b4d 100644
|
||||
--- a/drivers/reset/Makefile
|
||||
+++ b/drivers/reset/Makefile
|
||||
@@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
|
||||
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
|
||||
obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
|
||||
obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
|
||||
+obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
|
||||
obj-$(CONFIG_RESET_AST2500) += reset-ast2500.o
|
||||
obj-$(CONFIG_RESET_AST2600) += reset-ast2600.o
|
||||
diff --git a/drivers/reset/reset-brcmstb-rescal.c b/drivers/reset/reset-brcmstb-rescal.c
|
||||
new file mode 100644
|
||||
index 0000000000..37096bb9ff
|
||||
--- /dev/null
|
||||
+++ b/drivers/reset/reset-brcmstb-rescal.c
|
||||
@@ -0,0 +1,101 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Broadcom RESCAL reset controller, based on upstream Linux driver:
|
||||
+ * drivers/reset/reset-brcmstb-rescal.c
|
||||
+ *
|
||||
+ * Copyright (C) 2018-2020 Broadcom
|
||||
+ */
|
||||
+
|
||||
+#include <dm.h>
|
||||
+#include <errno.h>
|
||||
+#include <malloc.h>
|
||||
+#include <reset-uclass.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+
|
||||
+#define BRCM_RESCAL_START 0x0
|
||||
+#define BRCM_RESCAL_START_BIT BIT(0)
|
||||
+#define BRCM_RESCAL_CTRL 0x4
|
||||
+#define BRCM_RESCAL_STATUS 0x8
|
||||
+#define BRCM_RESCAL_STATUS_BIT BIT(0)
|
||||
+
|
||||
+struct brcm_rescal_reset_priv {
|
||||
+ void __iomem *base;
|
||||
+};
|
||||
+
|
||||
+static int brcm_rescal_reset_assert(struct reset_ctl *rst)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int brcm_rescal_reset_deassert(struct reset_ctl *rst)
|
||||
+{
|
||||
+ struct brcm_rescal_reset_priv *priv = dev_get_priv(rst->dev);
|
||||
+ u32 reg;
|
||||
+ int ret;
|
||||
+
|
||||
+ reg = readl(priv->base + BRCM_RESCAL_START);
|
||||
+ writel(reg | BRCM_RESCAL_START_BIT, priv->base + BRCM_RESCAL_START);
|
||||
+ reg = readl(priv->base + BRCM_RESCAL_START);
|
||||
+ if (!(reg & BRCM_RESCAL_START_BIT)) {
|
||||
+ printf("failed to start SATA/PCIe rescal\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ ret = read_poll_timeout(readl, reg, (reg & BRCM_RESCAL_STATUS_BIT),
|
||||
+ 100, 1000, priv->base + BRCM_RESCAL_STATUS);
|
||||
+ if (ret) {
|
||||
+ printf("time out on SATA/PCIe rescal\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ reg = readl(priv->base + BRCM_RESCAL_START);
|
||||
+ writel(reg & ~BRCM_RESCAL_START_BIT, priv->base + BRCM_RESCAL_START);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int brcm_rescal_reset_of_xlate(struct reset_ctl *reset_ctl,
|
||||
+ struct ofnode_phandle_args *args)
|
||||
+{
|
||||
+ /* Rescal takes no parameters. */
|
||||
+ if (args->args_count != 0) {
|
||||
+ printf("Invalid args_count: %d\n", args->args_count);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+struct reset_ops brcm_rescal_reset_reset_ops = {
|
||||
+ .rst_assert = brcm_rescal_reset_assert,
|
||||
+ .rst_deassert = brcm_rescal_reset_deassert,
|
||||
+ .of_xlate = brcm_rescal_reset_of_xlate,
|
||||
+};
|
||||
+
|
||||
+static const struct udevice_id brcm_rescal_reset_ids[] = {
|
||||
+ { .compatible = "brcm,bcm7216-pcie-sata-rescal" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
+static int brcm_rescal_reset_probe(struct udevice *dev)
|
||||
+{
|
||||
+ struct brcm_rescal_reset_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ priv->base = dev_remap_addr(dev);
|
||||
+ if (!priv->base)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+U_BOOT_DRIVER(brcmstb_rescal_reset) = {
|
||||
+ .name = "brcm-rescal-reset",
|
||||
+ .id = UCLASS_RESET,
|
||||
+ .of_match = brcm_rescal_reset_ids,
|
||||
+ .ops = &brcm_rescal_reset_reset_ops,
|
||||
+ .probe = brcm_rescal_reset_probe,
|
||||
+ .priv_auto = sizeof(struct brcm_rescal_reset_priv),
|
||||
+};
|
@ -0,0 +1,386 @@
|
||||
From 6e16ad9e01d746f78f8a2391dec9aae3f39a96e5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <sairon@sairon.cz>
|
||||
Date: Mon, 30 Sep 2024 18:13:09 +0200
|
||||
Subject: [PATCH] pci: pcie-brcmstb: Add basic support for BCM2712 PCIe
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add support for BCM2712 (Raspberry Pi 5) by adapting the Raspberry Pi's
|
||||
dowstream kernel driver. Apart from resets handled by dedicated reset
|
||||
controllers, there are couple of hacks that were needed to be ported
|
||||
over from the reference implementation, most notably the function
|
||||
adjusting the controller's reference clock and the BAR2 config address
|
||||
remapping. None of these seem to be present in the upstream kernel
|
||||
driver so eventually it'd be worthwile to check what does
|
||||
U-Boot/downstream do differently that it's not needed in upstream (and
|
||||
check that upstream really works with BCM2712 - it's still not merged
|
||||
yet [1]).
|
||||
|
||||
Methods for handling the resets and address of the relocated hard debug
|
||||
register are defined in new driver data structures that are implemented
|
||||
in a similar fashion as in upstream/downstream Linux drivers.
|
||||
|
||||
[1] https://lore.kernel.org/lkml/20240910151845.17308-1-svarbanov@suse.de/
|
||||
|
||||
Signed-off-by: Jan Čermák <sairon@sairon.cz>
|
||||
---
|
||||
arch/arm/mach-bcm283x/init.c | 10 +-
|
||||
drivers/pci/pcie_brcmstb.c | 191 +++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 189 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c
|
||||
index 1b459707bc..2d34d67075 100644
|
||||
--- a/arch/arm/mach-bcm283x/init.c
|
||||
+++ b/arch/arm/mach-bcm283x/init.c
|
||||
@@ -18,7 +18,7 @@
|
||||
#ifdef CONFIG_ARM64
|
||||
#include <asm/armv8/mmu.h>
|
||||
|
||||
-#define MEM_MAP_MAX_ENTRIES (4)
|
||||
+#define MEM_MAP_MAX_ENTRIES (5)
|
||||
|
||||
static struct mm_region bcm283x_mem_map[MEM_MAP_MAX_ENTRIES] = {
|
||||
{
|
||||
@@ -83,6 +83,14 @@ static struct mm_region bcm2712_mem_map[MEM_MAP_MAX_ENTRIES] = {
|
||||
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
PTE_BLOCK_NON_SHARE |
|
||||
PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
+ }, {
|
||||
+ /* PCIe1 memory region */
|
||||
+ .virt = 0x1B80000000UL,
|
||||
+ .phys = 0x1B80000000UL,
|
||||
+ .size = 0x0000400000UL,
|
||||
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
|
||||
+ PTE_BLOCK_NON_SHARE |
|
||||
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
|
||||
}, {
|
||||
/* SoC bus */
|
||||
.virt = 0x107c000000UL,
|
||||
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
|
||||
index f978c64365..df3e177629 100644
|
||||
--- a/drivers/pci/pcie_brcmstb.c
|
||||
+++ b/drivers/pci/pcie_brcmstb.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <dm.h>
|
||||
#include <dm/ofnode.h>
|
||||
#include <pci.h>
|
||||
+#include <reset.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/log2.h>
|
||||
@@ -39,6 +40,10 @@
|
||||
#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
|
||||
#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
|
||||
|
||||
+#define PCIE_RC_PL_PHY_CTL_15 0x184c
|
||||
+#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000
|
||||
+#define PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK 0xff
|
||||
+
|
||||
#define PCIE_MISC_MISC_CTRL 0x4008
|
||||
#define MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
|
||||
#define MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
|
||||
@@ -64,6 +69,10 @@
|
||||
#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
|
||||
#define RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
|
||||
|
||||
+#define PCIE_MISC_PCIE_CTRL 0x4064
|
||||
+#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
|
||||
+#define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4
|
||||
+
|
||||
#define PCIE_MISC_PCIE_STATUS 0x4068
|
||||
#define STATUS_PCIE_PORT_MASK 0x80
|
||||
#define STATUS_PCIE_PORT_SHIFT 7
|
||||
@@ -89,9 +98,11 @@
|
||||
#define PCIE_MEM_WIN0_LIMIT_HI(win) \
|
||||
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
|
||||
|
||||
-#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
|
||||
#define PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
|
||||
|
||||
+#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP 0x40b4
|
||||
+#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0)
|
||||
+
|
||||
#define PCIE_MSI_INTR2_CLR 0x4508
|
||||
#define PCIE_MSI_INTR2_MASK_SET 0x4510
|
||||
|
||||
@@ -130,6 +141,26 @@
|
||||
#define SSC_STATUS_PLL_LOCK_MASK 0x800
|
||||
#define SSC_STATUS_PLL_LOCK_SHIFT 11
|
||||
|
||||
+#define HARD_DEBUG(pcie) ((pcie)->reg_offsets[PCIE_HARD_DEBUG])
|
||||
+
|
||||
+struct brcm_pcie;
|
||||
+
|
||||
+enum {
|
||||
+ PCIE_HARD_DEBUG,
|
||||
+};
|
||||
+
|
||||
+enum pcie_soc_base {
|
||||
+ BCM2711,
|
||||
+ BCM2712,
|
||||
+};
|
||||
+
|
||||
+struct pcie_cfg_data {
|
||||
+ const int *offsets;
|
||||
+ const enum pcie_soc_base soc_base;
|
||||
+ int (*perst_set)(struct brcm_pcie *pcie, u32 val);
|
||||
+ int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct brcm_pcie - the PCIe controller state
|
||||
* @base: Base address of memory mapped IO registers of the controller
|
||||
@@ -140,8 +171,15 @@
|
||||
struct brcm_pcie {
|
||||
void __iomem *base;
|
||||
|
||||
+ const int *reg_offsets;
|
||||
+ enum pcie_soc_base soc_base;
|
||||
int gen;
|
||||
bool ssc;
|
||||
+
|
||||
+ struct reset_ctl *rescal;
|
||||
+ struct reset_ctl *bridge_reset;
|
||||
+ int (*perst_set)(struct brcm_pcie *pcie, u32 val);
|
||||
+ int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -367,6 +405,27 @@ static int brcm_pcie_set_ssc(void __iomem *base)
|
||||
return ssc && pll ? 0 : -EIO;
|
||||
}
|
||||
|
||||
+static void brcm_pcie_munge_pll(struct brcm_pcie *pcie)
|
||||
+{
|
||||
+ /* Upstream Linux doesn't touch these so maybe there's other way */
|
||||
+
|
||||
+ u32 tmp;
|
||||
+ int i;
|
||||
+ u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e };
|
||||
+ u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 };
|
||||
+
|
||||
+ brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET,
|
||||
+ 0x1600);
|
||||
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
+ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp);
|
||||
+ }
|
||||
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
+ brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]);
|
||||
+ brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp);
|
||||
+ }
|
||||
+ udelay(200);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* brcm_pcie_set_gen() - Limits operation to a specific generation (1, 2 or 3)
|
||||
* @pcie: pointer to the PCIe controller state
|
||||
@@ -426,6 +485,52 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
|
||||
writel(tmp, base + PCIE_MEM_WIN0_LIMIT_HI(win));
|
||||
}
|
||||
|
||||
+static int brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val)
|
||||
+{
|
||||
+ if (val)
|
||||
+ setbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
|
||||
+ else
|
||||
+ clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int brcm_pcie_bridge_sw_init_set_generic(struct brcm_pcie *pcie, u32 val)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (pcie->bridge_reset) {
|
||||
+ if (val)
|
||||
+ ret = reset_assert(pcie->bridge_reset);
|
||||
+ else
|
||||
+ ret = reset_deassert(pcie->bridge_reset);
|
||||
+
|
||||
+ if (ret)
|
||||
+ printf("PCIe BRCM: failed to %s bridge reset: err=%d\n",
|
||||
+ val ? "assert" : "deassert", ret);
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (val)
|
||||
+ setbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
|
||||
+ else
|
||||
+ clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val)
|
||||
+{
|
||||
+ /* Perst bit has moved and assert value is 0 */
|
||||
+ if (val)
|
||||
+ clrbits_le32(pcie->base + PCIE_MISC_PCIE_CTRL, PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK);
|
||||
+ else
|
||||
+ setbits_le32(pcie->base + PCIE_MISC_PCIE_CTRL, PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int brcm_pcie_probe(struct udevice *dev)
|
||||
{
|
||||
struct udevice *ctlr = pci_get_controller(dev);
|
||||
@@ -441,13 +546,17 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
u16 nlw, cls, lnksta;
|
||||
u32 tmp;
|
||||
|
||||
+ if (pcie->rescal)
|
||||
+ reset_deassert(pcie->rescal);
|
||||
+
|
||||
/*
|
||||
* Reset the bridge, assert the fundamental reset. Note for some SoCs,
|
||||
* e.g. BCM7278, the fundamental reset should not be asserted here.
|
||||
* This will need to be changed when support for other SoCs is added.
|
||||
*/
|
||||
- setbits_le32(base + PCIE_RGR1_SW_INIT_1,
|
||||
- RGR1_SW_INIT_1_INIT_MASK | RGR1_SW_INIT_1_PERST_MASK);
|
||||
+ pcie->perst_set(pcie, 1);
|
||||
+ pcie->bridge_sw_init_set(pcie, 1);
|
||||
+
|
||||
/*
|
||||
* The delay is a safety precaution to preclude the reset signal
|
||||
* from looking like a glitch.
|
||||
@@ -455,14 +564,26 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
udelay(100);
|
||||
|
||||
/* Take the bridge out of reset */
|
||||
- clrbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
|
||||
+ pcie->bridge_sw_init_set(pcie, 0);
|
||||
|
||||
- clrbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
|
||||
+ clrbits_le32(base + HARD_DEBUG(pcie),
|
||||
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
|
||||
|
||||
/* Wait for SerDes to be stable */
|
||||
udelay(100);
|
||||
|
||||
+ if (pcie->soc_base == BCM2712) {
|
||||
+ /* Hack from RPi downstream, unable to probe without it */
|
||||
+ /* Allow a 54MHz (xosc) refclk source */
|
||||
+ brcm_pcie_munge_pll(pcie);
|
||||
+ /* Fix for L1SS errata */
|
||||
+ tmp = readl(base + PCIE_RC_PL_PHY_CTL_15);
|
||||
+ tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK;
|
||||
+ /* PM clock period is 18.52ns (round down) */
|
||||
+ tmp |= 0x12;
|
||||
+ writel(tmp, base + PCIE_RC_PL_PHY_CTL_15);
|
||||
+ }
|
||||
+
|
||||
/* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
|
||||
clrsetbits_le32(base + PCIE_MISC_MISC_CTRL,
|
||||
MISC_CTRL_MAX_BURST_SIZE_MASK,
|
||||
@@ -481,6 +602,13 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
writel(upper_32_bits(rc_bar2_offset),
|
||||
base + PCIE_MISC_RC_BAR2_CONFIG_HI);
|
||||
|
||||
+ if (pcie->soc_base == BCM2712) {
|
||||
+ /* RPi downstream kernel does do this also for 2711 - is it okay? */
|
||||
+ tmp = readl(base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP);
|
||||
+ u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK);
|
||||
+ writel(tmp, base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP);
|
||||
+ }
|
||||
+
|
||||
scb_size_val = rc_bar2_size ?
|
||||
ilog2(rc_bar2_size) - 15 : 0xf; /* 0xf is 1GB */
|
||||
|
||||
@@ -507,8 +635,7 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
brcm_pcie_set_gen(pcie, pcie->gen);
|
||||
|
||||
/* Unassert the fundamental reset */
|
||||
- clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1,
|
||||
- RGR1_SW_INIT_1_PERST_MASK);
|
||||
+ pcie->perst_set(pcie, 0);
|
||||
|
||||
/*
|
||||
* Wait for 100ms after PERST# deassertion; see PCIe CEM specification
|
||||
@@ -595,20 +722,23 @@ static int brcm_pcie_remove(struct udevice *dev)
|
||||
void __iomem *base = pcie->base;
|
||||
|
||||
/* Assert fundamental reset */
|
||||
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_PERST_MASK);
|
||||
+ pcie->perst_set(pcie, 1);
|
||||
|
||||
/* Turn off SerDes */
|
||||
- setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
|
||||
+ setbits_le32(base + HARD_DEBUG(pcie),
|
||||
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
|
||||
|
||||
/* Shutdown bridge */
|
||||
- setbits_le32(base + PCIE_RGR1_SW_INIT_1, RGR1_SW_INIT_1_INIT_MASK);
|
||||
+ /* On BCM2712 it will block access to the RESCAL, so don't do it. */
|
||||
+ if (pcie->soc_base != BCM2712)
|
||||
+ pcie->bridge_sw_init_set(pcie, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brcm_pcie_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
+ const struct pcie_cfg_data *data;
|
||||
struct brcm_pcie *pcie = dev_get_priv(dev);
|
||||
ofnode dn = dev_ofnode(dev);
|
||||
u32 max_link_speed;
|
||||
@@ -619,6 +749,22 @@ static int brcm_pcie_of_to_plat(struct udevice *dev)
|
||||
if (!pcie->base)
|
||||
return -EINVAL;
|
||||
|
||||
+ data = (struct pcie_cfg_data *)dev_get_driver_data(dev);
|
||||
+
|
||||
+ pcie->soc_base = data->soc_base;
|
||||
+ pcie->reg_offsets = data->offsets;
|
||||
+ pcie->perst_set = data->perst_set;
|
||||
+ pcie->bridge_sw_init_set = data->bridge_sw_init_set;
|
||||
+
|
||||
+ pcie->rescal = devm_reset_control_get_optional(dev, "rescal");
|
||||
+ if (IS_ERR(pcie->rescal)) {
|
||||
+ return PTR_ERR(pcie->rescal);
|
||||
+ }
|
||||
+ pcie->bridge_reset = devm_reset_control_get_optional(dev, "bridge");
|
||||
+ if (IS_ERR(pcie->bridge_reset)) {
|
||||
+ return PTR_ERR(pcie->bridge_reset);
|
||||
+ }
|
||||
+
|
||||
pcie->ssc = ofnode_read_bool(dn, "brcm,enable-ssc");
|
||||
|
||||
ret = ofnode_read_u32(dn, "max-link-speed", &max_link_speed);
|
||||
@@ -635,8 +781,31 @@ static const struct dm_pci_ops brcm_pcie_ops = {
|
||||
.write_config = brcm_pcie_write_config,
|
||||
};
|
||||
|
||||
+static const int pcie_offsets[] = {
|
||||
+ [PCIE_HARD_DEBUG] = 0x4204,
|
||||
+};
|
||||
+
|
||||
+static const int pcie_offsets_bcm2712[] = {
|
||||
+ [PCIE_HARD_DEBUG] = 0x4304,
|
||||
+};
|
||||
+
|
||||
+static const struct pcie_cfg_data bcm2711_cfg = {
|
||||
+ .offsets = pcie_offsets,
|
||||
+ .soc_base = BCM2711,
|
||||
+ .perst_set = brcm_pcie_perst_set_generic,
|
||||
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
|
||||
+};
|
||||
+
|
||||
+static const struct pcie_cfg_data bcm2712_cfg = {
|
||||
+ .offsets = pcie_offsets_bcm2712,
|
||||
+ .soc_base = BCM2712,
|
||||
+ .perst_set = brcm_pcie_perst_set_2712,
|
||||
+ .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
|
||||
+};
|
||||
+
|
||||
static const struct udevice_id brcm_pcie_ids[] = {
|
||||
- { .compatible = "brcm,bcm2711-pcie" },
|
||||
+ { .compatible = "brcm,bcm2711-pcie", .data = (ulong)&bcm2711_cfg },
|
||||
+ { .compatible = "brcm,bcm2712-pcie", .data = (ulong)&bcm2712_cfg },
|
||||
{ }
|
||||
};
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 61693f4e8db08d263c6036afeecd6d30e7b23660 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <sairon@sairon.cz>
|
||||
Date: Thu, 3 Oct 2024 11:09:53 +0200
|
||||
Subject: [PATCH] ARM: bcm2835: add BCM2712 config option
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add config option for RPi 5's BCM2712, which can only run in 64bit mode.
|
||||
Also tie the PCIe controller's option to the required reset controllers
|
||||
if PCI_BRCMSTB is enabled along the BCM2712 option.
|
||||
|
||||
Signed-off-by: Jan Čermák <sairon@sairon.cz>
|
||||
---
|
||||
arch/arm/mach-bcm283x/Kconfig | 5 +++++
|
||||
drivers/pci/Kconfig | 2 ++
|
||||
2 files changed, 7 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig
|
||||
index b3287ce8bc..3b8672cfe0 100644
|
||||
--- a/arch/arm/mach-bcm283x/Kconfig
|
||||
+++ b/arch/arm/mach-bcm283x/Kconfig
|
||||
@@ -44,6 +44,11 @@ config BCM2711_64B
|
||||
select BCM2711
|
||||
select ARM64
|
||||
|
||||
+config BCM2712
|
||||
+ bool "Broadcom BCM2712 SoC support (64-bit only)"
|
||||
+ depends on ARCH_BCM283X
|
||||
+ select ARM64
|
||||
+
|
||||
menu "Broadcom BCM283X family"
|
||||
depends on ARCH_BCM283X
|
||||
|
||||
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
|
||||
index 22a56f4ca3..6badc60d13 100644
|
||||
--- a/drivers/pci/Kconfig
|
||||
+++ b/drivers/pci/Kconfig
|
||||
@@ -386,6 +386,8 @@ config PCIE_DW_ROCKCHIP
|
||||
config PCI_BRCMSTB
|
||||
bool "Broadcom STB PCIe controller"
|
||||
depends on ARCH_BCM283X
|
||||
+ select RESET_BRCMSTB if BCM2712
|
||||
+ select RESET_BRCMSTB_RESCAL if BCM2712
|
||||
help
|
||||
Say Y here if you want to enable support for PCIe controller
|
||||
on Broadcom set-top-box (STB) SoCs.
|
@ -0,0 +1,54 @@
|
||||
From d613be9ca405b2e65ac03b137cf6351b1aae7154 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <sairon@sairon.cz>
|
||||
Date: Mon, 7 Oct 2024 15:13:40 +0200
|
||||
Subject: [PATCH] pci: pcie-brcmstb: HACK - add DT property for skipping device
|
||||
probe
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It appears that when pcie2 on RPi 5 is probed by U-Boot, the controller
|
||||
is not initialized properly and initialization of the RP1 fails when
|
||||
Linux is loaded. Add u-boot,no-probe boolean parameter that can be added
|
||||
to the node that doesn't need to be probed in U-Boot now. This would
|
||||
need to be sorted out when we actually need to control RP1 from U-Boot
|
||||
but since we only need pcie1 for NVMe now, we can ignore the other
|
||||
device.
|
||||
|
||||
Signed-off-by: Jan Čermák <sairon@sairon.cz>
|
||||
---
|
||||
drivers/pci/pcie_brcmstb.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
|
||||
index df3e177629..02d9e7a1b3 100644
|
||||
--- a/drivers/pci/pcie_brcmstb.c
|
||||
+++ b/drivers/pci/pcie_brcmstb.c
|
||||
@@ -175,6 +175,7 @@ struct brcm_pcie {
|
||||
enum pcie_soc_base soc_base;
|
||||
int gen;
|
||||
bool ssc;
|
||||
+ bool no_probe;
|
||||
|
||||
struct reset_ctl *rescal;
|
||||
struct reset_ctl *bridge_reset;
|
||||
@@ -546,6 +547,11 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
u16 nlw, cls, lnksta;
|
||||
u32 tmp;
|
||||
|
||||
+ if (pcie->no_probe) {
|
||||
+ printf("PCIe BRCM: skipping probe\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if (pcie->rescal)
|
||||
reset_deassert(pcie->rescal);
|
||||
|
||||
@@ -766,6 +772,7 @@ static int brcm_pcie_of_to_plat(struct udevice *dev)
|
||||
}
|
||||
|
||||
pcie->ssc = ofnode_read_bool(dn, "brcm,enable-ssc");
|
||||
+ pcie->no_probe = ofnode_read_bool(dn, "u-boot,no-probe");
|
||||
|
||||
ret = ofnode_read_u32(dn, "max-link-speed", &max_link_speed);
|
||||
if (ret < 0 || max_link_speed > 4)
|
@ -28,6 +28,10 @@ gpu_mem=32
|
||||
|
||||
# Additional overlays and parameters are documented /boot/overlays/README
|
||||
|
||||
[all]
|
||||
[cm4]
|
||||
device_tree=bcm2711-rpi-cm4-ha-yellow.dtb
|
||||
|
||||
[cm5]
|
||||
device_tree=bcm2712-rpi-cm5-ha-yellow.dtb
|
||||
|
||||
[all]
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,22 @@
|
||||
CONFIG_TARGET_RPI_4=y
|
||||
CONFIG_BCM2712=y
|
||||
|
||||
CONFIG_MMC_SDHCI_BCMSTB=y
|
||||
|
||||
CONFIG_DM_USB_GADGET=y
|
||||
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_MANUFACTURER="FSL"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0525
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
|
||||
CONFIG_USB_GADGET_DWC2_OTG=y
|
||||
CONFIG_USB_GADGET_DOWNLOAD=y
|
||||
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_CMD_LED=y
|
||||
|
||||
# CONFIG_EFI_LOADER is not set
|
||||
# CONFIG_TOOLS_MKEFICAPSULE is not set
|
||||
|
@ -22,7 +22,7 @@ BR2_LINUX_KERNEL_DEFCONFIG="bcm2711"
|
||||
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/hassos.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/docker.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/device-support.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/device-support-pci.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/device-support-wireless.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/kernel.config"
|
||||
BR2_LINUX_KERNEL_LZ4=y
|
||||
BR2_LINUX_KERNEL_DTS_SUPPORT=y
|
||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="broadcom/bcm2711-rpi-cm4-ha-yellow"
|
||||
BR2_LINUX_KERNEL_INTREE_DTS_NAME="broadcom/bcm2711-rpi-cm4-ha-yellow broadcom/bcm2712-rpi-cm5-ha-yellow"
|
||||
BR2_LINUX_KERNEL_DTB_OVERLAY_SUPPORT=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
|
||||
@ -143,8 +143,8 @@ BR2_TARGET_ROOTFS_EROFS_PCLUSTERSIZE=262144
|
||||
BR2_TARGET_UBOOT=y
|
||||
BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y
|
||||
BR2_TARGET_UBOOT_CUSTOM_VERSION=y
|
||||
BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2024.01"
|
||||
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="rpi_4"
|
||||
BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2024.10"
|
||||
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="rpi_arm64"
|
||||
BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/bootloader/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/uboot.config $(BR2_EXTERNAL_HASSOS_PATH)/board/raspberrypi/yellow/uboot.config"
|
||||
BR2_PACKAGE_HOST_DOSFSTOOLS=y
|
||||
BR2_PACKAGE_HOST_E2FSPROGS=y
|
||||
|
@ -88,6 +88,25 @@ check_grubenv() {
|
||||
fi
|
||||
}
|
||||
|
||||
post_install_boot() {
|
||||
BOOT_MNT=/mnt/boot
|
||||
|
||||
# Add CM5 support for Yellow. Can be removed in HAOS 15.
|
||||
if [ "$RAUC_SYSTEM_COMPATIBLE" = "haos-yellow" ]; then
|
||||
# Mount boot
|
||||
if ! systemctl -q is-active mnt-boot.mount; then
|
||||
systemctl start mnt-boot.mount
|
||||
fi
|
||||
|
||||
if ! grep -q "\[cm5\]" "${BOOT_MNT}/config.txt"; then
|
||||
echo "Adding CM5 config to config.txt"
|
||||
|
||||
# Remove old single device_tree config and add CM-specific ones
|
||||
sed -i '/device_tree=bcm2711-rpi-cm4-ha-yellow.dtb/d; s/\[all\]/\[cm4\]\ndevice_tree=bcm2711-rpi-cm4-ha-yellow.dtb\n\n\[cm5\]\ndevice_tree=bcm2712-rpi-cm5-ha-yellow.dtb\n\n\[all\]/' "${BOOT_MNT}/config.txt"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
post_install_kernel() {
|
||||
BOOT_MNT=/mnt/boot
|
||||
|
||||
@ -125,6 +144,9 @@ case "$1" in
|
||||
fi
|
||||
;;
|
||||
slot-post-install)
|
||||
if [ "${RAUC_SLOT_CLASS}" = "boot" ]; then
|
||||
post_install_boot
|
||||
fi
|
||||
if [ "${RAUC_SLOT_CLASS}" = "kernel" ]; then
|
||||
post_install_kernel
|
||||
fi
|
||||
|
@ -1,4 +1,4 @@
|
||||
From d44635df07c79c6e6e6832a5c59d27d27aacfa75 Mon Sep 17 00:00:00 2001
|
||||
From 01d614198feedef81ce60e61bbdf5f1ddc62be52 Mon Sep 17 00:00:00 2001
|
||||
From: Pascal Vizeli <pvizeli@syshack.ch>
|
||||
Date: Sun, 5 Aug 2018 20:43:03 +0000
|
||||
Subject: [PATCH] CMD: read string from fileinto env
|
||||
@ -7,8 +7,8 @@ Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
|
||||
---
|
||||
cmd/Kconfig | 5 +++++
|
||||
cmd/Makefile | 1 +
|
||||
cmd/fileenv.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 52 insertions(+)
|
||||
cmd/fileenv.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 51 insertions(+)
|
||||
create mode 100644 cmd/fileenv.c
|
||||
|
||||
diff --git a/cmd/Kconfig b/cmd/Kconfig
|
||||
@ -41,12 +41,11 @@ index 9a6790cc17..a521653ff8 100644
|
||||
obj-$(CONFIG_CMD_SMC) += smccc.o
|
||||
diff --git a/cmd/fileenv.c b/cmd/fileenv.c
|
||||
new file mode 100644
|
||||
index 0000000000..9891cb05ab
|
||||
index 0000000000..4154c8df0f
|
||||
--- /dev/null
|
||||
+++ b/cmd/fileenv.c
|
||||
@@ -0,0 +1,46 @@
|
||||
@@ -0,0 +1,45 @@
|
||||
+#include <config.h>
|
||||
+#include <common.h>
|
||||
+#include <command.h>
|
||||
+#include <fs.h>
|
||||
+#include <linux/ctype.h>
|
||||
@ -91,6 +90,3 @@ index 0000000000..9891cb05ab
|
||||
+ "<interface> <dev:part> <addr> <filename> <envname>\n"
|
||||
+ " - Read file from fat32 and store it as env."
|
||||
+);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user