From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Subject: [PATCH] Revert "PCI: iproc: Add PAXC interface support" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding PAXC support fixed all "invalid BAR" firmware bug messages but also broke finding extra buses and attached devices. This affected e.g. Netgear R8000 which has 2 (out of 3) BCM43602 cards connected to the 2nd "PCIe Gen 2" controller. None of them is detected with PAXC code. This reverts commit 943ebae781f519ecfecbfa1b997f15f59116e41d. Signed-off-by: Rafał Miłecki --- 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, 40 insertions(+), 205 deletions(-) --- a/drivers/pci/host/pcie-iproc-platform.c +++ b/drivers/pci/host/pcie-iproc-platform.c @@ -26,21 +26,8 @@ #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; @@ -48,16 +35,11 @@ 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, ®); @@ -133,6 +115,12 @@ 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,16 +30,20 @@ #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 @@ -51,8 +55,12 @@ #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 @@ -63,54 +71,12 @@ #define OARR_SIZE_CFG_SHIFT 1 #define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) -#define MAX_NUM_OB_WINDOWS 2 -#define MAX_NUM_PAXC_PF 4 - -#define IPROC_PCIE_REG_INVALID 0xffff +#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) -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, -}; +#define MAX_NUM_OB_WINDOWS 2 static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) { @@ -125,65 +91,6 @@ 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 @@ -197,34 +104,28 @@ 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) { - 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)) + if (slot >= 1) return NULL; - else - return (pcie->base + offset); + writel(where & CFG_IND_ADDR_MASK, + pcie->base + CFG_IND_ADDR_OFFSET); + return (pcie->base + CFG_IND_DATA_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); - 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); + writel(val, pcie->base + CFG_ADDR_OFFSET); + + return (pcie->base + CFG_DATA_OFFSET); } static struct pci_ops iproc_pcie_ops = { @@ -237,29 +138,18 @@ 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 = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL); + val = readl(pcie->base + CLK_CONTROL_OFFSET); val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST & ~RC_PCIE_RST_OUTPUT; - iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); + writel(val, pcie->base + CLK_CONTROL_OFFSET); udelay(250); val |= RC_PCIE_RST_OUTPUT; - iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); + writel(val, pcie->base + CLK_CONTROL_OFFSET); msleep(100); } @@ -270,14 +160,7 @@ static int iproc_pcie_check_link(struct u16 pos, link_status; bool link_is_active = false; - /* - * 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); + val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET); if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { dev_err(pcie->dev, "PHY or data link is INACTIVE!\n"); return -ENODEV; @@ -338,7 +221,7 @@ static int iproc_pcie_check_link(struct static void iproc_pcie_enable(struct iproc_pcie *pcie) { - iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK); + writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); } /** @@ -389,15 +272,11 @@ static int iproc_pcie_setup_ob(struct ip axi_addr -= ob->axi_offset; for (i = 0; i < MAX_NUM_OB_WINDOWS; 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)); + 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)); size -= ob->window_size; if (size == 0) @@ -481,19 +360,6 @@ 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,20 +15,6 @@ #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 @@ -45,10 +31,7 @@ struct iproc_msi; /** * 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 * @base_addr: PCIe host controller register base physical address * @sysdata: Per PCI controller data (ARM-specific) @@ -61,8 +44,6 @@ struct iproc_msi; */ struct iproc_pcie { struct device *dev; - enum iproc_pcie_type type; - const u16 *reg_offsets; void __iomem *base; phys_addr_t base_addr; #ifdef CONFIG_ARM