429 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			429 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From a13fc4733b25d6dad6ec1826f09225c69ee21e3a Mon Sep 17 00:00:00 2001
 | 
						|
From: Ray Jui <rjui@broadcom.com>
 | 
						|
Date: Mon, 16 Nov 2015 17:41:43 -0800
 | 
						|
Subject: [PATCH 151/154] PCI: iproc: Add PAXC interface support
 | 
						|
 | 
						|
Traditionally, all iProc PCIe root complexes use PAXB based wrapper,
 | 
						|
with an integrated on-chip Serdes to support external endpoint devices.
 | 
						|
On newer iProc platforms, a PAXC based wrapper is introduced, for
 | 
						|
connection with internally emulated PCIe endpoint devices in the ASIC
 | 
						|
 | 
						|
This patch adds support for PAXC based iProc PCIe root complex in the
 | 
						|
iProc PCIe core driver. This change fators out common logic between
 | 
						|
PAXB and PAXC, and use tables to store register offsets that are
 | 
						|
different between PAXB and PAXC. This allows the driver to be scaled to
 | 
						|
support subsequent PAXC revisions in the future
 | 
						|
 | 
						|
Signed-off-by: Ray Jui <rjui@broadcom.com>
 | 
						|
Reviewed-by: Scott Branden <sbranden@broadcom.com>
 | 
						|
---
 | 
						|
 drivers/pci/host/pcie-iproc-platform.c |  24 +++-
 | 
						|
 drivers/pci/host/pcie-iproc.c          | 202 +++++++++++++++++++++++++++------
 | 
						|
 drivers/pci/host/pcie-iproc.h          |  19 ++++
 | 
						|
 3 files changed, 205 insertions(+), 40 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/pci/host/pcie-iproc-platform.c
 | 
						|
+++ b/drivers/pci/host/pcie-iproc-platform.c
 | 
						|
@@ -26,8 +26,21 @@
 | 
						|
 
 | 
						|
 #include "pcie-iproc.h"
 | 
						|
 
 | 
						|
+static const struct of_device_id iproc_pcie_of_match_table[] = {
 | 
						|
+	{
 | 
						|
+		.compatible = "brcm,iproc-pcie",
 | 
						|
+		.data = (int *)IPROC_PCIE_PAXB,
 | 
						|
+	}, {
 | 
						|
+		.compatible = "brcm,iproc-pcie-paxc",
 | 
						|
+		.data = (int *)IPROC_PCIE_PAXC,
 | 
						|
+	},
 | 
						|
+	{ /* sentinel */ }
 | 
						|
+};
 | 
						|
+MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
 | 
						|
+
 | 
						|
 static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
 | 
						|
 {
 | 
						|
+	const struct of_device_id *of_id;
 | 
						|
 	struct iproc_pcie *pcie;
 | 
						|
 	struct device_node *np = pdev->dev.of_node;
 | 
						|
 	struct resource reg;
 | 
						|
@@ -35,11 +48,16 @@ static int iproc_pcie_pltfm_probe(struct
 | 
						|
 	LIST_HEAD(res);
 | 
						|
 	int ret;
 | 
						|
 
 | 
						|
+	of_id = of_match_device(iproc_pcie_of_match_table, &pdev->dev);
 | 
						|
+	if (!of_id)
 | 
						|
+		return -EINVAL;
 | 
						|
+
 | 
						|
 	pcie = devm_kzalloc(&pdev->dev, sizeof(struct iproc_pcie), GFP_KERNEL);
 | 
						|
 	if (!pcie)
 | 
						|
 		return -ENOMEM;
 | 
						|
 
 | 
						|
 	pcie->dev = &pdev->dev;
 | 
						|
+	pcie->type = (enum iproc_pcie_type)of_id->data;
 | 
						|
 	platform_set_drvdata(pdev, pcie);
 | 
						|
 
 | 
						|
 	ret = of_address_to_resource(np, 0, ®);
 | 
						|
@@ -114,12 +132,6 @@ static int iproc_pcie_pltfm_remove(struc
 | 
						|
 	return iproc_pcie_remove(pcie);
 | 
						|
 }
 | 
						|
 
 | 
						|
-static const struct of_device_id iproc_pcie_of_match_table[] = {
 | 
						|
-	{ .compatible = "brcm,iproc-pcie", },
 | 
						|
-	{ /* sentinel */ }
 | 
						|
-};
 | 
						|
-MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
 | 
						|
-
 | 
						|
 static struct platform_driver iproc_pcie_pltfm_driver = {
 | 
						|
 	.driver = {
 | 
						|
 		.name = "iproc-pcie",
 | 
						|
--- a/drivers/pci/host/pcie-iproc.c
 | 
						|
+++ b/drivers/pci/host/pcie-iproc.c
 | 
						|
@@ -30,20 +30,16 @@
 | 
						|
 
 | 
						|
 #include "pcie-iproc.h"
 | 
						|
 
 | 
						|
-#define CLK_CONTROL_OFFSET           0x000
 | 
						|
 #define EP_PERST_SOURCE_SELECT_SHIFT 2
 | 
						|
 #define EP_PERST_SOURCE_SELECT       BIT(EP_PERST_SOURCE_SELECT_SHIFT)
 | 
						|
 #define EP_MODE_SURVIVE_PERST_SHIFT  1
 | 
						|
 #define EP_MODE_SURVIVE_PERST        BIT(EP_MODE_SURVIVE_PERST_SHIFT)
 | 
						|
 #define RC_PCIE_RST_OUTPUT_SHIFT     0
 | 
						|
 #define RC_PCIE_RST_OUTPUT           BIT(RC_PCIE_RST_OUTPUT_SHIFT)
 | 
						|
+#define PAXC_RESET_MASK              0x7f
 | 
						|
 
 | 
						|
-#define CFG_IND_ADDR_OFFSET          0x120
 | 
						|
 #define CFG_IND_ADDR_MASK            0x00001ffc
 | 
						|
 
 | 
						|
-#define CFG_IND_DATA_OFFSET          0x124
 | 
						|
-
 | 
						|
-#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
 | 
						|
@@ -55,12 +51,8 @@
 | 
						|
 #define CFG_ADDR_CFG_TYPE_SHIFT      0
 | 
						|
 #define CFG_ADDR_CFG_TYPE_MASK       0x00000003
 | 
						|
 
 | 
						|
-#define CFG_DATA_OFFSET              0x1fc
 | 
						|
-
 | 
						|
-#define SYS_RC_INTX_EN               0x330
 | 
						|
 #define SYS_RC_INTX_MASK             0xf
 | 
						|
 
 | 
						|
-#define PCIE_LINK_STATUS_OFFSET      0xf0c
 | 
						|
 #define PCIE_PHYLINKUP_SHIFT         3
 | 
						|
 #define PCIE_PHYLINKUP               BIT(PCIE_PHYLINKUP_SHIFT)
 | 
						|
 #define PCIE_DL_ACTIVE_SHIFT         2
 | 
						|
@@ -71,12 +63,54 @@
 | 
						|
 #define OARR_SIZE_CFG_SHIFT          1
 | 
						|
 #define OARR_SIZE_CFG                BIT(OARR_SIZE_CFG_SHIFT)
 | 
						|
 
 | 
						|
-#define OARR_LO(window)              (0xd20 + (window) * 8)
 | 
						|
-#define OARR_HI(window)              (0xd24 + (window) * 8)
 | 
						|
-#define OMAP_LO(window)              (0xd40 + (window) * 8)
 | 
						|
-#define OMAP_HI(window)              (0xd44 + (window) * 8)
 | 
						|
-
 | 
						|
 #define MAX_NUM_OB_WINDOWS           2
 | 
						|
+#define MAX_NUM_PAXC_PF              4
 | 
						|
+
 | 
						|
+#define IPROC_PCIE_REG_INVALID 0xffff
 | 
						|
+
 | 
						|
+enum iproc_pcie_reg {
 | 
						|
+	IPROC_PCIE_CLK_CTRL = 0,
 | 
						|
+	IPROC_PCIE_CFG_IND_ADDR,
 | 
						|
+	IPROC_PCIE_CFG_IND_DATA,
 | 
						|
+	IPROC_PCIE_CFG_ADDR,
 | 
						|
+	IPROC_PCIE_CFG_DATA,
 | 
						|
+	IPROC_PCIE_INTX_EN,
 | 
						|
+	IPROC_PCIE_OARR_LO,
 | 
						|
+	IPROC_PCIE_OARR_HI,
 | 
						|
+	IPROC_PCIE_OMAP_LO,
 | 
						|
+	IPROC_PCIE_OMAP_HI,
 | 
						|
+	IPROC_PCIE_LINK_STATUS,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/* iProc PCIe PAXB registers */
 | 
						|
+static const u16 iproc_pcie_reg_paxb[] = {
 | 
						|
+	[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_OARR_LO]      = 0xd20,
 | 
						|
+	[IPROC_PCIE_OARR_HI]      = 0xd24,
 | 
						|
+	[IPROC_PCIE_OMAP_LO]      = 0xd40,
 | 
						|
+	[IPROC_PCIE_OMAP_HI]      = 0xd44,
 | 
						|
+	[IPROC_PCIE_LINK_STATUS]  = 0xf0c,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/* iProc PCIe PAXC v1 registers */
 | 
						|
+static const u16 iproc_pcie_reg_paxc[] = {
 | 
						|
+	[IPROC_PCIE_CLK_CTRL]     = 0x000,
 | 
						|
+	[IPROC_PCIE_CFG_IND_ADDR] = 0x1f0,
 | 
						|
+	[IPROC_PCIE_CFG_IND_DATA] = 0x1f4,
 | 
						|
+	[IPROC_PCIE_CFG_ADDR]     = 0x1f8,
 | 
						|
+	[IPROC_PCIE_CFG_DATA]     = 0x1fc,
 | 
						|
+	[IPROC_PCIE_INTX_EN]      = IPROC_PCIE_REG_INVALID,
 | 
						|
+	[IPROC_PCIE_OARR_LO]      = IPROC_PCIE_REG_INVALID,
 | 
						|
+	[IPROC_PCIE_OARR_HI]      = IPROC_PCIE_REG_INVALID,
 | 
						|
+	[IPROC_PCIE_OMAP_LO]      = IPROC_PCIE_REG_INVALID,
 | 
						|
+	[IPROC_PCIE_OMAP_HI]      = IPROC_PCIE_REG_INVALID,
 | 
						|
+	[IPROC_PCIE_LINK_STATUS]  = IPROC_PCIE_REG_INVALID,
 | 
						|
+};
 | 
						|
 
 | 
						|
 static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
 | 
						|
 {
 | 
						|
@@ -91,6 +125,65 @@ static inline struct iproc_pcie *iproc_d
 | 
						|
 	return pcie;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static inline bool iproc_pcie_reg_is_invalid(u16 reg_offset)
 | 
						|
+{
 | 
						|
+	return !!(reg_offset == IPROC_PCIE_REG_INVALID);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline u16 iproc_pcie_reg_offset(struct iproc_pcie *pcie,
 | 
						|
+					enum iproc_pcie_reg reg)
 | 
						|
+{
 | 
						|
+	return pcie->reg_offsets[reg];
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline u32 iproc_pcie_read_reg(struct iproc_pcie *pcie,
 | 
						|
+				      enum iproc_pcie_reg reg)
 | 
						|
+{
 | 
						|
+	u16 offset = iproc_pcie_reg_offset(pcie, reg);
 | 
						|
+
 | 
						|
+	if (iproc_pcie_reg_is_invalid(offset))
 | 
						|
+		return 0;
 | 
						|
+
 | 
						|
+	return readl(pcie->base + offset);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void iproc_pcie_write_reg(struct iproc_pcie *pcie,
 | 
						|
+					enum iproc_pcie_reg reg, u32 val)
 | 
						|
+{
 | 
						|
+	u16 offset = iproc_pcie_reg_offset(pcie, reg);
 | 
						|
+
 | 
						|
+	if (iproc_pcie_reg_is_invalid(offset))
 | 
						|
+		return;
 | 
						|
+
 | 
						|
+	writel(val, pcie->base + offset);
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline void iproc_pcie_ob_write(struct iproc_pcie *pcie,
 | 
						|
+				       enum iproc_pcie_reg reg,
 | 
						|
+				       unsigned window, u32 val)
 | 
						|
+{
 | 
						|
+	u16 offset = iproc_pcie_reg_offset(pcie, reg);
 | 
						|
+
 | 
						|
+	if (iproc_pcie_reg_is_invalid(offset))
 | 
						|
+		return;
 | 
						|
+
 | 
						|
+	writel(val, pcie->base + offset + (window * 8));
 | 
						|
+}
 | 
						|
+
 | 
						|
+static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie,
 | 
						|
+					      unsigned int slot,
 | 
						|
+					      unsigned int fn)
 | 
						|
+{
 | 
						|
+	if (slot > 0)
 | 
						|
+		return false;
 | 
						|
+
 | 
						|
+	/* PAXC can only support limited number of functions */
 | 
						|
+	if (pcie->type == IPROC_PCIE_PAXC && fn >= MAX_NUM_PAXC_PF)
 | 
						|
+		return false;
 | 
						|
+
 | 
						|
+	return true;
 | 
						|
+}
 | 
						|
+
 | 
						|
 /**
 | 
						|
  * Note access to the configuration registers are protected at the higher layer
 | 
						|
  * by 'pci_lock' in drivers/pci/access.c
 | 
						|
@@ -104,28 +197,34 @@ static void __iomem *iproc_pcie_map_cfg_
 | 
						|
 	unsigned fn = PCI_FUNC(devfn);
 | 
						|
 	unsigned busno = bus->number;
 | 
						|
 	u32 val;
 | 
						|
+	u16 offset;
 | 
						|
+
 | 
						|
+	if (!iproc_pcie_device_is_valid(pcie, slot, fn))
 | 
						|
+		return NULL;
 | 
						|
 
 | 
						|
 	/* root complex access */
 | 
						|
 	if (busno == 0) {
 | 
						|
-		if (slot >= 1)
 | 
						|
+		iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR,
 | 
						|
+				     where & CFG_IND_ADDR_MASK);
 | 
						|
+		offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_IND_DATA);
 | 
						|
+		if (iproc_pcie_reg_is_invalid(offset))
 | 
						|
 			return NULL;
 | 
						|
-		writel(where & CFG_IND_ADDR_MASK,
 | 
						|
-		       pcie->base + CFG_IND_ADDR_OFFSET);
 | 
						|
-		return (pcie->base + CFG_IND_DATA_OFFSET);
 | 
						|
+		else
 | 
						|
+			return (pcie->base + offset);
 | 
						|
 	}
 | 
						|
 
 | 
						|
-	if (fn > 1)
 | 
						|
-		return NULL;
 | 
						|
-
 | 
						|
 	/* EP device access */
 | 
						|
 	val = (busno << CFG_ADDR_BUS_NUM_SHIFT) |
 | 
						|
 		(slot << CFG_ADDR_DEV_NUM_SHIFT) |
 | 
						|
 		(fn << CFG_ADDR_FUNC_NUM_SHIFT) |
 | 
						|
 		(where & CFG_ADDR_REG_NUM_MASK) |
 | 
						|
 		(1 & CFG_ADDR_CFG_TYPE_MASK);
 | 
						|
-	writel(val, pcie->base + CFG_ADDR_OFFSET);
 | 
						|
-
 | 
						|
-	return (pcie->base + CFG_DATA_OFFSET);
 | 
						|
+	iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_ADDR, val);
 | 
						|
+	offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_DATA);
 | 
						|
+	if (iproc_pcie_reg_is_invalid(offset))
 | 
						|
+		return NULL;
 | 
						|
+	else
 | 
						|
+		return (pcie->base + offset);
 | 
						|
 }
 | 
						|
 
 | 
						|
 static struct pci_ops iproc_pcie_ops = {
 | 
						|
@@ -138,18 +237,29 @@ static void iproc_pcie_reset(struct ipro
 | 
						|
 {
 | 
						|
 	u32 val;
 | 
						|
 
 | 
						|
+	if (pcie->type == IPROC_PCIE_PAXC) {
 | 
						|
+		val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
 | 
						|
+		val &= ~PAXC_RESET_MASK;
 | 
						|
+		iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
 | 
						|
+		udelay(100);
 | 
						|
+		val |= PAXC_RESET_MASK;
 | 
						|
+		iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
 | 
						|
+		udelay(100);
 | 
						|
+		return;
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	/*
 | 
						|
 	 * Select perst_b signal as reset source. Put the device into reset,
 | 
						|
 	 * and then bring it out of reset
 | 
						|
 	 */
 | 
						|
-	val = readl(pcie->base + CLK_CONTROL_OFFSET);
 | 
						|
+	val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
 | 
						|
 	val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
 | 
						|
 		~RC_PCIE_RST_OUTPUT;
 | 
						|
-	writel(val, pcie->base + CLK_CONTROL_OFFSET);
 | 
						|
+	iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
 | 
						|
 	udelay(250);
 | 
						|
 
 | 
						|
 	val |= RC_PCIE_RST_OUTPUT;
 | 
						|
-	writel(val, pcie->base + CLK_CONTROL_OFFSET);
 | 
						|
+	iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
 | 
						|
 	msleep(100);
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -160,7 +270,14 @@ static int iproc_pcie_check_link(struct
 | 
						|
 	u16 pos, link_status;
 | 
						|
 	bool link_is_active = false;
 | 
						|
 
 | 
						|
-	val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
 | 
						|
+	/*
 | 
						|
+	 * PAXC connects to emulated endpoint devices directly and does not
 | 
						|
+	 * have a Serdes. Therefore skip the link detection logic here
 | 
						|
+	 */
 | 
						|
+	if (pcie->type == IPROC_PCIE_PAXC)
 | 
						|
+		return 0;
 | 
						|
+
 | 
						|
+	val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS);
 | 
						|
 	if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) {
 | 
						|
 		dev_err(pcie->dev, "PHY or data link is INACTIVE!\n");
 | 
						|
 		return -ENODEV;
 | 
						|
@@ -221,7 +338,7 @@ static int iproc_pcie_check_link(struct
 | 
						|
 
 | 
						|
 static void iproc_pcie_enable(struct iproc_pcie *pcie)
 | 
						|
 {
 | 
						|
-	writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN);
 | 
						|
+	iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK);
 | 
						|
 }
 | 
						|
 
 | 
						|
 /**
 | 
						|
@@ -272,11 +389,15 @@ static int iproc_pcie_setup_ob(struct ip
 | 
						|
 	axi_addr -= ob->axi_offset;
 | 
						|
 
 | 
						|
 	for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) {
 | 
						|
-		writel(lower_32_bits(axi_addr) | OARR_VALID |
 | 
						|
-		       (ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i));
 | 
						|
-		writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i));
 | 
						|
-		writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i));
 | 
						|
-		writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i));
 | 
						|
+		iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_LO, i,
 | 
						|
+				    lower_32_bits(axi_addr) | OARR_VALID |
 | 
						|
+				    (ob->set_oarr_size ? 1 : 0));
 | 
						|
+		iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_HI, i,
 | 
						|
+				    upper_32_bits(axi_addr));
 | 
						|
+		iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_LO, i,
 | 
						|
+				    lower_32_bits(pci_addr));
 | 
						|
+		iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_HI, i,
 | 
						|
+				    upper_32_bits(pci_addr));
 | 
						|
 
 | 
						|
 		size -= ob->window_size;
 | 
						|
 		if (size == 0)
 | 
						|
@@ -340,6 +461,19 @@ int iproc_pcie_setup(struct iproc_pcie *
 | 
						|
 		goto err_exit_phy;
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	switch (pcie->type) {
 | 
						|
+	case IPROC_PCIE_PAXB:
 | 
						|
+		pcie->reg_offsets = iproc_pcie_reg_paxb;
 | 
						|
+		break;
 | 
						|
+	case IPROC_PCIE_PAXC:
 | 
						|
+		pcie->reg_offsets = iproc_pcie_reg_paxc;
 | 
						|
+		break;
 | 
						|
+	default:
 | 
						|
+		dev_err(pcie->dev, "incompatible iProc PCIe interface\n");
 | 
						|
+		ret = -EINVAL;
 | 
						|
+		goto err_power_off_phy;
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	iproc_pcie_reset(pcie);
 | 
						|
 
 | 
						|
 	if (pcie->need_ob_cfg) {
 | 
						|
--- a/drivers/pci/host/pcie-iproc.h
 | 
						|
+++ b/drivers/pci/host/pcie-iproc.h
 | 
						|
@@ -15,6 +15,20 @@
 | 
						|
 #define _PCIE_IPROC_H
 | 
						|
 
 | 
						|
 /**
 | 
						|
+ * iProc PCIe interface type
 | 
						|
+ *
 | 
						|
+ * PAXB is the wrapper used in root complex that can be connected to an
 | 
						|
+ * external endpoint device
 | 
						|
+ *
 | 
						|
+ * PAXC is the wrapper used in root complex dedicated for internal emulated
 | 
						|
+ * endpoint devices
 | 
						|
+ */
 | 
						|
+enum iproc_pcie_type {
 | 
						|
+	IPROC_PCIE_PAXB = 0,
 | 
						|
+	IPROC_PCIE_PAXC,
 | 
						|
+};
 | 
						|
+
 | 
						|
+/**
 | 
						|
  * iProc PCIe outbound mapping
 | 
						|
  * @set_oarr_size: indicates the OARR size bit needs to be set
 | 
						|
  * @axi_offset: offset from the AXI address to the internal address used by
 | 
						|
@@ -29,7 +43,10 @@ struct iproc_pcie_ob {
 | 
						|
 
 | 
						|
 /**
 | 
						|
  * iProc PCIe device
 | 
						|
+ *
 | 
						|
  * @dev: pointer to device data structure
 | 
						|
+ * @type: iProc PCIe interface type
 | 
						|
+ * @reg_offsets: register offsets
 | 
						|
  * @base: PCIe host controller I/O register base
 | 
						|
  * @sysdata: Per PCI controller data (ARM-specific)
 | 
						|
  * @root_bus: pointer to root bus
 | 
						|
@@ -41,6 +58,8 @@ struct iproc_pcie_ob {
 | 
						|
  */
 | 
						|
 struct iproc_pcie {
 | 
						|
 	struct device *dev;
 | 
						|
+	enum iproc_pcie_type type;
 | 
						|
+	const u16 *reg_offsets;
 | 
						|
 	void __iomem *base;
 | 
						|
 #ifdef CONFIG_ARM
 | 
						|
 	struct pci_sys_data sysdata;
 |