summaryrefslogtreecommitdiff
path: root/target/linux/bcm53xx
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2016-01-21 05:59:16 +0000
committerRafał Miłecki <zajec5@gmail.com>2016-01-21 05:59:16 +0000
commita6ec12bb098ecb634871f3401ed77f365f04c47c (patch)
treec73ddb656f2fb4fe26054ffd7733cc2f10d17307 /target/linux/bcm53xx
parent08e817569630b79a2a2e552cd551c29309f5aacd (diff)
downloadmtk-20170518-a6ec12bb098ecb634871f3401ed77f365f04c47c.zip
mtk-20170518-a6ec12bb098ecb634871f3401ed77f365f04c47c.tar.gz
mtk-20170518-a6ec12bb098ecb634871f3401ed77f365f04c47c.tar.bz2
bcm53xx: fix iProc regression with sent patch instead of a revert
This properly fixes #21393. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 48423
Diffstat (limited to 'target/linux/bcm53xx')
-rw-r--r--target/linux/bcm53xx/patches-4.1/175-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch51
-rw-r--r--target/linux/bcm53xx/patches-4.1/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch425
-rw-r--r--target/linux/bcm53xx/patches-4.4/180-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch51
-rw-r--r--target/linux/bcm53xx/patches-4.4/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch425
4 files changed, 102 insertions, 850 deletions
diff --git a/target/linux/bcm53xx/patches-4.1/175-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch b/target/linux/bcm53xx/patches-4.1/175-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch
new file mode 100644
index 0000000..21c7716
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/175-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch
@@ -0,0 +1,51 @@
+From patchwork Wed Jan 20 22:55:10 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: PCI: iproc: Fix BCMA PCIe bus scanning regression
+From: Ray Jui <rjui@broadcom.com>
+X-Patchwork-Id: 570953
+Message-Id: <1453330510-21926-1-git-send-email-rjui@broadcom.com>
+To: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Rafal Milecki <zajec5@gmail.com>, Hante Meuleman <meuleman@broadcom.com>,
+ Hauke Mehrtens <hauke@hauke-m.de>, <linux-kernel@vger.kernel.org>,
+ <bcm-kernel-feedback-list@broadcom.com>,
+ <linux-pci@vger.kernel.org>, Ray Jui <rjui@broadcom.com>
+Date: Wed, 20 Jan 2016 14:55:10 -0800
+
+Commit 943ebae781f5 ("PCI: iproc: Add PAXC interface support") causes
+regression on EP device detection on BCMA based platforms. This patch
+fixes the issue by allowing multiple devices to be configured on the
+same bus, for all PAXB based child buses
+
+Reported-by: Rafal Milecki <zajec5@gmail.com>
+Fixes: 943ebae781f5 ("PCI: iproc: Add PAXC interface support")
+Signed-off-by: Ray Jui <rjui@broadcom.com>
+---
+ drivers/pci/host/pcie-iproc.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/pci/host/pcie-iproc.c
++++ b/drivers/pci/host/pcie-iproc.c
+@@ -171,10 +171,11 @@ static inline void iproc_pcie_ob_write(s
+ }
+
+ static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie,
++ unsigned int busnum,
+ unsigned int slot,
+ unsigned int fn)
+ {
+- if (slot > 0)
++ if ((pcie->type == IPROC_PCIE_PAXC || busnum == 0) && slot > 0)
+ return false;
+
+ /* PAXC can only support limited number of functions */
+@@ -199,7 +200,7 @@ static void __iomem *iproc_pcie_map_cfg_
+ u32 val;
+ u16 offset;
+
+- if (!iproc_pcie_device_is_valid(pcie, slot, fn))
++ if (!iproc_pcie_device_is_valid(pcie, busno, slot, fn))
+ return NULL;
+
+ /* root complex access */
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
deleted file mode 100644
index 4aad686..0000000
--- a/target/linux/bcm53xx/patches-4.1/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch
+++ /dev/null
@@ -1,425 +0,0 @@
-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, &reg);
-@@ -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
diff --git a/target/linux/bcm53xx/patches-4.4/180-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch b/target/linux/bcm53xx/patches-4.4/180-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch
new file mode 100644
index 0000000..21c7716
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.4/180-PCI-iproc-Fix-BCMA-PCIe-bus-scanning-regression.patch
@@ -0,0 +1,51 @@
+From patchwork Wed Jan 20 22:55:10 2016
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: PCI: iproc: Fix BCMA PCIe bus scanning regression
+From: Ray Jui <rjui@broadcom.com>
+X-Patchwork-Id: 570953
+Message-Id: <1453330510-21926-1-git-send-email-rjui@broadcom.com>
+To: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Rafal Milecki <zajec5@gmail.com>, Hante Meuleman <meuleman@broadcom.com>,
+ Hauke Mehrtens <hauke@hauke-m.de>, <linux-kernel@vger.kernel.org>,
+ <bcm-kernel-feedback-list@broadcom.com>,
+ <linux-pci@vger.kernel.org>, Ray Jui <rjui@broadcom.com>
+Date: Wed, 20 Jan 2016 14:55:10 -0800
+
+Commit 943ebae781f5 ("PCI: iproc: Add PAXC interface support") causes
+regression on EP device detection on BCMA based platforms. This patch
+fixes the issue by allowing multiple devices to be configured on the
+same bus, for all PAXB based child buses
+
+Reported-by: Rafal Milecki <zajec5@gmail.com>
+Fixes: 943ebae781f5 ("PCI: iproc: Add PAXC interface support")
+Signed-off-by: Ray Jui <rjui@broadcom.com>
+---
+ drivers/pci/host/pcie-iproc.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/pci/host/pcie-iproc.c
++++ b/drivers/pci/host/pcie-iproc.c
+@@ -171,10 +171,11 @@ static inline void iproc_pcie_ob_write(s
+ }
+
+ static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie,
++ unsigned int busnum,
+ unsigned int slot,
+ unsigned int fn)
+ {
+- if (slot > 0)
++ if ((pcie->type == IPROC_PCIE_PAXC || busnum == 0) && slot > 0)
+ return false;
+
+ /* PAXC can only support limited number of functions */
+@@ -199,7 +200,7 @@ static void __iomem *iproc_pcie_map_cfg_
+ u32 val;
+ u16 offset;
+
+- if (!iproc_pcie_device_is_valid(pcie, slot, fn))
++ if (!iproc_pcie_device_is_valid(pcie, busno, slot, fn))
+ return NULL;
+
+ /* root complex access */
diff --git a/target/linux/bcm53xx/patches-4.4/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch b/target/linux/bcm53xx/patches-4.4/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch
deleted file mode 100644
index 4aad686..0000000
--- a/target/linux/bcm53xx/patches-4.4/800-Revert-PCI-iproc-Add-PAXC-interface-support.patch
+++ /dev/null
@@ -1,425 +0,0 @@
-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, &reg);
-@@ -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