diff --git a/configs/bcm958712k_defconfig b/configs/bcm958712k_defconfig
index 96e4bce..0c4e566 100644
--- a/configs/bcm958712k_defconfig
+++ b/configs/bcm958712k_defconfig
@@ -6,5 +6,7 @@ CONFIG_BOOTDELAY=5
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SYS_PROMPT="u-boot> "
 # CONFIG_CMD_IMLS is not set
+CONFIG_PCI=y
+CONFIG_PCIE_IPROC=y
 CONFIG_SYS_NS16550=y
 CONFIG_OF_LIBFDT=y
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 692a398..001ddc1 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -79,4 +79,10 @@ config PCIE_LAYERSCAPE
 	  PCIe controllers. The PCIe may works in RC or EP mode according to
 	  RCW[HOST_AGT_PEX] setting.
 
+config PCIE_IPROC
+	bool "iProc PCI support"
+	depends on TARGET_BCMNS2
+	help
+	  PCIe Support on iProc based SoCs
+
 endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index ad44e83..ddfde4c 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o
 obj-$(CONFIG_PCI_GT64120) += pci_gt64120.o
 obj-$(CONFIG_PCI_MSC01) += pci_msc01.o
 obj-$(CONFIG_PCIE_IMX) += pcie_imx.o
+obj-$(CONFIG_PCIE_IPROC) += pcie_iproc.o
 obj-$(CONFIG_FTPCI100) += pci_ftpci100.o
 obj-$(CONFIG_PCI_MVEBU) += pci_mvebu.o
 obj-$(CONFIG_SH4_PCI) += pci_sh4.o
diff --git a/drivers/pci/pcie_iproc.c b/drivers/pci/pcie_iproc.c
new file mode 100644
index 0000000..66f5cb5
--- /dev/null
+++ b/drivers/pci/pcie_iproc.c
@@ -0,0 +1,285 @@
+/*
+ * Broadcom iProc PCI Express Root-Complex driver
+ *
+ * Copyright (C) 2016 Broadcom
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+#include <common.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+#include <linux/compat.h>
+//#include <asm/arch/bcm_mdio.h>
+//#include <asm/arch-bcm_ns2/socregs.h>
+
+#ifdef DEBUG
+#define pr_debug	printf
+#else
+#define pr_debug(...)	do {} while (0)
+#endif
+
+enum iproc_pcie_type {
+	IPROC_PCI_GEN,
+	IPROC_PCI_NITRO,
+};
+
+struct iproc_pcie {
+	void __iomem *reg;
+
+	struct pci_controller hose;
+	enum iproc_pcie_type type;
+};
+
+#define GEN_CFG_IND_ADDR_OFFSET		0x120
+#define GEN_CFG_IND_DATA_OFFSET		0x124
+
+#define NITRO_CFG_IND_ADDR_OFFSET	0x1f0
+#define NITRO_CFG_IND_DATA_OFFSET	0x1f4
+
+#define CLK_CONTROL_OFFSET		0x000
+#define EP_PERST_SOURCE_SELECT_SHIFT	2
+#define EP_PERST_SOURCE_SELECT		(1 << EP_PERST_SOURCE_SELECT_SHIFT)
+#define EP_MODE_SURVIVE_PERST_SHIFT	1
+#define EP_MODE_SURVIVE_PERST		(1 << EP_MODE_SURVIVE_PERST_SHIFT)
+#define RC_PCIE_RST_OUTPUT_SHIFT	0
+#define RC_PCIE_RST_OUTPUT		(1 << RC_PCIE_RST_OUTPUT_SHIFT)
+
+#define CFG_ADDR_OFFSET			0x1F8
+#define CFG_ADDR_BUS_NUM_SHIFT		20
+#define CFG_ADDR_BUS_NUM_MASK		0x0FF00000
+#define CFG_ADDR_DEV_NUM_SHIFT		15
+#define CFG_ADDR_DEV_NUM_MASK		0x000F8000
+#define CFG_ADDR_FUNC_NUM_SHIFT		12
+#define CFG_ADDR_FUNC_NUM_MASK		0x00007000
+#define CFG_ADDR_REG_NUM_SHIFT		2
+#define CFG_ADDR_REG_NUM_MASK		0x00000FFC
+#define CFG_ADDR_CFG_TYPE_SHIFT		0
+#define CFG_ADDR_CFG_TYPE_MASK		0x00000003
+
+#define CFG_DATA_OFFSET			0x1FC
+#define CFG_IND_ADDR_MASK		0x00001FFC
+
+#define PCIE_LINK_STATUS_OFFSET		0xF0C
+#define PCIE_PHYLINKUP_SHITF		3
+#define PCIE_PHYLINKUP			(1 << PCIE_PHYLINKUP_SHITF)
+#define PCIE_DL_ACTIVE_SHIFT		2
+#define PCIE_DL_ACTIVE			(1 << PCIE_DL_ACTIVE_SHIFT)
+
+#define INVALID_ACCESS_OFFSET		0xFFFFFFFF
+
+#define PAXC_ROOT			0x60c00000
+#define PAXB_0_CLK_CONTROL		0x20020000
+
+
+
+static u32 iproc_pcie_conf_access(struct pci_controller *hose, pci_dev_t d,
+				  int where)
+{
+	struct iproc_pcie *pcie = hose->priv_data;
+	int bus, dev, func;
+	u32 val;
+
+	if (!pcie || !pcie->reg)
+		return INVALID_ACCESS_OFFSET;
+
+	/* root complex access */
+	if (PCI_DEV(d) == 0) {
+		if (pcie->type == IPROC_PCI_NITRO) {
+			writel(where & CFG_IND_ADDR_MASK,
+			       pcie->reg + NITRO_CFG_IND_ADDR_OFFSET);
+			return NITRO_CFG_IND_DATA_OFFSET;
+		} else {
+			writel(where & CFG_IND_ADDR_MASK,
+			       pcie->reg + GEN_CFG_IND_ADDR_OFFSET);
+			return GEN_CFG_IND_DATA_OFFSET;
+		}
+	}
+
+	pr_debug("%s:%d - Bus %x, Dev %x, Fun %x, where %x, val %x\n",
+		 __func__, __LINE__, PCI_BUS(d), PCI_DEV(d), PCI_FUNC(d), where,
+		 *val);
+
+	/* Note, u-boot starts off the dev at 1, but the func at 0.  Linux
+	 * starts at 0 for dev.  Our code assumes starting at 0, so we need to
+	 * subtact 1.
+	 */
+	dev = PCI_DEV(d) - 1;
+
+	/* FIXME - Nitro only wants to respond if the Bus is 1, but the regular
+	 * PCI only wants to respond if the bus is 0.  Investigation needs to
+	 * be done to determine why
+	 */
+	if (pcie->type == IPROC_PCI_NITRO)
+		bus = 1;
+	else
+		bus = PCI_BUS(d) - pcie->hose.first_busno;
+	func = PCI_FUNC(d);
+
+	/* FIXME - Quick and dirty hack to fix a problem only found on e1000
+	 * adapters.  For those adapters, a device is found for every "dev"
+	 * queried, even though only one is physically present.  To work
+	 * around that, stop looking after the first device
+	 */
+	if (dev > 0)
+		return INVALID_ACCESS_OFFSET;
+
+	/* access of EP deivce */
+	val = (bus << CFG_ADDR_BUS_NUM_SHIFT) |
+	      (dev << CFG_ADDR_DEV_NUM_SHIFT) |
+	      (func << CFG_ADDR_FUNC_NUM_SHIFT) |
+	      (where & CFG_ADDR_REG_NUM_MASK) |
+	      (1 & CFG_ADDR_CFG_TYPE_MASK);
+	writel(val, pcie->reg + CFG_ADDR_OFFSET);
+
+	return CFG_DATA_OFFSET;
+}
+
+static int iproc_pcie_read_config(struct pci_controller *hose, pci_dev_t d,
+				  int where, u32 *val)
+{
+	struct iproc_pcie *pcie = hose->priv_data;
+	u32 offset;
+
+
+	offset = iproc_pcie_conf_access(hose, d, where);
+	if (offset == INVALID_ACCESS_OFFSET)
+		return -EINVAL;
+
+	*val = readl(pcie->reg + offset);
+
+
+	return 0;
+}
+
+static int iproc_pcie_write_config(struct pci_controller *hose, pci_dev_t d,
+				   int where, u32 val)
+{
+	struct iproc_pcie *pcie = hose->priv_data;
+	u32 offset;
+
+	offset = iproc_pcie_conf_access(hose, d, where);
+	if (offset == INVALID_ACCESS_OFFSET)
+		return -EINVAL;
+
+	writel(val, pcie->reg + offset);
+
+	return 0;
+}
+
+static int iproc_pcie_init_hose(struct iproc_pcie *pcie)
+{
+	u32 val32;
+	u16 val;
+
+	/* Check for a device to be present.  Only proceed if one is present.
+	 * If not, it will cause a spurious interrupt (which is found when
+	 * booting Linux after the fact)
+	 */
+	val32 = readl(pcie->reg + PCIE_LINK_STATUS_OFFSET);
+	if (pcie->type != IPROC_PCI_NITRO &&
+	    (!(val32 & PCIE_PHYLINKUP) || !(val32 & PCIE_DL_ACTIVE)))
+		return -ENODEV;
+
+	pcie->hose.priv_data = pcie;
+
+	/* FIXME - Major hack below.  This should be more limited than saying
+	 * all of memory
+	 */
+	pci_set_region(&pcie->hose.regions[0], 0, 0, SZ_2G * 2 - 1,
+		       PCI_REGION_MEM);
+	pcie->hose.region_count = 1;
+
+	pci_set_ops(&pcie->hose,
+		    pci_hose_read_config_byte_via_dword,
+		    pci_hose_read_config_word_via_dword,
+		    iproc_pcie_read_config,
+		    pci_hose_write_config_byte_via_dword,
+		    pci_hose_write_config_word_via_dword,
+		    iproc_pcie_write_config);
+
+	/* Before we register, we need to fix up the bridge's incorrect device
+	 * class
+	 */
+	pci_hose_write_config_word(&pcie->hose, PCI_BDF(0, 0, 0),
+				   PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
+
+	pci_hose_read_config_word(&pcie->hose, PCI_BDF(0, 0, 0),
+				  PCI_CLASS_DEVICE, &val);
+	pr_debug("%s:%d - Dev Class = %x\n", __func__, __LINE__, val);
+
+	pci_register_hose(&pcie->hose);
+	pciauto_config_init(&pcie->hose);
+	pcie->hose.last_busno = pci_hose_scan(&pcie->hose);
+
+	return 0;
+}
+
+static void iproc_pcie_reset(struct iproc_pcie *pcie)
+{
+	if (pcie->type == IPROC_PCI_NITRO) {
+		writel(0x0000007F, pcie->reg + CLK_CONTROL_OFFSET);
+	} else {
+		u32 val;
+
+		/*
+		 * Select perst_b signal as reset source, and put the device in
+		 * reset
+		 */
+		val = readl(pcie->reg + CLK_CONTROL_OFFSET);
+		val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
+			~RC_PCIE_RST_OUTPUT;
+		writel(val, pcie->reg + CLK_CONTROL_OFFSET);
+		udelay(250);
+
+		/* now bring it out of reset*/
+		val |= RC_PCIE_RST_OUTPUT;
+		writel(val, pcie->reg + CLK_CONTROL_OFFSET);
+		mdelay(250);
+	}
+}
+
+void pci_init_board(void)
+{
+	struct iproc_pcie *pcie;
+	int i, rc;
+
+	/* Do PCI slots first */
+	for (i = 0; i < 2; i++) {
+		pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
+		if (!pcie)
+			return;
+
+		pcie->type = IPROC_PCI_GEN;
+		pcie->hose.first_busno = i;
+
+		/* map registers */
+		pcie->reg = (void *)PAXB_0_CLK_CONTROL + (0x30000000 * i);
+
+#if 0
+		/* turn on the phys. NOTE: Only for NS2. */
+		bcm_mdio_write(INTERNAL, CLAUS22, i * 7, 0, 0x1F, 0x2100);
+		bcm_mdio_write(INTERNAL, CLAUS22, i * 7, 0, 0x3, 0x2b18);
+#endif
+		iproc_pcie_reset(pcie);
+
+		rc = iproc_pcie_init_hose(pcie);
+		if (rc)
+			kfree(pcie);
+	}
+
+	/* Now do Nitro */
+	pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return;
+
+	pcie->type = IPROC_PCI_NITRO;
+	pcie->hose.first_busno = i;
+	pcie->reg = (void *)PAXC_ROOT;
+
+	iproc_pcie_reset(pcie);
+
+	rc = iproc_pcie_init_hose(pcie);
+	if (rc)
+		kfree(pcie);
+}
diff --git a/include/configs/bcm_northstar2.h b/include/configs/bcm_northstar2.h
index ec2ce3f..7a0d26e 100644
--- a/include/configs/bcm_northstar2.h
+++ b/include/configs/bcm_northstar2.h
@@ -52,4 +52,7 @@
 #define CONFIG_COMMAND_HISTORY
 #define CONFIG_SYS_LONGHELP
 
+/* PCI/PCIE */
+#define CONFIG_CMD_PCI
+
 #endif /* __BCM_NORTHSTAR2_H */
