diff mbox

[12/12] PCI: iproc: Add support for the next-gen PAXB controller

Message ID 1477347432-17656-13-git-send-email-ray.jui@broadcom.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show

Commit Message

Ray Jui Oct. 24, 2016, 10:17 p.m. UTC
This patch adds the support for the next generation of the iProc PAXB
host controller, used in Stingray

Signed-off-by: Oza Oza <oza.oza@broadcom.com>
Signed-off-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Scott Branden <scott.branden@broadcom.com>
---
 drivers/pci/host/pcie-iproc-platform.c |   3 +
 drivers/pci/host/pcie-iproc.c          | 128 +++++++++++++++++++++++++++++++++
 drivers/pci/host/pcie-iproc.h          |   1 +
 3 files changed, 132 insertions(+)
diff mbox

Patch

diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c
index 47329d3..fd3ed9b 100644
--- a/drivers/pci/host/pcie-iproc-platform.c
+++ b/drivers/pci/host/pcie-iproc-platform.c
@@ -31,6 +31,9 @@  static const struct of_device_id iproc_pcie_of_match_table[] = {
 		.compatible = "brcm,iproc-pcie",
 		.data = (int *)IPROC_PCIE_PAXB,
 	}, {
+		.compatible = "brcm,iproc-pcie-paxb-v2",
+		.data = (int *)IPROC_PCIE_PAXB_V2,
+	}, {
 		.compatible = "brcm,iproc-pcie-paxc",
 		.data = (int *)IPROC_PCIE_PAXC,
 	}, {
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
index c4e2211..8ffb9d4 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -118,6 +118,29 @@  static const struct iproc_pcie_ob_map paxb_ob_map[] = {
 	},
 };
 
+static const struct iproc_pcie_ob_map paxb_v2_ob_map[] = {
+	{
+		/* OARR0/OMAP0 */
+		.window_sizes = { 128, 256 },
+		.nr_sizes = 2,
+	},
+	{
+		/* OARR1/OMAP1 */
+		.window_sizes = { 128, 256 },
+		.nr_sizes = 2,
+	},
+	{
+		/* OARR2/OMAP2 */
+		.window_sizes = { 128, 256, 512, 1024 },
+		.nr_sizes = 4,
+	},
+	{
+		/* OARR3/OMAP3 */
+		.window_sizes = { 128, 256, 512, 1024 },
+		.nr_sizes = 4,
+	},
+};
+
 /**
  * iProc PCIe inbound mapping type
  */
@@ -156,6 +179,54 @@  struct iproc_pcie_ib_map {
 	u16 imap_window_offset;
 };
 
+static const struct iproc_pcie_ib_map paxb_v2_ib_map[] = {
+	{
+		/* IARR0/IMAP0 */
+		.type = IPROC_PCIE_IB_MAP_IO,
+		.size_unit = SZ_1K,
+		.region_sizes = { 32 },
+		.nr_sizes = 1,
+		.nr_windows = 8,
+		.imap_addr_offset = 0x40,
+		.imap_window_offset = 0x4,
+	},
+	{
+		/* IARR1/IMAP1 (currently unused) */
+		.type = IPROC_PCIE_IB_MAP_INVALID,
+	},
+	{
+		/* IARR2/IMAP2 */
+		.type = IPROC_PCIE_IB_MAP_MEM,
+		.size_unit = SZ_1M,
+		.region_sizes = { 64, 128, 256, 512, 1024, 2048, 4096, 8192,
+				  16384 },
+		.nr_sizes = 9,
+		.nr_windows = 1,
+		.imap_addr_offset = 0x4,
+		.imap_window_offset = 0x8,
+	},
+	{
+		/* IARR3/IMAP3 */
+		.type = IPROC_PCIE_IB_MAP_MEM,
+		.size_unit = SZ_1G,
+		.region_sizes = { 1, 2, 4, 8, 16, 32 },
+		.nr_sizes = 6,
+		.nr_windows = 8,
+		.imap_addr_offset = 0x4,
+		.imap_window_offset = 0x8,
+	},
+	{
+		/* IARR4/IMAP4 */
+		.type = IPROC_PCIE_IB_MAP_MEM,
+		.size_unit = SZ_1G,
+		.region_sizes = { 32, 64, 128, 256, 512 },
+		.nr_sizes = 5,
+		.nr_windows = 8,
+		.imap_addr_offset = 0x4,
+		.imap_window_offset = 0x8,
+	},
+};
+
 /*
  * iProc PCIe host registers
  */
@@ -258,6 +329,34 @@  static const u16 iproc_pcie_reg_paxb[] = {
 	[IPROC_PCIE_APB_ERR_EN]       = 0xf40,
 };
 
+/* iProc PCIe PAXB v2 registers */
+static const u16 iproc_pcie_reg_paxb_v2[] = {
+	[IPROC_PCIE_CLK_CTRL]         = 0x000,
+	[IPROC_PCIE_CFG_IND_ADDR]     = 0x120,
+	[IPROC_PCIE_CFG_IND_DATA]     = 0x124,
+	[IPROC_PCIE_CFG_ADDR]         = 0x1f8,
+	[IPROC_PCIE_CFG_DATA]         = 0x1fc,
+	[IPROC_PCIE_INTX_EN]          = 0x330,
+	[IPROC_PCIE_OARR0]            = 0xd20,
+	[IPROC_PCIE_OMAP0]            = 0xd40,
+	[IPROC_PCIE_OARR1]            = 0xd28,
+	[IPROC_PCIE_OMAP1]            = 0xd48,
+	[IPROC_PCIE_OARR2]            = 0xd60,
+	[IPROC_PCIE_OMAP2]            = 0xd68,
+	[IPROC_PCIE_OARR3]            = 0xdf0,
+	[IPROC_PCIE_OMAP3]            = 0xdf8,
+	[IPROC_PCIE_IARR0]            = 0xd00,
+	[IPROC_PCIE_IMAP0]            = 0xc00,
+	[IPROC_PCIE_IARR2]            = 0xd10,
+	[IPROC_PCIE_IMAP2]            = 0xcc0,
+	[IPROC_PCIE_IARR3]            = 0xe00,
+	[IPROC_PCIE_IMAP3]            = 0xe08,
+	[IPROC_PCIE_IARR4]            = 0xe68,
+	[IPROC_PCIE_IMAP4]            = 0xe70,
+	[IPROC_PCIE_LINK_STATUS]      = 0xf0c,
+	[IPROC_PCIE_APB_ERR_EN]       = 0xf40,
+};
+
 /* iProc PCIe PAXC v1 registers */
 static const u16 iproc_pcie_reg_paxc[] = {
 	[IPROC_PCIE_CLK_CTRL]         = 0x000,
@@ -912,6 +1011,19 @@  static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
 	return 0;
 }
 
+static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr)
+{
+	int ret;
+	struct of_pci_range range;
+
+	memset(&range, 0, sizeof(range));
+	range.size = SZ_32K;
+	range.pci_addr = range.cpu_addr = ALIGN(msi_addr, range.size);
+
+	ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_IO);
+	return ret;
+}
+
 static void iproc_pcie_paxc_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr)
 {
 	u32 val;
@@ -963,6 +1075,11 @@  static int iproc_pcie_msi_steer(struct iproc_pcie *pcie,
 	}
 
 	switch (pcie->type) {
+	case IPROC_PCIE_PAXB_V2:
+		ret = iproc_pcie_paxb_v2_msi_steer(pcie, msi_addr);
+		if (ret)
+			return ret;
+		break;
 	case IPROC_PCIE_PAXC_V2:
 		iproc_pcie_paxc_v2_msi_steer(pcie, msi_addr);
 		break;
@@ -1040,6 +1157,17 @@  static int iproc_pcie_rev_init(struct iproc_pcie *pcie)
 			pcie->ob.nr_windows = ARRAY_SIZE(paxb_ob_map);
 		}
 		break;
+	case IPROC_PCIE_PAXB_V2:
+		regs = iproc_pcie_reg_paxb_v2;
+		pcie->has_apb_err_disable = true;
+		if (pcie->need_ob_cfg) {
+			pcie->ob_map = paxb_v2_ob_map;
+			pcie->ob.nr_windows = ARRAY_SIZE(paxb_v2_ob_map);
+		}
+		pcie->ib.nr_regions = ARRAY_SIZE(paxb_v2_ib_map);
+		pcie->ib_map = paxb_v2_ib_map;
+		pcie->need_msi_steer = true;
+		break;
 	case IPROC_PCIE_PAXC:
 		regs = iproc_pcie_reg_paxc;
 		pcie->ep_is_internal = true;
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h
index 3f2709a..04fed8e 100644
--- a/drivers/pci/host/pcie-iproc.h
+++ b/drivers/pci/host/pcie-iproc.h
@@ -26,6 +26,7 @@ 
 enum iproc_pcie_type {
 	IPROC_PCIE_PAXB_BCMA = 0,
 	IPROC_PCIE_PAXB,
+	IPROC_PCIE_PAXB_V2,
 	IPROC_PCIE_PAXC,
 	IPROC_PCIE_PAXC_V2,
 };