diff --git a/target/linux/mvebu/config-default b/target/linux/mvebu/config-default
index 1fe6b839e6a247458546a8d1187a2570bfaae2bb..f41c7c227b0bf414518dc1080b3b22d4809e91f7 100644
--- a/target/linux/mvebu/config-default
+++ b/target/linux/mvebu/config-default
@@ -172,6 +172,7 @@ CONFIG_MACH_ARMADA_XP=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_MDIO_BOARDINFO=y
 CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MIGHT_HAVE_PCI=y
 CONFIG_MODULES_USE_ELF_REL=y
 # CONFIG_MPCORE_WATCHDOG is not set
 CONFIG_MSDOS_FS=y
@@ -210,6 +211,7 @@ CONFIG_OUTER_CACHE=y
 CONFIG_OUTER_CACHE_SYNC=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PCI is not set
 # CONFIG_PCI_SYSCALL is not set
 CONFIG_PERCPU_RWSEM=y
 CONFIG_PERF_USE_VMALLOC=y
diff --git a/target/linux/mvebu/patches-3.8/028-lib_devres_dont_enclose_pcim.patch b/target/linux/mvebu/patches-3.8/028-lib_devres_dont_enclose_pcim.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3872924a6150eacf35163f00006a737fb4bddd91
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/028-lib_devres_dont_enclose_pcim.patch
@@ -0,0 +1,28 @@
+The pcim_*() functions are used by the libata-sff subsystem, and this
+subsystem is used for many SATA drivers on ARM platforms that do not
+necessarily have I/O ports.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
+Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
+Cc: Yinghai Lu <yinghai@kernel.org>
+Cc: linux-kernel@vger.kernel.org
+---
+ lib/devres.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/lib/devres.c
++++ b/lib/devres.c
+@@ -195,6 +195,7 @@ void devm_ioport_unmap(struct device *de
+ 			       devm_ioport_map_match, (void *)addr));
+ }
+ EXPORT_SYMBOL(devm_ioport_unmap);
++#endif /* CONFIG_HAS_IOPORT */
+ 
+ #ifdef CONFIG_PCI
+ /*
+@@ -400,4 +401,3 @@ void pcim_iounmap_regions(struct pci_dev
+ }
+ EXPORT_SYMBOL(pcim_iounmap_regions);
+ #endif /* CONFIG_PCI */
+-#endif /* CONFIG_HAS_IOPORT */
diff --git a/target/linux/mvebu/patches-3.8/029-clk_mvebu_create_parent_child_relation.patch b/target/linux/mvebu/patches-3.8/029-clk_mvebu_create_parent_child_relation.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2cccc0357b3f873b4562fef7e7c82747241edf91
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/029-clk_mvebu_create_parent_child_relation.patch
@@ -0,0 +1,24 @@
+The Armada 370 has two gatable clocks for each PCIe interface, and we
+want both of them to be enabled. We therefore make one of the two
+clocks a child of the other, as we did for the sataX and sataXlnk
+clocks on Armada XP.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: Mike Turquette <mturquette@linaro.org>
+---
+ drivers/clk/mvebu/clk-gating-ctrl.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/mvebu/clk-gating-ctrl.c
++++ b/drivers/clk/mvebu/clk-gating-ctrl.c
+@@ -119,8 +119,8 @@ static const struct mvebu_soc_descr __in
+ 	{ "pex1_en", NULL,  2 },
+ 	{ "ge1", NULL, 3 },
+ 	{ "ge0", NULL, 4 },
+-	{ "pex0", NULL, 5 },
+-	{ "pex1", NULL, 9 },
++	{ "pex0", "pex0_en", 5 },
++	{ "pex1", "pex1_en", 9 },
+ 	{ "sata0", NULL, 15 },
+ 	{ "sdio", NULL, 17 },
+ 	{ "tdm", NULL, 25 },
diff --git a/target/linux/mvebu/patches-3.8/030-arm_plat_orion_introduce_win_ctrl_enable.patch b/target/linux/mvebu/patches-3.8/030-arm_plat_orion_introduce_win_ctrl_enable.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9a237ec9b90eea74b0fe386e6ee4a4a3944f2c19
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/030-arm_plat_orion_introduce_win_ctrl_enable.patch
@@ -0,0 +1,28 @@
+Instead of hardcoding "1" as being the bit value to enable an address
+decoding window, introduce and use a WIN_CTRL_ENABLE definition.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/plat-orion/addr-map.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/plat-orion/addr-map.c
++++ b/arch/arm/plat-orion/addr-map.c
+@@ -38,6 +38,7 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
+  * CPU Address Decode Windows registers
+  */
+ #define WIN_CTRL_OFF		0x0000
++#define   WIN_CTRL_ENABLE       BIT(0)
+ #define WIN_BASE_OFF		0x0004
+ #define WIN_REMAP_LO_OFF	0x0008
+ #define WIN_REMAP_HI_OFF	0x000c
+@@ -79,7 +80,8 @@ void __init orion_setup_cpu_win(const st
+ 	}
+ 
+ 	base_high = base & 0xffff0000;
+-	ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1;
++	ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) |
++		WIN_CTRL_ENABLE;
+ 
+ 	writel(base_high, addr + WIN_BASE_OFF);
+ 	writel(ctrl, addr + WIN_CTRL_OFF);
diff --git a/target/linux/mvebu/patches-3.8/031-arm_plat_orion_refactor.patch b/target/linux/mvebu/patches-3.8/031-arm_plat_orion_refactor.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fe9f6285f774a830febe8f5e4ae6c4b943371ec4
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/031-arm_plat_orion_refactor.patch
@@ -0,0 +1,80 @@
+In the address decoding code, the orion_disable_wins() function is
+used at boot time to disable all address decoding windows, before
+configuring only the ones that are needed. This allows to make sure
+that no configuration is left from the bootloader.
+
+As a preparation for the introduction of address decoding window
+allocation/deallocation function, we refactor this function into an
+orion_disable_cpu_win() which disables a single window.
+
+The orion_config_wins() function is changed to call
+orion_disable_cpu_win() in a loop, to preserve an identical behavior.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/plat-orion/addr-map.c |   35 +++++++++++++++++------------------
+ 1 file changed, 17 insertions(+), 18 deletions(-)
+
+--- a/arch/arm/plat-orion/addr-map.c
++++ b/arch/arm/plat-orion/addr-map.c
+@@ -95,6 +95,19 @@ void __init orion_setup_cpu_win(const st
+ 	}
+ }
+ 
++static void __init orion_disable_cpu_win(const struct orion_addr_map_cfg *cfg,
++					 const int win)
++{
++	void __iomem *addr = cfg->win_cfg_base(cfg, win);
++
++	writel(0, addr + WIN_BASE_OFF);
++	writel(0, addr + WIN_CTRL_OFF);
++	if (cfg->cpu_win_can_remap(cfg, win)) {
++		writel(0, addr + WIN_REMAP_LO_OFF);
++		writel(0, addr + WIN_REMAP_HI_OFF);
++	}
++}
++
+ /*
+  * Configure a number of windows.
+  */
+@@ -108,36 +121,22 @@ static void __init orion_setup_cpu_wins(
+ 	}
+ }
+ 
+-static void __init orion_disable_wins(const struct orion_addr_map_cfg * cfg)
+-{
+-	void __iomem *addr;
+-	int i;
+-
+-	for (i = 0; i < cfg->num_wins; i++) {
+-		addr = cfg->win_cfg_base(cfg, i);
+-
+-		writel(0, addr + WIN_BASE_OFF);
+-		writel(0, addr + WIN_CTRL_OFF);
+-		if (cfg->cpu_win_can_remap(cfg, i)) {
+-			writel(0, addr + WIN_REMAP_LO_OFF);
+-			writel(0, addr + WIN_REMAP_HI_OFF);
+-		}
+-	}
+-}
+-
+ /*
+  * Disable, clear and configure windows.
+  */
+ void __init orion_config_wins(struct orion_addr_map_cfg * cfg,
+ 			      const struct orion_addr_map_info *info)
+ {
++	int win;
++
+ 	if (!cfg->cpu_win_can_remap)
+ 		cfg->cpu_win_can_remap = orion_cpu_win_can_remap;
+ 
+ 	if (!cfg->win_cfg_base)
+ 		cfg->win_cfg_base = orion_win_cfg_base;
+ 
+-	orion_disable_wins(cfg);
++	for (win = 0; win < cfg->num_wins; win++)
++		orion_disable_cpu_win(cfg, win);
+ 
+ 	if (info)
+ 		orion_setup_cpu_wins(cfg, info);
diff --git a/target/linux/mvebu/patches-3.8/032-arm_plat_orion_introduce_orion_alloc_free_cpu_win.patch b/target/linux/mvebu/patches-3.8/032-arm_plat_orion_introduce_orion_alloc_free_cpu_win.patch
new file mode 100644
index 0000000000000000000000000000000000000000..91ed678b27f680cb2e345ad3011cbf0caaa35184
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/032-arm_plat_orion_introduce_orion_alloc_free_cpu_win.patch
@@ -0,0 +1,96 @@
+In the address decoding code, we implement two new functions:
+orion_alloc_cpu_win() and orion_free_cpu_win(). The first function
+finds an unused address decoding window, and configures it according
+to the given arguments (in terms of base address, size, target,
+attributes). The second function frees an address decoding window,
+given a physical base address.
+
+Those two new functions will be used by the PCIe code, which needs to
+dynamically register address decoding windows depending on the PCIe
+devices that are detected.
+
+The orion_free_cpu_win() function is only here to handle error cases
+in the PCIe devices initialization, in the normal case, address
+decoding windows are never freed.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/plat-orion/addr-map.c              |   50 +++++++++++++++++++++++++++
+ arch/arm/plat-orion/include/plat/addr-map.h |    7 ++++
+ 2 files changed, 57 insertions(+)
+
+--- a/arch/arm/plat-orion/addr-map.c
++++ b/arch/arm/plat-orion/addr-map.c
+@@ -109,6 +109,56 @@ static void __init orion_disable_cpu_win
+ }
+ 
+ /*
++ * Find an unused address decoding window, and enable it according to
++ * the arguments passed (base, size, target, attributes, remap).
++ */
++int __init orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg,
++			       const u32 base, const u32 size,
++			       const u8 target, const u8 attr, const int remap)
++{
++	int win;
++
++	for (win = 0; win < cfg->num_wins; win++) {
++		void __iomem *addr = cfg->win_cfg_base(cfg, win);
++		u32 ctrl = readl(addr + WIN_CTRL_OFF);
++		if (!(ctrl & WIN_CTRL_ENABLE))
++			break;
++	}
++
++	/* No more windows available */
++	if (win == cfg->num_wins)
++		return -ENOMEM;
++
++	orion_setup_cpu_win(cfg, win, base, size, target, attr, remap);
++	return 0;
++}
++
++/*
++ * Free an address decoding window, given its base address.
++ */
++int __init orion_free_cpu_win(const struct orion_addr_map_cfg *cfg,
++			      const u32 base)
++{
++	int win;
++
++	for (win = 0; win < cfg->num_wins; win++) {
++		void __iomem *addr = cfg->win_cfg_base(cfg, win);
++		u32 winbase = readl(addr + WIN_BASE_OFF);
++		u32 ctrl = readl(addr + WIN_CTRL_OFF);
++
++		if (!(ctrl & WIN_CTRL_ENABLE))
++			continue;
++
++		if (winbase == (base & 0xffff0000)) {
++			orion_disable_cpu_win(cfg, win);
++			return 0;
++		}
++	}
++
++	return -EINVAL;
++}
++
++/*
+  * Configure a number of windows.
+  */
+ static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg,
+--- a/arch/arm/plat-orion/include/plat/addr-map.h
++++ b/arch/arm/plat-orion/include/plat/addr-map.h
+@@ -49,6 +49,13 @@ void __init orion_setup_cpu_win(const st
+ 				const u32 size, const u8 target,
+ 				const u8 attr, const int remap);
+ 
++int __init orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg,
++			       const u32 base, const u32 size,
++			       const u8 target, const u8 attr, const int remap);
++
++int __init orion_free_cpu_win(const struct orion_addr_map_cfg *cfg,
++			      const u32 base);
++
+ void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
+ 					const void __iomem *ddr_window_cpu_base);
+ #endif
diff --git a/target/linux/mvebu/patches-3.8/033-arm_mvebu_add_functions_to_alloc_free_pcie.patch b/target/linux/mvebu/patches-3.8/033-arm_mvebu_add_functions_to_alloc_free_pcie.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fd3c1af92e2f42b4e08f5d65c7a9fa60e3d10097
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/033-arm_mvebu_add_functions_to_alloc_free_pcie.patch
@@ -0,0 +1,201 @@
+This commit adds two functions armada_370_xp_alloc_pcie_window() and
+armada_370_xp_free_pcie_window() that respectively allocate and free
+an address decoding window pointing to either a memory or I/O region
+of a PCIe device.
+
+Those functions will be used by the PCIe driver to create and remove
+those regions depending on the PCIe devices that are detected.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/mach-mvebu/addr-map.c |  156 ++++++++++++++++++++++++++++++++++++++--
+ arch/arm/mach-mvebu/common.h   |    4 ++
+ 2 files changed, 156 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/mach-mvebu/addr-map.c
++++ b/arch/arm/mach-mvebu/addr-map.c
+@@ -24,14 +24,10 @@
+ #define ARMADA_XP_TARGET_DEV_BUS	1
+ #define   ARMADA_XP_ATTR_DEV_BOOTROM    0x1D
+ #define ARMADA_XP_TARGET_ETH1		3
+-#define ARMADA_XP_TARGET_PCIE_0_2	4
+ #define ARMADA_XP_TARGET_ETH0		7
+-#define ARMADA_XP_TARGET_PCIE_1_3	8
+ 
+ #define ARMADA_370_TARGET_DEV_BUS       1
+ #define   ARMADA_370_ATTR_DEV_BOOTROM   0x1D
+-#define ARMADA_370_TARGET_PCIE_0        4
+-#define ARMADA_370_TARGET_PCIE_1        8
+ 
+ #define ARMADA_WINDOW_8_PLUS_OFFSET       0x90
+ #define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180
+@@ -89,6 +85,158 @@ static struct __initdata orion_addr_map_
+ 	.win_cfg_base = armada_cfg_base,
+ };
+ 
++#ifdef CONFIG_PCI
++/*
++ * PCIe windows allocation code.
++ */
++#define ARMADA_370_XP_PCIE_MEM_START 0xC0000000
++#define ARMADA_370_XP_PCIE_MEM_END   (ARMADA_370_XP_PCIE_MEM_START + SZ_256M)
++#define ARMADA_370_XP_PCIE_IO_START  0xF2000000
++#define ARMADA_370_XP_PCIE_IO_END    (ARMADA_370_XP_PCIE_IO_START + SZ_1M)
++
++static unsigned long armada_370_xp_pcie_memaddr = ARMADA_370_XP_PCIE_MEM_START;
++static unsigned long armada_370_xp_pcie_ioaddr = ARMADA_370_XP_PCIE_IO_START;
++
++/*
++ * This structure and the following arrays allow to map a PCIe (port,
++ * lane) tuple to the corresponding (target, attribute) tuple needed
++ * to configure an address decoding window for the given PCIe (port,
++ * lane).
++ */
++struct pcie_mapping {
++	int port;
++	int lane;
++	u8  target;
++	u8  attr;
++};
++
++struct pcie_mapping armada_xp_pcie_mappings[] = {
++	{ .port = 0, .lane = 0, .target = 4, .attr = 0xE0 },
++	{ .port = 0, .lane = 1, .target = 4, .attr = 0xD0 },
++	{ .port = 0, .lane = 2, .target = 4, .attr = 0xB0 },
++	{ .port = 0, .lane = 3, .target = 4, .attr = 0x70 },
++	{ .port = 1, .lane = 0, .target = 8, .attr = 0xE0 },
++	{ .port = 1, .lane = 1, .target = 8, .attr = 0xD0 },
++	{ .port = 1, .lane = 2, .target = 8, .attr = 0xB0 },
++	{ .port = 1, .lane = 3, .target = 8, .attr = 0x70 },
++	{ .port = 2, .lane = 0, .target = 4, .attr = 0xF0 },
++	{ .port = 3, .lane = 0, .target = 8, .attr = 0xF0 },
++	{ .port = -1 },
++};
++
++struct pcie_mapping armada_370_pcie_mappings[] = {
++	{ .port = 0, .lane = 0, .target = 4, .attr = 0xE0 },
++	{ .port = 1, .lane = 0, .target = 8, .attr = 0xE0 },
++	{ .port = -1 },
++};
++
++/*
++ * This function finds an available physical address range between
++ * ARMADA_370_XP_PCIE_MEM_START and ARMADA_370_XP_PCIE_MEM_END (for
++ * PCIe memory regions) or between ARMADA_370_XP_PCIE_IO_START and
++ * ARMADA_370_XP_PCIE_IO_END (for PCIe I/O regions) and creates an
++ * address decoding window from this allocated address pointing to the
++ * right PCIe device.
++ *
++ * An error code is returned, the allocated base address is returned
++ * through the 'outbase' argument.
++ */
++int __init armada_370_xp_alloc_pcie_window(int pcie_port, int pcie_lane,
++					   int type, u32 size,
++					   unsigned long *outbase)
++{
++	struct pcie_mapping *mapping, *mappings;
++	u8 target, attr;
++	u32 base;
++	int ret;
++
++	if (of_machine_is_compatible("marvell,armadaxp"))
++		mappings = armada_xp_pcie_mappings;
++	else if (of_machine_is_compatible("marvell,armada370"))
++		mappings = armada_370_pcie_mappings;
++	else
++		return -ENODEV;
++
++	for (mapping = mappings; mapping->port != -1; mapping++)
++		if (mapping->port == pcie_port && mapping->lane == pcie_lane)
++			break;
++
++	if (mapping->port == -1)
++		return -ENODEV;
++
++	target = mapping->target;
++	attr = mapping->attr;
++
++	if (type == IORESOURCE_MEM) {
++		/*
++		 * Bit 3 of the attributes indicates that it is a
++		 * memory region, as opposed to an I/O region
++		 */
++		attr |= (1 << 3);
++
++		if (armada_370_xp_pcie_memaddr + size >
++		    ARMADA_370_XP_PCIE_MEM_END)
++			return -ENOMEM;
++
++		base = armada_370_xp_pcie_memaddr;
++		armada_370_xp_pcie_memaddr += size;
++
++		ret = orion_alloc_cpu_win(&addr_map_cfg, base, size, target,
++					  attr, -1);
++		if (ret) {
++			armada_370_xp_pcie_memaddr -= size;
++			return ret;
++		}
++	} else if (type == IORESOURCE_IO) {
++		if (armada_370_xp_pcie_ioaddr + size >
++		    ARMADA_370_XP_PCIE_IO_END)
++			return -ENOMEM;
++
++		base = armada_370_xp_pcie_ioaddr;
++		armada_370_xp_pcie_ioaddr += size;
++
++		ret = orion_alloc_cpu_win(&addr_map_cfg, base, size, target,
++					  attr, -1);
++		if (ret) {
++			armada_370_xp_pcie_ioaddr -= size;
++			return ret;
++		}
++	} else
++		return -ENODEV;
++
++	*outbase = base;
++	return 0;
++}
++
++/*
++ * Frees an address decoding window previously allocated by
++ * armada_370_xp_alloc_pcie_window(). Note that only the last window
++ * allocated for a given type (MEM or IO) can be freed, due to the
++ * simplicity of the allocator. This is however sufficient to handle
++ * the error cases when initializing one PCIe device.
++ */
++int __init armada_370_xp_free_pcie_window(int type, unsigned long base,
++					  u32 size)
++{
++	if (type == IORESOURCE_MEM) {
++		/* We can only free the last allocated window */
++		if (base + size != armada_370_xp_pcie_memaddr)
++			return -EINVAL;
++		orion_free_cpu_win(&addr_map_cfg, base);
++		armada_370_xp_pcie_memaddr -= size;
++	} else if (type == IORESOURCE_IO) {
++		/* We can only free the last allocated window */
++		if (base + size != armada_370_xp_pcie_ioaddr)
++			return -EINVAL;
++		orion_free_cpu_win(&addr_map_cfg, base);
++		armada_370_xp_pcie_ioaddr -= size;
++	} else
++		return -EINVAL;
++
++	return 0;
++}
++#endif
++
+ static int __init armada_setup_cpu_mbus(void)
+ {
+ 	struct device_node *np;
+--- a/arch/arm/mach-mvebu/common.h
++++ b/arch/arm/mach-mvebu/common.h
+@@ -25,4 +25,8 @@ int armada_370_xp_coherency_init(void);
+ int armada_370_xp_pmsu_init(void);
+ void armada_xp_secondary_startup(void);
+ extern struct smp_operations armada_xp_smp_ops;
++
++int armada_370_xp_alloc_pcie_window(int pcie_port, int pcie_lane,
++				    int type, u32 size, unsigned long *outbase);
++int armada_370_xp_free_pcie_window(int type, unsigned long base, u32 size);
+ #endif
diff --git a/target/linux/mvebu/patches-3.8/034-arm_plat_orion_make_common_pcie.patch b/target/linux/mvebu/patches-3.8/034-arm_plat_orion_make_common_pcie.patch
new file mode 100644
index 0000000000000000000000000000000000000000..40ac714c10cba18eebeacf900250ef5c1e6c49b6
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/034-arm_plat_orion_make_common_pcie.patch
@@ -0,0 +1,25 @@
+mvebu is a new-style Orion platform, so it only selects PLAT_ORION,
+but not PLAT_ORION_LEGACY. It will however need the common PCIe code
+from plat-orion, so make this code available for PLAT_ORION platforms
+as a whole, and not only PLAT_ORION_LEGACY platforms.
+
+We also take this opportunity to build the PCIe code only when
+CONFIG_PCI is enabled.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/plat-orion/Makefile |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/plat-orion/Makefile
++++ b/arch/arm/plat-orion/Makefile
+@@ -4,7 +4,8 @@
+ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+ 
+ obj-y                             += addr-map.o
++obj-$(CONFIG_PCI)                 += pcie.o
+ 
+ orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o
+-obj-$(CONFIG_PLAT_ORION_LEGACY)   += irq.o pcie.o time.o common.o mpp.o
++obj-$(CONFIG_PLAT_ORION_LEGACY)   += irq.o time.o common.o mpp.o
+ obj-$(CONFIG_PLAT_ORION_LEGACY)   += $(orion-gpio-y)
diff --git a/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch b/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch
new file mode 100644
index 0000000000000000000000000000000000000000..48f828344f2bb981c1f9af12357ab6b237aa60f2
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/035-arm_mvebu_the_core_pcie_driver.patch
@@ -0,0 +1,474 @@
+This driver implements the hw_pci operations needed by the core ARM
+PCI code to setup PCI devices and get their corresponding IRQs, and
+the pci_ops operations that are used by the PCI core to read/write the
+configuration space of PCI devices.
+
+In addition, this driver enumerates the different PCIe slots, and for
+those having a device plugged in, it allocates the necessary address
+decoding windows, using the new armada_370_xp_alloc_pcie_window()
+function from mach-mvebu/addr-map.c.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ .../devicetree/bindings/pci/armada-370-xp-pcie.txt |  136 +++++++++
+ arch/arm/mach-mvebu/Makefile                       |    1 +
+ arch/arm/mach-mvebu/pcie.c                         |  306 ++++++++++++++++++++
+ 3 files changed, 443 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt
+ create mode 100644 arch/arm/mach-mvebu/pcie.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/armada-370-xp-pcie.txt
+@@ -0,0 +1,136 @@
++* Marvell Armada 370/XP PCIe interfaces
++
++Mandatory properties:
++- compatible: must be "marvell,armada-370-xp-pcie"
++- status: either "disabled" or "okay"
++- #address-cells, set to <1>
++- #size-cells, set to <1>
++- ranges: describes the association between the physical addresses of
++  the PCIe registers for each PCIe interface with "virtual" addresses
++  as seen by the sub-nodes. One entry per PCIe interface. Each entry
++  must have 3 values: the "virtual" address seen by the sub-nodes, the
++  real physical address of the PCIe registers, and the size.
++
++In addition, the Device Tree node must have sub-nodes describing each
++PCIe interface, having the following mandatory properties:
++- reg: the address and size of the PCIe registers (translated
++  addresses according to the ranges property of the parent)
++- interrupts: the interrupt number of this PCIe interface
++- clocks: the clock associated to this PCIe interface
++- marvell,pcie-port: the physical PCIe port number
++- status: either "disabled" or "okay"
++
++and the following optional properties:
++- marvell,pcie-lane: the physical PCIe lane number, for ports having
++  multiple lanes. If this property is not found, we assume that the
++  value is 0.
++
++Example:
++
++pcie-controller {
++	compatible = "marvell,armada-370-xp-pcie";
++	status = "disabled";
++	#address-cells = <1>;
++	#size-cells = <1>;
++	ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */
++		  0x2000  0xd0042000 0x2000 /* port2x1_port0 */
++		  0x4000  0xd0044000 0x2000 /* port0x1_port1 */
++		  0x8000  0xd0048000 0x2000 /* port0x1_port2 */
++		  0xC000  0xd004C000 0x2000 /* port0x1_port3 */
++		  0x10000 0xd0080000 0x2000 /* port1x1_port0 */
++		  0x12000 0xd0082000 0x2000 /* port3x1_port0 */
++		  0x14000 0xd0084000 0x2000 /* port1x1_port1 */
++		  0x18000 0xd0088000 0x2000 /* port1x1_port2 */
++		  0x1C000 0xd008C000 0x2000 /* port1x1_port3 */>;
++
++	pcie0.0@0xd0040000 {
++		reg = <0x0 0x2000>;
++		interrupts = <58>;
++		clocks = <&gateclk 5>;
++		marvell,pcie-port = <0>;
++		marvell,pcie-lane = <0>;
++		status = "disabled";
++	};
++
++	pcie0.1@0xd0044000 {
++		reg = <0x4000 0x2000>;
++		interrupts = <59>;
++		clocks = <&gateclk 5>;
++		marvell,pcie-port = <0>;
++		marvell,pcie-lane = <1>;
++		status = "disabled";
++	};
++
++	pcie0.2@0xd0048000 {
++		reg = <0x8000 0x2000>;
++		interrupts = <60>;
++		clocks = <&gateclk 5>;
++		marvell,pcie-port = <0>;
++		marvell,pcie-lane = <2>;
++		status = "disabled";
++	};
++
++	pcie0.3@0xd004C000 {
++		reg = <0xC000 0x2000>;
++		interrupts = <61>;
++		clocks = <&gateclk 5>;
++		marvell,pcie-port = <0>;
++		marvell,pcie-lane = <3>;
++		status = "disabled";
++	};
++
++	pcie1.0@0xd0040000 {
++		reg = <0x10000 0x2000>;
++		interrupts = <62>;
++		clocks = <&gateclk 6>;
++		marvell,pcie-port = <1>;
++		marvell,pcie-lane = <0>;
++		status = "disabled";
++	};
++
++	pcie1.1@0xd0044000 {
++		reg = <0x14000 0x2000>;
++		interrupts = <63>;
++		clocks = <&gateclk 6>;
++		marvell,pcie-port = <1>;
++		marvell,pcie-lane = <1>;
++		status = "disabled";
++	};
++
++	pcie1.2@0xd0048000 {
++		reg = <0x18000 0x2000>;
++		interrupts = <64>;
++		clocks = <&gateclk 6>;
++		marvell,pcie-port = <1>;
++		marvell,pcie-lane = <2>;
++		status = "disabled";
++	};
++
++	pcie1.3@0xd004C000 {
++		reg = <0x1C000 0x2000>;
++		interrupts = <65>;
++		clocks = <&gateclk 6>;
++		marvell,pcie-port = <1>;
++		marvell,pcie-lane = <3>;
++		status = "disabled";
++	};
++
++	pcie2@0xd0042000 {
++		reg = <0x2000 0x2000>;
++		interrupts = <99>;
++		clocks = <&gateclk 7>;
++		marvell,pcie-port = <2>;
++		marvell,pcie-lane = <0>;
++		status = "disabled";
++	};
++
++	pcie3@0xd0082000 {
++		reg = <0x12000 0x2000>;
++		interrupts = <103>;
++		clocks = <&gateclk 8>;
++		marvell,pcie-port = <3>;
++		marvell,pcie-lane = <0>;
++		status = "disabled";
++	};
++};
++
+--- a/arch/arm/mach-mvebu/Makefile
++++ b/arch/arm/mach-mvebu/Makefile
+@@ -5,3 +5,4 @@ obj-y += system-controller.o
+ obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
+ obj-$(CONFIG_SMP)                += platsmp.o headsmp.o
+ obj-$(CONFIG_HOTPLUG_CPU)        += hotplug.o
++obj-$(CONFIG_PCI)		 += pcie.o
+--- /dev/null
++++ b/arch/arm/mach-mvebu/pcie.c
+@@ -0,0 +1,306 @@
++/*
++ * PCIe driver for Marvell Armada 370 and Armada XP SoCs
++ *
++ * 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 <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/clk.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/platform_device.h>
++#include <linux/of_address.h>
++#include <linux/of_pci.h>
++#include <linux/of_irq.h>
++#include <linux/of_platform.h>
++#include <plat/pcie.h>
++#include "common.h"
++
++struct pcie_port {
++	u8		  root_bus_nr;
++	void __iomem	 *base;
++	spinlock_t	  conf_lock;
++	int		  irq;
++	struct resource	  res;
++	int               haslink;
++	u32               port;
++	u32               lane;
++	struct clk       *clk;
++};
++
++static struct pcie_port *pcie_ports;
++
++static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
++{
++	/*
++	 * Don't go out when trying to access --
++	 * 1. nonexisting device on local bus
++	 * 2. where there's no device connected (no link)
++	 */
++	if (bus == pp->root_bus_nr && dev == 0)
++		return 1;
++
++	if (!orion_pcie_link_up(pp->base))
++		return 0;
++
++	if (bus == pp->root_bus_nr && dev != 1)
++		return 0;
++
++	return 1;
++}
++
++/*
++ * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
++ * and then reading the PCIE_CONF_DATA register. Need to make sure these
++ * transactions are atomic.
++ */
++static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
++			int size, u32 *val)
++{
++	struct pci_sys_data *sys = bus->sysdata;
++	struct pcie_port *pp = sys->private_data;
++	unsigned long flags;
++	int ret;
++
++	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
++		*val = 0xffffffff;
++		return PCIBIOS_DEVICE_NOT_FOUND;
++	}
++
++	spin_lock_irqsave(&pp->conf_lock, flags);
++	ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
++	spin_unlock_irqrestore(&pp->conf_lock, flags);
++
++	return ret;
++}
++
++static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
++			int where, int size, u32 val)
++{
++	struct pci_sys_data *sys = bus->sysdata;
++	struct pcie_port *pp = sys->private_data;
++	unsigned long flags;
++	int ret;
++
++	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	spin_lock_irqsave(&pp->conf_lock, flags);
++	ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
++	spin_unlock_irqrestore(&pp->conf_lock, flags);
++
++	return ret;
++}
++
++static struct pci_ops pcie_ops = {
++	.read = pcie_rd_conf,
++	.write = pcie_wr_conf,
++};
++
++/*
++ * Returns 0 when the device could not be initialized, 1 when
++ * initialization is successful
++ */
++static int __init armada_370_xp_pcie_setup(int nr, struct pci_sys_data *sys)
++{
++	struct pcie_port *port = &pcie_ports[nr];
++	unsigned long membase, iobase;
++	int ret;
++
++	if (!port->haslink)
++		return 0;
++
++	sys->private_data = port;
++	port->root_bus_nr = sys->busnr;
++	spin_lock_init(&port->conf_lock);
++
++	ret = armada_370_xp_alloc_pcie_window(port->port, port->lane,
++					      IORESOURCE_MEM, SZ_64M, &membase);
++	if (ret) {
++		pr_err("PCIe%d.%d: Cannot get memory window, device disabled\n",
++		       port->port, port->lane);
++		return 0;
++	}
++
++	ret = armada_370_xp_alloc_pcie_window(port->port, port->lane,
++					      IORESOURCE_IO, SZ_64K, &iobase);
++	if (ret) {
++		pr_err("PCIe%d.%d: Cannot get I/O window, device disabled\n",
++		       port->port, port->lane);
++		armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M);
++		return 0;
++	}
++
++	port->res.name = kasprintf(GFP_KERNEL, "PCIe %d.%d MEM",
++				   port->port, port->lane);
++	if (!port->res.name) {
++		armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K);
++		armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M);
++		return 0;
++	}
++
++	port->res.start = membase;
++	port->res.end = membase + SZ_32M - 1;
++	port->res.flags = IORESOURCE_MEM;
++
++	pci_ioremap_io(SZ_64K * sys->busnr, iobase);
++
++	if (request_resource(&iomem_resource, &port->res)) {
++		pr_err("PCIe%d.%d: Cannot request memory resource\n",
++		       port->port, port->lane);
++		kfree(port->res.name);
++		armada_370_xp_free_pcie_window(IORESOURCE_IO, iobase, SZ_64K);
++		armada_370_xp_free_pcie_window(IORESOURCE_MEM, membase, SZ_64M);
++		return 0;
++	}
++
++	pci_add_resource_offset(&sys->resources, &port->res, sys->mem_offset);
++
++	orion_pcie_set_local_bus_nr(port->base, sys->busnr);
++	orion_pcie_setup(port->base);
++
++	return 1;
++}
++
++static void __devinit rc_pci_fixup(struct pci_dev *dev)
++{
++	/*
++	 * Prevent enumeration of root complex.
++	 */
++	if (dev->bus->parent == NULL && dev->devfn == 0) {
++		int i;
++
++		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++			dev->resource[i].start = 0;
++			dev->resource[i].end   = 0;
++			dev->resource[i].flags = 0;
++		}
++	}
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
++
++static int __init armada_370_xp_pcie_map_irq(const struct pci_dev *dev, u8 slot,
++					     u8 pin)
++{
++	struct pci_sys_data *sys = dev->sysdata;
++	struct pcie_port *port = sys->private_data;
++
++	return port->irq;
++}
++
++static struct hw_pci armada_370_xp_pci __initdata = {
++	.setup		= armada_370_xp_pcie_setup,
++	.map_irq	= armada_370_xp_pcie_map_irq,
++	.ops            = &pcie_ops,
++};
++
++static int __init armada_370_xp_pcie_probe(struct platform_device *pdev)
++{
++	struct device_node *child;
++	int nports, i;
++
++	nports = 0;
++	for_each_child_of_node(pdev->dev.of_node, child) {
++		if (!of_device_is_available(child))
++			continue;
++		nports++;
++	}
++
++	pcie_ports = devm_kzalloc(&pdev->dev, nports * sizeof(*pcie_ports),
++				  GFP_KERNEL);
++	if (!pcie_ports)
++		return -ENOMEM;
++
++	i = 0;
++	for_each_child_of_node(pdev->dev.of_node, child) {
++		struct pcie_port *port = &pcie_ports[i];
++
++		if (!of_device_is_available(child))
++			continue;
++
++		if (of_property_read_u32(child, "marvell,pcie-port",
++					 &port->port))
++			continue;
++
++		if (of_property_read_u32(child, "marvell,pcie-lane",
++					 &port->lane))
++			port->lane = 0;
++
++		port->base = of_iomap(child, 0);
++		if (!port->base) {
++			dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
++				port->port, port->lane);
++			continue;
++		}
++
++		if (orion_pcie_link_up(port->base)) {
++			port->haslink = 1;
++			dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
++				 port->port, port->lane);
++		} else {
++			port->haslink = 0;
++			dev_info(&pdev->dev, "PCIe%d.%d: link down\n",
++				 port->port, port->lane);
++			iounmap(port->base);
++			continue;
++		}
++
++		port->irq = irq_of_parse_and_map(child, 0);
++		if (port->irq == 0) {
++			dev_err(&pdev->dev, "PCIe%d.%d: cannot parse and map IRQ\n",
++				port->port, port->lane);
++			iounmap(port->base);
++			port->haslink = 0;
++			continue;
++		}
++
++		port->clk = of_clk_get_by_name(child, NULL);
++		if (!port->clk) {
++			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
++			       port->port, port->lane);
++			irq_dispose_mapping(port->irq);
++			iounmap(port->base);
++			port->haslink = 0;
++			continue;
++		}
++
++		clk_prepare_enable(port->clk);
++
++		i++;
++	}
++
++	armada_370_xp_pci.nr_controllers = nports;
++	pci_common_init(&armada_370_xp_pci);
++
++	return 0;
++}
++
++static const struct of_device_id armada_370_xp_pcie_of_match_table[] = {
++	{ .compatible = "marvell,armada-370-xp-pcie", },
++	{},
++};
++MODULE_DEVICE_TABLE(of, armada_370_xp_pcie_of_match_table);
++
++static struct platform_driver armada_370_xp_pcie_driver = {
++	.driver = {
++		.owner = THIS_MODULE,
++		.name = "armada-370-xp-pcie",
++		.of_match_table =
++		   of_match_ptr(armada_370_xp_pcie_of_match_table),
++	},
++};
++
++static int armada_370_xp_pcie_init(void)
++{
++	return platform_driver_probe(&armada_370_xp_pcie_driver,
++				     armada_370_xp_pcie_probe);
++}
++
++subsys_initcall(armada_370_xp_pcie_init);
++
++MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
++MODULE_DESCRIPTION("Marvell Armada 370/XP PCIe driver");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/mvebu/patches-3.8/036-arm_mvebu_pcie_support_is_now_available.patch b/target/linux/mvebu/patches-3.8/036-arm_mvebu_pcie_support_is_now_available.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b3c9a63d53fe8386c44445da08c971060059278b
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/036-arm_mvebu_pcie_support_is_now_available.patch
@@ -0,0 +1,20 @@
+Now that the PCIe driver for mvebu has been integrated and all its
+relevant dependencies, we can mark the ARCH_MVEBU platform has
+MIGHT_HAVE_PCI, which allows to select the PCI bus support if needed.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/mach-mvebu/Kconfig |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/mach-mvebu/Kconfig
++++ b/arch/arm/mach-mvebu/Kconfig
+@@ -13,6 +13,8 @@ config ARCH_MVEBU
+ 	select MVEBU_CLK_CORE
+ 	select MVEBU_CLK_CPU
+ 	select MVEBU_CLK_GATING
++	select MIGHT_HAVE_PCI
++	select PCI_QUIRKS if PCI
+ 
+ if ARCH_MVEBU
+ 
diff --git a/target/linux/mvebu/patches-3.8/037-arm_mvebu_add_pcie_dt_a370.patch b/target/linux/mvebu/patches-3.8/037-arm_mvebu_add_pcie_dt_a370.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2cb8a17f07c1cc0e6a3eb58cac0a642ce5c81221
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/037-arm_mvebu_add_pcie_dt_a370.patch
@@ -0,0 +1,40 @@
+The Armada 370 SoC has two 1x PCIe 2.0 interfaces, so we add the
+necessary Device Tree informations to make these interfaces availabel.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-370.dtsi |   25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-370.dtsi
++++ b/arch/arm/boot/dts/armada-370.dtsi
+@@ -153,5 +153,29 @@
+ 			clocks = <&coreclk 0>;
+ 		};
+ 
++		pcie-controller {
++			compatible = "marvell,armada-370-xp-pcie";
++			status = "disabled";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <0      0xd0040000 0x2000
++			          0x2000 0xd0080000 0x2000>;
++
++			pcie0@0xd0040000 {
++				reg = <0x0 0x2000>;
++				interrupts = <58>;
++				clocks = <&gateclk 5>;
++				status = "disabled";
++				marvell,pcie-port = <0>;
++			};
++
++			pcie1@0xd0080000 {
++				reg = <0x2000 0x2000>;
++				interrupts = <62>;
++				clocks = <&gateclk 9>;
++				status = "disabled";
++				marvell,pcie-port = <1>;
++			};
++		};
+ 	};
+ };
diff --git a/target/linux/mvebu/patches-3.8/038-arm_mvebu_add_pcie_dt_axp.patch b/target/linux/mvebu/patches-3.8/038-arm_mvebu_add_pcie_dt_axp.patch
new file mode 100644
index 0000000000000000000000000000000000000000..647f1da5f7166df4aedc8267e61ffec491e9b6fd
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/038-arm_mvebu_add_pcie_dt_axp.patch
@@ -0,0 +1,284 @@
+The Armada XP SoCs have multiple PCIe interfaces. The MV78230 has 2
+PCIe units (one 4x or quad 1x, the other 1x only), the MV78260 has 3
+PCIe units (two 4x or quad 1x and one 4x/1x), the MV78460 has 4 PCIe
+units (two 4x or quad 1x and two 4x/1x). We therefore add the
+necessary Device Tree informations to make those PCIe interfaces
+usable.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-xp-mv78230.dtsi |   62 +++++++++++++++++
+ arch/arm/boot/dts/armada-xp-mv78260.dtsi |   72 +++++++++++++++++++
+ arch/arm/boot/dts/armada-xp-mv78460.dtsi |  112 ++++++++++++++++++++++++++++++
+ 3 files changed, 246 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+@@ -76,5 +76,67 @@
+ 			#interrupts-cells = <2>;
+ 			interrupts = <87>, <88>, <89>;
+ 		};
++
++		/*
++		 * MV78230 has 2 PCIe units Gen2.0: One unit can be
++		 * configured as x4 or quad x1 lanes. One unit is
++		 * x4/x1.
++		 */
++		pcie-controller {
++			compatible = "marvell,armada-370-xp-pcie";
++			status = "disabled";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */
++				  0x2000  0xd0042000 0x2000 /* port2x1_port0 */
++				  0x4000  0xd0044000 0x2000 /* port0x1_port1 */
++				  0x8000  0xd0048000 0x2000 /* port0x1_port2 */
++				  0xC000  0xd004C000 0x2000 /* port0x1_port3 */>;
++
++			pcie0.0@0xd0040000 {
++				reg = <0x0 0x2000>;
++				interrupts = <58>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++
++			pcie0.1@0xd0044000 {
++				reg = <0x4000 0x2000>;
++				interrupts = <59>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <1>;
++				status = "disabled";
++			};
++
++			pcie0.2@0xd0048000 {
++				reg = <0x8000 0x2000>;
++				interrupts = <60>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <2>;
++				status = "disabled";
++			};
++
++			pcie0.3@0xd004C000 {
++				reg = <0xC000 0x2000>;
++				interrupts = <61>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <3>;
++				status = "disabled";
++			};
++
++			pcie2@0xd0042000 {
++				reg = <0x2000 0x2000>;
++				interrupts = <99>;
++				clocks = <&gateclk 7>;
++				marvell,pcie-port = <2>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+@@ -96,5 +96,77 @@
+ 				clocks = <&gateclk 1>;
+ 				status = "disabled";
+ 		};
++
++		/*
++		 * MV78260 has 3 PCIe units Gen2.0: Two units can be
++		 * configured as x4 or quad x1 lanes. One unit is
++		 * x4/x1.
++		 */
++		pcie-controller {
++			compatible = "marvell,armada-370-xp-pcie";
++			status = "okay";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */
++				  0x2000  0xd0042000 0x2000 /* port2x1_port0 */
++				  0x4000  0xd0044000 0x2000 /* port0x1_port1 */
++				  0x8000  0xd0048000 0x2000 /* port0x1_port2 */
++				  0xC000  0xd004C000 0x2000 /* port0x1_port3 */
++				  0x12000 0xd0082000 0x2000 /* port3x1_port0 */>;
++
++			pcie0.0@0xd0040000 {
++				reg = <0x0 0x2000>;
++				interrupts = <58>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++
++			pcie0.1@0xd0044000 {
++				reg = <0x4000 0x2000>;
++				interrupts = <59>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <1>;
++				status = "disabled";
++			};
++
++			pcie0.2@0xd0048000 {
++				reg = <0x8000 0x2000>;
++				interrupts = <60>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <2>;
++				status = "disabled";
++			};
++
++			pcie0.3@0xd004C000 {
++				reg = <0xC000 0x2000>;
++				interrupts = <61>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <3>;
++				status = "disabled";
++			};
++
++			pcie2@0xd0042000 {
++				reg = <0x2000 0x2000>;
++				interrupts = <99>;
++				clocks = <&gateclk 7>;
++				marvell,pcie-port = <2>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++
++			pcie3@0xd0082000 {
++				reg = <0x12000 0x2000>;
++				interrupts = <103>;
++				clocks = <&gateclk 8>;
++				marvell,pcie-port = <3>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+@@ -111,5 +111,117 @@
+ 				clocks = <&gateclk 1>;
+ 				status = "disabled";
+ 		};
++
++		/*
++		 * MV78460 has 4 PCIe units Gen2.0: Two units can be
++		 * configured as x4 or quad x1 lanes. Two units are
++		 * x4/x1.
++		 */
++		pcie-controller {
++			compatible = "marvell,armada-370-xp-pcie";
++			status = "disabled";
++			#address-cells = <1>;
++			#size-cells = <1>;
++			ranges = <0       0xd0040000 0x2000 /* port0x1_port0 */
++				  0x2000  0xd0042000 0x2000 /* port2x1_port0 */
++				  0x4000  0xd0044000 0x2000 /* port0x1_port1 */
++				  0x8000  0xd0048000 0x2000 /* port0x1_port2 */
++				  0xC000  0xd004C000 0x2000 /* port0x1_port3 */
++				  0x10000 0xd0080000 0x2000 /* port1x1_port0 */
++				  0x12000 0xd0082000 0x2000 /* port3x1_port0 */
++				  0x14000 0xd0084000 0x2000 /* port1x1_port1 */
++				  0x18000 0xd0088000 0x2000 /* port1x1_port2 */
++				  0x1C000 0xd008C000 0x2000 /* port1x1_port3 */>;
++
++			pcie0.0@0xd0040000 {
++				reg = <0x0 0x2000>;
++				interrupts = <58>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++
++			pcie0.1@0xd0044000 {
++				reg = <0x4000 0x2000>;
++				interrupts = <59>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <1>;
++				status = "disabled";
++			};
++
++			pcie0.2@0xd0048000 {
++				reg = <0x8000 0x2000>;
++				interrupts = <60>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <2>;
++				status = "disabled";
++			};
++
++			pcie0.3@0xd004C000 {
++				reg = <0xC000 0x2000>;
++				interrupts = <61>;
++				clocks = <&gateclk 5>;
++				marvell,pcie-port = <0>;
++				marvell,pcie-lane = <3>;
++				status = "disabled";
++			};
++
++			pcie1.0@0xd0040000 {
++				reg = <0x10000 0x2000>;
++				interrupts = <62>;
++				clocks = <&gateclk 6>;
++				marvell,pcie-port = <1>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++
++			pcie1.1@0xd0044000 {
++				reg = <0x14000 0x2000>;
++				interrupts = <63>;
++				clocks = <&gateclk 6>;
++				marvell,pcie-port = <1>;
++				marvell,pcie-lane = <1>;
++				status = "disabled";
++			};
++
++			pcie1.2@0xd0048000 {
++				reg = <0x18000 0x2000>;
++				interrupts = <64>;
++				clocks = <&gateclk 6>;
++				marvell,pcie-port = <1>;
++				marvell,pcie-lane = <2>;
++				status = "disabled";
++			};
++
++			pcie1.3@0xd004C000 {
++				reg = <0x1C000 0x2000>;
++				interrupts = <65>;
++				clocks = <&gateclk 6>;
++				marvell,pcie-port = <1>;
++				marvell,pcie-lane = <3>;
++				status = "disabled";
++			};
++
++			pcie2@0xd0042000 {
++				reg = <0x2000 0x2000>;
++				interrupts = <99>;
++				clocks = <&gateclk 7>;
++				marvell,pcie-port = <2>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++
++			pcie3@0xd0082000 {
++				reg = <0x12000 0x2000>;
++				interrupts = <103>;
++				clocks = <&gateclk 8>;
++				marvell,pcie-port = <3>;
++				marvell,pcie-lane = <0>;
++				status = "disabled";
++			};
++		};
+ 	};
+  };
diff --git a/target/linux/mvebu/patches-3.8/039-arm_mvebu_add_pcie_dt_ax34.patch b/target/linux/mvebu/patches-3.8/039-arm_mvebu_add_pcie_dt_ax34.patch
new file mode 100644
index 0000000000000000000000000000000000000000..893c073eb5c860e144fb8b63ec6c0cd6764b21dd
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/039-arm_mvebu_add_pcie_dt_ax34.patch
@@ -0,0 +1,24 @@
+The PlatHome OpenBlocks AX3-4 has an internal mini-PCIe slot that can
+be used to plug mini-PCIe devices. We therefore enable the PCIe
+interface that corresponds to this slot.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
++++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
+@@ -130,5 +130,12 @@
+ 		usb@d0052000 {
+ 			status = "okay";
+ 		};
++		pcie-controller {
++			status = "okay";
++			/* Internal mini-PCIe connector */
++			pcie0.0@0xd0040000 {
++				status = "okay";
++			};
++		};
+ 	};
+ };
diff --git a/target/linux/mvebu/patches-3.8/040-arm_mvebu_add_pcie_axp_db.patch b/target/linux/mvebu/patches-3.8/040-arm_mvebu_add_pcie_axp_db.patch
new file mode 100644
index 0000000000000000000000000000000000000000..af15d4b85dfe632d7ece78e1973a9268a53649e4
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/040-arm_mvebu_add_pcie_axp_db.patch
@@ -0,0 +1,44 @@
+The Marvell evaluation board (DB) for the Armada XP SoC has 6
+physicals full-size PCIe slots, so we enable the corresponding PCIe
+interfaces in the Device Tree.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-xp-db.dts |   27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-xp-db.dts
++++ b/arch/arm/boot/dts/armada-xp-db.dts
+@@ -109,5 +109,32 @@
+ 		usb@d0052000 {
+ 			status = "okay";
+ 		};
++
++		pcie-controller {
++			status = "okay";
++
++			/*
++			 * All 6 slots are physically present as
++			 * standard PCIe slots on the board.
++			 */
++			pcie0.0@0xd0040000 {
++				status = "okay";
++			};
++			pcie0.1@0xd0044000 {
++				status = "okay";
++			};
++			pcie0.2@0xd0048000 {
++				status = "okay";
++			};
++			pcie0.3@0xd004C000 {
++				status = "okay";
++			};
++			pcie2@0xd0042000 {
++				status = "okay";
++			};
++			pcie3@0xd0082000 {
++				status = "okay";
++			};
++		};
+ 	};
+ };
diff --git a/target/linux/mvebu/patches-3.8/041-arm_mvebu_add_pcie_dt_mirabox.patch b/target/linux/mvebu/patches-3.8/041-arm_mvebu_add_pcie_dt_mirabox.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1b6089eef8b3dae7e04347031795b989c67b45ce
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/041-arm_mvebu_add_pcie_dt_mirabox.patch
@@ -0,0 +1,32 @@
+The Globalscale Mirabox platform uses one PCIe interface for an
+available mini-PCIe slot, and the other PCIe interface for an internal
+USB 3.0 controller. We add the necessary Device Tree informations to
+enable those two interfaces.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-370-mirabox.dts |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-370-mirabox.dts
++++ b/arch/arm/boot/dts/armada-370-mirabox.dts
+@@ -70,5 +70,19 @@
+ 		usb@d0051000 {
+ 			status = "okay";
+ 		};
++
++		pcie-controller {
++			status = "okay";
++
++			/* Internal mini-PCIe connector */
++			pcie0@0xd0040000 {
++				status = "okay";
++			};
++
++			/* Connected on the PCB to a USB 3.0 XHCI controller */
++			pcie1@0xd0080000 {
++				status = "okay";
++			};
++		};
+ 	};
+ };
diff --git a/target/linux/mvebu/patches-3.8/042-arm_mvebu_add_pcie_dt_a370_db.patch b/target/linux/mvebu/patches-3.8/042-arm_mvebu_add_pcie_dt_a370_db.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1a853f35c799dea2d0e3da61fc1ef4c415a2e92e
--- /dev/null
+++ b/target/linux/mvebu/patches-3.8/042-arm_mvebu_add_pcie_dt_a370_db.patch
@@ -0,0 +1,32 @@
+The Marvell evaluation board (DB) for the Armada 370 SoC has 2
+physical full-size PCIe slots, so we enable the corresponding PCIe
+interfaces in the Device Tree.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-370-db.dts |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-370-db.dts
++++ b/arch/arm/boot/dts/armada-370-db.dts
+@@ -82,5 +82,20 @@
+ 		usb@d0051000 {
+ 			status = "okay";
+ 		};
++
++		pcie-controller {
++			status = "okay";
++			/*
++			 * The two PCIe units are accessible through
++			 * both standard PCIe slots and mini-PCIe
++			 * slots on the board.
++			 */
++			pcie0@0xd0040000 {
++				status = "okay";
++			};
++			pcie1@0xd0080000 {
++				status = "okay";
++			};
++		};
+ 	};
+ };