diff options
Diffstat (limited to 'target/linux/bcm53xx/patches-4.4/087-0002-PCI-iproc-Add-PAXC-interface-support.patch')
-rw-r--r-- | target/linux/bcm53xx/patches-4.4/087-0002-PCI-iproc-Add-PAXC-interface-support.patch | 429 |
1 files changed, 0 insertions, 429 deletions
diff --git a/target/linux/bcm53xx/patches-4.4/087-0002-PCI-iproc-Add-PAXC-interface-support.patch b/target/linux/bcm53xx/patches-4.4/087-0002-PCI-iproc-Add-PAXC-interface-support.patch deleted file mode 100644 index b011328761..0000000000 --- a/target/linux/bcm53xx/patches-4.4/087-0002-PCI-iproc-Add-PAXC-interface-support.patch +++ /dev/null @@ -1,429 +0,0 @@ -From 943ebae781f519ecfecbfa1b997f15f59116e41d Mon Sep 17 00:00:00 2001 -From: Ray Jui <rjui@broadcom.com> -Date: Fri, 4 Dec 2015 09:34:59 -0800 -Subject: [PATCH 2/5] 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. - -Add support for PAXC-based iProc PCIe root complex in the iProc PCIe core -driver. This change factors out common logic between PAXB and PAXC, and -uses 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> -Signed-off-by: Bjorn Helgaas <bhelgaas@google.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; |