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
owl
Rafał Miłecki 2016-01-21 05:59:16 +00:00
parent 08e8175696
commit a6ec12bb09
4 changed files with 102 additions and 850 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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