mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH RESEND 0/6] Marvell EBU PCIe driver
@ 2014-07-23  9:26 Sebastian Hesselbarth
  2014-07-23  9:26 ` [PATCH RESEND 1/6] bus: mvebu: fix resource size handling Sebastian Hesselbarth
                   ` (6 more replies)
  0 siblings, 7 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23  9:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox; +Cc: Thomas Petazzoni

[Resending because I made a mistake when calling git send-email causing
the barebox ML to be dropped]

This patch set adds support for PCIe controllers found on Marvell EBU
SoCs.

First, it fixes mvebu-mbus to properly compute resources from DT and
extends pci_scan_bus for 64-bit BAR detection. Then it prepares PCI
framework to allow to access the host controller struct from struct
pci_bus and set a non-zero bus number. Also, a DT helper for parsing
devfn number is imported from Linux.

Finally, it adds the PCIe host controller driver and SoC specific PHY
setup (for Armada 370 only yet) allowing to access PCI devices attached
to it.

I have tested the driver on Armada 370 Mirabox on both mini-PCIe slot
and on-board USB 3.0 controller. The dts is missing reset-gpios
properties for gpio1.28 and gpio1.22 respectively. A corresponding
patch to add them to armada-370-mirabox.dts will be sent on Linux ML.

As soon as I get barebox running on Dove and Kirkwood boards with
accessible/populated PCIe slots, I'll add PHY support for those.
For Armada XP, I still struggle to fully understand the DT binding
which IMHO allows to configure both available ports to Nx1 but not
to 1x4. Anyway, I don't have an Armada XP board available, but maybe
Thomas or Ezequiel can shed some light into it.

Sebastian

Sebastian Hesselbarth (6):
  bus: mvebu: fix resource size handling
  pci: pci_scan_bus: respect 64b BARs
  pci: add host controller struct to sysdata
  pci: allow to set bus number on register_pci_controller
  of: pci: import of_pci_get_devfn()
  pci: mvebu: Add PCIe driver

 arch/arm/Kconfig            |   1 +
 arch/mips/mach-malta/pci.c  |   2 +-
 drivers/bus/mvebu-mbus.c    |   8 +-
 drivers/of/Kconfig          |   6 +
 drivers/of/Makefile         |   1 +
 drivers/of/of_pci.c         |  27 +++
 drivers/pci/Kconfig         |   6 +
 drivers/pci/Makefile        |   2 +
 drivers/pci/pci-mvebu-phy.c | 102 +++++++++++
 drivers/pci/pci-mvebu.c     | 436 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci-mvebu.h     |  35 ++++
 drivers/pci/pci.c           |  12 +-
 include/linux/pci.h         |   2 +-
 include/of_pci.h            |  17 ++
 14 files changed, 649 insertions(+), 8 deletions(-)
 create mode 100644 drivers/of/of_pci.c
 create mode 100644 drivers/pci/pci-mvebu-phy.c
 create mode 100644 drivers/pci/pci-mvebu.c
 create mode 100644 drivers/pci/pci-mvebu.h
 create mode 100644 include/of_pci.h

---
To: barebox@lists.infradead.org
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH RESEND 1/6] bus: mvebu: fix resource size handling
  2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
@ 2014-07-23  9:26 ` Sebastian Hesselbarth
  2014-07-23  9:26 ` [PATCH RESEND 2/6] pci: pci_scan_bus: respect 64b BARs Sebastian Hesselbarth
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23  9:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox; +Cc: Thomas Petazzoni

A resource_size is defined as res->end - res->start + 1. Marvell
MBUS driver gets some ranges from DT as start and size but mis-calculates
end of range. This fixes 4 occurences of those mistakes.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
To: barebox@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/bus/mvebu-mbus.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 11e3777a6094..c67646f61722 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -187,7 +187,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
 				       phys_addr_t base, size_t size,
 				       u8 target, u8 attr)
 {
-	u64 end = (u64)base + size;
+	u64 end = (u64)base + size - 1;
 	int win;
 
 	for (win = 0; win < mbus->soc->num_wins; win++) {
@@ -203,7 +203,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
 		if (!enabled)
 			continue;
 
-		wend = wbase + wsize;
+		wend = wbase + wsize - 1;
 
 		/*
 		 * Check if the current window overlaps with the
@@ -661,7 +661,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np,
 					 reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		mem->start = reg[0];
-		mem->end = mem->start + reg[1];
+		mem->end = mem->start + reg[1] - 1;
 		mem->flags = IORESOURCE_MEM;
 	}
 
@@ -669,7 +669,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np,
 					 reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		io->start = reg[0];
-		io->end = io->start + reg[1];
+		io->end = io->start + reg[1] - 1;
 		io->flags = IORESOURCE_IO;
 	}
 }
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH RESEND 2/6] pci: pci_scan_bus: respect 64b BARs
  2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
  2014-07-23  9:26 ` [PATCH RESEND 1/6] bus: mvebu: fix resource size handling Sebastian Hesselbarth
@ 2014-07-23  9:26 ` Sebastian Hesselbarth
  2014-07-25  8:51   ` Lucas Stach
  2014-07-23  9:26 ` [PATCH RESEND 3/6] pci: add host controller struct to sysdata Sebastian Hesselbarth
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23  9:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox; +Cc: Thomas Petazzoni

In PCI 64-bit BARs span two 32-bit BARs, therefore if BAR type
indicates a 64-bit BAR we have to skip the next BAR register.
Note that this does not add proper support for 64-bit BARs and
64-bit addresses but still picks the lower 32-bit address.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
To: barebox@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/pci/pci.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3d88b0ff5fd0..e5cd8a33b2be 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -196,6 +196,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
 
 		for (bar = 0; bar < 6; bar++) {
 			resource_size_t last_addr;
+			bool found_bar64 = false;
 
 			pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &old_bar);
 			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
@@ -213,17 +214,22 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
 				pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
 				last_addr = last_io;
 				last_io += size;
-
 			} else { /* MEM */
 				size = -(mask & 0xfffffff0);
 				DBG("  PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size);
 				pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
 				last_addr = last_mem;
 				last_mem += size;
+
+				if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+				    PCI_BASE_ADDRESS_MEM_TYPE_64)
+					found_bar64 = true;
 			}
 
 			dev->resource[bar].start = last_addr;
 			dev->resource[bar].end = last_addr + size - 1;
+			if (found_bar64)
+				bar++;
 		}
 	}
 
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH RESEND 3/6] pci: add host controller struct to sysdata
  2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
  2014-07-23  9:26 ` [PATCH RESEND 1/6] bus: mvebu: fix resource size handling Sebastian Hesselbarth
  2014-07-23  9:26 ` [PATCH RESEND 2/6] pci: pci_scan_bus: respect 64b BARs Sebastian Hesselbarth
@ 2014-07-23  9:26 ` Sebastian Hesselbarth
  2014-07-25  9:07   ` Lucas Stach
  2014-07-23  9:26 ` [PATCH RESEND 4/6] pci: allow to set bus number on register_pci_controller Sebastian Hesselbarth
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23  9:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox; +Cc: Thomas Petazzoni

struct pci_bus allows to set some private sysdata. Assign the host
controller struct to it by default.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
To: barebox@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/pci/pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e5cd8a33b2be..b30cdd96f8ca 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -39,6 +39,7 @@ void register_pci_controller(struct pci_controller *hose)
 	bus->ops = hose->pci_ops;
 	bus->resource[0] = hose->mem_resource;
 	bus->resource[1] = hose->io_resource;
+	bus->sysdata = hose;
 
 	pci_scan_bus(bus);
 
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH RESEND 4/6] pci: allow to set bus number on register_pci_controller
  2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
                   ` (2 preceding siblings ...)
  2014-07-23  9:26 ` [PATCH RESEND 3/6] pci: add host controller struct to sysdata Sebastian Hesselbarth
@ 2014-07-23  9:26 ` Sebastian Hesselbarth
  2014-07-23  9:26 ` [PATCH RESEND 5/6] of: pci: import of_pci_get_devfn() Sebastian Hesselbarth
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23  9:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox; +Cc: Thomas Petazzoni

Currently, all PCI controllers are registered with struct pci_bus
number set to zero. Allow to set the bus number before registering
the controller and scan the bus.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
To: barebox@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/mips/mach-malta/pci.c | 2 +-
 drivers/pci/pci.c          | 3 ++-
 include/linux/pci.h        | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/mips/mach-malta/pci.c b/arch/mips/mach-malta/pci.c
index 90351758e06d..47bfb4cc0833 100644
--- a/arch/mips/mach-malta/pci.c
+++ b/arch/mips/mach-malta/pci.c
@@ -229,7 +229,7 @@ static int pcibios_init(void)
 		GT_WRITE(GT_PCI0IOREMAP_OFS, map);
 	}
 
-	register_pci_controller(&gt64120_controller);
+	register_pci_controller(&gt64120_controller, 0);
 
 	return 0;
 }
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b30cdd96f8ca..f755d13e14ee 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -27,7 +27,7 @@ static struct pci_bus *pci_alloc_bus(void)
 	return b;
 }
 
-void register_pci_controller(struct pci_controller *hose)
+void register_pci_controller(struct pci_controller *hose, int num)
 {
 	struct pci_bus *bus;
 
@@ -39,6 +39,7 @@ void register_pci_controller(struct pci_controller *hose)
 	bus->ops = hose->pci_ops;
 	bus->resource[0] = hose->mem_resource;
 	bus->resource[1] = hose->io_resource;
+	bus->number = num;
 	bus->sysdata = hose;
 
 	pci_scan_bus(bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6caed01c9939..c044225c3ecb 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -246,7 +246,7 @@ int pci_register_device(struct pci_dev *pdev);
 extern struct list_head pci_root_buses; /* list of all known PCI buses */
 
 extern unsigned int pci_scan_bus(struct pci_bus *bus);
-extern void register_pci_controller(struct pci_controller *hose);
+extern void register_pci_controller(struct pci_controller *hose, int num);
 
 int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
 			     int where, u8 *val);
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH RESEND 5/6] of: pci: import of_pci_get_devfn()
  2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
                   ` (3 preceding siblings ...)
  2014-07-23  9:26 ` [PATCH RESEND 4/6] pci: allow to set bus number on register_pci_controller Sebastian Hesselbarth
@ 2014-07-23  9:26 ` Sebastian Hesselbarth
  2014-07-23  9:26 ` [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
  6 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23  9:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox; +Cc: Thomas Petazzoni

Marvell MVEBU PCIe driver requires of_pcie_get_devfn(), import it from
Linux.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
To: barebox@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/of/Kconfig  |  6 ++++++
 drivers/of/Makefile |  1 +
 drivers/of/of_pci.c | 27 +++++++++++++++++++++++++++
 include/of_pci.h    | 17 +++++++++++++++++
 4 files changed, 51 insertions(+)
 create mode 100644 drivers/of/of_pci.c
 create mode 100644 include/of_pci.h

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 2b28cf3fb425..81955063d70c 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -27,6 +27,12 @@ config OF_GPIO
 	depends on OFDEVICE
 	def_bool y
 
+config OF_PCI
+	bool
+	depends on PCI
+	help
+	  OpenFirmware PCI bus accessors
+
 config OF_BAREBOX_DRIVERS
 	depends on OFDEVICE
 	depends on ENV_HANDLING
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index c883e516c834..0dc2f8d63ed0 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,6 +1,7 @@
 obj-y += address.o base.o fdt.o platform.o
 obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o
 obj-$(CONFIG_OF_GPIO) += of_gpio.o
+obj-$(CONFIG_OF_PCI) += of_pci.o
 obj-y += partition.o
 obj-y += of_net.o
 obj-$(CONFIG_MTD) += of_mtd.o
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
new file mode 100644
index 000000000000..2d0fbd2e5f69
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,27 @@
+#include <common.h>
+#include <errno.h>
+#include <of.h>
+#include <of_pci.h>
+
+/**
+ * of_pci_get_devfn() - Get device and function numbers for a device node
+ * @np: device node
+ *
+ * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
+ * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
+ * and function numbers respectively. On error a negative error code is
+ * returned.
+ */
+int of_pci_get_devfn(struct device_node *np)
+{
+	unsigned int size;
+	const __be32 *reg;
+
+	reg = of_get_property(np, "reg", &size);
+
+	if (!reg || size < 5 * sizeof(__be32))
+		return -EINVAL;
+
+	return (be32_to_cpup(reg) >> 8) & 0xff;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_devfn);
diff --git a/include/of_pci.h b/include/of_pci.h
new file mode 100644
index 000000000000..c95cb0135ae0
--- /dev/null
+++ b/include/of_pci.h
@@ -0,0 +1,17 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+#ifdef CONFIG_OF_PCI
+int of_pci_get_devfn(struct device_node *np);
+
+#else
+static inline int of_pci_get_devfn(struct device_node *np)
+{
+	return -EINVAL;
+}
+
+#endif
+
+#endif
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
                   ` (4 preceding siblings ...)
  2014-07-23  9:26 ` [PATCH RESEND 5/6] of: pci: import of_pci_get_devfn() Sebastian Hesselbarth
@ 2014-07-23  9:26 ` Sebastian Hesselbarth
  2014-07-23 10:35   ` Sebastian Hesselbarth
                     ` (2 more replies)
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
  6 siblings, 3 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23  9:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, barebox; +Cc: Thomas Petazzoni

This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
Besides the functional driver itself, it also adds SoC specific PHY
setup required for PCIe. Currently, only Armada 370 is fully supported.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
To: barebox@lists.infradead.org
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/Kconfig            |   1 +
 drivers/pci/Kconfig         |   6 +
 drivers/pci/Makefile        |   2 +
 drivers/pci/pci-mvebu-phy.c | 102 +++++++++++
 drivers/pci/pci-mvebu.c     | 436 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci-mvebu.h     |  35 ++++
 6 files changed, 582 insertions(+)
 create mode 100644 drivers/pci/pci-mvebu-phy.c
 create mode 100644 drivers/pci/pci-mvebu.c
 create mode 100644 drivers/pci/pci-mvebu.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8465d4a7f739..be5c7bd1981b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -93,6 +93,7 @@ config ARCH_MVEBU
 	select GPIOLIB
 	select HAS_DEBUG_LL
 	select HAVE_PBL_MULTI_IMAGES
+	select HW_HAS_PCI
 	select MVEBU_MBUS
 	select OFTREE
 	select OF_ADDRESS_PCI
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 9e4659270d25..d17a1510821f 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -24,6 +24,12 @@ config PCI_DEBUG
 
 	  When in doubt, say N.
 
+config PCI_MVEBU
+	bool "Marvell EBU PCIe driver"
+	depends on ARCH_MVEBU
+	select OF_PCI
+	select PCI
+
 endmenu
 
 endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index edac1a53de78..442353173c9e 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -6,3 +6,5 @@ obj-y		+= pci.o bus.o pci_iomap.o
 ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
 
 CPPFLAGS += $(ccflags-y)
+
+obj-$(CONFIG_PCI_MVEBU)	+= pci-mvebu.o pci-mvebu-phy.o
diff --git a/drivers/pci/pci-mvebu-phy.c b/drivers/pci/pci-mvebu-phy.c
new file mode 100644
index 000000000000..9997cdbb0a6a
--- /dev/null
+++ b/drivers/pci/pci-mvebu-phy.c
@@ -0,0 +1,102 @@
+/*
+ * SoC specific PCIe PHY setup for Marvell MVEBU SoCs
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * based on Marvell BSP code (C) Marvell International Ltd.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <of.h>
+#include <of_address.h>
+
+#include "pci-mvebu.h"
+
+static u32 mvebu_pcie_phy_indirect(void __iomem *phybase, u8 lane,
+				   u8 off, u16 val, bool is_read)
+{
+	u32 reg = (lane << 24) | (off << 16) | val;
+
+	if (is_read)
+		reg |= BIT(31);
+	writel(reg, phybase);
+
+	return (is_read) ? readl(phybase) & 0xffff : 0;
+}
+
+static inline u32 mvebu_pcie_phy_read(void __iomem *phybase, u8 lane,
+				      u8 off)
+{
+	return mvebu_pcie_phy_indirect(phybase, lane, off, 0, true);
+}
+
+static inline void mvebu_pcie_phy_write(void __iomem *phybase, u8 lane,
+					u8 off, u16 val)
+{
+	mvebu_pcie_phy_indirect(phybase, lane, off, val, false);
+}
+
+#define ARMADA_370_PHY_OFFSET	0x1b00
+#define ARMADA_370_SOC_CTRL	0x04
+#define ARMADA_370_SERDES03_SEL	0x70
+
+int armada_370_phy_setup(struct mvebu_pcie *pcie)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+				 "marvell,armada-370-xp-system-controller");
+	void __iomem *sysctrl = of_iomap(np, 0);
+	void __iomem *phybase = pcie->base + ARMADA_370_PHY_OFFSET;
+	u32 reg;
+
+	if (!sysctrl)
+		return -ENODEV;
+
+	/* Enable PEX */
+	reg = readl(sysctrl + ARMADA_370_SOC_CTRL);
+	reg |= BIT(pcie->port);
+	writel(reg, sysctrl + ARMADA_370_SOC_CTRL);
+
+	/* Set SERDES selector */
+	reg = readl(sysctrl + ARMADA_370_SERDES03_SEL);
+	reg &= ~(0xf << (pcie->port * 4));
+	reg |= (0x1 << (pcie->port * 4));
+	writel(reg, sysctrl + ARMADA_370_SERDES03_SEL);
+
+	/* BTS #232 - PCIe clock (undocumented) */
+	writel(0x00000077, sysctrl + 0x2f0);
+
+	/* Disable Link (undocumented) */
+	reg = readl(pcie->base + 0x6c);
+	reg &= ~0x3f0;
+	reg |= BIT(4);
+	writel(reg, pcie->base + 0x6c);
+
+	/* PEX pipe configuration */
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0025);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x000f);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc8, 0x0005);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xd0, 0x0100);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xd1, 0x3014);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc5, 0x011f);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x80, 0x1000);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x81, 0x0011);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x0f, 0x2a21);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x45, 0x00df);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x4f, 0x6219);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x01, 0xfc60);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x46, 0x0000);
+
+	reg = mvebu_pcie_phy_read(phybase, pcie->lane, 0x48) & ~0x4;
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, reg & 0xffff);
+
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x02, 0x0040);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0024);
+
+	mdelay(15);
+
+	return 0;
+}
diff --git a/drivers/pci/pci-mvebu.c b/drivers/pci/pci-mvebu.c
new file mode 100644
index 000000000000..6fee0800e98e
--- /dev/null
+++ b/drivers/pci/pci-mvebu.c
@@ -0,0 +1,436 @@
+/*
+ * PCIe driver for Marvell MVEBU SoCs
+ *
+ * Based on Linux drivers/pci/host/pci-mvebu.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mbus.h>
+#include <linux/pci_regs.h>
+#include <malloc.h>
+#include <of_address.h>
+#include <of_gpio.h>
+#include <of_pci.h>
+#include <sizes.h>
+
+#include "pci-mvebu.h"
+
+/* PCIe unit register offsets */
+#define PCIE_DEV_ID_OFF			0x0000
+#define PCIE_CMD_OFF			0x0004
+#define PCIE_DEV_REV_OFF		0x0008
+#define  PCIE_BAR_LO_OFF(n)		(0x0010 + ((n) << 3))
+#define  PCIE_BAR_HI_OFF(n)		(0x0014 + ((n) << 3))
+#define PCIE_HEADER_LOG_4_OFF		0x0128
+#define  PCIE_BAR_CTRL_OFF(n)		(0x1804 + (((n) - 1) * 4))
+#define  PCIE_WIN04_CTRL_OFF(n)		(0x1820 + ((n) << 4))
+#define  PCIE_WIN04_BASE_OFF(n)		(0x1824 + ((n) << 4))
+#define  PCIE_WIN04_REMAP_OFF(n)	(0x182c + ((n) << 4))
+#define PCIE_WIN5_CTRL_OFF		0x1880
+#define PCIE_WIN5_BASE_OFF		0x1884
+#define PCIE_WIN5_REMAP_OFF		0x188c
+#define PCIE_CONF_ADDR_OFF		0x18f8
+#define  PCIE_CONF_ADDR_EN		BIT(31)
+#define  PCIE_CONF_REG(r)		((((r) & 0xf00) << 16) | ((r) & 0xfc))
+#define  PCIE_CONF_BUS(b)		(((b) & 0xff) << 16)
+#define  PCIE_CONF_DEV(d)		(((d) & 0x1f) << 11)
+#define  PCIE_CONF_FUNC(f)		(((f) & 0x7) << 8)
+#define  PCIE_CONF_ADDR(bus, devfn, where) \
+	(PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn))    | \
+	 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | \
+	 PCIE_CONF_ADDR_EN)
+#define PCIE_CONF_DATA_OFF		0x18fc
+#define PCIE_MASK_OFF			0x1910
+#define  PCIE_MASK_ENABLE_INTS          (0xf << 24)
+#define PCIE_CTRL_OFF			0x1a00
+#define  PCIE_CTRL_X1_MODE		BIT(0)
+#define PCIE_STAT_OFF			0x1a04
+#define  PCIE_STAT_BUS                  (0xff << 8)
+#define  PCIE_STAT_DEV                  (0x1f << 16)
+#define  PCIE_STAT_LINK_DOWN		BIT(0)
+#define PCIE_DEBUG_CTRL         	0x1a60
+#define  PCIE_DEBUG_SOFT_RESET		BIT(20)
+
+#define to_pcie(_hc)	container_of(_hc, struct mvebu_pcie, pci)
+
+/*
+ * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
+ * into SoCs address space. Each controller will map 32M of MEM
+ * and 64K of I/O space when registered.
+ */
+static void __iomem *mvebu_pcie_membase = IOMEM(0xe0000000);
+static void __iomem *mvebu_pcie_iobase = IOMEM(0xffe00000);
+
+static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
+{
+	return !(readl(pcie->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
+}
+
+static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie *pcie, int nr)
+{
+	u32 stat;
+
+	stat = readl(pcie->base + PCIE_STAT_OFF);
+	stat &= ~PCIE_STAT_BUS;
+	stat |= nr << 8;
+	writel(stat, pcie->base + PCIE_STAT_OFF);
+}
+
+static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie *pcie, int nr)
+{
+	u32 stat;
+
+	stat = readl(pcie->base + PCIE_STAT_OFF);
+	stat &= ~PCIE_STAT_DEV;
+	stat |= nr << 16;
+	writel(stat, pcie->base + PCIE_STAT_OFF);
+}
+
+static int mvebu_pcie_indirect_rd_conf(struct pci_bus *bus,
+	       unsigned int devfn, int where, int size, u32 *val)
+{
+	struct pci_controller *pci = bus->sysdata;
+	struct mvebu_pcie *pcie = to_pcie(pci);
+
+	/* Skip all requests not directed to device behind bridge */
+	if (devfn != 0x08 || !mvebu_pcie_link_up(pcie)) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
+	       pcie->base + PCIE_CONF_ADDR_OFF);
+
+	*val = readl(pcie->base + PCIE_CONF_DATA_OFF);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mvebu_pcie_indirect_wr_conf(struct pci_bus *bus,
+	       unsigned int devfn, int where, int size, u32 val)
+{
+	struct pci_controller *pci = bus->sysdata;
+	struct mvebu_pcie *pcie = to_pcie(pci);
+	u32 _val, shift = 8 * (where & 3);
+
+	/* Skip all requests not directed to device behind bridge */
+	if (devfn != 0x08 || !mvebu_pcie_link_up(pcie))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
+	       pcie->base + PCIE_CONF_ADDR_OFF);
+	_val = readl(pcie->base + PCIE_CONF_DATA_OFF);
+
+	if (size == 4)
+		_val = val;
+	else if (size == 2)
+		_val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
+	else if (size == 1)
+		_val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
+	else
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	writel(_val, pcie->base + PCIE_CONF_DATA_OFF);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mvebu_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr)
+{
+	struct pci_controller *pci = bus->sysdata;
+	struct mvebu_pcie *pcie = to_pcie(pci);
+
+	return (int)pcie->membase + res_addr;
+}
+
+static struct pci_ops mvebu_pcie_indirect_ops = {
+	.read = mvebu_pcie_indirect_rd_conf,
+	.write = mvebu_pcie_indirect_wr_conf,
+	.res_start = mvebu_pcie_res_start,
+};
+
+/*
+ * Setup PCIE BARs and Address Decode Wins:
+ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+ * WIN[0-3] -> DRAM bank[0-3]
+ */
+static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
+{
+	const struct mbus_dram_target_info *dram = mvebu_mbus_dram_info();
+	u32 size;
+	int i;
+
+	/* First, disable and clear BARs and windows. */
+	for (i = 1; i < 3; i++) {
+		writel(0, pcie->base + PCIE_BAR_CTRL_OFF(i));
+		writel(0, pcie->base + PCIE_BAR_LO_OFF(i));
+		writel(0, pcie->base + PCIE_BAR_HI_OFF(i));
+	}
+
+	for (i = 0; i < 5; i++) {
+		writel(0, pcie->base + PCIE_WIN04_CTRL_OFF(i));
+		writel(0, pcie->base + PCIE_WIN04_BASE_OFF(i));
+		writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
+	}
+
+	writel(0, pcie->base + PCIE_WIN5_CTRL_OFF);
+	writel(0, pcie->base + PCIE_WIN5_BASE_OFF);
+	writel(0, pcie->base + PCIE_WIN5_REMAP_OFF);
+
+	/* Setup windows for DDR banks.  Count total DDR size on the fly. */
+	size = 0;
+	for (i = 0; i < dram->num_cs; i++) {
+		const struct mbus_dram_window *cs = dram->cs + i;
+
+		writel(cs->base & 0xffff0000,
+		       pcie->base + PCIE_WIN04_BASE_OFF(i));
+		writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
+		writel(((cs->size - 1) & 0xffff0000) |
+		       (cs->mbus_attr << 8) |
+		       (dram->mbus_dram_target_id << 4) | 1,
+		       pcie->base + PCIE_WIN04_CTRL_OFF(i));
+
+		size += cs->size;
+	}
+
+	/* Round up 'size' to the nearest power of two. */
+	if ((size & (size - 1)) != 0)
+		size = 1 << fls(size);
+
+	/* Setup BAR[1] to all DRAM banks. */
+	writel(dram->cs[0].base, pcie->base + PCIE_BAR_LO_OFF(1));
+	writel(0, pcie->base + PCIE_BAR_HI_OFF(1));
+	writel(((size - 1) & 0xffff0000) | 1,
+	       pcie->base + PCIE_BAR_CTRL_OFF(1));
+}
+
+#define DT_FLAGS_TO_TYPE(flags)		(((flags) >> 24) & 0x03)
+#define  DT_TYPE_IO	0x1
+#define  DT_TYPE_MEM32	0x2
+#define DT_CPUADDR_TO_TARGET(cpuaddr)	(((cpuaddr) >> 56) & 0xFF)
+#define DT_CPUADDR_TO_ATTR(cpuaddr)	(((cpuaddr) >> 48) & 0xFF)
+
+static int mvebu_get_target_attr(struct device_node *np, int devfn,
+		 unsigned long type, unsigned int *target, unsigned int *attr)
+{
+	const int na = 3, ns = 2;
+	const __be32 *range;
+	int rlen, nranges, rangesz, pna, i;
+
+	*target = -1;
+	*attr = -1;
+
+	range = of_get_property(np, "ranges", &rlen);
+	if (!range)
+		return -EINVAL;
+
+	pna = of_n_addr_cells(np);
+	rangesz = pna + na + ns;
+	nranges = rlen / sizeof(__be32) / rangesz;
+
+	for (i = 0; i < nranges; i++) {
+		u32 flags = of_read_number(range, 1);
+		u32 slot = of_read_number(range + 1, 1);
+		u64 cpuaddr = of_read_number(range + na, pna);
+		unsigned long rtype;
+
+		if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO)
+			rtype = IORESOURCE_IO;
+		else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32)
+			rtype = IORESOURCE_MEM;
+
+		if (slot == PCI_SLOT(devfn) && type == rtype) {
+			*target = DT_CPUADDR_TO_TARGET(cpuaddr);
+			*attr = DT_CPUADDR_TO_ATTR(cpuaddr);
+			return 0;
+		}
+
+		range += rangesz;
+	}
+
+	return -ENOENT;
+}
+
+static struct mvebu_pcie *mvebu_pcie_port_probe(struct device_d *dev,
+						struct device_node *np)
+{
+	struct mvebu_pcie *pcie;
+	struct clk *clk;
+	enum of_gpio_flags flags;
+	int reset_gpio;
+	u32 port, lane, devfn;
+	int mem_target, mem_attr;
+	int io_target, io_attr;
+	int ret;
+
+	if (of_property_read_u32(np, "marvell,pcie-port", &port)) {
+		dev_err(dev, "missing pcie-port property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	of_property_read_u32(np, "marvell,pcie-lane", &lane);
+
+	devfn = of_pci_get_devfn(np);
+	if (devfn < 0) {
+		dev_err(dev, "unable to parse devfn\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_MEM,
+				  &mem_target, &mem_attr)) {
+		dev_err(dev, "unable to get target/attr for mem window\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* I/O windows are optional */
+	mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_IO,
+			      &io_target, &io_attr);
+
+	reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
+	if (gpio_is_valid(reset_gpio)) {
+		int reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+		char *reset_name = asprintf("pcie%d.%d-reset", port, lane);
+		u32 reset_udelay = 20000;
+
+		of_property_read_u32(np, "reset-delay-us", &reset_udelay);
+
+		ret = gpio_request_one(reset_gpio, GPIOF_DIR_OUT, reset_name);
+		if (ret)
+			return ERR_PTR(ret);
+
+		/* Ensure a full reset cycle*/
+		gpio_set_value(reset_gpio, 1 ^ reset_active_low);
+		udelay(reset_udelay);
+		gpio_set_value(reset_gpio, 0 ^ reset_active_low);
+		udelay(reset_udelay);
+	}
+
+	pcie = xzalloc(sizeof(*pcie));
+	pcie->port = port;
+	pcie->lane = lane;
+	pcie->name = asprintf("pcie%d.%d", port, lane);
+	pcie->devfn = devfn;
+
+	pcie->base = of_iomap(np, 0);
+	if (!pcie->base) {
+		dev_err(dev, "PCIe%d.%d unable to map registers\n", port, lane);
+		free(pcie);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pcie->membase = mvebu_pcie_membase;
+	pcie->mem.start = 0;
+	pcie->mem.end = pcie->mem.start + SZ_32M - 1;
+	if (mvebu_mbus_add_window_remap_by_id(mem_target, mem_attr,
+		(resource_size_t)pcie->membase, resource_size(&pcie->mem), 0)) {
+		dev_err(dev, "PCIe%d.%d unable to add mbus window for mem at %08x+%08x",
+			port, lane, (u32)pcie->mem.start, resource_size(&pcie->mem));
+
+		free(pcie);
+		return ERR_PTR(-EBUSY);
+	}
+	mvebu_pcie_membase += SZ_32M;
+
+	if (io_target >= 0 && io_attr >= 0) {
+		pcie->iobase = mvebu_pcie_iobase;
+		pcie->io.start = 0;
+		pcie->io.end = pcie->io.start + SZ_64K - 1;
+
+		mvebu_mbus_add_window_remap_by_id(io_target, io_attr,
+			(resource_size_t)pcie->iobase, resource_size(&pcie->io), 0);
+		mvebu_pcie_iobase += SZ_64K;
+	}
+
+	clk = of_clk_get(np, 0);
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	pcie->pci.pci_ops = &mvebu_pcie_indirect_ops;
+	pcie->pci.mem_resource = &pcie->mem;
+	pcie->pci.io_resource = &pcie->io;
+
+	return pcie;
+}
+
+static struct mvebu_pcie_ops armada_370_ops = {
+	.phy_setup = armada_370_phy_setup,
+};
+
+static struct of_device_id mvebu_pcie_dt_ids[] = {
+#if defined(CONFIG_ARCH_ARMADA_XP)
+	{ .compatible = "marvell,armada-xp-pcie", },
+#endif
+#if defined(CONFIG_ARCH_ARMADA_370)
+	{ .compatible = "marvell,armada-370-pcie", .data = (u32)&armada_370_ops, },
+#endif
+#if defined(CONFIG_ARCH_DOVE)
+	{ .compatible = "marvell,dove-pcie", },
+#endif
+#if defined(CONFIG_ARCH_KIRKWOOD)
+	{ .compatible = "marvell,kirkwood-pcie", },
+#endif
+	{ },
+};
+
+static int mvebu_pcie_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	const struct of_device_id *match = of_match_node(mvebu_pcie_dt_ids, np);
+	struct mvebu_pcie_ops *ops = (struct mvebu_pcie_ops *)match->data;
+	struct device_node *pnp;
+
+	for_each_child_of_node(np, pnp) {
+		struct mvebu_pcie *pcie;
+		u32 reg;
+
+		if (!of_device_is_available(pnp))
+			continue;
+
+		pcie = mvebu_pcie_port_probe(dev, pnp);
+		if (IS_ERR(pcie))
+			continue;
+
+		if (ops && ops->phy_setup)
+			ops->phy_setup(pcie);
+
+		mvebu_pcie_set_local_bus_nr(pcie, pcie->port);
+		mvebu_pcie_set_local_dev_nr(pcie, 0);
+		mvebu_pcie_setup_wins(pcie);
+
+		/* Master + slave enable. */
+		reg = readl(pcie->base + PCIE_CMD_OFF);
+		reg |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+		reg |= PCI_COMMAND_MASTER;
+		writel(reg, pcie->base + PCIE_CMD_OFF);
+
+		/* Disable interrupts */
+		reg = readl(pcie->base + PCIE_MASK_OFF);
+		reg &= ~PCIE_MASK_ENABLE_INTS;
+		writel(reg, pcie->base + PCIE_MASK_OFF);
+
+		register_pci_controller(&pcie->pci, pcie->port);
+	}
+
+	return 0;
+}
+
+static struct driver_d mvebu_pcie_driver = {
+	.name = "mvebu-pcie",
+	.probe = mvebu_pcie_probe,
+	.of_compatible = mvebu_pcie_dt_ids,
+};
+device_platform_driver(mvebu_pcie_driver);
diff --git a/drivers/pci/pci-mvebu.h b/drivers/pci/pci-mvebu.h
new file mode 100644
index 000000000000..2e4ed636227e
--- /dev/null
+++ b/drivers/pci/pci-mvebu.h
@@ -0,0 +1,35 @@
+/*
+ * PCIe include for Marvell MVEBU SoCs
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_PCI_H
+#define __MVEBU_PCI_H
+
+#include <linux/pci.h>
+
+struct mvebu_pcie {
+	struct pci_controller pci;
+	char *name;
+	void __iomem *base;
+	void __iomem *membase;
+	struct resource mem;
+	void __iomem *iobase;
+	struct resource io;
+	u32 port;
+	u32 lane;
+	int devfn;
+};
+
+struct mvebu_pcie_ops {
+	int (*phy_setup)(struct mvebu_pcie *pcie);
+};
+
+int armada_370_phy_setup(struct mvebu_pcie *pcie);
+
+#endif
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-23  9:26 ` [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
@ 2014-07-23 10:35   ` Sebastian Hesselbarth
  2014-07-25  7:27   ` Sascha Hauer
  2014-07-25  9:16   ` Lucas Stach
  2 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-23 10:35 UTC (permalink / raw)
  To: barebox; +Cc: Thomas Petazzoni

On 07/23/2014 11:26 AM, Sebastian Hesselbarth wrote:
> This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
> Besides the functional driver itself, it also adds SoC specific PHY
> setup required for PCIe. Currently, only Armada 370 is fully supported.
>
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
[...]
> diff --git a/drivers/pci/pci-mvebu.c b/drivers/pci/pci-mvebu.c
> new file mode 100644
> index 000000000000..6fee0800e98e
> --- /dev/null
> +++ b/drivers/pci/pci-mvebu.c
> @@ -0,0 +1,436 @@
> +/*
> + * PCIe driver for Marvell MVEBU SoCs
> + *
> + * Based on Linux drivers/pci/host/pci-mvebu.c
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
[...]
> +static int mvebu_pcie_indirect_rd_conf(struct pci_bus *bus,
> +	       unsigned int devfn, int where, int size, u32 *val)
> +{
> +	struct pci_controller *pci = bus->sysdata;
> +	struct mvebu_pcie *pcie = to_pcie(pci);
> +
> +	/* Skip all requests not directed to device behind bridge */
> +	if (devfn != 0x08 || !mvebu_pcie_link_up(pcie)) {

nit: this and below should be

	if (devfn != pcie->devfn || !mvebu_pcie_link_up(pcie))

Still, I have no clue how link state can be determined for
individual lanes on Armada XP. But I think this has to be fixed
up when we stumble upon it on a XP board that makes use of 4x1
PCIe slots.

> +		*val = 0xffffffff;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}
> +
> +	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
> +	       pcie->base + PCIE_CONF_ADDR_OFF);
> +
> +	*val = readl(pcie->base + PCIE_CONF_DATA_OFF);
> +
> +	if (size == 1)
> +		*val = (*val >> (8 * (where & 3))) & 0xff;
> +	else if (size == 2)
> +		*val = (*val >> (8 * (where & 3))) & 0xffff;
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mvebu_pcie_indirect_wr_conf(struct pci_bus *bus,
> +	       unsigned int devfn, int where, int size, u32 val)
> +{
> +	struct pci_controller *pci = bus->sysdata;
> +	struct mvebu_pcie *pcie = to_pcie(pci);
> +	u32 _val, shift = 8 * (where & 3);
> +
> +	/* Skip all requests not directed to device behind bridge */
> +	if (devfn != 0x08 || !mvebu_pcie_link_up(pcie))
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
> +	       pcie->base + PCIE_CONF_ADDR_OFF);
> +	_val = readl(pcie->base + PCIE_CONF_DATA_OFF);
> +
> +	if (size == 4)
> +		_val = val;
> +	else if (size == 2)
> +		_val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
> +	else if (size == 1)
> +		_val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
> +	else
> +		return PCIBIOS_BAD_REGISTER_NUMBER;
> +
> +	writel(_val, pcie->base + PCIE_CONF_DATA_OFF);
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
[...]
> +static struct mvebu_pcie *mvebu_pcie_port_probe(struct device_d *dev,
> +						struct device_node *np)
> +{
[...]
> +	pcie->membase = mvebu_pcie_membase;
> +	pcie->mem.start = 0;
> +	pcie->mem.end = pcie->mem.start + SZ_32M - 1;
> +	if (mvebu_mbus_add_window_remap_by_id(mem_target, mem_attr,
> +		(resource_size_t)pcie->membase, resource_size(&pcie->mem), 0)) {
> +		dev_err(dev, "PCIe%d.%d unable to add mbus window for mem at %08x+%08x",
> +			port, lane, (u32)pcie->mem.start, resource_size(&pcie->mem));
> +
> +		free(pcie);
> +		return ERR_PTR(-EBUSY);
> +	}
> +	mvebu_pcie_membase += SZ_32M;

Thinking about the 10 possible lanes on Armada XP, this size will
collide with internal registers for the last two as we are starting
from 0xe0000000. Either we limit the MEM size to 16M now or again wait
for any board suffering from it.

I see no point in adding any dynamic window resize now.

Sebastian

> +	if (io_target >= 0 && io_attr >= 0) {
> +		pcie->iobase = mvebu_pcie_iobase;
> +		pcie->io.start = 0;
> +		pcie->io.end = pcie->io.start + SZ_64K - 1;
> +
> +		mvebu_mbus_add_window_remap_by_id(io_target, io_attr,
> +			(resource_size_t)pcie->iobase, resource_size(&pcie->io), 0);
> +		mvebu_pcie_iobase += SZ_64K;
> +	}
> +
> +	clk = of_clk_get(np, 0);
> +	if (!IS_ERR(clk))
> +		clk_enable(clk);
> +
> +	pcie->pci.pci_ops = &mvebu_pcie_indirect_ops;
> +	pcie->pci.mem_resource = &pcie->mem;
> +	pcie->pci.io_resource = &pcie->io;
> +
> +	return pcie;
> +}


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-23  9:26 ` [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
  2014-07-23 10:35   ` Sebastian Hesselbarth
@ 2014-07-25  7:27   ` Sascha Hauer
  2014-07-25 15:00     ` Sebastian Hesselbarth
  2014-07-25  9:16   ` Lucas Stach
  2 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2014-07-25  7:27 UTC (permalink / raw)
  To: Sebastian Hesselbarth; +Cc: Thomas Petazzoni, barebox

On Wed, Jul 23, 2014 at 11:26:08AM +0200, Sebastian Hesselbarth wrote:
> This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
> Besides the functional driver itself, it also adds SoC specific PHY
> setup required for PCIe. Currently, only Armada 370 is fully supported.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

For now I applied 1/6 - 5/6. Are you happy enough with the driver so I
can apply it?

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 2/6] pci: pci_scan_bus: respect 64b BARs
  2014-07-23  9:26 ` [PATCH RESEND 2/6] pci: pci_scan_bus: respect 64b BARs Sebastian Hesselbarth
@ 2014-07-25  8:51   ` Lucas Stach
  2014-07-25 14:43     ` Sebastian Hesselbarth
  0 siblings, 1 reply; 26+ messages in thread
From: Lucas Stach @ 2014-07-25  8:51 UTC (permalink / raw)
  To: Sebastian Hesselbarth; +Cc: Thomas Petazzoni, barebox

Hi Sebastian,

Am Mittwoch, den 23.07.2014, 11:26 +0200 schrieb Sebastian Hesselbarth:
> In PCI 64-bit BARs span two 32-bit BARs, therefore if BAR type
> indicates a 64-bit BAR we have to skip the next BAR register.
> Note that this does not add proper support for 64-bit BARs and
> 64-bit addresses but still picks the lower 32-bit address.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> To: barebox@lists.infradead.org
> To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Cc: Antony Pavlov <antonynpavlov@gmail.com>
> Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ---
>  drivers/pci/pci.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 3d88b0ff5fd0..e5cd8a33b2be 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -196,6 +196,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
>  
>  		for (bar = 0; bar < 6; bar++) {
>  			resource_size_t last_addr;
> +			bool found_bar64 = false;

I don't think we need this variable...

>  
>  			pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &old_bar);
>  			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
> @@ -213,17 +214,22 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
>  				pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
>  				last_addr = last_io;
>  				last_io += size;
> -
>  			} else { /* MEM */
>  				size = -(mask & 0xfffffff0);
>  				DBG("  PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size);
>  				pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
>  				last_addr = last_mem;
>  				last_mem += size;
> +
> +				if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
> +				    PCI_BASE_ADDRESS_MEM_TYPE_64)
> +					found_bar64 = true;

... if we set the dev->resource.flags to IORESOURCE_MEM_64 (bonus points
for setting the flags in other cases properly also) here...

>  			}
>  
>  			dev->resource[bar].start = last_addr;
>  			dev->resource[bar].end = last_addr + size - 1;
> +			if (found_bar64)
> +				bar++;

... and check for this flag here.
>  		}
>  	}
>  

Regards,
Lucas
-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 3/6] pci: add host controller struct to sysdata
  2014-07-23  9:26 ` [PATCH RESEND 3/6] pci: add host controller struct to sysdata Sebastian Hesselbarth
@ 2014-07-25  9:07   ` Lucas Stach
  2014-07-25 14:54     ` Sebastian Hesselbarth
  0 siblings, 1 reply; 26+ messages in thread
From: Lucas Stach @ 2014-07-25  9:07 UTC (permalink / raw)
  To: Sebastian Hesselbarth; +Cc: Thomas Petazzoni, barebox

Am Mittwoch, den 23.07.2014, 11:26 +0200 schrieb Sebastian Hesselbarth:
> struct pci_bus allows to set some private sysdata. Assign the host
> controller struct to it by default.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> To: barebox@lists.infradead.org
> To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Cc: Antony Pavlov <antonynpavlov@gmail.com>
> Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ---
>  drivers/pci/pci.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index e5cd8a33b2be..b30cdd96f8ca 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -39,6 +39,7 @@ void register_pci_controller(struct pci_controller *hose)
>  	bus->ops = hose->pci_ops;
>  	bus->resource[0] = hose->mem_resource;
>  	bus->resource[1] = hose->io_resource;
> +	bus->sysdata = hose;
>  
This doesn't seem right. You are not only assigning hose to sysdata by
default, but make it the only option as there is no sane way to override
this assignment before bus scanning happens.

Either make this a parameter to this function, so pci host controller
drivers can pass in whatever they want as the sysdata, or add an
explicit backlink pointer from bus to controller. Hm, maybe even both.

Regards,
Lucas

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-23  9:26 ` [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
  2014-07-23 10:35   ` Sebastian Hesselbarth
  2014-07-25  7:27   ` Sascha Hauer
@ 2014-07-25  9:16   ` Lucas Stach
  2014-07-25 14:57     ` Sebastian Hesselbarth
  2 siblings, 1 reply; 26+ messages in thread
From: Lucas Stach @ 2014-07-25  9:16 UTC (permalink / raw)
  To: Sebastian Hesselbarth; +Cc: Thomas Petazzoni, barebox

Am Mittwoch, den 23.07.2014, 11:26 +0200 schrieb Sebastian Hesselbarth:
> This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
> Besides the functional driver itself, it also adds SoC specific PHY
> setup required for PCIe. Currently, only Armada 370 is fully supported.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

I can't really comment about the details, as I have no knowledge about
this hardware in particular, but aside from the sysdata thing and one
nit below this looks reasonable, so:

Acked-by: Lucas Stach <l.stach@pengutronix.de>

> ---
> To: barebox@lists.infradead.org
> To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ---
>  arch/arm/Kconfig            |   1 +
>  drivers/pci/Kconfig         |   6 +
>  drivers/pci/Makefile        |   2 +
>  drivers/pci/pci-mvebu-phy.c | 102 +++++++++++
>  drivers/pci/pci-mvebu.c     | 436 ++++++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/pci-mvebu.h     |  35 ++++
>  6 files changed, 582 insertions(+)
>  create mode 100644 drivers/pci/pci-mvebu-phy.c
>  create mode 100644 drivers/pci/pci-mvebu.c
>  create mode 100644 drivers/pci/pci-mvebu.h
> 
[...]
> +
> +static struct mvebu_pcie_ops armada_370_ops = {
> +	.phy_setup = armada_370_phy_setup,
> +};
> +
> +static struct of_device_id mvebu_pcie_dt_ids[] = {
> +#if defined(CONFIG_ARCH_ARMADA_XP)
> +	{ .compatible = "marvell,armada-xp-pcie", },
> +#endif
> +#if defined(CONFIG_ARCH_ARMADA_370)
> +	{ .compatible = "marvell,armada-370-pcie", .data = (u32)&armada_370_ops, },
> +#endif
> +#if defined(CONFIG_ARCH_DOVE)
> +	{ .compatible = "marvell,dove-pcie", },
> +#endif
> +#if defined(CONFIG_ARCH_KIRKWOOD)
> +	{ .compatible = "marvell,kirkwood-pcie", },
> +#endif
> +	{ },
> +};
> +

Do those #if defined really buy us anything? I don't think they make a
big difference on code size, so please get rid of those.

Regards,
Lucas
-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 2/6] pci: pci_scan_bus: respect 64b BARs
  2014-07-25  8:51   ` Lucas Stach
@ 2014-07-25 14:43     ` Sebastian Hesselbarth
  0 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-25 14:43 UTC (permalink / raw)
  To: Lucas Stach; +Cc: Thomas Petazzoni, barebox

On Fri, Jul 25, 2014 at 10:51 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> Am Mittwoch, den 23.07.2014, 11:26 +0200 schrieb Sebastian Hesselbarth:
>> In PCI 64-bit BARs span two 32-bit BARs, therefore if BAR type
>> indicates a 64-bit BAR we have to skip the next BAR register.
>> Note that this does not add proper support for 64-bit BARs and
>> 64-bit addresses but still picks the lower 32-bit address.
>>
>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>> ---
>> To: barebox@lists.infradead.org
>> To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>> Cc: Antony Pavlov <antonynpavlov@gmail.com>
>> Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
>> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
>> Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
>> ---
>>  drivers/pci/pci.c | 8 +++++++-
>>  1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 3d88b0ff5fd0..e5cd8a33b2be 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -196,6 +196,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
>>
>>               for (bar = 0; bar < 6; bar++) {
>>                       resource_size_t last_addr;
>> +                     bool found_bar64 = false;
>
> I don't think we need this variable...
>
>>
>>                       pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &old_bar);
>>                       pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
>> @@ -213,17 +214,22 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
>>                               pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
>>                               last_addr = last_io;
>>                               last_io += size;
>> -
>>                       } else { /* MEM */
>>                               size = -(mask & 0xfffffff0);
>>                               DBG("  PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size);
>>                               pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
>>                               last_addr = last_mem;
>>                               last_mem += size;
>> +
>> +                             if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
>> +                                 PCI_BASE_ADDRESS_MEM_TYPE_64)
>> +                                     found_bar64 = true;
>
> ... if we set the dev->resource.flags to IORESOURCE_MEM_64 (bonus points
> for setting the flags in other cases properly also) here...
>
>>                       }
>>
>>                       dev->resource[bar].start = last_addr;
>>                       dev->resource[bar].end = last_addr + size - 1;
>> +                     if (found_bar64)
>> +                             bar++;
>
> ... and check for this flag here.

Yup, sounds like a good plan. I'll consider this when I come back to it.

Sebastian

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 3/6] pci: add host controller struct to sysdata
  2014-07-25  9:07   ` Lucas Stach
@ 2014-07-25 14:54     ` Sebastian Hesselbarth
  0 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-25 14:54 UTC (permalink / raw)
  To: Lucas Stach; +Cc: Thomas Petazzoni, barebox

On Fri, Jul 25, 2014 at 11:07 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> Am Mittwoch, den 23.07.2014, 11:26 +0200 schrieb Sebastian Hesselbarth:
>> struct pci_bus allows to set some private sysdata. Assign the host
>> controller struct to it by default.
>>
>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>> ---
>> To: barebox@lists.infradead.org
>> To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>> Cc: Antony Pavlov <antonynpavlov@gmail.com>
>> Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
>> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
>> Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
>> ---
>>  drivers/pci/pci.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index e5cd8a33b2be..b30cdd96f8ca 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -39,6 +39,7 @@ void register_pci_controller(struct pci_controller *hose)
>>       bus->ops = hose->pci_ops;
>>       bus->resource[0] = hose->mem_resource;
>>       bus->resource[1] = hose->io_resource;
>> +     bus->sysdata = hose;
>>
> This doesn't seem right. You are not only assigning hose to sysdata by
> default, but make it the only option as there is no sane way to override
> this assignment before bus scanning happens.

Yeah, the is some things with pci core already, that make it seem not right,
e.g. IIRC it is pci_register_driver which makes it impossible to use the
register_driver_macro() as it expects <bus>_driver_register.

My concern still stands, that it may be more useful to split above up in
_alloc and _register phase.

> Either make this a parameter to this function, so pci host controller
> drivers can pass in whatever they want as the sysdata, or add an
> explicit backlink pointer from bus to controller. Hm, maybe even both.

I guess it will be best to have both, i.e. bus->host = hose and an extra
parameter to pass sysdata. Or we could also drop sysdata now until
anyone requires it.

Sebastian

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-25  9:16   ` Lucas Stach
@ 2014-07-25 14:57     ` Sebastian Hesselbarth
  0 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-25 14:57 UTC (permalink / raw)
  To: Lucas Stach; +Cc: Thomas Petazzoni, barebox

On Fri, Jul 25, 2014 at 11:16 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> Am Mittwoch, den 23.07.2014, 11:26 +0200 schrieb Sebastian Hesselbarth:
>> This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
>> Besides the functional driver itself, it also adds SoC specific PHY
>> setup required for PCIe. Currently, only Armada 370 is fully supported.
>>
>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>
> I can't really comment about the details, as I have no knowledge about
> this hardware in particular, but aside from the sysdata thing and one
> nit below this looks reasonable, so:
>
> Acked-by: Lucas Stach <l.stach@pengutronix.de>
>
>> ---
>> To: barebox@lists.infradead.org
>> To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
>> Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
>> ---
> [...]
>> +
>> +static struct mvebu_pcie_ops armada_370_ops = {
>> +     .phy_setup = armada_370_phy_setup,
>> +};
>> +
>> +static struct of_device_id mvebu_pcie_dt_ids[] = {
>> +#if defined(CONFIG_ARCH_ARMADA_XP)
>> +     { .compatible = "marvell,armada-xp-pcie", },
>> +#endif
>> +#if defined(CONFIG_ARCH_ARMADA_370)
>> +     { .compatible = "marvell,armada-370-pcie", .data = (u32)&armada_370_ops, },
>> +#endif
>> +#if defined(CONFIG_ARCH_DOVE)
>> +     { .compatible = "marvell,dove-pcie", },
>> +#endif
>> +#if defined(CONFIG_ARCH_KIRKWOOD)
>> +     { .compatible = "marvell,kirkwood-pcie", },
>> +#endif
>> +     { },
>> +};
>> +
>
> Do those #if defined really buy us anything? I don't think they make a
> big difference on code size, so please get rid of those.

Hmm, without the #ifdef's we'd carry armada_370_ops _and_
armada_370_phy_setup on all SoCs, don't we?

Assuming there will also be armada_xp_foo, dove_foo, and kirkwood_foo
it will be quite a bunch of unnecessary code to carry around. But I admit,
I haven't checked code sizes, yet.

Sebastian

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-25  7:27   ` Sascha Hauer
@ 2014-07-25 15:00     ` Sebastian Hesselbarth
  2014-07-28  5:19       ` Sascha Hauer
  0 siblings, 1 reply; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-25 15:00 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Thomas Petazzoni, barebox

On Fri, Jul 25, 2014 at 9:27 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Wed, Jul 23, 2014 at 11:26:08AM +0200, Sebastian Hesselbarth wrote:
>> This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
>> Besides the functional driver itself, it also adds SoC specific PHY
>> setup required for PCIe. Currently, only Armada 370 is fully supported.
>>
>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>
> For now I applied 1/6 - 5/6. Are you happy enough with the driver so I
> can apply it?

If you already took in the other patches, yes, then it is okay to pick up this
one, too. It would be nice, if you fixup the one devfn line when applying.

I can send follow-up patches on whatever is the result of discussion on
this and the other patches of this series.

Sebastian

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-25 15:00     ` Sebastian Hesselbarth
@ 2014-07-28  5:19       ` Sascha Hauer
  2014-07-28  6:10         ` Sebastian Hesselbarth
  0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2014-07-28  5:19 UTC (permalink / raw)
  To: Sebastian Hesselbarth; +Cc: Thomas Petazzoni, barebox

On Fri, Jul 25, 2014 at 05:00:36PM +0200, Sebastian Hesselbarth wrote:
> On Fri, Jul 25, 2014 at 9:27 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > On Wed, Jul 23, 2014 at 11:26:08AM +0200, Sebastian Hesselbarth wrote:
> >> This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
> >> Besides the functional driver itself, it also adds SoC specific PHY
> >> setup required for PCIe. Currently, only Armada 370 is fully supported.
> >>
> >> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> >
> > For now I applied 1/6 - 5/6. Are you happy enough with the driver so I
> > can apply it?
> 
> If you already took in the other patches, yes, then it is okay to pick up this
> one, too. It would be nice, if you fixup the one devfn line when applying.
> 
> I can send follow-up patches on whatever is the result of discussion on
> this and the other patches of this series.

Please resend the whole series then. I'll replace the patches.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver
  2014-07-28  5:19       ` Sascha Hauer
@ 2014-07-28  6:10         ` Sebastian Hesselbarth
  0 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-28  6:10 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Thomas Petazzoni, barebox

On 07/28/2014 07:19 AM, Sascha Hauer wrote:
> On Fri, Jul 25, 2014 at 05:00:36PM +0200, Sebastian Hesselbarth wrote:
>> On Fri, Jul 25, 2014 at 9:27 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
>>> On Wed, Jul 23, 2014 at 11:26:08AM +0200, Sebastian Hesselbarth wrote:
>>>> This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
>>>> Besides the functional driver itself, it also adds SoC specific PHY
>>>> setup required for PCIe. Currently, only Armada 370 is fully supported.
>>>>
>>>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>>
>>> For now I applied 1/6 - 5/6. Are you happy enough with the driver so I
>>> can apply it?
>>
>> If you already took in the other patches, yes, then it is okay to pick up this
>> one, too. It would be nice, if you fixup the one devfn line when applying.
>>
>> I can send follow-up patches on whatever is the result of discussion on
>> this and the other patches of this series.
> 
> Please resend the whole series then. I'll replace the patches.

Ok, fair enough. I'll rework and respect any of the comments made.

Sebastian


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v2 0/5] Marvell EBU PCIe driver
  2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
                   ` (5 preceding siblings ...)
  2014-07-23  9:26 ` [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
@ 2014-07-28 13:26 ` Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 1/5] bus: mvebu: fix resource size handling Sebastian Hesselbarth
                     ` (5 more replies)
  6 siblings, 6 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-28 13:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Sascha Hauer; +Cc: Thomas Petazzoni, barebox

Second round of the Marvell EBU PCIe driver patch set. Compared
to v1, I reworked pci_scan_bus to properly set IORESOURCE flags
for all resources, and added auto-incrementing pci bus numbering.

Patch 1 is unchanged and still fixes resource computation of mbus
driver. Patch 2 now properly sets IORESOURCE flags for I/O, 32b
MEM, and 64b MEM resources.

Patch 3 is a squashed and reworked patch dealing with pci host
controller registration: bus number is now assigned from an auto-
incremented bus_index and already provided pci_controller's
set_busno is called right before pci_scan_bus to allow the
controller to update internal registers related with bus number.
This patch also sets a back-reference to the pci_controller of
a pci_bus and cleans up some unused left-overs from Linux import.

Patch 4 is unchanged import of of_pci_get_devfn() and Patch 5
finally adds the PCIe controller driver for Marvell MVEBU SoCs.
Individual changelogs are also at the corresponding patch mails.

Again, this has been tested on Armada 370 Mirabox.

I added Lucas's Acked-by to all individual patches except new
Patch 3, although I did not respect his request for
'#if defined(FOO)' removal in MVEBU PCIe driver.

Sebastian

Sebastian Hesselbarth (5):
  bus: mvebu: fix resource size handling
  pci: pci_scan_bus: respect 64b BARs
  pci: set auto-incremented bus number
  of: pci: import of_pci_get_devfn()
  pci: mvebu: Add PCIe driver

 arch/arm/Kconfig            |   1 +
 drivers/bus/mvebu-mbus.c    |   8 +-
 drivers/of/Kconfig          |   6 +
 drivers/of/Makefile         |   1 +
 drivers/of/of_pci.c         |  27 +++
 drivers/pci/Kconfig         |   6 +
 drivers/pci/Makefile        |   2 +
 drivers/pci/pci-mvebu-phy.c | 102 +++++++++++
 drivers/pci/pci-mvebu.c     | 434 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci-mvebu.h     |  35 ++++
 drivers/pci/pci.c           |  14 +-
 include/linux/pci.h         |  12 +-
 include/of_pci.h            |  17 ++
 13 files changed, 651 insertions(+), 14 deletions(-)
 create mode 100644 drivers/of/of_pci.c
 create mode 100644 drivers/pci/pci-mvebu-phy.c
 create mode 100644 drivers/pci/pci-mvebu.c
 create mode 100644 drivers/pci/pci-mvebu.h
 create mode 100644 include/of_pci.h

---
Cc: barebox@lists.infradead.org
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v2 1/5] bus: mvebu: fix resource size handling
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
@ 2014-07-28 13:26   ` Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 2/5] pci: pci_scan_bus: respect 64b BARs Sebastian Hesselbarth
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-28 13:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Sascha Hauer; +Cc: Thomas Petazzoni, barebox

A resource_size is defined as res->end - res->start + 1. Marvell
MBUS driver gets some ranges from DT as start and size but mis-calculates
end of range. This fixes 4 occurences of those mistakes.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Acked-by: Lucas Stach <l.stach@pengutronix.de>
---
Changelog:
v1->v2:
- none

Cc: barebox@lists.infradead.org
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/bus/mvebu-mbus.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 11e3777a6094..c67646f61722 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -187,7 +187,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
 				       phys_addr_t base, size_t size,
 				       u8 target, u8 attr)
 {
-	u64 end = (u64)base + size;
+	u64 end = (u64)base + size - 1;
 	int win;
 
 	for (win = 0; win < mbus->soc->num_wins; win++) {
@@ -203,7 +203,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
 		if (!enabled)
 			continue;
 
-		wend = wbase + wsize;
+		wend = wbase + wsize - 1;
 
 		/*
 		 * Check if the current window overlaps with the
@@ -661,7 +661,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np,
 					 reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		mem->start = reg[0];
-		mem->end = mem->start + reg[1];
+		mem->end = mem->start + reg[1] - 1;
 		mem->flags = IORESOURCE_MEM;
 	}
 
@@ -669,7 +669,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np,
 					 reg, ARRAY_SIZE(reg));
 	if (!ret) {
 		io->start = reg[0];
-		io->end = io->start + reg[1];
+		io->end = io->start + reg[1] - 1;
 		io->flags = IORESOURCE_IO;
 	}
 }
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v2 2/5] pci: pci_scan_bus: respect 64b BARs
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 1/5] bus: mvebu: fix resource size handling Sebastian Hesselbarth
@ 2014-07-28 13:26   ` Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 3/5] pci: set auto-incremented bus number Sebastian Hesselbarth
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-28 13:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Sascha Hauer; +Cc: Thomas Petazzoni, barebox

In PCI 64-bit BARs span two 32-bit BARs, therefore if BAR type
indicates a 64-bit BAR we have to skip the next BAR register.
Note that this does not add proper support for 64-bit BARs and
64-bit addresses but still picks the lower 32-bit address.

While at it, also set proper IORESOURCE flags for I/O and
32b MEM.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Acked-by: Lucas Stach <l.stach@pengutronix.de>
---
Changelog:
v1->v2:
- set resource flags for all resources found (Suggested by Lucas Stach)
- use MEM_64 resource flag for BAR64 detection (Suggested by Lucas Stach)

Cc: barebox@lists.infradead.org
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/pci/pci.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3d88b0ff5fd0..501a36cc8356 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -211,19 +211,26 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
 				size = -(mask & 0xfffffffe);
 				DBG("  PCI: pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
 				pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
+				dev->resource[bar].flags = IORESOURCE_IO;
 				last_addr = last_io;
 				last_io += size;
-
 			} else { /* MEM */
 				size = -(mask & 0xfffffff0);
 				DBG("  PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size);
 				pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
+				dev->resource[bar].flags = IORESOURCE_MEM;
 				last_addr = last_mem;
 				last_mem += size;
+
+				if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+				    PCI_BASE_ADDRESS_MEM_TYPE_64)
+					dev->resource[bar].flags = IORESOURCE_MEM_64;
 			}
 
 			dev->resource[bar].start = last_addr;
 			dev->resource[bar].end = last_addr + size - 1;
+			if (dev->resource[bar].flags & IORESOURCE_MEM_64)
+				bar++;
 		}
 	}
 
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v2 3/5] pci: set auto-incremented bus number
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 1/5] bus: mvebu: fix resource size handling Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 2/5] pci: pci_scan_bus: respect 64b BARs Sebastian Hesselbarth
@ 2014-07-28 13:26   ` Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 4/5] of: pci: import of_pci_get_devfn() Sebastian Hesselbarth
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-28 13:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Sascha Hauer; +Cc: Thomas Petazzoni, barebox

When using more than one PCI bus, we have to assign unique numbers
to each bus. Use an auto-incremented bus index and assign it to
each registered bus. Also, allow the PCI host controller to update
internal registers by calling set_busno with assigned bus number.

While at it, add pci_controller struct to set_busno callback,
add a back reference to pci_controller to pci_bus, and clean up
unused left-overs from Linux import.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Changelog:
v1->v2:
- set pci_controller reference to bus->bus (Suggested by Lucas Stach)
- auto-increment pci_bus number for each registered bus
- call pci_controller set_busno() before pci_scan_bus
- remove sysdata and proc_dir_entry from pci_dev and pci_bus
- pass pci_controller to set_busno callback

Cc: barebox@lists.infradead.org
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/pci/pci.c   |  5 +++++
 include/linux/pci.h | 12 +++---------
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 501a36cc8356..2dafaf8d6bab 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -11,6 +11,7 @@ static struct pci_controller *hose_head, **hose_tail = &hose_head;
 
 LIST_HEAD(pci_root_buses);
 EXPORT_SYMBOL(pci_root_buses);
+static u8 bus_index;
 
 static struct pci_bus *pci_alloc_bus(void)
 {
@@ -36,10 +37,14 @@ void register_pci_controller(struct pci_controller *hose)
 
 	bus = pci_alloc_bus();
 	hose->bus = bus;
+	bus->host = hose;
 	bus->ops = hose->pci_ops;
 	bus->resource[0] = hose->mem_resource;
 	bus->resource[1] = hose->io_resource;
+	bus->number = bus_index++;
 
+	if (hose->set_busno)
+		hose->set_busno(hose, bus->number);
 	pci_scan_bus(bus);
 
 	list_add_tail(&bus->node, &pci_root_buses);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6caed01c9939..0ec1320b2f71 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -91,9 +91,6 @@ struct pci_dev {
 	struct list_head bus_list;	/* node in per-bus list */
 	struct pci_bus	*bus;		/* bus this device is on */
 	struct pci_bus	*subordinate;	/* bus this device bridges to */
-
-	void		*sysdata;	/* hook for sys-specific extension */
-	struct proc_dir_entry *procent;	/* device entry in /proc/bus/pci */
 	struct pci_slot	*slot;		/* Physical slot this device is in */
 
 	struct device_d dev;
@@ -118,6 +115,7 @@ struct pci_dev {
 #define	to_pci_dev(dev) container_of(dev, struct pci_dev, dev)
 
 struct pci_bus {
+	struct pci_controller *host;	/* associated host controller */
 	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 */
@@ -126,8 +124,6 @@ struct pci_bus {
 	struct list_head resources;	/* address space routed to this bus */
 
 	struct pci_ops	*ops;		/* configuration access functions */
-	void		*sysdata;	/* hook for sys-specific extension */
-	struct proc_dir_entry *procdir;	/* directory entry in /proc/bus/pci */
 
 	unsigned char	number;		/* bus number */
 	unsigned char	primary;	/* number of primary bridge */
@@ -167,10 +163,8 @@ struct pci_controller {
 
 	unsigned int index;
 
-	/* Optional access methods for reading/writing the bus number
-	   of the PCI controller */
-	int (*get_busno)(void);
-	void (*set_busno)(int busno);
+	/* Optional access method for writing the bus number */
+	void (*set_busno)(struct pci_controller *host, int busno);
 };
 
 struct pci_driver {
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v2 4/5] of: pci: import of_pci_get_devfn()
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
                     ` (2 preceding siblings ...)
  2014-07-28 13:26   ` [PATCH v2 3/5] pci: set auto-incremented bus number Sebastian Hesselbarth
@ 2014-07-28 13:26   ` Sebastian Hesselbarth
  2014-07-28 13:26   ` [PATCH v2 5/5] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
  2014-07-29 19:58   ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
  5 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-28 13:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Sascha Hauer; +Cc: Thomas Petazzoni, barebox

Marvell MVEBU PCIe driver requires of_pcie_get_devfn(), import it from
Linux.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Acked-by: Lucas Stach <l.stach@pengutronix.de>
---
Changelog:
v1->v2:
- none

Cc: barebox@lists.infradead.org
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 drivers/of/Kconfig  |  6 ++++++
 drivers/of/Makefile |  1 +
 drivers/of/of_pci.c | 27 +++++++++++++++++++++++++++
 include/of_pci.h    | 17 +++++++++++++++++
 4 files changed, 51 insertions(+)
 create mode 100644 drivers/of/of_pci.c
 create mode 100644 include/of_pci.h

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 2b28cf3fb425..81955063d70c 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -27,6 +27,12 @@ config OF_GPIO
 	depends on OFDEVICE
 	def_bool y
 
+config OF_PCI
+	bool
+	depends on PCI
+	help
+	  OpenFirmware PCI bus accessors
+
 config OF_BAREBOX_DRIVERS
 	depends on OFDEVICE
 	depends on ENV_HANDLING
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index c883e516c834..0dc2f8d63ed0 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,6 +1,7 @@
 obj-y += address.o base.o fdt.o platform.o
 obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o
 obj-$(CONFIG_OF_GPIO) += of_gpio.o
+obj-$(CONFIG_OF_PCI) += of_pci.o
 obj-y += partition.o
 obj-y += of_net.o
 obj-$(CONFIG_MTD) += of_mtd.o
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
new file mode 100644
index 000000000000..2d0fbd2e5f69
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,27 @@
+#include <common.h>
+#include <errno.h>
+#include <of.h>
+#include <of_pci.h>
+
+/**
+ * of_pci_get_devfn() - Get device and function numbers for a device node
+ * @np: device node
+ *
+ * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
+ * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
+ * and function numbers respectively. On error a negative error code is
+ * returned.
+ */
+int of_pci_get_devfn(struct device_node *np)
+{
+	unsigned int size;
+	const __be32 *reg;
+
+	reg = of_get_property(np, "reg", &size);
+
+	if (!reg || size < 5 * sizeof(__be32))
+		return -EINVAL;
+
+	return (be32_to_cpup(reg) >> 8) & 0xff;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_devfn);
diff --git a/include/of_pci.h b/include/of_pci.h
new file mode 100644
index 000000000000..c95cb0135ae0
--- /dev/null
+++ b/include/of_pci.h
@@ -0,0 +1,17 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+#ifdef CONFIG_OF_PCI
+int of_pci_get_devfn(struct device_node *np);
+
+#else
+static inline int of_pci_get_devfn(struct device_node *np)
+{
+	return -EINVAL;
+}
+
+#endif
+
+#endif
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v2 5/5] pci: mvebu: Add PCIe driver
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
                     ` (3 preceding siblings ...)
  2014-07-28 13:26   ` [PATCH v2 4/5] of: pci: import of_pci_get_devfn() Sebastian Hesselbarth
@ 2014-07-28 13:26   ` Sebastian Hesselbarth
  2014-07-29 19:58   ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
  5 siblings, 0 replies; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-28 13:26 UTC (permalink / raw)
  To: Sebastian Hesselbarth, Sascha Hauer; +Cc: Thomas Petazzoni, barebox

This adds a PCI driver for the controllers found on Marvell MVEBU SoCs.
Besides the functional driver itself, it also adds SoC specific PHY
setup required for PCIe. Currently, only Armada 370 is fully supported.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Acked-by: Lucas Stach <l.stach@pengutronix.de>
---
Changelog:
v1->v2:
- rework on top of pci controller changes
- properly check for devfn passed from DT in
  mvebu_pcie_indirect_{rd,wr}_conf

Cc: barebox@lists.infradead.org
Cc: Antony Pavlov <antonynpavlov@gmail.com>
Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
 arch/arm/Kconfig            |   1 +
 drivers/pci/Kconfig         |   6 +
 drivers/pci/Makefile        |   2 +
 drivers/pci/pci-mvebu-phy.c | 102 +++++++++++
 drivers/pci/pci-mvebu.c     | 434 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci-mvebu.h     |  35 ++++
 6 files changed, 580 insertions(+)
 create mode 100644 drivers/pci/pci-mvebu-phy.c
 create mode 100644 drivers/pci/pci-mvebu.c
 create mode 100644 drivers/pci/pci-mvebu.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8465d4a7f739..be5c7bd1981b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -93,6 +93,7 @@ config ARCH_MVEBU
 	select GPIOLIB
 	select HAS_DEBUG_LL
 	select HAVE_PBL_MULTI_IMAGES
+	select HW_HAS_PCI
 	select MVEBU_MBUS
 	select OFTREE
 	select OF_ADDRESS_PCI
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 9e4659270d25..d17a1510821f 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -24,6 +24,12 @@ config PCI_DEBUG
 
 	  When in doubt, say N.
 
+config PCI_MVEBU
+	bool "Marvell EBU PCIe driver"
+	depends on ARCH_MVEBU
+	select OF_PCI
+	select PCI
+
 endmenu
 
 endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index edac1a53de78..442353173c9e 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -6,3 +6,5 @@ obj-y		+= pci.o bus.o pci_iomap.o
 ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
 
 CPPFLAGS += $(ccflags-y)
+
+obj-$(CONFIG_PCI_MVEBU)	+= pci-mvebu.o pci-mvebu-phy.o
diff --git a/drivers/pci/pci-mvebu-phy.c b/drivers/pci/pci-mvebu-phy.c
new file mode 100644
index 000000000000..9997cdbb0a6a
--- /dev/null
+++ b/drivers/pci/pci-mvebu-phy.c
@@ -0,0 +1,102 @@
+/*
+ * SoC specific PCIe PHY setup for Marvell MVEBU SoCs
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * based on Marvell BSP code (C) Marvell International Ltd.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <of.h>
+#include <of_address.h>
+
+#include "pci-mvebu.h"
+
+static u32 mvebu_pcie_phy_indirect(void __iomem *phybase, u8 lane,
+				   u8 off, u16 val, bool is_read)
+{
+	u32 reg = (lane << 24) | (off << 16) | val;
+
+	if (is_read)
+		reg |= BIT(31);
+	writel(reg, phybase);
+
+	return (is_read) ? readl(phybase) & 0xffff : 0;
+}
+
+static inline u32 mvebu_pcie_phy_read(void __iomem *phybase, u8 lane,
+				      u8 off)
+{
+	return mvebu_pcie_phy_indirect(phybase, lane, off, 0, true);
+}
+
+static inline void mvebu_pcie_phy_write(void __iomem *phybase, u8 lane,
+					u8 off, u16 val)
+{
+	mvebu_pcie_phy_indirect(phybase, lane, off, val, false);
+}
+
+#define ARMADA_370_PHY_OFFSET	0x1b00
+#define ARMADA_370_SOC_CTRL	0x04
+#define ARMADA_370_SERDES03_SEL	0x70
+
+int armada_370_phy_setup(struct mvebu_pcie *pcie)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+				 "marvell,armada-370-xp-system-controller");
+	void __iomem *sysctrl = of_iomap(np, 0);
+	void __iomem *phybase = pcie->base + ARMADA_370_PHY_OFFSET;
+	u32 reg;
+
+	if (!sysctrl)
+		return -ENODEV;
+
+	/* Enable PEX */
+	reg = readl(sysctrl + ARMADA_370_SOC_CTRL);
+	reg |= BIT(pcie->port);
+	writel(reg, sysctrl + ARMADA_370_SOC_CTRL);
+
+	/* Set SERDES selector */
+	reg = readl(sysctrl + ARMADA_370_SERDES03_SEL);
+	reg &= ~(0xf << (pcie->port * 4));
+	reg |= (0x1 << (pcie->port * 4));
+	writel(reg, sysctrl + ARMADA_370_SERDES03_SEL);
+
+	/* BTS #232 - PCIe clock (undocumented) */
+	writel(0x00000077, sysctrl + 0x2f0);
+
+	/* Disable Link (undocumented) */
+	reg = readl(pcie->base + 0x6c);
+	reg &= ~0x3f0;
+	reg |= BIT(4);
+	writel(reg, pcie->base + 0x6c);
+
+	/* PEX pipe configuration */
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0025);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x000f);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc8, 0x0005);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xd0, 0x0100);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xd1, 0x3014);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc5, 0x011f);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x80, 0x1000);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x81, 0x0011);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x0f, 0x2a21);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x45, 0x00df);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x4f, 0x6219);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x01, 0xfc60);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x46, 0x0000);
+
+	reg = mvebu_pcie_phy_read(phybase, pcie->lane, 0x48) & ~0x4;
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, reg & 0xffff);
+
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0x02, 0x0040);
+	mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0024);
+
+	mdelay(15);
+
+	return 0;
+}
diff --git a/drivers/pci/pci-mvebu.c b/drivers/pci/pci-mvebu.c
new file mode 100644
index 000000000000..3bcdb9593922
--- /dev/null
+++ b/drivers/pci/pci-mvebu.c
@@ -0,0 +1,434 @@
+/*
+ * PCIe driver for Marvell MVEBU SoCs
+ *
+ * Based on Linux drivers/pci/host/pci-mvebu.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mbus.h>
+#include <linux/pci_regs.h>
+#include <malloc.h>
+#include <of_address.h>
+#include <of_gpio.h>
+#include <of_pci.h>
+#include <sizes.h>
+
+#include "pci-mvebu.h"
+
+/* PCIe unit register offsets */
+#define PCIE_DEV_ID_OFF			0x0000
+#define PCIE_CMD_OFF			0x0004
+#define PCIE_DEV_REV_OFF		0x0008
+#define  PCIE_BAR_LO_OFF(n)		(0x0010 + ((n) << 3))
+#define  PCIE_BAR_HI_OFF(n)		(0x0014 + ((n) << 3))
+#define PCIE_HEADER_LOG_4_OFF		0x0128
+#define  PCIE_BAR_CTRL_OFF(n)		(0x1804 + (((n) - 1) * 4))
+#define  PCIE_WIN04_CTRL_OFF(n)		(0x1820 + ((n) << 4))
+#define  PCIE_WIN04_BASE_OFF(n)		(0x1824 + ((n) << 4))
+#define  PCIE_WIN04_REMAP_OFF(n)	(0x182c + ((n) << 4))
+#define PCIE_WIN5_CTRL_OFF		0x1880
+#define PCIE_WIN5_BASE_OFF		0x1884
+#define PCIE_WIN5_REMAP_OFF		0x188c
+#define PCIE_CONF_ADDR_OFF		0x18f8
+#define  PCIE_CONF_ADDR_EN		BIT(31)
+#define  PCIE_CONF_REG(r)		((((r) & 0xf00) << 16) | ((r) & 0xfc))
+#define  PCIE_CONF_BUS(b)		(((b) & 0xff) << 16)
+#define  PCIE_CONF_DEV(d)		(((d) & 0x1f) << 11)
+#define  PCIE_CONF_FUNC(f)		(((f) & 0x7) << 8)
+#define  PCIE_CONF_ADDR(bus, devfn, where) \
+	(PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn))    | \
+	 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | \
+	 PCIE_CONF_ADDR_EN)
+#define PCIE_CONF_DATA_OFF		0x18fc
+#define PCIE_MASK_OFF			0x1910
+#define  PCIE_MASK_ENABLE_INTS          (0xf << 24)
+#define PCIE_CTRL_OFF			0x1a00
+#define  PCIE_CTRL_X1_MODE		BIT(0)
+#define PCIE_STAT_OFF			0x1a04
+#define  PCIE_STAT_BUS                  (0xff << 8)
+#define  PCIE_STAT_DEV                  (0x1f << 16)
+#define  PCIE_STAT_LINK_DOWN		BIT(0)
+#define PCIE_DEBUG_CTRL         	0x1a60
+#define  PCIE_DEBUG_SOFT_RESET		BIT(20)
+
+#define to_pcie(_hc)	container_of(_hc, struct mvebu_pcie, pci)
+
+/*
+ * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
+ * into SoCs address space. Each controller will map 32M of MEM
+ * and 64K of I/O space when registered.
+ */
+static void __iomem *mvebu_pcie_membase = IOMEM(0xe0000000);
+static void __iomem *mvebu_pcie_iobase = IOMEM(0xffe00000);
+
+static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
+{
+	return !(readl(pcie->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
+}
+
+static void mvebu_pcie_set_local_bus_nr(struct pci_controller *host, int busno)
+{
+	struct mvebu_pcie *pcie = to_pcie(host);
+	u32 stat;
+
+	stat = readl(pcie->base + PCIE_STAT_OFF);
+	stat &= ~PCIE_STAT_BUS;
+	stat |= busno << 8;
+	writel(stat, pcie->base + PCIE_STAT_OFF);
+}
+
+static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie *pcie, int devno)
+{
+	u32 stat;
+
+	stat = readl(pcie->base + PCIE_STAT_OFF);
+	stat &= ~PCIE_STAT_DEV;
+	stat |= devno << 16;
+	writel(stat, pcie->base + PCIE_STAT_OFF);
+}
+
+static int mvebu_pcie_indirect_rd_conf(struct pci_bus *bus,
+	       unsigned int devfn, int where, int size, u32 *val)
+{
+	struct mvebu_pcie *pcie = to_pcie(bus->host);
+
+	/* Skip all requests not directed to device behind bridge */
+	if (devfn != pcie->devfn || !mvebu_pcie_link_up(pcie)) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
+	       pcie->base + PCIE_CONF_ADDR_OFF);
+
+	*val = readl(pcie->base + PCIE_CONF_DATA_OFF);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mvebu_pcie_indirect_wr_conf(struct pci_bus *bus,
+	       unsigned int devfn, int where, int size, u32 val)
+{
+	struct mvebu_pcie *pcie = to_pcie(bus->host);
+	u32 _val, shift = 8 * (where & 3);
+
+	/* Skip all requests not directed to device behind bridge */
+	if (devfn != pcie->devfn || !mvebu_pcie_link_up(pcie))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
+	       pcie->base + PCIE_CONF_ADDR_OFF);
+	_val = readl(pcie->base + PCIE_CONF_DATA_OFF);
+
+	if (size == 4)
+		_val = val;
+	else if (size == 2)
+		_val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
+	else if (size == 1)
+		_val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
+	else
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	writel(_val, pcie->base + PCIE_CONF_DATA_OFF);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int mvebu_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr)
+{
+	struct mvebu_pcie *pcie = to_pcie(bus->host);
+
+	return (int)pcie->membase + res_addr;
+}
+
+static struct pci_ops mvebu_pcie_indirect_ops = {
+	.read = mvebu_pcie_indirect_rd_conf,
+	.write = mvebu_pcie_indirect_wr_conf,
+	.res_start = mvebu_pcie_res_start,
+};
+
+/*
+ * Setup PCIE BARs and Address Decode Wins:
+ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+ * WIN[0-3] -> DRAM bank[0-3]
+ */
+static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
+{
+	const struct mbus_dram_target_info *dram = mvebu_mbus_dram_info();
+	u32 size;
+	int i;
+
+	/* First, disable and clear BARs and windows. */
+	for (i = 1; i < 3; i++) {
+		writel(0, pcie->base + PCIE_BAR_CTRL_OFF(i));
+		writel(0, pcie->base + PCIE_BAR_LO_OFF(i));
+		writel(0, pcie->base + PCIE_BAR_HI_OFF(i));
+	}
+
+	for (i = 0; i < 5; i++) {
+		writel(0, pcie->base + PCIE_WIN04_CTRL_OFF(i));
+		writel(0, pcie->base + PCIE_WIN04_BASE_OFF(i));
+		writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
+	}
+
+	writel(0, pcie->base + PCIE_WIN5_CTRL_OFF);
+	writel(0, pcie->base + PCIE_WIN5_BASE_OFF);
+	writel(0, pcie->base + PCIE_WIN5_REMAP_OFF);
+
+	/* Setup windows for DDR banks.  Count total DDR size on the fly. */
+	size = 0;
+	for (i = 0; i < dram->num_cs; i++) {
+		const struct mbus_dram_window *cs = dram->cs + i;
+
+		writel(cs->base & 0xffff0000,
+		       pcie->base + PCIE_WIN04_BASE_OFF(i));
+		writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
+		writel(((cs->size - 1) & 0xffff0000) |
+		       (cs->mbus_attr << 8) |
+		       (dram->mbus_dram_target_id << 4) | 1,
+		       pcie->base + PCIE_WIN04_CTRL_OFF(i));
+
+		size += cs->size;
+	}
+
+	/* Round up 'size' to the nearest power of two. */
+	if ((size & (size - 1)) != 0)
+		size = 1 << fls(size);
+
+	/* Setup BAR[1] to all DRAM banks. */
+	writel(dram->cs[0].base, pcie->base + PCIE_BAR_LO_OFF(1));
+	writel(0, pcie->base + PCIE_BAR_HI_OFF(1));
+	writel(((size - 1) & 0xffff0000) | 1,
+	       pcie->base + PCIE_BAR_CTRL_OFF(1));
+}
+
+#define DT_FLAGS_TO_TYPE(flags)		(((flags) >> 24) & 0x03)
+#define  DT_TYPE_IO	0x1
+#define  DT_TYPE_MEM32	0x2
+#define DT_CPUADDR_TO_TARGET(cpuaddr)	(((cpuaddr) >> 56) & 0xFF)
+#define DT_CPUADDR_TO_ATTR(cpuaddr)	(((cpuaddr) >> 48) & 0xFF)
+
+static int mvebu_get_target_attr(struct device_node *np, int devfn,
+		 unsigned long type, unsigned int *target, unsigned int *attr)
+{
+	const int na = 3, ns = 2;
+	const __be32 *range;
+	int rlen, nranges, rangesz, pna, i;
+
+	*target = -1;
+	*attr = -1;
+
+	range = of_get_property(np, "ranges", &rlen);
+	if (!range)
+		return -EINVAL;
+
+	pna = of_n_addr_cells(np);
+	rangesz = pna + na + ns;
+	nranges = rlen / sizeof(__be32) / rangesz;
+
+	for (i = 0; i < nranges; i++) {
+		u32 flags = of_read_number(range, 1);
+		u32 slot = of_read_number(range + 1, 1);
+		u64 cpuaddr = of_read_number(range + na, pna);
+		unsigned long rtype;
+
+		if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO)
+			rtype = IORESOURCE_IO;
+		else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32)
+			rtype = IORESOURCE_MEM;
+
+		if (slot == PCI_SLOT(devfn) && type == rtype) {
+			*target = DT_CPUADDR_TO_TARGET(cpuaddr);
+			*attr = DT_CPUADDR_TO_ATTR(cpuaddr);
+			return 0;
+		}
+
+		range += rangesz;
+	}
+
+	return -ENOENT;
+}
+
+static struct mvebu_pcie *mvebu_pcie_port_probe(struct device_d *dev,
+						struct device_node *np)
+{
+	struct mvebu_pcie *pcie;
+	struct clk *clk;
+	enum of_gpio_flags flags;
+	int reset_gpio;
+	u32 port, lane, devfn;
+	int mem_target, mem_attr;
+	int io_target, io_attr;
+	int ret;
+
+	if (of_property_read_u32(np, "marvell,pcie-port", &port)) {
+		dev_err(dev, "missing pcie-port property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	of_property_read_u32(np, "marvell,pcie-lane", &lane);
+
+	devfn = of_pci_get_devfn(np);
+	if (devfn < 0) {
+		dev_err(dev, "unable to parse devfn\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_MEM,
+				  &mem_target, &mem_attr)) {
+		dev_err(dev, "unable to get target/attr for mem window\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* I/O windows are optional */
+	mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_IO,
+			      &io_target, &io_attr);
+
+	reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
+	if (gpio_is_valid(reset_gpio)) {
+		int reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+		char *reset_name = asprintf("pcie%d.%d-reset", port, lane);
+		u32 reset_udelay = 20000;
+
+		of_property_read_u32(np, "reset-delay-us", &reset_udelay);
+
+		ret = gpio_request_one(reset_gpio, GPIOF_DIR_OUT, reset_name);
+		if (ret)
+			return ERR_PTR(ret);
+
+		/* Ensure a full reset cycle*/
+		gpio_set_value(reset_gpio, 1 ^ reset_active_low);
+		udelay(reset_udelay);
+		gpio_set_value(reset_gpio, 0 ^ reset_active_low);
+		udelay(reset_udelay);
+	}
+
+	pcie = xzalloc(sizeof(*pcie));
+	pcie->port = port;
+	pcie->lane = lane;
+	pcie->name = asprintf("pcie%d.%d", port, lane);
+	pcie->devfn = devfn;
+
+	pcie->base = of_iomap(np, 0);
+	if (!pcie->base) {
+		dev_err(dev, "PCIe%d.%d unable to map registers\n", port, lane);
+		free(pcie);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pcie->membase = mvebu_pcie_membase;
+	pcie->mem.start = 0;
+	pcie->mem.end = pcie->mem.start + SZ_32M - 1;
+	if (mvebu_mbus_add_window_remap_by_id(mem_target, mem_attr,
+		(resource_size_t)pcie->membase, resource_size(&pcie->mem), 0)) {
+		dev_err(dev, "PCIe%d.%d unable to add mbus window for mem at %08x+%08x",
+			port, lane, (u32)pcie->mem.start, resource_size(&pcie->mem));
+
+		free(pcie);
+		return ERR_PTR(-EBUSY);
+	}
+	mvebu_pcie_membase += SZ_32M;
+
+	if (io_target >= 0 && io_attr >= 0) {
+		pcie->iobase = mvebu_pcie_iobase;
+		pcie->io.start = 0;
+		pcie->io.end = pcie->io.start + SZ_64K - 1;
+
+		mvebu_mbus_add_window_remap_by_id(io_target, io_attr,
+			(resource_size_t)pcie->iobase, resource_size(&pcie->io), 0);
+		mvebu_pcie_iobase += SZ_64K;
+	}
+
+	clk = of_clk_get(np, 0);
+	if (!IS_ERR(clk))
+		clk_enable(clk);
+
+	pcie->pci.set_busno = mvebu_pcie_set_local_bus_nr;
+	pcie->pci.pci_ops = &mvebu_pcie_indirect_ops;
+	pcie->pci.mem_resource = &pcie->mem;
+	pcie->pci.io_resource = &pcie->io;
+
+	return pcie;
+}
+
+static struct mvebu_pcie_ops __maybe_unused armada_370_ops = {
+	.phy_setup = armada_370_phy_setup,
+};
+
+static struct of_device_id mvebu_pcie_dt_ids[] = {
+#if defined(CONFIG_ARCH_ARMADA_XP)
+	{ .compatible = "marvell,armada-xp-pcie", },
+#endif
+#if defined(CONFIG_ARCH_ARMADA_370)
+	{ .compatible = "marvell,armada-370-pcie", .data = (u32)&armada_370_ops, },
+#endif
+#if defined(CONFIG_ARCH_DOVE)
+	{ .compatible = "marvell,dove-pcie", },
+#endif
+#if defined(CONFIG_ARCH_KIRKWOOD)
+	{ .compatible = "marvell,kirkwood-pcie", },
+#endif
+	{ },
+};
+
+static int mvebu_pcie_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	const struct of_device_id *match = of_match_node(mvebu_pcie_dt_ids, np);
+	struct mvebu_pcie_ops *ops = (struct mvebu_pcie_ops *)match->data;
+	struct device_node *pnp;
+
+	for_each_child_of_node(np, pnp) {
+		struct mvebu_pcie *pcie;
+		u32 reg;
+
+		if (!of_device_is_available(pnp))
+			continue;
+
+		pcie = mvebu_pcie_port_probe(dev, pnp);
+		if (IS_ERR(pcie))
+			continue;
+
+		if (ops && ops->phy_setup)
+			ops->phy_setup(pcie);
+
+		mvebu_pcie_set_local_dev_nr(pcie, 0);
+		mvebu_pcie_setup_wins(pcie);
+
+		/* Master + slave enable. */
+		reg = readl(pcie->base + PCIE_CMD_OFF);
+		reg |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+		reg |= PCI_COMMAND_MASTER;
+		writel(reg, pcie->base + PCIE_CMD_OFF);
+
+		/* Disable interrupts */
+		reg = readl(pcie->base + PCIE_MASK_OFF);
+		reg &= ~PCIE_MASK_ENABLE_INTS;
+		writel(reg, pcie->base + PCIE_MASK_OFF);
+
+		register_pci_controller(&pcie->pci);
+	}
+
+	return 0;
+}
+
+static struct driver_d mvebu_pcie_driver = {
+	.name = "mvebu-pcie",
+	.probe = mvebu_pcie_probe,
+	.of_compatible = mvebu_pcie_dt_ids,
+};
+device_platform_driver(mvebu_pcie_driver);
diff --git a/drivers/pci/pci-mvebu.h b/drivers/pci/pci-mvebu.h
new file mode 100644
index 000000000000..2e4ed636227e
--- /dev/null
+++ b/drivers/pci/pci-mvebu.h
@@ -0,0 +1,35 @@
+/*
+ * PCIe include for Marvell MVEBU SoCs
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_PCI_H
+#define __MVEBU_PCI_H
+
+#include <linux/pci.h>
+
+struct mvebu_pcie {
+	struct pci_controller pci;
+	char *name;
+	void __iomem *base;
+	void __iomem *membase;
+	struct resource mem;
+	void __iomem *iobase;
+	struct resource io;
+	u32 port;
+	u32 lane;
+	int devfn;
+};
+
+struct mvebu_pcie_ops {
+	int (*phy_setup)(struct mvebu_pcie *pcie);
+};
+
+int armada_370_phy_setup(struct mvebu_pcie *pcie);
+
+#endif
-- 
2.0.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v2 0/5] Marvell EBU PCIe driver
  2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
                     ` (4 preceding siblings ...)
  2014-07-28 13:26   ` [PATCH v2 5/5] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
@ 2014-07-29 19:58   ` Sebastian Hesselbarth
  2014-07-30  6:21     ` Sascha Hauer
  5 siblings, 1 reply; 26+ messages in thread
From: Sebastian Hesselbarth @ 2014-07-29 19:58 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Thomas Petazzoni, barebox

On 07/28/2014 03:26 PM, Sebastian Hesselbarth wrote:
> Second round of the Marvell EBU PCIe driver patch set. Compared
> to v1, I reworked pci_scan_bus to properly set IORESOURCE flags
> for all resources, and added auto-incrementing pci bus numbering.
> 
> Patch 1 is unchanged and still fixes resource computation of mbus
> driver. Patch 2 now properly sets IORESOURCE flags for I/O, 32b
> MEM, and 64b MEM resources.
> 
> Patch 3 is a squashed and reworked patch dealing with pci host
> controller registration: bus number is now assigned from an auto-
> incremented bus_index and already provided pci_controller's
> set_busno is called right before pci_scan_bus to allow the
> controller to update internal registers related with bus number.
> This patch also sets a back-reference to the pci_controller of
> a pci_bus and cleans up some unused left-overs from Linux import.
> 
> Patch 4 is unchanged import of of_pci_get_devfn() and Patch 5
> finally adds the PCIe controller driver for Marvell MVEBU SoCs.
> Individual changelogs are also at the corresponding patch mails.
> 
> Again, this has been tested on Armada 370 Mirabox.

Sascha,

before you consider applying this, I had the chance to test it
on Armada XP, too. Both the driver and pci core need some more
fixes, so please wait for v3.

Sebastian


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH v2 0/5] Marvell EBU PCIe driver
  2014-07-29 19:58   ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
@ 2014-07-30  6:21     ` Sascha Hauer
  0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2014-07-30  6:21 UTC (permalink / raw)
  To: Sebastian Hesselbarth; +Cc: Thomas Petazzoni, barebox

On Tue, Jul 29, 2014 at 09:58:17PM +0200, Sebastian Hesselbarth wrote:
> On 07/28/2014 03:26 PM, Sebastian Hesselbarth wrote:
> > Second round of the Marvell EBU PCIe driver patch set. Compared
> > to v1, I reworked pci_scan_bus to properly set IORESOURCE flags
> > for all resources, and added auto-incrementing pci bus numbering.
> > 
> > Patch 1 is unchanged and still fixes resource computation of mbus
> > driver. Patch 2 now properly sets IORESOURCE flags for I/O, 32b
> > MEM, and 64b MEM resources.
> > 
> > Patch 3 is a squashed and reworked patch dealing with pci host
> > controller registration: bus number is now assigned from an auto-
> > incremented bus_index and already provided pci_controller's
> > set_busno is called right before pci_scan_bus to allow the
> > controller to update internal registers related with bus number.
> > This patch also sets a back-reference to the pci_controller of
> > a pci_bus and cleans up some unused left-overs from Linux import.
> > 
> > Patch 4 is unchanged import of of_pci_get_devfn() and Patch 5
> > finally adds the PCIe controller driver for Marvell MVEBU SoCs.
> > Individual changelogs are also at the corresponding patch mails.
> > 
> > Again, this has been tested on Armada 370 Mirabox.
> 
> Sascha,
> 
> before you consider applying this, I had the chance to test it
> on Armada XP, too. Both the driver and pci core need some more
> fixes, so please wait for v3.

Ok, I removed all patches from -next. I'll wait for the next round of
patches.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2014-07-30  6:21 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-23  9:26 [PATCH RESEND 0/6] Marvell EBU PCIe driver Sebastian Hesselbarth
2014-07-23  9:26 ` [PATCH RESEND 1/6] bus: mvebu: fix resource size handling Sebastian Hesselbarth
2014-07-23  9:26 ` [PATCH RESEND 2/6] pci: pci_scan_bus: respect 64b BARs Sebastian Hesselbarth
2014-07-25  8:51   ` Lucas Stach
2014-07-25 14:43     ` Sebastian Hesselbarth
2014-07-23  9:26 ` [PATCH RESEND 3/6] pci: add host controller struct to sysdata Sebastian Hesselbarth
2014-07-25  9:07   ` Lucas Stach
2014-07-25 14:54     ` Sebastian Hesselbarth
2014-07-23  9:26 ` [PATCH RESEND 4/6] pci: allow to set bus number on register_pci_controller Sebastian Hesselbarth
2014-07-23  9:26 ` [PATCH RESEND 5/6] of: pci: import of_pci_get_devfn() Sebastian Hesselbarth
2014-07-23  9:26 ` [PATCH RESEND 6/6] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
2014-07-23 10:35   ` Sebastian Hesselbarth
2014-07-25  7:27   ` Sascha Hauer
2014-07-25 15:00     ` Sebastian Hesselbarth
2014-07-28  5:19       ` Sascha Hauer
2014-07-28  6:10         ` Sebastian Hesselbarth
2014-07-25  9:16   ` Lucas Stach
2014-07-25 14:57     ` Sebastian Hesselbarth
2014-07-28 13:26 ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
2014-07-28 13:26   ` [PATCH v2 1/5] bus: mvebu: fix resource size handling Sebastian Hesselbarth
2014-07-28 13:26   ` [PATCH v2 2/5] pci: pci_scan_bus: respect 64b BARs Sebastian Hesselbarth
2014-07-28 13:26   ` [PATCH v2 3/5] pci: set auto-incremented bus number Sebastian Hesselbarth
2014-07-28 13:26   ` [PATCH v2 4/5] of: pci: import of_pci_get_devfn() Sebastian Hesselbarth
2014-07-28 13:26   ` [PATCH v2 5/5] pci: mvebu: Add PCIe driver Sebastian Hesselbarth
2014-07-29 19:58   ` [PATCH v2 0/5] Marvell EBU " Sebastian Hesselbarth
2014-07-30  6:21     ` Sascha Hauer

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