All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver
@ 2021-12-21 11:20 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
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

This patch series removes gdsys's board_pex_config() function by
converting it to spl_board_init(), adds a new mvebu-reset driver for
enabling / disabling PCIe ports and finally moves PCIe code from serdes
driver to pci_mvebu.c driver.

After all these changes, PCIe link is not initialized in serdes code
anymore, but in pci_mvebu.c driver with help of mvebu-reset driver.

I'm not sure if change for gdsys board is correct, so if somebody has
this board, please test it.

I tested this change on A385 board Turris Omnia and I verified that PCIe
links are really enabled by pci_mvebu.c driver and not before.

This patch series is based on u-boot-marvell/next branch.

Pali Rohár (9):
  arm: mvebu: Convert board_pex_config() to CONFIG_SPL_BOARD_INIT
  board: gdsys: a38x: Enable PCIe link 2 in spl_board_init()
  pci: pci_mvebu: Fix PCIe MEM and IO resources assignment and mbus
    mapping
  pci: pci_mvebu: Inline mvebu_pcie_port_parse_dt() function
  pci: pci_mvebu: Remove dependency on SOC_REGS_PHY_BASE macro
  pci: pci_mvebu: Split initialization of PCIe ports into 3 phases
  pci: pci_mvebu: Wait 100ms for Link Up in mvebu_pcie_probe()
  arm: mvebu: Implement simple mvebu-reset driver for enabling/disabling
    PCIe ports
  arm: mvebu: a38x: serdes: Move non-serdes PCIe code to pci_mvebu.c

 arch/arm/dts/armada-375.dtsi                  |   5 +-
 arch/arm/dts/armada-380.dtsi                  |   3 +
 arch/arm/dts/armada-385.dtsi                  |   4 +
 arch/arm/dts/armada-38x.dtsi                  |   1 +
 arch/arm/dts/armada-xp-98dx3236.dtsi          |   2 +
 arch/arm/dts/armada-xp-mv78230.dtsi           |   5 +
 arch/arm/dts/armada-xp-mv78260.dtsi           |   9 +
 arch/arm/dts/armada-xp-mv78460.dtsi           |  10 +
 arch/arm/dts/armada-xp-synology-ds414.dts     |   1 +
 arch/arm/dts/armada-xp-theadorable.dts        |   1 +
 arch/arm/dts/armada-xp.dtsi                   |   1 +
 arch/arm/mach-mvebu/Makefile                  |   1 +
 arch/arm/mach-mvebu/include/mach/cpu.h        |   5 +-
 arch/arm/mach-mvebu/serdes/a38x/Makefile      |   1 -
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c    |  64 ----
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h    |  28 --
 .../serdes/a38x/high_speed_env_spec.c         |  19 --
 arch/arm/mach-mvebu/system-controller.c       | 105 +++++++
 board/gdsys/a38x/controlcenterdc.c            |   6 +-
 configs/controlcenterdc_defconfig             |   1 +
 drivers/pci/Kconfig                           |   1 +
 drivers/pci/pci_mvebu.c                       | 275 ++++++++++++++----
 22 files changed, 371 insertions(+), 177 deletions(-)
 delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
 delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
 create mode 100644 arch/arm/mach-mvebu/system-controller.c

-- 
2.20.1


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

* [PATCH u-boot-marvell 1/9] arm: mvebu: Convert board_pex_config() to CONFIG_SPL_BOARD_INIT
  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 ` 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
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

The only user of board_pex_config() weak function is A385 controlcenterdc
board. It looks like that code in its board_pex_config() function needs to
be executed after PCIe link is up. Therefore put this code into
spl_board_init() function which is called after a38x serdes initialization,
and therefore it is after the serdes hws_pex_config() function finishes
(which is the state before this change).

With this change completely remove board_pex_config() function as it is not
used anymore.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c | 7 -------
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h | 1 -
 board/gdsys/a38x/controlcenterdc.c         | 2 +-
 configs/controlcenterdc_defconfig          | 1 +
 4 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
index 55c3f9ca390b..b3cbddf6a2f0 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
+++ b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
@@ -14,11 +14,6 @@
 #include "ctrl_pex.h"
 #include "sys_env_lib.h"
 
-__weak void board_pex_config(void)
-{
-	/* nothing in this weak default implementation */
-}
-
 int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
 {
 	enum serdes_type serdes_type;
@@ -58,7 +53,5 @@ int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
 
 	reg_write(SOC_CONTROL_REG1, tmp);
 
-	board_pex_config();
-
 	return MV_OK;
 }
diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
index 64193d528886..abdbe3c66045 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
+++ b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
@@ -23,6 +23,5 @@
 #define PCIE4_ENABLE_MASK		(0x1 << PCIE3_ENABLE_OFFS)
 
 int hws_pex_config(const struct serdes_map *serdes_map, u8 count);
-void board_pex_config(void);
 
 #endif
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
index dc424f271c5e..243d02232667 100644
--- a/board/gdsys/a38x/controlcenterdc.c
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -94,7 +94,7 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
 	return 0;
 }
 
-void board_pex_config(void)
+void spl_board_init(void)
 {
 #ifdef CONFIG_SPL_BUILD
 	uint k;
diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig
index 44db3110916c..87ad273a5131 100644
--- a/configs/controlcenterdc_defconfig
+++ b/configs/controlcenterdc_defconfig
@@ -33,6 +33,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_BOARD_LATE_INIT=y
 CONFIG_LAST_STAGE_INIT=y
+CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_I2C=y
 CONFIG_HUSH_PARSER=y
-- 
2.20.1


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

* [PATCH u-boot-marvell 2/9] board: gdsys: a38x: Enable PCIe link 2 in spl_board_init()
  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 ` 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
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

A385 controlcenterdc board does not use PCI DM properly and touches some
PCIe devices directly in its board code.

This controlcenterdc spl_board_init() function expects that PCIe link is
already initialized. Link itself is initialized in a38x serdes code but
this will change in future and link initialization will be postponed from
U-Boot SPL to proper U-Boot.

So explicitly enable PCIe link 2 in spl_board_init() function via
SoC Control Register 1 to not break this code by future changes. This board
has PCIe link 2 just x1, so no additional initialization (except enabling
PCIe port) is needed.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 board/gdsys/a38x/controlcenterdc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
index 243d02232667..7d65400ccb0d 100644
--- a/board/gdsys/a38x/controlcenterdc.c
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -100,6 +100,10 @@ void spl_board_init(void)
 	uint k;
 	struct gpio_desc gpio = {};
 
+	/* Enable PCIe link 2 */
+	setbits_32(MVEBU_REGISTER(0x18204), BIT(2));
+	mdelay(10);
+
 	if (!request_gpio_by_name(&gpio, "pca9698@22", 31, "fpga-program-gpio")) {
 		/* prepare FPGA reconfiguration */
 		dm_gpio_set_dir_flags(&gpio, GPIOD_IS_OUT);
-- 
2.20.1


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

* [PATCH u-boot-marvell 3/9] pci: pci_mvebu: Fix PCIe MEM and IO resources assignment and mbus mapping
  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 ` 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
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

Do not call pci_set_region() for resources which were not properly mapped.
This prevents U-Boot to access unmapped memory space.

Update MBUS_PCI_MEM_SIZE and MBUS_PCI_IO_SIZE macros to cover all PCIe MEM
and IO ranges. Previously these macros covered only address ranges for the
first PCIe port. Between MBUS_PCI_IO_BASE and MBUS_PCI_MEM_BASE there is
space for six 128 MB long address ranges. So set MBUS_PCI_MEM_SIZE to value
of 6*128 MB. Similarly set MBUS_PCI_IO_SIZE to 6*64 KB.

Function resource_size() returns zero when start address is 0 and end
address is -1. So set invalid resources to these values to indicate that
resource has no mapping.

Split global PCIe MEM and IO resources (defined by MBUS_PCI_*_* macros)
into PCIe ports in mvebu_pcie_bind() function which allocates per-port
based struct mvebu_pcie, instead of using global state variables
mvebu_pcie_membase and mvebu_pcie_iobase. This makes pci_mvebu.c driver
independent of global static variables (which store the state of
allocation) and allows to bind and unbind the driver more times.

Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
 arch/arm/mach-mvebu/include/mach/cpu.h |  5 +-
 drivers/pci/pci_mvebu.c                | 84 ++++++++++++++++++--------
 2 files changed, 62 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index a7a62c7e7d53..b99d86a87a03 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -74,10 +74,11 @@ enum {
 /*
  * Default Device Address MAP BAR values
  */
+#define MBUS_PCI_MAX_PORTS	6
 #define MBUS_PCI_MEM_BASE	MVEBU_SDRAM_SIZE_MAX
-#define MBUS_PCI_MEM_SIZE	(128 << 20)
+#define MBUS_PCI_MEM_SIZE	((MBUS_PCI_MAX_PORTS * 128) << 20)
 #define MBUS_PCI_IO_BASE	0xF1100000
-#define MBUS_PCI_IO_SIZE	(64 << 10)
+#define MBUS_PCI_IO_SIZE	((MBUS_PCI_MAX_PORTS * 64) << 10)
 #define MBUS_SPI_BASE		0xF4000000
 #define MBUS_SPI_SIZE		(8 << 20)
 #define MBUS_DFX_BASE		0xF6000000
diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index 9248cbc294ce..eaaa6cbe326d 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/mbus.h>
+#include <linux/sizes.h>
 
 /* PCIe unit register offsets */
 #define SELECT(x, n)			((x >> n) & 1UL)
@@ -89,14 +90,6 @@ struct mvebu_pcie {
 	u32 cfgcache[(0x3c - 0x10) / 4];
 };
 
-/*
- * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
- * into SoCs address space. Each controller will map 128M of MEM
- * and 64K of I/O space when registered.
- */
-static void __iomem *mvebu_pcie_membase = (void __iomem *)MBUS_PCI_MEM_BASE;
-static void __iomem *mvebu_pcie_iobase = (void __iomem *)MBUS_PCI_IO_BASE;
-
 static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
 {
 	u32 val;
@@ -442,26 +435,24 @@ static int mvebu_pcie_probe(struct udevice *dev)
 	mvebu_pcie_set_local_bus_nr(pcie, 0);
 	mvebu_pcie_set_local_dev_nr(pcie, 1);
 
-	pcie->mem.start = (u32)mvebu_pcie_membase;
-	pcie->mem.end = pcie->mem.start + MBUS_PCI_MEM_SIZE - 1;
-	mvebu_pcie_membase += MBUS_PCI_MEM_SIZE;
-
-	if (mvebu_mbus_add_window_by_id(pcie->mem_target, pcie->mem_attr,
+	if (resource_size(&pcie->mem) &&
+	    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",
 		       (u32)pcie->mem.start, (unsigned)resource_size(&pcie->mem));
+		pcie->mem.start = 0;
+		pcie->mem.end = -1;
 	}
 
-	pcie->io.start = (u32)mvebu_pcie_iobase;
-	pcie->io.end = pcie->io.start + MBUS_PCI_IO_SIZE - 1;
-	mvebu_pcie_iobase += MBUS_PCI_IO_SIZE;
-
-	if (mvebu_mbus_add_window_by_id(pcie->io_target, pcie->io_attr,
+	if (resource_size(&pcie->io) &&
+	    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",
 		       (u32)pcie->io.start, (unsigned)resource_size(&pcie->io));
+		pcie->io.start = 0;
+		pcie->io.end = -1;
 	}
 
 	/* Setup windows and configure host bridge */
@@ -470,13 +461,23 @@ static int mvebu_pcie_probe(struct udevice *dev)
 	/* PCI memory space */
 	pci_set_region(hose->regions + 0, pcie->mem.start,
 		       pcie->mem.start, resource_size(&pcie->mem), PCI_REGION_MEM);
-	pci_set_region(hose->regions + 1,
-		       0, 0,
-		       gd->ram_size,
-		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
-	pci_set_region(hose->regions + 2, pcie->io.start,
-		       pcie->io.start, resource_size(&pcie->io), PCI_REGION_IO);
-	hose->region_count = 3;
+	hose->region_count = 1;
+
+	if (resource_size(&pcie->mem)) {
+		pci_set_region(hose->regions + hose->region_count,
+			       pcie->mem.start, pcie->mem.start,
+			       resource_size(&pcie->mem),
+			       PCI_REGION_MEM);
+		hose->region_count++;
+	}
+
+	if (resource_size(&pcie->io)) {
+		pci_set_region(hose->regions + hose->region_count,
+			       pcie->io.start, pcie->io.start,
+			       resource_size(&pcie->io),
+			       PCI_REGION_IO);
+		hose->region_count++;
+	}
 
 	/* PCI Bridge support 32-bit I/O and 64-bit prefetch mem addressing */
 	pcie->cfgcache[(PCI_IO_BASE - 0x10) / 4] =
@@ -637,6 +638,8 @@ static int mvebu_pcie_bind(struct udevice *parent)
 	struct mvebu_pcie *pcie;
 	struct uclass_driver *drv;
 	struct udevice *dev;
+	struct resource mem;
+	struct resource io;
 	ofnode subnode;
 
 	/* Lookup pci driver */
@@ -646,6 +649,11 @@ static int mvebu_pcie_bind(struct udevice *parent)
 		return -ENOENT;
 	}
 
+	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;
+
 	ofnode_for_each_subnode(subnode, dev_ofnode(parent)) {
 		if (!ofnode_is_available(subnode))
 			continue;
@@ -654,6 +662,32 @@ static int mvebu_pcie_bind(struct udevice *parent)
 		if (!pcie)
 			return -ENOMEM;
 
+		/*
+		 * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
+		 * into SoCs address space. Each controller will map 128M of MEM
+		 * and 64K of I/O space when registered.
+		 */
+
+		if (resource_size(&mem) >= SZ_128M) {
+			pcie->mem.start = mem.start;
+			pcie->mem.end = mem.start + SZ_128M - 1;
+			mem.start += SZ_128M;
+		} else {
+			printf("PCIe unable to assign mbus window for mem\n");
+			pcie->mem.start = 0;
+			pcie->mem.end = -1;
+		}
+
+		if (resource_size(&io) >= SZ_64K) {
+			pcie->io.start = io.start;
+			pcie->io.end = io.start + SZ_64K - 1;
+			io.start += SZ_64K;
+		} else {
+			printf("PCIe unable to assign mbus window for io\n");
+			pcie->io.start = 0;
+			pcie->io.end = -1;
+		}
+
 		/* Create child device UCLASS_PCI and bind it */
 		device_bind(parent, &pcie_mvebu_drv, pcie->name, pcie, subnode,
 			    &dev);
-- 
2.20.1


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

* [PATCH u-boot-marvell 4/9] pci: pci_mvebu: Inline mvebu_pcie_port_parse_dt() function
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (2 preceding siblings ...)
  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 ` 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
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

Function mvebu_pcie_port_parse_dt() is called only from
mvebu_pcie_of_to_plat() function. Both these function parse DT properties
required to setup mvebu pcie. So inline mvebu_pcie_port_parse_dt() function
into mvebu_pcie_of_to_plat() to have all code related to parsing DT
properties at one place.

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

diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index eaaa6cbe326d..c47551807bc2 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -488,22 +488,6 @@ static int mvebu_pcie_probe(struct udevice *dev)
 	return 0;
 }
 
-static int mvebu_pcie_port_parse_dt(ofnode node, struct mvebu_pcie *pcie)
-{
-	const u32 *addr;
-	int len;
-
-	addr = ofnode_get_property(node, "assigned-addresses", &len);
-	if (!addr) {
-		pr_err("property \"assigned-addresses\" not found");
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	pcie->base = (void *)(fdt32_to_cpu(addr[2]) + SOC_REGS_PHY_BASE);
-
-	return 0;
-}
-
 #define DT_FLAGS_TO_TYPE(flags)       (((flags) >> 24) & 0x03)
 #define    DT_TYPE_IO                 0x1
 #define    DT_TYPE_MEM32              0x2
@@ -567,7 +551,9 @@ static int mvebu_get_tgt_attr(ofnode node, int devfn,
 static int mvebu_pcie_of_to_plat(struct udevice *dev)
 {
 	struct mvebu_pcie *pcie = dev_get_plat(dev);
+	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",
@@ -605,9 +591,14 @@ static int mvebu_pcie_of_to_plat(struct udevice *dev)
 	}
 
 	/* Parse PCIe controller register base from DT */
-	ret = mvebu_pcie_port_parse_dt(dev_ofnode(dev), pcie);
-	if (ret < 0)
+	addr = ofnode_get_property(dev_ofnode(dev), "assigned-addresses", &len);
+	if (!addr) {
+		printf("%s: property \"assigned-addresses\" not found\n", pcie->name);
+		ret = -FDT_ERR_NOTFOUND;
 		goto err;
+	}
+
+	pcie->base = (void *)(fdt32_to_cpu(addr[2]) + SOC_REGS_PHY_BASE);
 
 	return 0;
 
-- 
2.20.1


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

* [PATCH u-boot-marvell 5/9] pci: pci_mvebu: Remove dependency on SOC_REGS_PHY_BASE macro
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (3 preceding siblings ...)
  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 ` Pali Rohár
  2021-12-21 11:20 ` [PATCH u-boot-marvell 6/9] pci: pci_mvebu: Split initialization of PCIe ports into 3 phases Pali Rohár
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

SoC specific macro SOC_REGS_PHY_BASE is used for two things:

* calculation of base PCIe port address
* filling PCIe register with address of internal registers

For calculating base PCIe port address use function
ofnode_translate_address() which translates DT "assigned-addresses" to
final PCIe port address.

And for calculating address of internal registers use untranslated and
translated DT "assigned-addresses".

Basically this change reads SOC_REGS_PHY_BASE address indirectly from DT.

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

diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index c47551807bc2..ba776217c9e6 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -76,6 +76,7 @@ struct mvebu_pcie {
 	struct resource mem;
 	void __iomem *iobase;
 	struct resource io;
+	u32 intregs;
 	u32 port;
 	u32 lane;
 	int devfn;
@@ -359,7 +360,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
 	       pcie->base + PCIE_BAR_CTRL_OFF(1));
 
 	/* Setup BAR[0] to internal registers. */
-	writel(SOC_REGS_PHY_BASE, pcie->base + PCIE_BAR_LO_OFF(0));
+	writel(pcie->intregs, pcie->base + PCIE_BAR_LO_OFF(0));
 	writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
 }
 
@@ -598,7 +599,8 @@ static int mvebu_pcie_of_to_plat(struct udevice *dev)
 		goto err;
 	}
 
-	pcie->base = (void *)(fdt32_to_cpu(addr[2]) + SOC_REGS_PHY_BASE);
+	pcie->base = (void *)(u32)ofnode_translate_address(dev_ofnode(dev), addr);
+	pcie->intregs = (u32)pcie->base - fdt32_to_cpu(addr[2]);
 
 	return 0;
 
-- 
2.20.1


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

* [PATCH u-boot-marvell 6/9] pci: pci_mvebu: Split initialization of PCIe ports into 3 phases
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (4 preceding siblings ...)
  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
  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
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

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


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

* [PATCH u-boot-marvell 7/9] pci: pci_mvebu: Wait 100ms for Link Up in mvebu_pcie_probe()
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (5 preceding siblings ...)
  2021-12-21 11:20 ` [PATCH u-boot-marvell 6/9] pci: pci_mvebu: Split initialization of PCIe ports into 3 phases Pali Rohár
@ 2021-12-21 11:20 ` 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
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

After function mvebu_pcie_probe() returns U-Boot DM expects that PCIe link
is already up. In followup patches link initialization will be moved from
SPL to proper and therefore explicitly link up delay is required.

Delay mvebu_pcie_probe() for 100ms to ensure that PCIe link is up after
function finish. In the case when no card is connected to the PCIe slot,
this will delay probe time by 100ms, which should not be problematic.

This change fixes detection and initialization of some QCA98xx cards on
the first serdes when configured in x1 mode. Default configuration of
the first serdes on A385 is x4 mode, so it looks as if some delay is
required when x4 is changed to x1 and card correctly links with A385.
Other PCIe serdes ports on A385 are x1-only, and so they don't have this
problem.

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

diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index 504ff501aa2e..b5b0897b2124 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -22,6 +22,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/mbus.h>
@@ -69,6 +70,9 @@
 #define PCIE_DEBUG_CTRL			0x1a60
 #define  PCIE_DEBUG_SOFT_RESET		BIT(20)
 
+#define LINK_WAIT_RETRIES	100
+#define LINK_WAIT_TIMEOUT	1000
+
 struct mvebu_pcie {
 	struct pci_controller hose;
 	void __iomem *base;
@@ -98,6 +102,23 @@ static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
 	return !(val & PCIE_STAT_LINK_DOWN);
 }
 
+static void mvebu_pcie_wait_for_link(struct mvebu_pcie *pcie)
+{
+	int retries;
+
+	/* check if the link is up or not */
+	for (retries = 0; retries < LINK_WAIT_RETRIES; retries++) {
+		if (mvebu_pcie_link_up(pcie)) {
+			printf("%s: Link up\n", pcie->name);
+			return;
+		}
+
+		udelay(LINK_WAIT_TIMEOUT);
+	}
+
+	printf("%s: Link down\n", pcie->name);
+}
+
 static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie *pcie, int busno)
 {
 	u32 stat;
@@ -501,6 +522,8 @@ static int mvebu_pcie_probe(struct udevice *dev)
 	pcie->cfgcache[(PCI_PREF_MEMORY_BASE - 0x10) / 4] =
 		PCI_PREF_RANGE_TYPE_64 | (PCI_PREF_RANGE_TYPE_64 << 16);
 
+	mvebu_pcie_wait_for_link(pcie);
+
 	return 0;
 }
 
-- 
2.20.1


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

* [PATCH u-boot-marvell 8/9] arm: mvebu: Implement simple mvebu-reset driver for enabling/disabling PCIe ports
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (6 preceding siblings ...)
  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 ` 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
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

Enabling and disabling PCIe ports is done via address space of system
controller. All 32-bit Armada SoCs use low 4 bits in SoC Control 1 Register
for enabling and disabling some or more PCIe ports. Correct mapping needs
to be set in particular DTS files.

DT API for mvebu-reset is prepared for implementing resets also for other
HW blocks, but currently only PCIe is implemented via index 0.

Currently this driver is not used as PCIe ports are automatically enabled
by SerDes code executed by U-Boot SPL. But this will change in followup
patches.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/dts/armada-375.dtsi            |   3 +-
 arch/arm/dts/armada-38x.dtsi            |   1 +
 arch/arm/dts/armada-xp-98dx3236.dtsi    |   1 +
 arch/arm/dts/armada-xp.dtsi             |   1 +
 arch/arm/mach-mvebu/Makefile            |   1 +
 arch/arm/mach-mvebu/system-controller.c | 105 ++++++++++++++++++++++++
 6 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-mvebu/system-controller.c

diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi
index 62a548a55f3f..fdf2d6dbdc84 100644
--- a/arch/arm/dts/armada-375.dtsi
+++ b/arch/arm/dts/armada-375.dtsi
@@ -384,9 +384,10 @@
 				interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
-			system-controller@18200 {
+			systemc: system-controller@18200 {
 				compatible = "marvell,armada-375-system-controller";
 				reg = <0x18200 0x100>;
+				#reset-cells = <2>;
 			};
 
 			gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi
index 72c49beb71a4..061bd7852081 100644
--- a/arch/arm/dts/armada-38x.dtsi
+++ b/arch/arm/dts/armada-38x.dtsi
@@ -328,6 +328,7 @@
 				compatible = "marvell,armada-380-system-controller",
 					     "marvell,armada-370-xp-system-controller";
 				reg = <0x18200 0x100>;
+				#reset-cells = <2>;
 			};
 
 			gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-xp-98dx3236.dtsi b/arch/arm/dts/armada-xp-98dx3236.dtsi
index 5df1d1848dbc..8369de79afa2 100644
--- a/arch/arm/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/dts/armada-xp-98dx3236.dtsi
@@ -136,6 +136,7 @@
 			systemc: system-controller@18200 {
 				compatible = "marvell,armada-370-xp-system-controller";
 				reg = <0x18200 0x500>;
+				#reset-cells = <2>;
 			};
 
 			gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/dts/armada-xp.dtsi b/arch/arm/dts/armada-xp.dtsi
index d856d9602272..fb5640bbd93c 100644
--- a/arch/arm/dts/armada-xp.dtsi
+++ b/arch/arm/dts/armada-xp.dtsi
@@ -78,6 +78,7 @@
 			systemc: system-controller@18200 {
 				compatible = "marvell,armada-370-xp-system-controller";
 				reg = <0x18200 0x500>;
+				#reset-cells = <2>;
 			};
 
 			gateclk: clock-gating-control@18220 {
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 7e9c206ed6b8..0b2c57e57360 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -21,6 +21,7 @@ else # CONFIG_ARCH_KIRKWOOD
 
 obj-y	= cpu.o
 obj-y	+= dram.o
+obj-$(CONFIG_DM_RESET) += system-controller.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
new file mode 100644
index 000000000000..a59fc26e38b1
--- /dev/null
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+// (C) 2021 Pali Rohár <pali@kernel.org>
+
+#include <common.h>
+#include <dm.h>
+#include <reset-uclass.h>
+#include <asm/io.h>
+
+#define MVEBU_SOC_CONTROL_1_REG 0x4
+
+#define MVEBU_PCIE_ID 0
+
+struct mvebu_reset_data {
+	void *base;
+};
+
+static int mvebu_reset_of_xlate(struct reset_ctl *rst,
+				struct ofnode_phandle_args *args)
+{
+	if (args->args_count < 2)
+		return -EINVAL;
+
+	rst->id = args->args[0];
+	rst->data = args->args[1];
+
+	/* Currently only PCIe is implemented */
+	if (rst->id != MVEBU_PCIE_ID)
+		return -EINVAL;
+
+	/* Four PCIe enable bits are shared across more PCIe links */
+	if (!(rst->data >= 0 && rst->data <= 3))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mvebu_reset_request(struct reset_ctl *rst)
+{
+	return 0;
+}
+
+static int mvebu_reset_free(struct reset_ctl *rst)
+{
+	return 0;
+}
+
+static int mvebu_reset_assert(struct reset_ctl *rst)
+{
+	struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+	clrbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
+	return 0;
+}
+
+static int mvebu_reset_deassert(struct reset_ctl *rst)
+{
+	struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+	setbits_32(data->base + MVEBU_SOC_CONTROL_1_REG, BIT(rst->data));
+	return 0;
+}
+
+static int mvebu_reset_status(struct reset_ctl *rst)
+{
+	struct mvebu_reset_data *data = dev_get_priv(rst->dev);
+
+	return !(readl(data->base + MVEBU_SOC_CONTROL_1_REG) & BIT(rst->data));
+}
+
+static int mvebu_reset_of_to_plat(struct udevice *dev)
+{
+	struct mvebu_reset_data *data = dev_get_priv(dev);
+
+	data->base = (void *)dev_read_addr(dev);
+	if ((fdt_addr_t)data->base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct udevice_id mvebu_reset_of_match[] = {
+	{ .compatible = "marvell,armada-370-xp-system-controller" },
+	{ .compatible = "marvell,armada-375-system-controller" },
+	{ .compatible = "marvell,armada-380-system-controller" },
+	{ .compatible = "marvell,armada-390-system-controller" },
+	{ },
+};
+
+static struct reset_ops mvebu_reset_ops = {
+	.of_xlate = mvebu_reset_of_xlate,
+	.request = mvebu_reset_request,
+	.rfree = mvebu_reset_free,
+	.rst_assert = mvebu_reset_assert,
+	.rst_deassert = mvebu_reset_deassert,
+	.rst_status = mvebu_reset_status,
+};
+
+U_BOOT_DRIVER(mvebu_reset) = {
+	.name = "mvebu-reset",
+	.id = UCLASS_RESET,
+	.of_match = mvebu_reset_of_match,
+	.of_to_plat = mvebu_reset_of_to_plat,
+	.priv_auto = sizeof(struct mvebu_reset_data),
+	.ops = &mvebu_reset_ops,
+};
-- 
2.20.1


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

* [PATCH u-boot-marvell 9/9] arm: mvebu: a38x: serdes: Move non-serdes PCIe code to pci_mvebu.c
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (7 preceding siblings ...)
  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 ` 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
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2021-12-21 11:20 UTC (permalink / raw)
  To: Stefan Roese, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

As explained in commit 3bedbcc3aa18 ("arm: mvebu: a38x: serdes: Don't
overwrite read-only SAR PCIe registers") it is required to set Maximum Link
Width bits of PCIe Root Port Link Capabilities Register depending of number
of used serdes lanes. As this register is part of PCIe address space and
not serdes address space, move it into pci_mvebu.c driver.

Read number of PCIe lanes from DT property "num-lanes" which is used also
by other PCIe controller drivers in Linux kernel. If this property is
absent then it defaults to 1. This property needs to be set to 4 for every
mvebu board which use PEX_ROOT_COMPLEX_X4 or PEX_BUS_MODE_X4.

Enabling of PCIe port needs to be done afer all registers in PCIe address
space are properly configure. For this purpose use new mvebu-reset driver
(part of system-controller) and remove this code from serdes code.

Because some PCIe ports cannot be enabled individually, it is required to
first setup all PCIe ports and then enable them.

This change contains also all required "num-lanes" and "resets" DTS
properties, to make pci_mvebu.c driver work correctly.

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 arch/arm/dts/armada-375.dtsi                  |  2 +
 arch/arm/dts/armada-380.dtsi                  |  3 +
 arch/arm/dts/armada-385.dtsi                  |  4 ++
 arch/arm/dts/armada-xp-98dx3236.dtsi          |  1 +
 arch/arm/dts/armada-xp-mv78230.dtsi           |  5 ++
 arch/arm/dts/armada-xp-mv78260.dtsi           |  9 +++
 arch/arm/dts/armada-xp-mv78460.dtsi           | 10 ++++
 arch/arm/dts/armada-xp-synology-ds414.dts     |  1 +
 arch/arm/dts/armada-xp-theadorable.dts        |  1 +
 arch/arm/mach-mvebu/serdes/a38x/Makefile      |  1 -
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c    | 57 -------------------
 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h    | 27 ---------
 .../serdes/a38x/high_speed_env_spec.c         | 19 -------
 drivers/pci/Kconfig                           |  1 +
 drivers/pci/pci_mvebu.c                       | 43 +++++++++++++-
 15 files changed, 79 insertions(+), 105 deletions(-)
 delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
 delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h

diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi
index fdf2d6dbdc84..ff0ad7a9c7fd 100644
--- a/arch/arm/dts/armada-375.dtsi
+++ b/arch/arm/dts/armada-375.dtsi
@@ -617,6 +617,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -635,6 +636,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/dts/armada-380.dtsi b/arch/arm/dts/armada-380.dtsi
index cff1269f3fbf..f3d7f4b27ddb 100644
--- a/arch/arm/dts/armada-380.dtsi
+++ b/arch/arm/dts/armada-380.dtsi
@@ -73,6 +73,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -92,6 +93,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -111,6 +113,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-385.dtsi b/arch/arm/dts/armada-385.dtsi
index f0022d10c715..581a7d9beac3 100644
--- a/arch/arm/dts/armada-385.dtsi
+++ b/arch/arm/dts/armada-385.dtsi
@@ -78,6 +78,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -97,6 +98,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -116,6 +118,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 
@@ -138,6 +141,7 @@
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 3>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-98dx3236.dtsi b/arch/arm/dts/armada-xp-98dx3236.dtsi
index 8369de79afa2..1a48ff3c6162 100644
--- a/arch/arm/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/dts/armada-xp-98dx3236.dtsi
@@ -85,6 +85,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-mv78230.dtsi b/arch/arm/dts/armada-xp-mv78230.dtsi
index 8558bf6bb54c..63d7f48cf456 100644
--- a/arch/arm/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/dts/armada-xp-mv78230.dtsi
@@ -92,6 +92,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -110,6 +111,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -128,6 +130,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -146,6 +149,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -164,6 +168,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 9>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-mv78260.dtsi b/arch/arm/dts/armada-xp-mv78260.dtsi
index 2d85fe8ac327..5dc413dd14be 100644
--- a/arch/arm/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/dts/armada-xp-mv78260.dtsi
@@ -107,6 +107,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -125,6 +126,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -143,6 +145,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -161,6 +164,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -179,6 +183,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 9>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -197,6 +202,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 10>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -215,6 +221,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 11>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -233,6 +240,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 12>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -251,6 +259,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 26>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-mv78460.dtsi b/arch/arm/dts/armada-xp-mv78460.dtsi
index 230a3fd36b30..6fbd0ce215ff 100644
--- a/arch/arm/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/dts/armada-xp-mv78460.dtsi
@@ -128,6 +128,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 5>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -146,6 +147,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 6>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -164,6 +166,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 7>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -182,6 +185,7 @@
 				marvell,pcie-port = <0>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 8>;
+				resets = <&systemc 0 0>;
 				status = "disabled";
 			};
 
@@ -200,6 +204,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 9>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -218,6 +223,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <1>;
 				clocks = <&gateclk 10>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -236,6 +242,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <2>;
 				clocks = <&gateclk 11>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -254,6 +261,7 @@
 				marvell,pcie-port = <1>;
 				marvell,pcie-lane = <3>;
 				clocks = <&gateclk 12>;
+				resets = <&systemc 0 1>;
 				status = "disabled";
 			};
 
@@ -272,6 +280,7 @@
 				marvell,pcie-port = <2>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 26>;
+				resets = <&systemc 0 2>;
 				status = "disabled";
 			};
 
@@ -290,6 +299,7 @@
 				marvell,pcie-port = <3>;
 				marvell,pcie-lane = <0>;
 				clocks = <&gateclk 27>;
+				resets = <&systemc 0 3>;
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/dts/armada-xp-synology-ds414.dts b/arch/arm/dts/armada-xp-synology-ds414.dts
index 861967cd7e87..35909e3c69c6 100644
--- a/arch/arm/dts/armada-xp-synology-ds414.dts
+++ b/arch/arm/dts/armada-xp-synology-ds414.dts
@@ -187,6 +187,7 @@
 	pcie@1,0 {
 		/* Port 0, Lane 0 */
 		status = "okay";
+		num-lanes = <4>;
 	};
 
 	/*
diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts
index 24cc1cc5278e..a06a65af1587 100644
--- a/arch/arm/dts/armada-xp-theadorable.dts
+++ b/arch/arm/dts/armada-xp-theadorable.dts
@@ -214,5 +214,6 @@
 	pcie@9,0 {
 		/* Port 2, Lane 0 */
 		status = "okay";
+		num-lanes = <4>;
 	};
 };
diff --git a/arch/arm/mach-mvebu/serdes/a38x/Makefile b/arch/arm/mach-mvebu/serdes/a38x/Makefile
index 917fc1350ce5..5a70b3759667 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/Makefile
+++ b/arch/arm/mach-mvebu/serdes/a38x/Makefile
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0+
 
-obj-$(CONFIG_SPL_BUILD)	= ctrl_pex.o
 obj-$(CONFIG_SPL_BUILD)	+= high_speed_env_spec.o
 obj-$(CONFIG_SPL_BUILD)	+= high_speed_env_spec-38x.o
 obj-$(CONFIG_SPL_BUILD)	+= seq_exec.o
diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
deleted file mode 100644
index b3cbddf6a2f0..000000000000
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
+++ /dev/null
@@ -1,57 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#include <common.h>
-#include <spl.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/soc.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-
-#include "ctrl_pex.h"
-#include "sys_env_lib.h"
-
-int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
-{
-	enum serdes_type serdes_type;
-	u32 idx, tmp;
-
-	DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
-
-	tmp = reg_read(SOC_CONTROL_REG1);
-	tmp &= ~0x03;
-
-	for (idx = 0; idx < count; idx++) {
-		serdes_type = serdes_map[idx].serdes_type;
-		if ((serdes_type != PEX0) &&
-		    ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
-		     (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
-			/* for PEX by4 - relevant for the first port only */
-			continue;
-		}
-
-		switch (serdes_type) {
-		case PEX0:
-			tmp |= 0x1 << PCIE0_ENABLE_OFFS;
-			break;
-		case PEX1:
-			tmp |= 0x1 << PCIE1_ENABLE_OFFS;
-			break;
-		case PEX2:
-			tmp |= 0x1 << PCIE2_ENABLE_OFFS;
-			break;
-		case PEX3:
-			tmp |= 0x1 << PCIE3_ENABLE_OFFS;
-			break;
-		default:
-			break;
-		}
-	}
-
-	reg_write(SOC_CONTROL_REG1, tmp);
-
-	return MV_OK;
-}
diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
deleted file mode 100644
index abdbe3c66045..000000000000
--- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
-
-#ifndef _CTRL_PEX_H
-#define _CTRL_PEX_H
-
-#include <pci.h>
-#include "high_speed_env_spec.h"
-
-/* Direct access to PEX0 Root Port's PCIe Capability structure */
-#define PEX0_RP_PCIE_CFG_OFFSET		(0x00080000 + 0x60)
-
-/* SOC_CONTROL_REG1 fields */
-#define PCIE0_ENABLE_OFFS		0
-#define PCIE0_ENABLE_MASK		(0x1 << PCIE0_ENABLE_OFFS)
-#define PCIE1_ENABLE_OFFS		1
-#define PCIE1_ENABLE_MASK		(0x1 << PCIE1_ENABLE_OFFS)
-#define PCIE2_ENABLE_OFFS		2
-#define PCIE2_ENABLE_MASK		(0x1 << PCIE2_ENABLE_OFFS)
-#define PCIE3_ENABLE_OFFS		3
-#define PCIE4_ENABLE_MASK		(0x1 << PCIE3_ENABLE_OFFS)
-
-int hws_pex_config(const struct serdes_map *serdes_map, u8 count);
-
-#endif
diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
index 9ba60b57aac8..2e467b546d5f 100644
--- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
+++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c
@@ -12,7 +12,6 @@
 
 #include "high_speed_env_spec.h"
 #include "sys_env_lib.h"
-#include "ctrl_pex.h"
 
 /*
  * serdes_seq_db - holds all serdes sequences, their size and the
@@ -1555,9 +1554,6 @@ int hws_power_up_serdes_lanes(struct serdes_map *serdes_map, u8 count)
 		   After finish the Power_up sequence for all lanes,
 		   the lanes should be released from reset state.       */
 		CHECK_STATUS(hws_pex_tx_config_seq(serdes_map, count));
-
-		/* PEX configuration */
-		CHECK_STATUS(hws_pex_config(serdes_map, count));
 	}
 
 	/* USB2 configuration */
@@ -1743,21 +1739,6 @@ int serdes_power_up_ctrl(u32 serdes_num, int serdes_power_up,
 				else
 					reg_data &= ~0x4000;
 				reg_write(SOC_CONTROL_REG1, reg_data);
-
-				/*
-				 * Set Maximum Link Width to X1 or X4 in Root
-				 * Port's PCIe Link Capability register.
-				 * This register is read-only but if is not set
-				 * correctly then access to PCI config space of
-				 * endpoint card behind this Root Port does not
-				 * work.
-				 */
-				reg_data = reg_read(PEX0_RP_PCIE_CFG_OFFSET +
-						    PCI_EXP_LNKCAP);
-				reg_data &= ~PCI_EXP_LNKCAP_MLW;
-				reg_data |= (is_pex_by1 ? 1 : 4) << 4;
-				reg_write(PEX0_RP_PCIE_CFG_OFFSET +
-					  PCI_EXP_LNKCAP, reg_data);
 			}
 
 			CHECK_STATUS(mv_seq_exec(serdes_num, PEX_POWER_UP_SEQ));
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index cc139af6cb57..ba0d334e2009 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -259,6 +259,7 @@ config PCI_MVEBU
 	bool "Enable Armada XP/38x PCIe driver"
 	depends on ARCH_MVEBU
 	select MISC
+	select DM_RESET
 	help
 	  Say Y here if you want to enable PCIe controller support on
 	  Armada XP/38x SoCs.
diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index b5b0897b2124..84b8ab4fb4d6 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -18,6 +18,7 @@
 #include <dm/lists.h>
 #include <dm/of_access.h>
 #include <pci.h>
+#include <reset.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
@@ -83,6 +84,7 @@ struct mvebu_pcie {
 	u32 intregs;
 	u32 port;
 	u32 lane;
+	bool is_x4;
 	int devfn;
 	u32 lane_mask;
 	int first_busno;
@@ -388,7 +390,30 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
 /* 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 */
+	struct reset_ctl rst;
+	int ret;
+
+	ret = reset_get_by_index_nodev(node, 0, &rst);
+	if (ret == -ENOENT) {
+		return 0;
+	} else if (ret < 0) {
+		printf("%s: cannot get reset controller: %d\n", pcie->name, ret);
+		return ret;
+	}
+
+	ret = reset_request(&rst);
+	if (ret) {
+		printf("%s: cannot request reset controller: %d\n", pcie->name, ret);
+		return ret;
+	}
+
+	ret = reset_deassert(&rst);
+	reset_free(&rst);
+	if (ret) {
+		printf("%s: cannot enable PCIe port: %d\n", pcie->name, ret);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -401,6 +426,18 @@ static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie)
 	reg = readl(pcie->base + PCIE_CTRL_OFF);
 	reg |= PCIE_CTRL_RC_MODE;
 	writel(reg, pcie->base + PCIE_CTRL_OFF);
+
+	/*
+	 * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
+	 * Capability register. This register is defined by PCIe specification
+	 * as read-only but this mvebu controller has it as read-write and must
+	 * be set to number of SerDes PCIe lanes (1 or 4). If this register is
+	 * not set correctly then link with endpoint card is not established.
+	 */
+	reg = readl(pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
+	reg &= ~PCI_EXP_LNKCAP_MLW;
+	reg |= (pcie->is_x4 ? 4 : 1) << 4;
+	writel(reg, pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
 }
 
 static int mvebu_pcie_probe(struct udevice *dev)
@@ -591,6 +628,7 @@ static int mvebu_pcie_port_parse_dt(ofnode node, ofnode parent, struct mvebu_pci
 {
 	struct fdt_pci_addr pci_addr;
 	const u32 *addr;
+	u32 num_lanes;
 	int ret = 0;
 	int len;
 
@@ -606,6 +644,9 @@ static int mvebu_pcie_port_parse_dt(ofnode node, ofnode parent, struct mvebu_pci
 
 	sprintf(pcie->name, "pcie%d.%d", pcie->port, pcie->lane);
 
+	if (!ofnode_read_u32(node, "num-lanes", &num_lanes) && num_lanes == 4)
+		pcie->is_x4 = true;
+
 	/* 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) {
-- 
2.20.1


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

* Re: [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (8 preceding siblings ...)
  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 ` Pali Rohár
  2022-01-14 15:33 ` Stefan Roese
  10 siblings, 0 replies; 12+ messages in thread
From: Pali Rohár @ 2022-01-04 22:08 UTC (permalink / raw)
  To: Mario Six; +Cc: Stefan Roese, Marek Behún, Chris Packham, u-boot

Mario: Could you please look at this patch series? It touches gdsys
board and for future gdsys board should be converted to use u-boot
driver model API...

On Tuesday 21 December 2021 12:20:10 Pali Rohár wrote:
> This patch series removes gdsys's board_pex_config() function by
> converting it to spl_board_init(), adds a new mvebu-reset driver for
> enabling / disabling PCIe ports and finally moves PCIe code from serdes
> driver to pci_mvebu.c driver.
> 
> After all these changes, PCIe link is not initialized in serdes code
> anymore, but in pci_mvebu.c driver with help of mvebu-reset driver.
> 
> I'm not sure if change for gdsys board is correct, so if somebody has
> this board, please test it.
> 
> I tested this change on A385 board Turris Omnia and I verified that PCIe
> links are really enabled by pci_mvebu.c driver and not before.
> 
> This patch series is based on u-boot-marvell/next branch.
> 
> Pali Rohár (9):
>   arm: mvebu: Convert board_pex_config() to CONFIG_SPL_BOARD_INIT
>   board: gdsys: a38x: Enable PCIe link 2 in spl_board_init()
>   pci: pci_mvebu: Fix PCIe MEM and IO resources assignment and mbus
>     mapping
>   pci: pci_mvebu: Inline mvebu_pcie_port_parse_dt() function
>   pci: pci_mvebu: Remove dependency on SOC_REGS_PHY_BASE macro
>   pci: pci_mvebu: Split initialization of PCIe ports into 3 phases
>   pci: pci_mvebu: Wait 100ms for Link Up in mvebu_pcie_probe()
>   arm: mvebu: Implement simple mvebu-reset driver for enabling/disabling
>     PCIe ports
>   arm: mvebu: a38x: serdes: Move non-serdes PCIe code to pci_mvebu.c
> 
>  arch/arm/dts/armada-375.dtsi                  |   5 +-
>  arch/arm/dts/armada-380.dtsi                  |   3 +
>  arch/arm/dts/armada-385.dtsi                  |   4 +
>  arch/arm/dts/armada-38x.dtsi                  |   1 +
>  arch/arm/dts/armada-xp-98dx3236.dtsi          |   2 +
>  arch/arm/dts/armada-xp-mv78230.dtsi           |   5 +
>  arch/arm/dts/armada-xp-mv78260.dtsi           |   9 +
>  arch/arm/dts/armada-xp-mv78460.dtsi           |  10 +
>  arch/arm/dts/armada-xp-synology-ds414.dts     |   1 +
>  arch/arm/dts/armada-xp-theadorable.dts        |   1 +
>  arch/arm/dts/armada-xp.dtsi                   |   1 +
>  arch/arm/mach-mvebu/Makefile                  |   1 +
>  arch/arm/mach-mvebu/include/mach/cpu.h        |   5 +-
>  arch/arm/mach-mvebu/serdes/a38x/Makefile      |   1 -
>  arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c    |  64 ----
>  arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h    |  28 --
>  .../serdes/a38x/high_speed_env_spec.c         |  19 --
>  arch/arm/mach-mvebu/system-controller.c       | 105 +++++++
>  board/gdsys/a38x/controlcenterdc.c            |   6 +-
>  configs/controlcenterdc_defconfig             |   1 +
>  drivers/pci/Kconfig                           |   1 +
>  drivers/pci/pci_mvebu.c                       | 275 ++++++++++++++----
>  22 files changed, 371 insertions(+), 177 deletions(-)
>  delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
>  delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
>  create mode 100644 arch/arm/mach-mvebu/system-controller.c
> 
> -- 
> 2.20.1
> 

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

* Re: [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver
  2021-12-21 11:20 [PATCH u-boot-marvell 0/9] mvebu: Move PCIe code from serdes to PCIe driver Pali Rohár
                   ` (9 preceding siblings ...)
  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
  10 siblings, 0 replies; 12+ messages in thread
From: Stefan Roese @ 2022-01-14 15:33 UTC (permalink / raw)
  To: Pali Rohár, Dirk Eibach, Mario Six, Marek Behún, Chris Packham
  Cc: u-boot

On 12/21/21 12:20, Pali Rohár wrote:
> This patch series removes gdsys's board_pex_config() function by
> converting it to spl_board_init(), adds a new mvebu-reset driver for
> enabling / disabling PCIe ports and finally moves PCIe code from serdes
> driver to pci_mvebu.c driver.
> 
> After all these changes, PCIe link is not initialized in serdes code
> anymore, but in pci_mvebu.c driver with help of mvebu-reset driver.
> 
> I'm not sure if change for gdsys board is correct, so if somebody has
> this board, please test it.
> 
> I tested this change on A385 board Turris Omnia and I verified that PCIe
> links are really enabled by pci_mvebu.c driver and not before.
> 
> This patch series is based on u-boot-marvell/next branch.
> 
> Pali Rohár (9):
>    arm: mvebu: Convert board_pex_config() to CONFIG_SPL_BOARD_INIT
>    board: gdsys: a38x: Enable PCIe link 2 in spl_board_init()
>    pci: pci_mvebu: Fix PCIe MEM and IO resources assignment and mbus
>      mapping
>    pci: pci_mvebu: Inline mvebu_pcie_port_parse_dt() function
>    pci: pci_mvebu: Remove dependency on SOC_REGS_PHY_BASE macro
>    pci: pci_mvebu: Split initialization of PCIe ports into 3 phases
>    pci: pci_mvebu: Wait 100ms for Link Up in mvebu_pcie_probe()
>    arm: mvebu: Implement simple mvebu-reset driver for enabling/disabling
>      PCIe ports
>    arm: mvebu: a38x: serdes: Move non-serdes PCIe code to pci_mvebu.c
> 
>   arch/arm/dts/armada-375.dtsi                  |   5 +-
>   arch/arm/dts/armada-380.dtsi                  |   3 +
>   arch/arm/dts/armada-385.dtsi                  |   4 +
>   arch/arm/dts/armada-38x.dtsi                  |   1 +
>   arch/arm/dts/armada-xp-98dx3236.dtsi          |   2 +
>   arch/arm/dts/armada-xp-mv78230.dtsi           |   5 +
>   arch/arm/dts/armada-xp-mv78260.dtsi           |   9 +
>   arch/arm/dts/armada-xp-mv78460.dtsi           |  10 +
>   arch/arm/dts/armada-xp-synology-ds414.dts     |   1 +
>   arch/arm/dts/armada-xp-theadorable.dts        |   1 +
>   arch/arm/dts/armada-xp.dtsi                   |   1 +
>   arch/arm/mach-mvebu/Makefile                  |   1 +
>   arch/arm/mach-mvebu/include/mach/cpu.h        |   5 +-
>   arch/arm/mach-mvebu/serdes/a38x/Makefile      |   1 -
>   arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c    |  64 ----
>   arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h    |  28 --
>   .../serdes/a38x/high_speed_env_spec.c         |  19 --
>   arch/arm/mach-mvebu/system-controller.c       | 105 +++++++
>   board/gdsys/a38x/controlcenterdc.c            |   6 +-
>   configs/controlcenterdc_defconfig             |   1 +
>   drivers/pci/Kconfig                           |   1 +
>   drivers/pci/pci_mvebu.c                       | 275 ++++++++++++++----
>   22 files changed, 371 insertions(+), 177 deletions(-)
>   delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
>   delete mode 100644 arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h
>   create mode 100644 arch/arm/mach-mvebu/system-controller.c
> 

Applied to u-boot-marvell/master

Thanks,
Stefan

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

end of thread, other threads:[~2022-01-14 15:33 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH u-boot-marvell 6/9] pci: pci_mvebu: Split initialization of PCIe ports into 3 phases Pali Rohár
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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.