U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Pali Rohár" <pali@kernel.org>
To: "Stefan Roese" <sr@denx.de>, "Dirk Eibach" <dirk.eibach@gdsys.cc>,
	"Mario Six" <mario.six@gdsys.cc>,
	"Marek Behún" <marek.behun@nic.cz>,
	"Chris Packham" <judge.packham@gmail.com>
Cc: u-boot@lists.denx.de
Subject: [PATCH u-boot-marvell 6/9] pci: pci_mvebu: Split initialization of PCIe ports into 3 phases
Date: Tue, 21 Dec 2021 12:20:16 +0100	[thread overview]
Message-ID: <20211221112019.15088-7-pali@kernel.org> (raw)
In-Reply-To: <20211221112019.15088-1-pali@kernel.org>

In first phase just parse DT properties and fill struct mvebu_pcie. In
second phase setup all PCIe links (without enabling them). And in the last
third phase enable all PCIe links and create UCLASS_PCI device for each
one.

Because parsing of DT is done before UCLASS_PCI is created, we cannot use
DM for this action anymore. So remove .of_to_plat callback and replace it
by ad-hoc function for parsing DT properties and filling struct mvebu_pcie.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 drivers/pci/pci_mvebu.c | 106 +++++++++++++++++++++++++++++++---------
 1 file changed, 84 insertions(+), 22 deletions(-)

diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index ba776217c9e6..504ff501aa2e 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -364,17 +364,30 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
 	writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
 }
 
-static int mvebu_pcie_probe(struct udevice *dev)
+/* Only enable PCIe link, do not setup it */
+static int mvebu_pcie_enable_link(struct mvebu_pcie *pcie, ofnode node)
+{
+	/* PCIe link is currently automatically enabled in SerDes code */
+	return 0;
+}
+
+/* Setup PCIe link but do not enable it */
+static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie)
 {
-	struct mvebu_pcie *pcie = dev_get_plat(dev);
-	struct udevice *ctlr = pci_get_controller(dev);
-	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
 	u32 reg;
 
 	/* Setup PCIe controller to Root Complex mode */
 	reg = readl(pcie->base + PCIE_CTRL_OFF);
 	reg |= PCIE_CTRL_RC_MODE;
 	writel(reg, pcie->base + PCIE_CTRL_OFF);
+}
+
+static int mvebu_pcie_probe(struct udevice *dev)
+{
+	struct mvebu_pcie *pcie = dev_get_plat(dev);
+	struct udevice *ctlr = pci_get_controller(dev);
+	struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+	u32 reg;
 
 	/*
 	 * Change Class Code of PCI Bridge device to PCI Bridge (0x600400)
@@ -440,7 +453,8 @@ static int mvebu_pcie_probe(struct udevice *dev)
 	    mvebu_mbus_add_window_by_id(pcie->mem_target, pcie->mem_attr,
 					(phys_addr_t)pcie->mem.start,
 					resource_size(&pcie->mem))) {
-		printf("PCIe unable to add mbus window for mem at %08x+%08x\n",
+		printf("%s: unable to add mbus window for mem at %08x+%08x\n",
+		       pcie->name,
 		       (u32)pcie->mem.start, (unsigned)resource_size(&pcie->mem));
 		pcie->mem.start = 0;
 		pcie->mem.end = -1;
@@ -450,7 +464,8 @@ static int mvebu_pcie_probe(struct udevice *dev)
 	    mvebu_mbus_add_window_by_id(pcie->io_target, pcie->io_attr,
 					(phys_addr_t)pcie->io.start,
 					resource_size(&pcie->io))) {
-		printf("PCIe unable to add mbus window for IO at %08x+%08x\n",
+		printf("%s: unable to add mbus window for IO at %08x+%08x\n",
+		       pcie->name,
 		       (u32)pcie->io.start, (unsigned)resource_size(&pcie->io));
 		pcie->io.start = 0;
 		pcie->io.end = -1;
@@ -549,33 +564,34 @@ static int mvebu_get_tgt_attr(ofnode node, int devfn,
 	return -ENOENT;
 }
 
-static int mvebu_pcie_of_to_plat(struct udevice *dev)
+static int mvebu_pcie_port_parse_dt(ofnode node, ofnode parent, struct mvebu_pcie *pcie)
 {
-	struct mvebu_pcie *pcie = dev_get_plat(dev);
+	struct fdt_pci_addr pci_addr;
 	const u32 *addr;
 	int ret = 0;
 	int len;
 
 	/* Get port number, lane number and memory target / attr */
-	if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-port",
+	if (ofnode_read_u32(node, "marvell,pcie-port",
 			    &pcie->port)) {
 		ret = -ENODEV;
 		goto err;
 	}
 
-	if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-lane", &pcie->lane))
+	if (ofnode_read_u32(node, "marvell,pcie-lane", &pcie->lane))
 		pcie->lane = 0;
 
 	sprintf(pcie->name, "pcie%d.%d", pcie->port, pcie->lane);
 
-	/* pci_get_devfn() returns devfn in bits 15..8, see PCI_DEV usage */
-	pcie->devfn = pci_get_devfn(dev);
-	if (pcie->devfn < 0) {
-		ret = -ENODEV;
+	/* devfn is in bits [15:8], see PCI_DEV usage */
+	ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg", &pci_addr);
+	if (ret < 0) {
+		printf("%s: property \"reg\" is invalid\n", pcie->name);
 		goto err;
 	}
+	pcie->devfn = pci_addr.phys_hi & 0xff00;
 
-	ret = mvebu_get_tgt_attr(dev_ofnode(dev->parent), pcie->devfn,
+	ret = mvebu_get_tgt_attr(parent, pcie->devfn,
 				 IORESOURCE_MEM,
 				 &pcie->mem_target, &pcie->mem_attr);
 	if (ret < 0) {
@@ -583,7 +599,7 @@ static int mvebu_pcie_of_to_plat(struct udevice *dev)
 		goto err;
 	}
 
-	ret = mvebu_get_tgt_attr(dev_ofnode(dev->parent), pcie->devfn,
+	ret = mvebu_get_tgt_attr(parent, pcie->devfn,
 				 IORESOURCE_IO,
 				 &pcie->io_target, &pcie->io_attr);
 	if (ret < 0) {
@@ -592,14 +608,14 @@ static int mvebu_pcie_of_to_plat(struct udevice *dev)
 	}
 
 	/* Parse PCIe controller register base from DT */
-	addr = ofnode_get_property(dev_ofnode(dev), "assigned-addresses", &len);
+	addr = ofnode_get_property(node, "assigned-addresses", &len);
 	if (!addr) {
 		printf("%s: property \"assigned-addresses\" not found\n", pcie->name);
 		ret = -FDT_ERR_NOTFOUND;
 		goto err;
 	}
 
-	pcie->base = (void *)(u32)ofnode_translate_address(dev_ofnode(dev), addr);
+	pcie->base = (void *)(u32)ofnode_translate_address(node, addr);
 	pcie->intregs = (u32)pcie->base - fdt32_to_cpu(addr[2]);
 
 	return 0;
@@ -618,7 +634,6 @@ static struct driver pcie_mvebu_drv = {
 	.id			= UCLASS_PCI,
 	.ops			= &mvebu_pcie_ops,
 	.probe			= mvebu_pcie_probe,
-	.of_to_plat	= mvebu_pcie_of_to_plat,
 	.plat_auto	= sizeof(struct mvebu_pcie),
 };
 
@@ -628,11 +643,14 @@ static struct driver pcie_mvebu_drv = {
  */
 static int mvebu_pcie_bind(struct udevice *parent)
 {
+	struct mvebu_pcie **ports_pcie;
 	struct mvebu_pcie *pcie;
 	struct uclass_driver *drv;
 	struct udevice *dev;
 	struct resource mem;
 	struct resource io;
+	int ports_count, i;
+	ofnode *ports_nodes;
 	ofnode subnode;
 
 	/* Lookup pci driver */
@@ -642,18 +660,34 @@ static int mvebu_pcie_bind(struct udevice *parent)
 		return -ENOENT;
 	}
 
+	ports_count = ofnode_get_child_count(dev_ofnode(parent));
+	ports_pcie = calloc(ports_count, sizeof(*ports_pcie));
+	ports_nodes = calloc(ports_count, sizeof(*ports_nodes));
+	if (!ports_pcie || !ports_nodes) {
+		free(ports_pcie);
+		free(ports_nodes);
+		return -ENOMEM;
+	}
+	ports_count = 0;
+
 	mem.start = MBUS_PCI_MEM_BASE;
 	mem.end = MBUS_PCI_MEM_BASE + MBUS_PCI_MEM_SIZE - 1;
 	io.start = MBUS_PCI_IO_BASE;
 	io.end = MBUS_PCI_IO_BASE + MBUS_PCI_IO_SIZE - 1;
 
+	/* First phase: Fill mvebu_pcie struct for each port */
 	ofnode_for_each_subnode(subnode, dev_ofnode(parent)) {
 		if (!ofnode_is_available(subnode))
 			continue;
 
 		pcie = calloc(1, sizeof(*pcie));
 		if (!pcie)
-			return -ENOMEM;
+			continue;
+
+		if (mvebu_pcie_port_parse_dt(subnode, dev_ofnode(parent), pcie) < 0) {
+			free(pcie);
+			continue;
+		}
 
 		/*
 		 * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
@@ -666,7 +700,7 @@ static int mvebu_pcie_bind(struct udevice *parent)
 			pcie->mem.end = mem.start + SZ_128M - 1;
 			mem.start += SZ_128M;
 		} else {
-			printf("PCIe unable to assign mbus window for mem\n");
+			printf("%s: unable to assign mbus window for mem\n", pcie->name);
 			pcie->mem.start = 0;
 			pcie->mem.end = -1;
 		}
@@ -676,16 +710,44 @@ static int mvebu_pcie_bind(struct udevice *parent)
 			pcie->io.end = io.start + SZ_64K - 1;
 			io.start += SZ_64K;
 		} else {
-			printf("PCIe unable to assign mbus window for io\n");
+			printf("%s: unable to assign mbus window for io\n", pcie->name);
 			pcie->io.start = 0;
 			pcie->io.end = -1;
 		}
 
+		ports_pcie[ports_count] = pcie;
+		ports_nodes[ports_count] = subnode;
+		ports_count++;
+	}
+
+	/* Second phase: Setup all PCIe links (do not enable them yet) */
+	for (i = 0; i < ports_count; i++)
+		mvebu_pcie_setup_link(ports_pcie[i]);
+
+	/* Third phase: Enable all PCIe links and create for each UCLASS_PCI device */
+	for (i = 0; i < ports_count; i++) {
+		pcie = ports_pcie[i];
+		subnode = ports_nodes[i];
+
+		/*
+		 * PCIe link can be enabled only after all PCIe links were
+		 * properly configured. This is because more PCIe links shares
+		 * one enable bit and some PCIe links cannot be enabled
+		 * individually.
+		 */
+		if (mvebu_pcie_enable_link(pcie, subnode) < 0) {
+			free(pcie);
+			continue;
+		}
+
 		/* Create child device UCLASS_PCI and bind it */
 		device_bind(parent, &pcie_mvebu_drv, pcie->name, pcie, subnode,
 			    &dev);
 	}
 
+	free(ports_pcie);
+	free(ports_nodes);
+
 	return 0;
 }
 
-- 
2.20.1


  parent reply	other threads:[~2021-12-21 11:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
2021-12-21 11:20 ` [PATCH u-boot-marvell 1/9] arm: mvebu: Convert board_pex_config() to CONFIG_SPL_BOARD_INIT Pali Rohár
2021-12-21 11:20 ` [PATCH u-boot-marvell 2/9] board: gdsys: a38x: Enable PCIe link 2 in spl_board_init() Pali Rohár
2021-12-21 11:20 ` [PATCH u-boot-marvell 3/9] pci: pci_mvebu: Fix PCIe MEM and IO resources assignment and mbus mapping Pali Rohár
2021-12-21 11:20 ` [PATCH u-boot-marvell 4/9] pci: pci_mvebu: Inline mvebu_pcie_port_parse_dt() function Pali Rohár
2021-12-21 11:20 ` [PATCH u-boot-marvell 5/9] pci: pci_mvebu: Remove dependency on SOC_REGS_PHY_BASE macro Pali Rohár
2021-12-21 11:20 ` Pali Rohár [this message]
2021-12-21 11:20 ` [PATCH u-boot-marvell 7/9] pci: pci_mvebu: Wait 100ms for Link Up in mvebu_pcie_probe() Pali Rohár
2021-12-21 11:20 ` [PATCH u-boot-marvell 8/9] arm: mvebu: Implement simple mvebu-reset driver for enabling/disabling PCIe ports Pali Rohár
2021-12-21 11:20 ` [PATCH u-boot-marvell 9/9] arm: mvebu: a38x: serdes: Move non-serdes PCIe code to pci_mvebu.c Pali Rohár
2022-01-04 22:08 ` [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
2022-01-14 15:33 ` Stefan Roese

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211221112019.15088-7-pali@kernel.org \
    --to=pali@kernel.org \
    --cc=dirk.eibach@gdsys.cc \
    --cc=judge.packham@gmail.com \
    --cc=marek.behun@nic.cz \
    --cc=mario.six@gdsys.cc \
    --cc=sr@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox