This properly fixes #21393. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 48423master
parent
08e8175696
commit
a6ec12bb09
@ -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 */
|
@ -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, ®);
|
|
||||||
@@ -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
|
|
@ -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 */
|
@ -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, ®);
|
|
||||||
@@ -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
|
|
Loading…
Reference in new issue