mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/16] PCI: support non 1:1 mappings
@ 2024-03-26 10:07 Sascha Hauer
  2024-03-26 10:07 ` [PATCH 01/16] net: phy: realtek: add phy for RTL8168 internal phy Sascha Hauer
                   ` (16 more replies)
  0 siblings, 17 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

This series evolved from getting PCIe to work on a RK3568 based board.
The device tree PCIe ranges property uses non 1:1 mappings between CPU
and PCI bus which this series adds support for. With this series we
parse the ranges property into struct resource_entry windows like done
in Linux. With this we get pcibios_resource_to_bus() and
pcibios_bus_to_resource() to translate between the PCI/CPU address
spaces. Additionally we have some cleanup for the pcie-designware driver
and we can remove the quirk we already introduced for the rk3588 Rock5b
board in which we have overwritten the ranges property.

Sascha Hauer (16):
  net: phy: realtek: add phy for RTL8168 internal phy
  pci: add 'self' member to struct pci_bus
  pci: rename parent_bus to parent
  add support for resource lists
  pci: pcie-designware: remove unused variable
  pci: dwc: Drop support for config space in 'ranges'
  pci: add pci_controller_init()
  pci: support non 1:1 mappings
  pci: pcie-designware: Speed up waiting for link
  pci: pcie-dw-rockchip: wait for link
  pci: drop resources from struct pci_bus
  pci: add of_pci_bridge_init()
  pci: pcie-designware: drop duplicate resource assigning
  pci: pcie-designware: remove dra7xx quirks
  pci: pcie-designware: iterate over windows
  ARM: dts: rk3588-rock-5b: remove pci ranges quirks

 arch/arm/dts/rk3588-rock-5b.dts    |  15 -----
 arch/mips/mach-malta/pci.c         |   2 +
 common/resource.c                  |  16 +++++
 drivers/net/phy/realtek.c          |   7 ++
 drivers/pci/Makefile               |   3 +-
 drivers/pci/bus.c                  |  23 +++++++
 drivers/pci/host-bridge.c          |  76 +++++++++++++++++++++
 drivers/pci/of.c                   | 102 +++++++++++++++++++++++++++++
 drivers/pci/pci-ecam-generic.c     |   2 +
 drivers/pci/pci-efi.c              |   4 +-
 drivers/pci/pci-layerscape.c       |   2 +-
 drivers/pci/pci-mvebu.c            |   3 +
 drivers/pci/pci-tegra.c            |   4 +-
 drivers/pci/pci.c                  |  67 +++++++++++--------
 drivers/pci/pcie-designware-host.c |  95 ++++++++-------------------
 drivers/pci/pcie-designware.c      |   8 ++-
 drivers/pci/pcie-designware.h      |   9 ---
 drivers/pci/pcie-dw-rockchip.c     |   2 +
 include/linux/pci.h                |  37 ++++++++++-
 include/linux/resource_ext.h       |  81 +++++++++++++++++++++++
 20 files changed, 426 insertions(+), 132 deletions(-)
 create mode 100644 drivers/pci/host-bridge.c
 create mode 100644 drivers/pci/of.c
 create mode 100644 include/linux/resource_ext.h

-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/16] net: phy: realtek: add phy for RTL8168 internal phy
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 02/16] pci: add 'self' member to struct pci_bus Sascha Hauer
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

The integrated PHY's of later RTL8168 network chips report the generic
PHYID 0x001cc800 (Realtek OUI, model and revision number both set to
zero) and therefore currently the genphy driver is used.

To be able to use the paged version of e.g. phy_write() we need a
PHY driver with the read_page and write_page callbacks implemented.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/net/phy/realtek.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index c23947b7cb..8ab3d63091 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -189,6 +189,13 @@ static struct phy_driver realtek_drvs[] = {
 		.config_init	= &rtl8211f_config_init,
 		.read_page	= rtl821x_read_page,
 		.write_page	= rtl821x_write_page,
+	}, {
+		PHY_ID_MATCH_EXACT(0x001cc800),
+		.drv.name	= "Generic FE-GE Realtek PHY",
+		.features	= PHY_GBIT_FEATURES,
+		.config_init	= &rtl8211f_config_init,
+		.read_page	= rtl821x_read_page,
+		.write_page	= rtl821x_write_page,
 	}, {
 		PHY_ID_MATCH_EXACT(0x001cc961),
 		.drv.name	= "RTL8366RB Gigabit Ethernet",
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 02/16] pci: add 'self' member to struct pci_bus
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
  2024-03-26 10:07 ` [PATCH 01/16] net: phy: realtek: add phy for RTL8168 internal phy Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 03/16] pci: rename parent_bus to parent Sascha Hauer
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

In Linux struct pci_bus has a 'parent' member which is a pointer to the
parent pci_bus. In barebox we also have a 'parent' member, but it is
of type struct device *. To be closer to Linux remove the parent member
and replace its usage with a struct pci_dev *self member (which also
exists in Linux).

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pci.c   | 10 ++++++----
 include/linux/pci.h |  3 ++-
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 84678e40a9..8b96ac78df 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -48,7 +48,6 @@ void register_pci_controller(struct pci_controller *hose)
 
 	bus = pci_alloc_bus();
 	hose->bus = bus;
-	bus->parent = hose->parent;
 	bus->host = hose;
 	bus->resource[PCI_BUS_RESOURCE_MEM] = hose->mem_resource;
 	bus->resource[PCI_BUS_RESOURCE_MEM_PREF] = hose->mem_pref_resource;
@@ -599,6 +598,8 @@ static unsigned int pci_scan_bus(struct pci_bus *bus)
 	max = bus->secondary;
 
 	for (devfn = 0; devfn < 0xff; ++devfn) {
+		struct device *parent;
+
 		if (PCI_FUNC(devfn) && !is_multi) {
 			/* not a multi-function device */
 			continue;
@@ -618,8 +619,9 @@ static unsigned int pci_scan_bus(struct pci_bus *bus)
 		dev->devfn = devfn;
 		dev->vendor = l & 0xffff;
 		dev->device = (l >> 16) & 0xffff;
-		dev->dev.parent = bus->parent;
-		dev->dev.of_node = pci_of_match_device(bus->parent, devfn);
+		parent = bus->self ? &bus->self->dev : bus->host->parent;
+		dev->dev.parent = parent;
+		dev->dev.of_node = pci_of_match_device(parent, devfn);
 		if (dev->dev.of_node)
 			pr_debug("found DT node %pOF for device %04x:%04x\n",
 				 dev->dev.of_node,
@@ -668,7 +670,7 @@ static unsigned int pci_scan_bus(struct pci_bus *bus)
 			child_bus->resource[PCI_BUS_RESOURCE_IO] =
 				bus->resource[PCI_BUS_RESOURCE_IO];
 
-			child_bus->parent = &dev->dev;
+			child_bus->self = dev;
 
 			if (pcibios_assign_all_busses()) {
 				child_bus->number = bus_index++;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index aa29ff5d17..c4ae53a235 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -139,9 +139,10 @@ enum {
 	PCI_BUS_RESOURCE_MEM_PREF = 2,
 	PCI_BUS_RESOURCE_BUSN = 3,
 };
+
 struct pci_bus {
 	struct pci_controller *host;	/* associated host controller */
-	struct device *parent;
+	struct pci_dev *self;
 	struct pci_bus *parent_bus;	/* parent bus */
 	struct list_head node;		/* node in list of buses */
 	struct list_head children;	/* list of child buses */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 03/16] pci: rename parent_bus to parent
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
  2024-03-26 10:07 ` [PATCH 01/16] net: phy: realtek: add phy for RTL8168 internal phy Sascha Hauer
  2024-03-26 10:07 ` [PATCH 02/16] pci: add 'self' member to struct pci_bus Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 04/16] add support for resource lists Sascha Hauer
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

In Linux struct pci_bus has a pointer to its parent bus named 'parent'.
Rename parent_bus to parent to be more conform with Linux.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pci-layerscape.c | 2 +-
 drivers/pci/pci.c            | 2 +-
 include/linux/pci.h          | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/pci-layerscape.c b/drivers/pci/pci-layerscape.c
index 12a0ec71a7..732232dec5 100644
--- a/drivers/pci/pci-layerscape.c
+++ b/drivers/pci/pci-layerscape.c
@@ -560,7 +560,7 @@ static void ls_pcie_fixup(struct pci_dev *pcidev)
 	p = pcidev->bus;
 	while (p) {
 		base_bus_num = p->number;
-		p = p->parent_bus;
+		p = p->parent;
 	}
 
 	devid = (pcidev->bus->number - base_bus_num) << 8 | pcidev->devfn;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8b96ac78df..15e8cd46bd 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -662,7 +662,7 @@ static unsigned int pci_scan_bus(struct pci_bus *bus)
 			child_bus = pci_alloc_bus();
 			/* inherit parent properties */
 			child_bus->host = bus->host;
-			child_bus->parent_bus = bus;
+			child_bus->parent = bus;
 			child_bus->resource[PCI_BUS_RESOURCE_MEM] =
 				bus->resource[PCI_BUS_RESOURCE_MEM];
 			child_bus->resource[PCI_BUS_RESOURCE_MEM_PREF] =
diff --git a/include/linux/pci.h b/include/linux/pci.h
index c4ae53a235..4d4ab818f8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -143,7 +143,7 @@ enum {
 struct pci_bus {
 	struct pci_controller *host;	/* associated host controller */
 	struct pci_dev *self;
-	struct pci_bus *parent_bus;	/* parent bus */
+	struct pci_bus *parent;		/* Parent bus this bridge is on */
 	struct list_head node;		/* node in list of buses */
 	struct list_head children;	/* list of child buses */
 	struct list_head devices;	/* list of devices on this bus */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 04/16] add support for resource lists
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (2 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 03/16] pci: rename parent_bus to parent Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 05/16] pci: pcie-designware: remove unused variable Sascha Hauer
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

Linux has support for resource_lists. These are for collecting resources
along with a translation offset on a list. Copy it over to barebox for
use in our pci support.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 common/resource.c            | 16 +++++++
 include/linux/resource_ext.h | 81 ++++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 include/linux/resource_ext.h

diff --git a/common/resource.c b/common/resource.c
index 8678609229..76f19de494 100644
--- a/common/resource.c
+++ b/common/resource.c
@@ -10,6 +10,7 @@
 #include <init.h>
 #include <linux/ioport.h>
 #include <linux/err.h>
+#include <linux/resource_ext.h>
 #include <asm/io.h>
 
 static int init_resource(struct resource *res, const char *name)
@@ -164,3 +165,18 @@ struct resource *request_ioport_region(const char *name,
 
 	return res;
 }
+
+struct resource_entry *resource_list_create_entry(struct resource *res,
+						  size_t extra_size)
+{
+	struct resource_entry *entry;
+
+	entry = kzalloc(sizeof(*entry) + extra_size, GFP_KERNEL);
+	if (entry) {
+		INIT_LIST_HEAD(&entry->node);
+		entry->res = res ? res : &entry->__res;
+	}
+
+	return entry;
+}
+EXPORT_SYMBOL(resource_list_create_entry);
diff --git a/include/linux/resource_ext.h b/include/linux/resource_ext.h
new file mode 100644
index 0000000000..ff0339df56
--- /dev/null
+++ b/include/linux/resource_ext.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2015, Intel Corporation
+ * Author: Jiang Liu <jiang.liu@linux.intel.com>
+ */
+#ifndef _LINUX_RESOURCE_EXT_H
+#define _LINUX_RESOURCE_EXT_H
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+/* Represent resource window for bridge devices */
+struct resource_win {
+	struct resource res;		/* In master (CPU) address space */
+	resource_size_t offset;		/* Translation offset for bridge */
+};
+
+/*
+ * Common resource list management data structure and interfaces to support
+ * ACPI, PNP and PCI host bridge etc.
+ */
+struct resource_entry {
+	struct list_head	node;
+	struct resource		*res;	/* In master (CPU) address space */
+	resource_size_t		offset;	/* Translation offset for bridge */
+	struct resource		__res;	/* Default storage for res */
+};
+
+extern struct resource_entry *
+resource_list_create_entry(struct resource *res, size_t extra_size);
+extern void resource_list_free(struct list_head *head);
+
+static inline void resource_list_add(struct resource_entry *entry,
+				     struct list_head *head)
+{
+	list_add(&entry->node, head);
+}
+
+static inline void resource_list_add_tail(struct resource_entry *entry,
+					  struct list_head *head)
+{
+	list_add_tail(&entry->node, head);
+}
+
+static inline void resource_list_del(struct resource_entry *entry)
+{
+	list_del(&entry->node);
+}
+
+static inline void resource_list_free_entry(struct resource_entry *entry)
+{
+	kfree(entry);
+}
+
+static inline void
+resource_list_destroy_entry(struct resource_entry *entry)
+{
+	resource_list_del(entry);
+	resource_list_free_entry(entry);
+}
+
+#define resource_list_for_each_entry(entry, list)	\
+	list_for_each_entry((entry), (list), node)
+
+#define resource_list_for_each_entry_safe(entry, tmp, list)	\
+	list_for_each_entry_safe((entry), (tmp), (list), node)
+
+static inline struct resource_entry *
+resource_list_first_type(struct list_head *list, unsigned long type)
+{
+	struct resource_entry *entry;
+
+	resource_list_for_each_entry(entry, list) {
+		if (resource_type(entry->res) == type)
+			return entry;
+	}
+	return NULL;
+}
+
+#endif /* _LINUX_RESOURCE_EXT_H */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 05/16] pci: pcie-designware: remove unused variable
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (3 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 04/16] add support for resource lists Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 06/16] pci: dwc: Drop support for config space in 'ranges' Sascha Hauer
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

struct pcie_port::mem_base is set but not used. Remove it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pcie-designware-host.c | 2 --
 drivers/pci/pcie-designware.h      | 1 -
 2 files changed, 3 deletions(-)

diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index b34fc482ed..bebdb5cbc7 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -152,8 +152,6 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 	if (!pci->dbi_base)
 		pci->dbi_base = IOMEM(pp->cfg.start);
 
-	pp->mem_base = pp->mem.start;
-
 	if (!pp->va_cfg0_base)
 		pp->va_cfg0_base = IOMEM((unsigned long)pp->cfg0_base);
 
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 4bb0795d06..0de7b8a868 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -158,7 +158,6 @@ struct pcie_port {
 	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
-	u64			mem_base;
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 06/16] pci: dwc: Drop support for config space in 'ranges'
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (4 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 05/16] pci: pcie-designware: remove unused variable Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 07/16] pci: add pci_controller_init() Sascha Hauer
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

Following Linux commit 2f5ab5afe018 ("PCI: dwc: Drop support for config
space in 'ranges'") let's do the same for barebox.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pcie-designware-host.c | 16 ++--------------
 drivers/pci/pcie-designware.h      |  1 -
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index bebdb5cbc7..644971d4a8 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -100,6 +100,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
 	} else {
 		dev_err(dev, "Missing *config* reg space\n");
+		return -ENODEV;
 	}
 
 	if (of_pci_range_parser_init(&parser, np)) {
@@ -134,23 +135,10 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 			pp->mem_mod_base = of_read_number(parser.range -
 							  parser.np + na, ns);
 		}
-		if (restype == 0) {
-			of_pci_range_to_resource(&range, np, &pp->cfg);
-			pp->cfg0_size = resource_size(&pp->cfg) >> 1;
-			pp->cfg1_size = resource_size(&pp->cfg) >> 1;
-			pp->cfg0_base = pp->cfg.start;
-			pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
-
-			/* Find the untranslated configuration space address */
-			pp->cfg0_mod_base = of_read_number(parser.range -
-							   parser.np + na, ns);
-			pp->cfg1_mod_base = pp->cfg0_mod_base +
-					    pp->cfg0_size;
-		}
 	}
 
 	if (!pci->dbi_base)
-		pci->dbi_base = IOMEM(pp->cfg.start);
+		pci->dbi_base = IOMEM(cfg_res->start);
 
 	if (!pp->va_cfg0_base)
 		pp->va_cfg0_base = IOMEM((unsigned long)pp->cfg0_base);
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 0de7b8a868..9840dde266 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -161,7 +161,6 @@ struct pcie_port {
 	u64			mem_mod_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
-	struct resource		cfg;
 	struct resource		io;
 	struct resource		mem;
 	struct resource		busn;
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 07/16] pci: add pci_controller_init()
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (5 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 06/16] pci: dwc: Drop support for config space in 'ranges' Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 08/16] pci: support non 1:1 mappings Sascha Hauer
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

Upcoming patches will add a list to struct pci_controller. To make
sure we have a single point to initialize the list introduce a
pci_controller_init() and call it from all drivers which use
register_pci_controller(). Make sure host->parent is set correctly
before calling register_pci_controller() as that will be needed for
device tree parsing later.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/mips/mach-malta/pci.c         | 2 ++
 drivers/pci/pci-ecam-generic.c     | 2 ++
 drivers/pci/pci-efi.c              | 4 +++-
 drivers/pci/pci-mvebu.c            | 3 +++
 drivers/pci/pci-tegra.c            | 4 +++-
 drivers/pci/pci.c                  | 4 ++++
 drivers/pci/pcie-designware-host.c | 4 +++-
 include/linux/pci.h                | 1 +
 8 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/arch/mips/mach-malta/pci.c b/arch/mips/mach-malta/pci.c
index c9c1c7790b..200d3c907c 100644
--- a/arch/mips/mach-malta/pci.c
+++ b/arch/mips/mach-malta/pci.c
@@ -154,6 +154,8 @@ static int pcibios_init(void)
 {
 	resource_size_t start, end, map, start1, end1, map1, mask;
 
+	pci_controller_init(&gt64120_controller);
+
 	/*
 	 * Due to a bug in the Galileo system controller, we need
 	 * to setup the PCI BAR for the Galileo internal registers.
diff --git a/drivers/pci/pci-ecam-generic.c b/drivers/pci/pci-ecam-generic.c
index e8609bd4b0..4db40975e2 100644
--- a/drivers/pci/pci-ecam-generic.c
+++ b/drivers/pci/pci-ecam-generic.c
@@ -186,6 +186,8 @@ static int pcie_ecam_probe(struct device *dev)
 	ecam->pci.io_resource = &ecam->io;
 	ecam->pci.mem_pref_resource = &ecam->prefetch;
 
+	pci_controller_init(&ecam->pci);
+
 	ret = pcie_ecam_parse_dt(ecam);
 	if (ret)
 		return ret;
diff --git a/drivers/pci/pci-efi.c b/drivers/pci/pci-efi.c
index 67868d09b6..b8cd663161 100644
--- a/drivers/pci/pci-efi.c
+++ b/drivers/pci/pci-efi.c
@@ -277,6 +277,9 @@ static int efi_pci_probe(struct efi_device *efidev)
 
 	priv = xzalloc(sizeof(*priv));
 
+	priv->pci.parent = &efidev->dev;
+	pci_controller_init(&priv->pci);
+
 	BS->handle_protocol(efidev->handle, &EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID,
 			(void **)&priv->protocol);
 	if (!priv->protocol)
@@ -310,7 +313,6 @@ static int efi_pci_probe(struct efi_device *efidev)
 		}
 	}
 
-	priv->pci.parent = &efidev->dev;
 	priv->pci.pci_ops = &efi_pci_ops;
 
 	INIT_LIST_HEAD(&priv->children);
diff --git a/drivers/pci/pci-mvebu.c b/drivers/pci/pci-mvebu.c
index 9e2c7dc648..988465a344 100644
--- a/drivers/pci/pci-mvebu.c
+++ b/drivers/pci/pci-mvebu.c
@@ -322,6 +322,9 @@ static struct mvebu_pcie *mvebu_pcie_port_probe(struct device *dev,
 	}
 
 	pcie = xzalloc(sizeof(*pcie));
+
+	pci_controller_init(&pcie->pci);
+
 	pcie->port = port;
 	pcie->lane = lane;
 	pcie->lane_mask = lane_mask;
diff --git a/drivers/pci/pci-tegra.c b/drivers/pci/pci-tegra.c
index fba8b47ece..9ef50207ab 100644
--- a/drivers/pci/pci-tegra.c
+++ b/drivers/pci/pci-tegra.c
@@ -1167,7 +1167,6 @@ static int tegra_pcie_enable(struct tegra_pcie *pcie)
 		tegra_pcie_port_free(port);
 	}
 
-	pcie->pci.parent = pcie->dev;
 	pcie->pci.pci_ops = &tegra_pcie_ops;
 	pcie->pci.mem_resource = &pcie->mem;
 	pcie->pci.mem_pref_resource = &pcie->prefetch;
@@ -1241,6 +1240,9 @@ static int tegra_pcie_probe(struct device *dev)
 	if (!pcie)
 		return -ENOMEM;
 
+	pcie->pci.parent = pcie->dev;
+	pci_controller_init(&pcie->pci);
+
 	INIT_LIST_HEAD(&pcie->buses);
 	INIT_LIST_HEAD(&pcie->ports);
 	dev_get_drvdata(dev, (const void **)&pcie->soc_data);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 15e8cd46bd..67a085d34e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -42,6 +42,10 @@ static void pci_bus_register_devices(struct pci_bus *bus)
 		pci_bus_register_devices(child_bus);
 }
 
+void pci_controller_init(struct pci_controller *hose)
+{
+}
+
 void register_pci_controller(struct pci_controller *hose)
 {
 	struct pci_bus *bus;
diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index 644971d4a8..387fac5c0e 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -80,6 +80,9 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 	const __be32 *addrp;
 	int index, ret;
 
+	pp->pci.parent = dev;
+	pci_controller_init(&pp->pci);
+
 	/* Find the address cell size and the number of cells in order to get
 	 * the untranslated address.
 	 */
@@ -156,7 +159,6 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 			return ret;
 	}
 
-	pp->pci.parent = dev;
 	pp->pci.pci_ops = &dw_pcie_ops;
 	pp->pci.set_busno = dw_pcie_set_local_bus_nr;
 	pp->pci.mem_resource = &pp->mem;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 4d4ab818f8..2fea9ba6c7 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -278,6 +278,7 @@ int pci_register_device(struct pci_dev *pdev);
 
 extern struct list_head pci_root_buses; /* list of all known PCI buses */
 
+extern void pci_controller_init(struct pci_controller *hose);
 extern void register_pci_controller(struct pci_controller *hose);
 
 int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 08/16] pci: support non 1:1 mappings
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (6 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 07/16] pci: add pci_controller_init() Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 09/16] pci: pcie-designware: Speed up waiting for link Sascha Hauer
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

Currently we assume that the addresses on the PCI bus are mapped 1:1
to the host CPU. This is not always true. Specifically on Rockchip
RK3568 and RK3588 we have ranges properties in the device tree which
introduce a different mapping. We already worked around this by
changing the ranges property to a 1:1 mapping in b10ee53 ("ARM:
rockchip: rock-5a: Disable non working devices"). To get rid of
the workaround this patch introduces support for non 1:1 mappings.
We do this by porting the bare minimum from Linux drivers/pci/host-bridge.c
over to barebox.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/Makefile      |  2 +-
 drivers/pci/bus.c         | 23 ++++++++++++
 drivers/pci/host-bridge.c | 76 +++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.c         | 15 ++++++--
 include/linux/pci.h       | 20 +++++++++++
 5 files changed, 133 insertions(+), 3 deletions(-)
 create mode 100644 drivers/pci/host-bridge.c

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 9249bffecb..c222f77b3b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -2,7 +2,7 @@
 #
 # Makefile for the PCI bus specific drivers.
 #
-obj-y		+= pci.o bus.o pci_iomap.o
+obj-y		+= pci.o bus.o pci_iomap.o host-bridge.o
 
 ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
 
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index b6eab56d87..37bdc9a22f 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -3,6 +3,29 @@
 #include <init.h>
 #include <driver.h>
 #include <linux/pci.h>
+#include <linux/resource_ext.h>
+
+void pci_add_resource_offset(struct list_head *resources, struct resource *res,
+			     resource_size_t offset)
+{
+	struct resource_entry *entry;
+
+	entry = resource_list_create_entry(res, 0);
+	if (!entry) {
+		pr_err("PCI: can't add host bridge window %pR\n", res);
+		return;
+	}
+	entry->offset = offset;
+
+	resource_list_add_tail(entry, resources);
+}
+EXPORT_SYMBOL(pci_add_resource_offset);
+
+void pci_add_resource(struct list_head *resources, struct resource *res)
+{
+	pci_add_resource_offset(resources, res, 0);
+}
+EXPORT_SYMBOL(pci_add_resource);
 
 /**
  * pci_match_one_device - Tell if a PCI device structure has a matching
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
new file mode 100644
index 0000000000..4460ad1971
--- /dev/null
+++ b/drivers/pci/host-bridge.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Host bridge related code
+ */
+
+#include <common.h>
+#include <linux/sizes.h>
+#include <linux/pci.h>
+
+static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
+{
+	while (bus->parent)
+		bus = bus->parent;
+
+	return bus;
+}
+
+struct pci_controller *pci_find_host_bridge(struct pci_bus *bus)
+{
+	struct pci_bus *root_bus = find_pci_root_bus(bus);
+
+	return root_bus->host;
+}
+EXPORT_SYMBOL_GPL(pci_find_host_bridge);
+
+void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
+			     struct resource *res)
+{
+	struct pci_controller *bridge = pci_find_host_bridge(bus);
+	struct resource_entry *window;
+	resource_size_t offset = 0;
+
+	resource_list_for_each_entry(window, &bridge->windows) {
+		if (resource_contains(window->res, res)) {
+			offset = window->offset;
+			break;
+		}
+	}
+
+	region->start = res->start - offset;
+	region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+static bool region_contains(struct pci_bus_region *region1,
+			    struct pci_bus_region *region2)
+{
+	return region1->start <= region2->start && region1->end >= region2->end;
+}
+
+void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
+			     struct pci_bus_region *region)
+{
+	struct pci_controller *bridge = pci_find_host_bridge(bus);
+	struct resource_entry *window;
+	resource_size_t offset = 0;
+
+	resource_list_for_each_entry(window, &bridge->windows) {
+		struct pci_bus_region bus_region;
+
+		if (resource_type(res) != resource_type(window->res))
+			continue;
+
+		bus_region.start = window->res->start - window->offset;
+		bus_region.end = window->res->end - window->offset;
+
+		if (region_contains(&bus_region, region)) {
+			offset = window->offset;
+			break;
+		}
+	}
+
+	res->start = region->start + offset;
+	res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 67a085d34e..5113abe0fc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -44,6 +44,7 @@ static void pci_bus_register_devices(struct pci_bus *bus)
 
 void pci_controller_init(struct pci_controller *hose)
 {
+	INIT_LIST_HEAD(&hose->windows);
 }
 
 void register_pci_controller(struct pci_controller *hose)
@@ -401,6 +402,9 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			 size);
 
 		if (pcibios_assign_all_busses()) {
+			struct resource res;
+			struct pci_bus_region region;
+
 			if (ALIGN(*last_addr, size) + size >
 			    dev->bus->resource[busres]->end) {
 				pr_debug("BAR does not fit within bus %s res\n", kind);
@@ -408,11 +412,18 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			}
 
 			*last_addr = ALIGN(*last_addr, size);
+
+			res.flags = flags;
+			res.start = *last_addr;
+			res.end = res.start + size - 1;
+
+			pcibios_resource_to_bus(dev->bus, &region, &res);
+
 			pci_write_config_dword(dev, pci_base_address_0,
-					       lower_32_bits(*last_addr));
+					       lower_32_bits(region.start));
 			if (mask & PCI_BASE_ADDRESS_MEM_TYPE_64)
 				pci_write_config_dword(dev, pci_base_address_1,
-						       upper_32_bits(*last_addr));
+						       upper_32_bits(region.start));
 			start = *last_addr;
 			*last_addr += size;
 		} else {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2fea9ba6c7..73117afa08 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -25,6 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/compiler.h>
+#include <linux/resource_ext.h>
 #include <driver.h>
 #include <errno.h>
 #include <io.h>
@@ -185,6 +186,8 @@ struct pci_controller {
 	unsigned long io_offset;
 	unsigned long io_map_base;
 
+	struct list_head windows;	/* resource_entry */
+
 	unsigned int index;
 
 	/* Optional access method for writing the bus number */
@@ -395,4 +398,21 @@ static inline const struct pci_device_id *pci_match_id(const struct pci_device_i
 { return NULL; }
 #endif
 
+/* drivers/pci/bus.c */
+void pci_add_resource_offset(struct list_head *resources, struct resource *res,
+			     resource_size_t offset);
+void pci_add_resource(struct list_head *resources, struct resource *res);
+
+struct pci_controller *pci_find_host_bridge(struct pci_bus *bus);
+
+struct pci_bus_region {
+	u64 start;
+	u64 end;
+};
+
+void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
+			     struct resource *res);
+void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
+			     struct pci_bus_region *region);
+
 #endif /* LINUX_PCI_H */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 09/16] pci: pcie-designware: Speed up waiting for link
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (7 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 08/16] pci: support non 1:1 mappings Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 10/16] pci: pcie-dw-rockchip: wait " Sascha Hauer
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

When the link is not up the first time we test for it, then we wait for
100ms before trying again. This adds unnecessary delays when the link
is up considerably faster than 100ms. As we do not have anything useful
to do with our CPU time during polling for link we can equally well poll
as fast as we can.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pcie-designware.c | 8 +++++---
 drivers/pci/pcie-designware.h | 4 ----
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c
index 9c8bc772f9..72820de282 100644
--- a/drivers/pci/pcie-designware.c
+++ b/drivers/pci/pcie-designware.c
@@ -237,15 +237,17 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
 
 int dw_pcie_wait_for_link(struct dw_pcie *pci)
 {
-	int retries;
+	u64 start = get_time_ns();
 
 	/* Check if the link is up or not */
-	for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+	while (1) {
 		if (dw_pcie_link_up(pci)) {
 			dev_dbg(pci->dev, "Link up\n");
 			return 0;
 		}
-		udelay(LINK_WAIT_USLEEP_MAX);
+
+		if (is_timeout(start, SECOND))
+			break;
 	}
 
 	dev_err(pci->dev, "Phy link never came up\n");
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 9840dde266..96a269dc59 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -13,10 +13,6 @@
 
 #include <linux/bitfield.h>
 
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES		10
-#define LINK_WAIT_USLEEP_MAX		100000
-
 /* Parameters for the waiting for iATU enabled routine */
 #define LINK_WAIT_MAX_IATU_RETRIES     5
 #define LINK_WAIT_IATU_MAX             10000
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 10/16] pci: pcie-dw-rockchip: wait for link
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (8 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 09/16] pci: pcie-designware: Speed up waiting for link Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 11/16] pci: drop resources from struct pci_bus Sascha Hauer
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

Wait for the link to be established before continuing the probe. While
in some configurations the link might come up fast enough, on a RK3568
no device was found without it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pcie-dw-rockchip.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pci/pcie-dw-rockchip.c b/drivers/pci/pcie-dw-rockchip.c
index cc771e2cae..22f41cc6bb 100644
--- a/drivers/pci/pcie-dw-rockchip.c
+++ b/drivers/pci/pcie-dw-rockchip.c
@@ -122,6 +122,8 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci)
 	mdelay(100);
 	gpiod_set_value(rockchip->rst_gpio, 1);
 
+	dw_pcie_wait_for_link(pci);
+
 	return 0;
 }
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 11/16] pci: drop resources from struct pci_bus
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (9 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 10/16] pci: pcie-dw-rockchip: wait " Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 12/16] pci: add of_pci_bridge_init() Sascha Hauer
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

struct pci_bus has resources attached to it. They pointers are copied
from the pci_controller to the pci_bus and from there to the child
buses. Drop them and use the resources from the pci_controller directly.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pci.c   | 32 +++++++++++---------------------
 include/linux/pci.h |  1 -
 2 files changed, 11 insertions(+), 22 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5113abe0fc..0a238cd190 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -54,27 +54,24 @@ void register_pci_controller(struct pci_controller *hose)
 	bus = pci_alloc_bus();
 	hose->bus = bus;
 	bus->host = hose;
-	bus->resource[PCI_BUS_RESOURCE_MEM] = hose->mem_resource;
-	bus->resource[PCI_BUS_RESOURCE_MEM_PREF] = hose->mem_pref_resource;
-	bus->resource[PCI_BUS_RESOURCE_IO] = hose->io_resource;
 
 	if (pcibios_assign_all_busses()) {
 		bus->number = bus_index++;
 		if (hose->set_busno)
 			hose->set_busno(hose, bus->number);
 
-		if (bus->resource[PCI_BUS_RESOURCE_MEM])
-			last_mem = bus->resource[PCI_BUS_RESOURCE_MEM]->start;
+		if (hose->mem_resource)
+			last_mem = hose->mem_resource->start;
 		else
 			last_mem = 0;
 
-		if (bus->resource[PCI_BUS_RESOURCE_MEM_PREF])
-			last_mem_pref = bus->resource[PCI_BUS_RESOURCE_MEM_PREF]->start;
+		if (hose->mem_pref_resource)
+			last_mem_pref = hose->mem_pref_resource->start;
 		else
 			last_mem_pref = 0;
 
-		if (bus->resource[PCI_BUS_RESOURCE_IO])
-			last_io = bus->resource[PCI_BUS_RESOURCE_IO]->start;
+		if (hose->io_resource)
+			last_io = hose->io_resource->start;
 		else
 			last_io = 0;
 	}
@@ -360,7 +357,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 		u32 orig, mask, size;
 		unsigned long flags;
 		const char *kind;
-		int busres;
+		struct resource *busres;
 
 		pci_read_config_dword(dev, pci_base_address_0, &orig);
 		pci_write_config_dword(dev, pci_base_address_0, 0xfffffffe);
@@ -377,20 +374,20 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			flags     = IORESOURCE_IO;
 			kind      = "IO";
 			last_addr = &last_io;
-			busres    = PCI_BUS_RESOURCE_IO;
+			busres    = dev->bus->host->io_resource;
 		} else if ((mask & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
 		           last_mem_pref) /* prefetchable MEM */ {
 			size      = pci_size(orig, mask, 0xfffffff0);
 			flags     = IORESOURCE_MEM | IORESOURCE_PREFETCH;
 			kind      = "P-MEM";
 			last_addr = &last_mem_pref;
-			busres    = PCI_BUS_RESOURCE_MEM_PREF;
+			busres    = dev->bus->host->mem_pref_resource;;
 		} else { /* non-prefetch MEM */
 			size      = pci_size(orig, mask, 0xfffffff0);
 			flags     = IORESOURCE_MEM;
 			kind      = "NP-MEM";
 			last_addr = &last_mem;
-			busres    = PCI_BUS_RESOURCE_MEM;
+			busres    = dev->bus->host->mem_resource;
 		}
 
 		if (!size) {
@@ -405,8 +402,7 @@ static void setup_device(struct pci_dev *dev, int max_bar)
 			struct resource res;
 			struct pci_bus_region region;
 
-			if (ALIGN(*last_addr, size) + size >
-			    dev->bus->resource[busres]->end) {
+			if (ALIGN(*last_addr, size) + size > busres->end) {
 				pr_debug("BAR does not fit within bus %s res\n", kind);
 				return;
 			}
@@ -678,12 +674,6 @@ static unsigned int pci_scan_bus(struct pci_bus *bus)
 			/* inherit parent properties */
 			child_bus->host = bus->host;
 			child_bus->parent = bus;
-			child_bus->resource[PCI_BUS_RESOURCE_MEM] =
-				bus->resource[PCI_BUS_RESOURCE_MEM];
-			child_bus->resource[PCI_BUS_RESOURCE_MEM_PREF] =
-				bus->resource[PCI_BUS_RESOURCE_MEM_PREF];
-			child_bus->resource[PCI_BUS_RESOURCE_IO] =
-				bus->resource[PCI_BUS_RESOURCE_IO];
 
 			child_bus->self = dev;
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 73117afa08..11a60f66a9 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -148,7 +148,6 @@ struct pci_bus {
 	struct list_head node;		/* node in list of buses */
 	struct list_head children;	/* list of child buses */
 	struct list_head devices;	/* list of devices on this bus */
-	struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
 
 	unsigned char	number;		/* bus number */
 	unsigned char	primary;	/* number of primary bridge */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 12/16] pci: add of_pci_bridge_init()
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (10 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 11/16] pci: drop resources from struct pci_bus Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-04-04  6:18   ` [PATCH v2] " Sascha Hauer
  2024-03-26 10:07 ` [PATCH 13/16] pci: pcie-designware: drop duplicate resource assigning Sascha Hauer
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/Makefile |   1 +
 drivers/pci/of.c     | 102 +++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.c    |   2 +
 include/linux/pci.h  |  10 +++++
 4 files changed, 115 insertions(+)
 create mode 100644 drivers/pci/of.c

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index c222f77b3b..69649fbcd2 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the PCI bus specific drivers.
 #
 obj-y		+= pci.o bus.o pci_iomap.o host-bridge.o
+obj-$(CONFIG_OFDEVICE) += of.o
 
 ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
 
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
new file mode 100644
index 0000000000..b1ee3fa938
--- /dev/null
+++ b/drivers/pci/of.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PCI <-> OF mapping helpers
+ *
+ * Copyright 2011 IBM Corp.
+ */
+#define pr_fmt(fmt)	"PCI: OF: " fmt
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <of.h>
+#include <of_address.h>
+#include <common.h>
+#include <linux/resource_ext.h>
+
+/**
+ * of_pci_get_host_bridge_resources() - parsing of PCI host bridge resources from DT
+ * @dev: host bridge device
+ * @resources: list where the range of resources will be added after DT parsing
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping based on its content. It is expected
+ * that the property conforms with the Power ePAPR document.
+ *
+ * It returns zero if the range parsing has been successful or a standard error
+ * value if it failed.
+ */
+static int of_pci_get_host_bridge_resources(struct device *dev,
+					    struct pci_controller *bridge)
+{
+	struct list_head *resources = &bridge->windows;
+	struct device_node *dev_node = dev->of_node;
+	struct resource *res, tmp_res;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	const char *range_type;
+	int err;
+
+	dev_dbg(dev, "host bridge %pOF ranges:\n", dev_node);
+
+	/* Check for ranges property */
+	err = of_pci_range_parser_init(&parser, dev_node);
+	if (err)
+		return 0;
+
+	dev_dbg(dev, "Parsing ranges property...\n");
+	for_each_of_pci_range(&parser, &range) {
+		/* Read next ranges element */
+		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
+			range_type = "IO";
+		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
+			range_type = "MEM";
+		else
+			range_type = "err";
+		dev_dbg(dev, "  %6s %#012llx..%#012llx -> %#012llx\n",
+			 range_type, range.cpu_addr,
+			 range.cpu_addr + range.size - 1, range.pci_addr);
+
+		/*
+		 * If we failed translation or got a zero-sized region
+		 * then skip this range
+		 */
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+			continue;
+
+		of_pci_range_to_resource(&range, dev_node, &tmp_res);
+
+		res = kmemdup(&tmp_res, sizeof(tmp_res), GFP_KERNEL);
+		if (!res) {
+			err = -ENOMEM;
+			goto failed;
+		}
+
+		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
+
+		switch (res->flags & IORESOURCE_TYPE_BITS) {
+		case IORESOURCE_IO:
+			bridge->io_resource = res;
+			break;
+
+		case IORESOURCE_MEM:
+			if (res->flags & IORESOURCE_PREFETCH)
+				bridge->mem_pref_resource = res;
+			else
+				bridge->mem_resource = res;
+			break;
+		}
+	}
+
+	return 0;
+
+failed:
+	return err;
+}
+
+int of_pci_bridge_init(struct device *dev, struct pci_controller *bridge)
+{
+	if (!dev->of_node)
+		return 0;
+
+	return of_pci_get_host_bridge_resources(dev, bridge);
+}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0a238cd190..bc083270d9 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -45,6 +45,8 @@ static void pci_bus_register_devices(struct pci_bus *bus)
 void pci_controller_init(struct pci_controller *hose)
 {
 	INIT_LIST_HEAD(&hose->windows);
+
+	of_pci_bridge_init(hose->parent, hose);
 }
 
 void register_pci_controller(struct pci_controller *hose)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 11a60f66a9..f6511e0095 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -414,4 +414,14 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
 void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
 			     struct pci_bus_region *region);
 
+/* drivers/pci/of.c */
+#ifdef CONFIG_OFDEVICE
+int of_pci_bridge_init(struct device *dev, struct pci_controller *bridge);
+#else
+static inline int of_pci_bridge_init(struct device *dev, struct pci_controller *bridge)
+{
+	return 0;
+}
+#endif
+
 #endif /* LINUX_PCI_H */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 13/16] pci: pcie-designware: drop duplicate resource assigning
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (11 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 12/16] pci: add of_pci_bridge_init() Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 14/16] pci: pcie-designware: remove dra7xx quirks Sascha Hauer
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

The resources in the pci_controller are already assigned in

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pcie-designware-host.c | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index 387fac5c0e..66ae5b59a1 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -30,7 +30,6 @@
 #include <abort.h>
 
 static const struct pci_ops dw_pcie_ops;
-static unsigned long global_io_offset;
 
 static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
 			       u32 *val)
@@ -116,11 +115,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
 
 		if (restype == IORESOURCE_IO) {
-			of_pci_range_to_resource(&range, np, &pp->io);
-			pp->io.name = "I/O";
-			pp->io.start = range.pci_addr + global_io_offset;
-			pp->io.end =  range.pci_addr + range.size + global_io_offset - 1;
-			pp->io_size = resource_size(&pp->io);
+			pp->io_size = range.size;
 			pp->io_bus_addr = range.pci_addr;
 			pp->io_base = range.cpu_addr;
 
@@ -129,9 +124,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 							 parser.np + na, ns);
 		}
 		if (restype == IORESOURCE_MEM) {
-			of_pci_range_to_resource(&range, np, &pp->mem);
-			pp->mem.name = "MEM";
-			pp->mem_size = resource_size(&pp->mem);
+			pp->mem_size = range.size;
 			pp->mem_bus_addr = range.pci_addr;
 
 			/* Find the untranslated MEM space address */
@@ -161,8 +154,6 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 
 	pp->pci.pci_ops = &dw_pcie_ops;
 	pp->pci.set_busno = dw_pcie_set_local_bus_nr;
-	pp->pci.mem_resource = &pp->mem;
-	pp->pci.io_resource = &pp->io;
 
 	register_pci_controller(&pp->pci);
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 14/16] pci: pcie-designware: remove dra7xx quirks
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (12 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 13/16] pci: pcie-designware: drop duplicate resource assigning Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 15/16] pci: pcie-designware: iterate over windows Sascha Hauer
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

The pcie-designware driver has several quirks needed only for dra7xx
which we currently do not support in barebox. In Linux these quirks
have been moved to the dra7xx glue code over time. Remove the quirks
to cleanup the driver a bit.

See these Linux commits for more explanations:

9cdce1cdc0c4 ("Revert "PCI: designware: Program ATU with untranslated address"")
883cc17cb193 ("PCI: designware: Move calculation of bus addresses to DRA7xx")

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pcie-designware-host.c | 41 ++++++++----------------------
 drivers/pci/pcie-designware.h      |  5 +---
 2 files changed, 11 insertions(+), 35 deletions(-)

diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index 66ae5b59a1..87842bf4ee 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -75,31 +75,17 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 	struct of_pci_range range;
 	struct of_pci_range_parser parser;
 	struct resource *cfg_res;
-	u32 na, ns;
-	const __be32 *addrp;
-	int index, ret;
+	int ret;
 
 	pp->pci.parent = dev;
 	pci_controller_init(&pp->pci);
 
-	/* Find the address cell size and the number of cells in order to get
-	 * the untranslated address.
-	 */
-	of_property_read_u32(np, "#address-cells", &na);
-	ns = of_n_size_cells(np);
-
 	cfg_res = dev_get_resource_by_name(dev, IORESOURCE_MEM, "config");
 	if (!IS_ERR(cfg_res)) {
 		pp->cfg0_size = resource_size(cfg_res) >> 1;
 		pp->cfg1_size = resource_size(cfg_res) >> 1;
 		pp->cfg0_base = cfg_res->start;
 		pp->cfg1_base = cfg_res->start + pp->cfg0_size;
-
-		/* Find the untranslated configuration space address */
-		index = of_property_match_string(np, "reg-names", "config");
-		addrp = of_get_address(np, index, NULL, NULL);
-		pp->cfg0_mod_base = of_read_number(addrp, ns);
-		pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
 	} else {
 		dev_err(dev, "Missing *config* reg space\n");
 		return -ENODEV;
@@ -118,18 +104,11 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 			pp->io_size = range.size;
 			pp->io_bus_addr = range.pci_addr;
 			pp->io_base = range.cpu_addr;
-
-			/* Find the untranslated IO space address */
-			pp->io_mod_base = of_read_number(parser.range -
-							 parser.np + na, ns);
 		}
 		if (restype == IORESOURCE_MEM) {
 			pp->mem_size = range.size;
 			pp->mem_bus_addr = range.pci_addr;
-
-			/* Find the untranslated MEM space address */
-			pp->mem_mod_base = of_read_number(parser.range -
-							  parser.np + na, ns);
+			pp->mem_base = range.cpu_addr;
 		}
 	}
 
@@ -179,12 +158,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->primary == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -195,7 +174,7 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 	ret = dw_pcie_read(va_cfg_base + where, size, val);
 	if (pci->num_viewport <= 2)
 		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
-					  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+					  PCIE_ATU_TYPE_IO, pp->io_base,
 					  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -219,12 +198,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 
 	if (bus->primary == pp->root_bus_nr) {
 		type = PCIE_ATU_TYPE_CFG0;
-		cpu_addr = pp->cfg0_mod_base;
+		cpu_addr = pp->cfg0_base;
 		cfg_size = pp->cfg0_size;
 		va_cfg_base = pp->va_cfg0_base;
 	} else {
 		type = PCIE_ATU_TYPE_CFG1;
-		cpu_addr = pp->cfg1_mod_base;
+		cpu_addr = pp->cfg1_base;
 		cfg_size = pp->cfg1_size;
 		va_cfg_base = pp->va_cfg1_base;
 	}
@@ -235,7 +214,7 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
 	ret = dw_pcie_write(va_cfg_base + where, size, val);
 	if (pci->num_viewport <= 2)
 		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
-					  PCIE_ATU_TYPE_IO, pp->io_mod_base,
+					  PCIE_ATU_TYPE_IO, pp->io_base,
 					  pp->io_bus_addr, pp->io_size);
 
 	return ret;
@@ -350,7 +329,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
         */
 	if (!pp->ops->rd_other_conf) {
 		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
-					  PCIE_ATU_TYPE_MEM, pp->mem_mod_base,
+					  PCIE_ATU_TYPE_MEM, pp->mem_base,
 					  pp->mem_bus_addr, pp->mem_size);
 		if (pci->num_viewport > 2)
 			dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2,
@@ -370,4 +349,4 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
 	val |= PORT_LOGIC_SPEED_CHANGE;
 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
-}
\ No newline at end of file
+}
diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h
index 96a269dc59..0c93e6f3b8 100644
--- a/drivers/pci/pcie-designware.h
+++ b/drivers/pci/pcie-designware.h
@@ -143,18 +143,15 @@ struct dw_pcie_host_ops {
 struct pcie_port {
 	u8			root_bus_nr;
 	u64			cfg0_base;
-	u64			cfg0_mod_base;
 	void __iomem		*va_cfg0_base;
 	u32			cfg0_size;
 	u64			cfg1_base;
-	u64			cfg1_mod_base;
 	void __iomem		*va_cfg1_base;
 	u32			cfg1_size;
 	u64			io_base;
-	u64			io_mod_base;
 	phys_addr_t		io_bus_addr;
 	u32			io_size;
-	u64			mem_mod_base;
+	u64			mem_base;
 	phys_addr_t		mem_bus_addr;
 	u32			mem_size;
 	struct resource		io;
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 15/16] pci: pcie-designware: iterate over windows
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (13 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 14/16] pci: pcie-designware: remove dra7xx quirks Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-03-26 10:07 ` [PATCH 16/16] ARM: dts: rk3588-rock-5b: remove pci ranges quirks Sascha Hauer
  2024-04-02  8:39 ` [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

The ranges property has already been parsed in pci_controller_init(), so
instead of iterating over the ranges again, use the result stored in
the resource_entry list to initialize the controller base addresses.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pci/pcie-designware-host.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c
index 87842bf4ee..cd1d9433aa 100644
--- a/drivers/pci/pcie-designware-host.c
+++ b/drivers/pci/pcie-designware-host.c
@@ -72,9 +72,9 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct device *dev = pci->dev;
 	struct device_node *np = dev->of_node;
-	struct of_pci_range range;
 	struct of_pci_range_parser parser;
 	struct resource *cfg_res;
+	struct resource_entry *window;
 	int ret;
 
 	pp->pci.parent = dev;
@@ -96,19 +96,18 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
 		return -EINVAL;
 	}
 
-	/* Get the I/O and memory ranges from DT */
-	for_each_of_pci_range(&parser, &range) {
-		unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
-		if (restype == IORESOURCE_IO) {
-			pp->io_size = range.size;
-			pp->io_bus_addr = range.pci_addr;
-			pp->io_base = range.cpu_addr;
-		}
-		if (restype == IORESOURCE_MEM) {
-			pp->mem_size = range.size;
-			pp->mem_bus_addr = range.pci_addr;
-			pp->mem_base = range.cpu_addr;
+	resource_list_for_each_entry(window, &pp->pci.windows) {
+		switch (resource_type(window->res)) {
+		case IORESOURCE_IO:
+			pp->io_size = resource_size(window->res);
+			pp->io_bus_addr = window->res->start - window->offset;
+			pp->io_base = window->res->start;
+			break;
+		case IORESOURCE_MEM:
+			pp->mem_size = resource_size(window->res);
+			pp->mem_bus_addr = window->res->start - window->offset;
+			pp->mem_base = window->res->start;
+			break;
 		}
 	}
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 16/16] ARM: dts: rk3588-rock-5b: remove pci ranges quirks
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (14 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 15/16] pci: pcie-designware: iterate over windows Sascha Hauer
@ 2024-03-26 10:07 ` Sascha Hauer
  2024-04-02  8:39 ` [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-03-26 10:07 UTC (permalink / raw)
  To: Barebox List

We did not support non 1:1 mappings between CPU and PCI bus, so
we had to adjust the ranges property to be 1:1 instead to make
PCIe work on the Rock-5b board. This has been fixed now, so we can
remove the overwritten ranges property.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/dts/rk3588-rock-5b.dts | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/arch/arm/dts/rk3588-rock-5b.dts b/arch/arm/dts/rk3588-rock-5b.dts
index ddff76028e..0af5442870 100644
--- a/arch/arm/dts/rk3588-rock-5b.dts
+++ b/arch/arm/dts/rk3588-rock-5b.dts
@@ -62,21 +62,6 @@ &pcie30phy {
 	status = "disabled";
 };
 
-&pcie2x1l2 {
-	/*
-	 * Originally in upstream dts this is:
-	 * ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>,
-	 *          <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x00e00000>,
-	 *          <0x03000000 0x0 0x40000000 0xa 0x00000000 0x0 0x40000000>;
-	 *
-	 * Overwriting this shouldn't be necessary, but without it PCI doesn't
-	 * work. We have some deficiency in the PCI driver that causes this.
-	 */
-	ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>,
-		 <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x00e00000>,
-		 <0x03000000 0xa 0x00000000 0xa 0x00000000 0x0 0x40000000>;
-};
-
 &pcie2x1l0 {
 	/* Does not work in barebox */
 	status = "disabled";
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 00/16] PCI: support non 1:1 mappings
  2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
                   ` (15 preceding siblings ...)
  2024-03-26 10:07 ` [PATCH 16/16] ARM: dts: rk3588-rock-5b: remove pci ranges quirks Sascha Hauer
@ 2024-04-02  8:39 ` Sascha Hauer
  16 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-04-02  8:39 UTC (permalink / raw)
  To: Barebox List, Sascha Hauer


On Tue, 26 Mar 2024 11:07:30 +0100, Sascha Hauer wrote:
> This series evolved from getting PCIe to work on a RK3568 based board.
> The device tree PCIe ranges property uses non 1:1 mappings between CPU
> and PCI bus which this series adds support for. With this series we
> parse the ranges property into struct resource_entry windows like done
> in Linux. With this we get pcibios_resource_to_bus() and
> pcibios_bus_to_resource() to translate between the PCI/CPU address
> spaces. Additionally we have some cleanup for the pcie-designware driver
> and we can remove the quirk we already introduced for the rk3588 Rock5b
> board in which we have overwritten the ranges property.
> 
> [...]

Applied, thanks!

[01/16] net: phy: realtek: add phy for RTL8168 internal phy
        https://git.pengutronix.de/cgit/barebox/commit/?id=f339f40dcc62 (link may not be stable)
[02/16] pci: add 'self' member to struct pci_bus
        https://git.pengutronix.de/cgit/barebox/commit/?id=1d6dae5748f0 (link may not be stable)
[03/16] pci: rename parent_bus to parent
        https://git.pengutronix.de/cgit/barebox/commit/?id=9de886af8ad5 (link may not be stable)
[04/16] add support for resource lists
        https://git.pengutronix.de/cgit/barebox/commit/?id=28aafff4c8c2 (link may not be stable)
[05/16] pci: pcie-designware: remove unused variable
        https://git.pengutronix.de/cgit/barebox/commit/?id=596975bddbed (link may not be stable)
[06/16] pci: dwc: Drop support for config space in 'ranges'
        https://git.pengutronix.de/cgit/barebox/commit/?id=990deb7c1f0a (link may not be stable)
[07/16] pci: add pci_controller_init()
        https://git.pengutronix.de/cgit/barebox/commit/?id=fd3be9d95f34 (link may not be stable)
[08/16] pci: support non 1:1 mappings
        https://git.pengutronix.de/cgit/barebox/commit/?id=8fbda940edd8 (link may not be stable)
[09/16] pci: pcie-designware: Speed up waiting for link
        https://git.pengutronix.de/cgit/barebox/commit/?id=61e0de057dc4 (link may not be stable)
[10/16] pci: pcie-dw-rockchip: wait for link
        https://git.pengutronix.de/cgit/barebox/commit/?id=0d0ae293d07c (link may not be stable)
[11/16] pci: drop resources from struct pci_bus
        https://git.pengutronix.de/cgit/barebox/commit/?id=b920c76bc307 (link may not be stable)
[12/16] pci: add of_pci_bridge_init()
        https://git.pengutronix.de/cgit/barebox/commit/?id=efb6fe50eb9e (link may not be stable)
[13/16] pci: pcie-designware: drop duplicate resource assigning
        https://git.pengutronix.de/cgit/barebox/commit/?id=a6fc50a2192f (link may not be stable)
[14/16] pci: pcie-designware: remove dra7xx quirks
        https://git.pengutronix.de/cgit/barebox/commit/?id=016ec9128b49 (link may not be stable)
[15/16] pci: pcie-designware: iterate over windows
        https://git.pengutronix.de/cgit/barebox/commit/?id=2fa3956c036a (link may not be stable)
[16/16] ARM: dts: rk3588-rock-5b: remove pci ranges quirks
        https://git.pengutronix.de/cgit/barebox/commit/?id=f10bd15859b2 (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2] pci: add of_pci_bridge_init()
  2024-03-26 10:07 ` [PATCH 12/16] pci: add of_pci_bridge_init() Sascha Hauer
@ 2024-04-04  6:18   ` Sascha Hauer
  0 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2024-04-04  6:18 UTC (permalink / raw)
  To: Barebox List

So far we assume a 1:1 mapping between the CPU and bus address space.
This is not always the case and different mappings are described in the
ranges device tree property. Parse the property and call
pci_add_resource_offset() accordingly. The code is based on the
corresponding Kernel code.

Link: https://lore.barebox.org/20240326100746.471532-13-s.hauer@pengutronix.de
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---

Changes since v1:
- add a commit message
- mips registers PCI controllers without a parent device. Do not crash in this case

 drivers/pci/Makefile |   1 +
 drivers/pci/of.c     | 102 +++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.c    |   2 +
 include/linux/pci.h  |  10 +++++
 4 files changed, 115 insertions(+)
 create mode 100644 drivers/pci/of.c

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index c222f77b3b..69649fbcd2 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -3,6 +3,7 @@
 # Makefile for the PCI bus specific drivers.
 #
 obj-y		+= pci.o bus.o pci_iomap.o host-bridge.o
+obj-$(CONFIG_OFDEVICE) += of.o
 
 ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
 
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
new file mode 100644
index 0000000000..1cf7fe302d
--- /dev/null
+++ b/drivers/pci/of.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PCI <-> OF mapping helpers
+ *
+ * Copyright 2011 IBM Corp.
+ */
+#define pr_fmt(fmt)	"PCI: OF: " fmt
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <of.h>
+#include <of_address.h>
+#include <common.h>
+#include <linux/resource_ext.h>
+
+/**
+ * of_pci_get_host_bridge_resources() - parsing of PCI host bridge resources from DT
+ * @dev: host bridge device
+ * @resources: list where the range of resources will be added after DT parsing
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping based on its content. It is expected
+ * that the property conforms with the Power ePAPR document.
+ *
+ * It returns zero if the range parsing has been successful or a standard error
+ * value if it failed.
+ */
+static int of_pci_get_host_bridge_resources(struct device *dev,
+					    struct pci_controller *bridge)
+{
+	struct list_head *resources = &bridge->windows;
+	struct device_node *dev_node = dev->of_node;
+	struct resource *res, tmp_res;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
+	const char *range_type;
+	int err;
+
+	dev_dbg(dev, "host bridge %pOF ranges:\n", dev_node);
+
+	/* Check for ranges property */
+	err = of_pci_range_parser_init(&parser, dev_node);
+	if (err)
+		return 0;
+
+	dev_dbg(dev, "Parsing ranges property...\n");
+	for_each_of_pci_range(&parser, &range) {
+		/* Read next ranges element */
+		if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
+			range_type = "IO";
+		else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
+			range_type = "MEM";
+		else
+			range_type = "err";
+		dev_dbg(dev, "  %6s %#012llx..%#012llx -> %#012llx\n",
+			 range_type, range.cpu_addr,
+			 range.cpu_addr + range.size - 1, range.pci_addr);
+
+		/*
+		 * If we failed translation or got a zero-sized region
+		 * then skip this range
+		 */
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+			continue;
+
+		of_pci_range_to_resource(&range, dev_node, &tmp_res);
+
+		res = kmemdup(&tmp_res, sizeof(tmp_res), GFP_KERNEL);
+		if (!res) {
+			err = -ENOMEM;
+			goto failed;
+		}
+
+		pci_add_resource_offset(resources, res,	res->start - range.pci_addr);
+
+		switch (res->flags & IORESOURCE_TYPE_BITS) {
+		case IORESOURCE_IO:
+			bridge->io_resource = res;
+			break;
+
+		case IORESOURCE_MEM:
+			if (res->flags & IORESOURCE_PREFETCH)
+				bridge->mem_pref_resource = res;
+			else
+				bridge->mem_resource = res;
+			break;
+		}
+	}
+
+	return 0;
+
+failed:
+	return err;
+}
+
+int of_pci_bridge_init(struct device *dev, struct pci_controller *bridge)
+{
+	if (!dev || !dev->of_node)
+		return 0;
+
+	return of_pci_get_host_bridge_resources(dev, bridge);
+}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0a238cd190..bc083270d9 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -45,6 +45,8 @@ static void pci_bus_register_devices(struct pci_bus *bus)
 void pci_controller_init(struct pci_controller *hose)
 {
 	INIT_LIST_HEAD(&hose->windows);
+
+	of_pci_bridge_init(hose->parent, hose);
 }
 
 void register_pci_controller(struct pci_controller *hose)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 11a60f66a9..f6511e0095 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -414,4 +414,14 @@ void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
 void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,
 			     struct pci_bus_region *region);
 
+/* drivers/pci/of.c */
+#ifdef CONFIG_OFDEVICE
+int of_pci_bridge_init(struct device *dev, struct pci_controller *bridge);
+#else
+static inline int of_pci_bridge_init(struct device *dev, struct pci_controller *bridge)
+{
+	return 0;
+}
+#endif
+
 #endif /* LINUX_PCI_H */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2024-04-04  6:18 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-26 10:07 [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer
2024-03-26 10:07 ` [PATCH 01/16] net: phy: realtek: add phy for RTL8168 internal phy Sascha Hauer
2024-03-26 10:07 ` [PATCH 02/16] pci: add 'self' member to struct pci_bus Sascha Hauer
2024-03-26 10:07 ` [PATCH 03/16] pci: rename parent_bus to parent Sascha Hauer
2024-03-26 10:07 ` [PATCH 04/16] add support for resource lists Sascha Hauer
2024-03-26 10:07 ` [PATCH 05/16] pci: pcie-designware: remove unused variable Sascha Hauer
2024-03-26 10:07 ` [PATCH 06/16] pci: dwc: Drop support for config space in 'ranges' Sascha Hauer
2024-03-26 10:07 ` [PATCH 07/16] pci: add pci_controller_init() Sascha Hauer
2024-03-26 10:07 ` [PATCH 08/16] pci: support non 1:1 mappings Sascha Hauer
2024-03-26 10:07 ` [PATCH 09/16] pci: pcie-designware: Speed up waiting for link Sascha Hauer
2024-03-26 10:07 ` [PATCH 10/16] pci: pcie-dw-rockchip: wait " Sascha Hauer
2024-03-26 10:07 ` [PATCH 11/16] pci: drop resources from struct pci_bus Sascha Hauer
2024-03-26 10:07 ` [PATCH 12/16] pci: add of_pci_bridge_init() Sascha Hauer
2024-04-04  6:18   ` [PATCH v2] " Sascha Hauer
2024-03-26 10:07 ` [PATCH 13/16] pci: pcie-designware: drop duplicate resource assigning Sascha Hauer
2024-03-26 10:07 ` [PATCH 14/16] pci: pcie-designware: remove dra7xx quirks Sascha Hauer
2024-03-26 10:07 ` [PATCH 15/16] pci: pcie-designware: iterate over windows Sascha Hauer
2024-03-26 10:07 ` [PATCH 16/16] ARM: dts: rk3588-rock-5b: remove pci ranges quirks Sascha Hauer
2024-04-02  8:39 ` [PATCH 00/16] PCI: support non 1:1 mappings Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox