diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2016-01-19 22:53:21 +0000 |
---|---|---|
committer | Rafał Miłecki <zajec5@gmail.com> | 2016-01-19 22:53:21 +0000 |
commit | 7c2356e2a011efbc146bd20b8136a06ea0000620 (patch) | |
tree | 0ca5705ad41267e3f495d36f6e13060998c4ea55 /target/linux/bcm53xx/patches-4.1 | |
parent | e3b3b7fb0ac5ddf807adc826f784a4bb72ca2795 (diff) | |
download | mtk-20170518-7c2356e2a011efbc146bd20b8136a06ea0000620.zip mtk-20170518-7c2356e2a011efbc146bd20b8136a06ea0000620.tar.gz mtk-20170518-7c2356e2a011efbc146bd20b8136a06ea0000620.tar.bz2 |
bcm53xx: revert iProc patch adding PAXC support
It broke detecting some PCIe devices. This fixes (workarounds) #21393.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 48382
Diffstat (limited to 'target/linux/bcm53xx/patches-4.1')
-rw-r--r-- | target/linux/bcm53xx/patches-4.1/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/target/linux/bcm53xx/patches-4.1/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch b/target/linux/bcm53xx/patches-4.1/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch new file mode 100644 index 0000000..4aad686 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch @@ -0,0 +1,425 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +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 <zajec5@gmail.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, 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 |