diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 8da2efdc5177..ae5a430387bc 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -5,7 +5,7 @@ menu "PCI controller drivers"
 
 config PCI_MVEBU
 	tristate "Marvell EBU PCIe controller"
-	depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST
+	depends on ARCH_MVEBU || ARCH_DOVE || ARCH_ORION5X || COMPILE_TEST
 	depends on MVEBU_MBUS
 	depends on ARM
 	depends on OF
@@ -15,7 +15,7 @@ config PCI_MVEBU
 	select HOTPLUG_PCI_PCIE
 	help
 	 Add support for Marvell EBU PCIe controller. This PCIe controller
-	 is used on 32-bit Marvell ARM SoCs: Dove, Kirkwood, Armada 370,
+	 is used on 32-bit Marvell ARM SoCs: Orion, Kirkwood, Dove, Armada 370,
 	 Armada XP, Armada 375, Armada 38x and Armada 39x.
 
 config PCI_AARDVARK
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 9986dd486680..2ef04a8241fc 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -96,6 +96,7 @@ struct mvebu_pcie {
 	struct resource io;
 	struct resource realio;
 	struct resource mem;
+	struct resource cfg;
 	int nports;
 };
 
@@ -127,6 +128,7 @@ struct mvebu_pcie_port {
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
 	struct resource regs;
+	struct resource cfg;
 	u8 slot_power_limit_value;
 	u8 slot_power_limit_scale;
 	struct irq_domain *rp_irq_domain;
@@ -409,6 +411,7 @@ static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
 	void __iomem *conf_data;
+	u32 offset;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port)
@@ -417,10 +420,20 @@ static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 	if (!mvebu_pcie_link_up(port))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	conf_data = port->base + PCIE_CONF_DATA_OFF;
+	if (resource_size(&port->cfg)) {
+		offset = PCIE_CONF_ADDR(bus->number, devfn, where) & ~PCIE_CONF_ADDR_EN;
+		if (offset >= resource_size(&port->cfg))
+			return PCIBIOS_DEVICE_NOT_FOUND;
 
-	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
-		     PCIE_CONF_ADDR_OFF);
+		conf_data = pci_remap_cfgspace(port->cfg.start + offset, size);
+		if (!conf_data)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	} else {
+		conf_data = port->base + PCIE_CONF_DATA_OFF;
+
+		mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
+			     PCIE_CONF_ADDR_OFF);
+	}
 
 	switch (size) {
 	case 1:
@@ -433,9 +446,14 @@ static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 		*val = readl_relaxed(conf_data);
 		break;
 	default:
+		if (resource_size(&port->cfg))
+			iounmap(conf_data);
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 	}
 
+	if (resource_size(&port->cfg))
+		iounmap(conf_data);
+
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -445,6 +463,7 @@ static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
 	struct mvebu_pcie *pcie = bus->sysdata;
 	struct mvebu_pcie_port *port;
 	void __iomem *conf_data;
+	u32 offset;
 
 	port = mvebu_pcie_find_port(pcie, bus, devfn);
 	if (!port)
@@ -453,10 +472,20 @@ static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
 	if (!mvebu_pcie_link_up(port))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	conf_data = port->base + PCIE_CONF_DATA_OFF;
+	if (resource_size(&port->cfg)) {
+		offset = PCIE_CONF_ADDR(bus->number, devfn, where) & ~PCIE_CONF_ADDR_EN;
+		if (offset >= resource_size(&port->cfg))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+		conf_data = pci_remap_cfgspace(port->cfg.start + offset, size);
+		if (!conf_data)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	} else {
+		conf_data = port->base + PCIE_CONF_DATA_OFF;
 
-	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
-		     PCIE_CONF_ADDR_OFF);
+		mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
+			     PCIE_CONF_ADDR_OFF);
+	}
 
 	switch (size) {
 	case 1:
@@ -469,9 +498,14 @@ static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
 		writel(val, conf_data);
 		break;
 	default:
+		if (resource_size(&port->cfg))
+			iounmap(conf_data);
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 	}
 
+	if (resource_size(&port->cfg))
+		iounmap(conf_data);
+
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -1472,6 +1506,7 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
 
 static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 			      unsigned long type,
+			      unsigned long offset,
 			      unsigned int *tgt,
 			      unsigned int *attr)
 {
@@ -1493,6 +1528,7 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 	for (i = 0; i < nranges; i++, range += rangesz) {
 		u32 flags = of_read_number(range, 1);
 		u32 slot = of_read_number(range + 1, 1);
+		u32 dtaddr = of_read_number(range + 2, 1);
 		u64 cpuaddr = of_read_number(range + na, pna);
 		unsigned long rtype;
 
@@ -1503,6 +1539,9 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 		else
 			continue;
 
+		if (dtaddr != offset)
+			continue;
+
 		if (slot == PCI_SLOT(devfn) && type == rtype) {
 			*tgt = DT_CPUADDR_TO_TARGET(cpuaddr);
 			*attr = DT_CPUADDR_TO_ATTR(cpuaddr);
@@ -1513,6 +1552,43 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
 	return -ENOENT;
 }
 
+static int mvebu_get_cfg_tgt_attr(struct device_node *np, phys_addr_t start,
+				  struct resource *res,
+				  unsigned int *tgt, unsigned int *attr)
+{
+	const __be32 *addrp;
+	unsigned int flags;
+	u64 offset;
+	u64 size;
+	int ret;
+
+	/* get second cell from assigned-addresses property */
+	addrp = of_get_address(np, 1, &size, &flags);
+	if (!addrp)
+		return -EINVAL;
+
+	if (!(flags & IORESOURCE_MEM))
+		return -EINVAL;
+
+	if (be32_to_cpu(addrp[1]) != 0x0)
+		return -EINVAL;
+
+	flags |= IORESOURCE_MEM_NONPOSTED;
+	offset = be32_to_cpu(addrp[2]);
+
+	ret = mvebu_get_tgt_attr(of_get_parent(np), 0, IORESOURCE_MEM, offset, tgt, attr);
+	if (ret)
+		return ret;
+
+	memset(res, 0, sizeof(*res));
+	res->start = start;
+	res->end = start + size - 1;
+	res->flags = flags;
+	res->name = "PCI CFG";
+
+	return 0;
+}
+
 static int mvebu_pcie_suspend(struct device *dev)
 {
 	struct mvebu_pcie *pcie;
@@ -1592,7 +1668,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 		goto skip;
 	}
 
-	ret = mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_MEM,
+	ret = mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_MEM, 0,
 				 &port->mem_target, &port->mem_attr);
 	if (ret < 0) {
 		dev_err(dev, "%s: cannot get tgt/attr for mem window\n",
@@ -1601,7 +1677,7 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
 	}
 
 	if (resource_size(&pcie->io) != 0) {
-		mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO,
+		mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO, 0,
 				   &port->io_target, &port->io_attr);
 	} else {
 		port->io_target = -1;
@@ -1794,6 +1870,20 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie)
 			return ret;
 	}
 
+	if (of_device_is_compatible(dev->of_node, "marvell,orion5x-pcie")) {
+		/* Get the PCIe configuration space aperture */
+		mvebu_mbus_get_pcie_cfg_aperture(&pcie->cfg);
+		if (resource_size(&pcie->cfg) == 0) {
+			dev_err(dev, "invalid config space aperature size\n");
+			return -EINVAL;
+		}
+
+		pcie->cfg.name = "PCI CFG";
+		ret = devm_request_resource(dev, &iomem_resource, &pcie->cfg);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -1804,6 +1894,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 	struct pci_host_bridge *bridge;
 	struct device_node *np = dev->of_node;
 	struct device_node *child;
+	phys_addr_t pcie_cfg_offset;
 	int num, i, ret;
 
 	bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct mvebu_pcie));
@@ -1818,6 +1909,8 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	pcie_cfg_offset = pcie->cfg.start;
+
 	num = of_get_available_child_count(np);
 
 	pcie->ports = devm_kcalloc(dev, num, sizeof(*pcie->ports), GFP_KERNEL);
@@ -1852,6 +1945,32 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 		if (ret < 0)
 			continue;
 
+		if (resource_size(&pcie->cfg) != 0) {
+			unsigned int cfg_target, cfg_attr;
+
+			ret = mvebu_get_cfg_tgt_attr(child, pcie_cfg_offset, &port->cfg, &cfg_target, &cfg_attr);
+			if (ret) {
+				dev_err(dev, "%s: missing address range for cfg space\n", port->name);
+				goto err_port_down;
+			}
+
+			if (port->cfg.end > pcie->cfg.end) {
+				dev_err(dev, "%s: requested cfg space of %u bytes is too large, available only %u bytes\n",
+					port->name, resource_size(&port->cfg), pcie->cfg.end - pcie_cfg_offset + 1);
+				port->cfg.start = port->cfg.end = 0;
+				goto err_port_down;
+			}
+
+			ret = mvebu_mbus_add_window_by_id(cfg_target, cfg_attr, port->cfg.start, resource_size(&port->cfg));
+			if (ret) {
+				dev_info(dev, "%s: cannot add mbus window for cfg space: %d\n", port->name, ret);
+				port->cfg.start = port->cfg.end = 0;
+				goto err_port_down;
+			}
+
+			pcie_cfg_offset += resource_size(&port->cfg);
+		}
+
 		port->base = mvebu_pcie_map_registers(pdev, child, port);
 		if (IS_ERR(port->base)) {
 			dev_err(dev, "%s: cannot map registers\n", port->name);
@@ -2011,6 +2130,9 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 		port->base = NULL;
 
 err_port_down:
+		if (port->cfg.end && resource_size(&port->cfg))
+			mvebu_mbus_del_window(port->cfg.start, resource_size(&port->cfg));
+
 		mvebu_pcie_powerdown(port);
 	}
 
@@ -2090,6 +2212,9 @@ static int mvebu_pcie_remove(struct platform_device *pdev)
 		if (port->memwin.size)
 			mvebu_pcie_del_windows(port, port->memwin.base, port->memwin.size);
 
+		if (port->cfg.end && resource_size(&port->cfg))
+			mvebu_mbus_del_window(port->cfg.start, resource_size(&port->cfg));
+
 		/* Power down card and disable clocks. Must be the last step. */
 		mvebu_pcie_powerdown(port);
 	}
@@ -2102,6 +2227,7 @@ static const struct of_device_id mvebu_pcie_of_match_table[] = {
 	{ .compatible = "marvell,armada-370-pcie", },
 	{ .compatible = "marvell,dove-pcie", },
 	{ .compatible = "marvell,kirkwood-pcie", },
+	{ .compatible = "marvell,orion5x-pcie", },
 	{},
 };
 
