summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2026-10-21 13:20:30 -0500
committerBjorn Helgaas <bhelgaas@google.com>2026-10-21 13:20:30 -0500
commit3ed79a3eec0bf9bb3f441e270f6b45d6e5ab356a (patch)
treeb6b966c9a0e8b82771dc735eb614778dbfe6a448
parentd2ac9aa59774f7dc80b85b03c2ff0a19acbdff05 (diff)
parent8a1c4ba99946d5e0e07c357792deea666df23f5f (diff)
Merge branch 'pci/controller/brcmstb'
- Remove unnecessary 'const' specifier from struct pcie_cfg_data members (Jim Quinlan) - Replace bool properties for each SoC configuration with a u32 bitvector and a BFLAG() helper (Jim Quinlan) - Use a similar BQUIRK() helper to test various SoC quirks (Jim Quinlan) * pci/controller/brcmstb: PCI: brcmstb: Declare and assign quirk PERST_PCIE_REV_CUTOFF PCI: brcmstb: Declare and assign quirk EARLY_PERST_ASSERT PCI: brcmstb: Declare and assign quirk NO_RGR1_TIMER PCI: brcmstb: Declare and assign quirk 32BIT_PCI_OPS PCI: brcmstb: Declare and assign flag IS_BMIPS PCI: brcmstb: Declare and assign quirk OB_WIN_MAXSZ_128MB PCI: brcmstb: Declare and assign quirk OB_WIN_32BIT_ADDR PCI: brcmstb: Add Broadcom quirks macro PCI: brcmstb: Use flags u32 instead of bools PCI: brcmstb: Remove redundant const specifier for struct fields
-rw-r--r--drivers/pci/controller/pcie-brcmstb.c92
1 files changed, 60 insertions, 32 deletions
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index 8a0c353d2abf..26d1305f5e70 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -277,6 +277,9 @@ struct inbound_win {
u64 cpu_addr;
};
+/* QUIRKS */
+#define BQUIRK(pcie, quirk) ((pcie)->cfg->quirks & CFG_QUIRK_ ## quirk)
+
/*
* The RESCAL block is tied to PCIe controller #1, regardless of the number of
* controllers, and turning off PCIe controller #1 prevents access to the RESCAL
@@ -285,17 +288,38 @@ struct inbound_win {
* or a hang (AXI).
*/
#define CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN BIT(0)
+/* The outbound windows must be within the 0-4GB region */
+#define CFG_QUIRK_OB_WIN_32BIT_ADDR BIT(1)
+/* Each of the outbound windows size must be <= SZ_128M */
+#define CFG_QUIRK_OB_WIN_MAXSZ_128MB BIT(2)
+/* PCIe HW can only access config space with 32bit R/W */
+#define CFG_QUIRK_32BIT_PCI_OPS BIT(3)
+/* PCIe HW does not have an internal bus timer */
+#define CFG_QUIRK_NO_RGR1_TIMER BIT(4)
+/* PCIe PERST# must be asserted before internal bridge turned on */
+#define CFG_QUIRK_EARLY_PERST_ASSERT BIT(5)
+/* PCIe SW PERST behavior only works up to a specific HW version */
+#define CFG_QUIRK_PERST_PCIE_REV_CUTOFF BIT(6)
+
+/* FLAGS */
+#define BFLAG(pcie, flag) ((pcie)->cfg->flags & CFG_FLG_ ## flag)
+
+/* The PCIe HW registers have phy control of a "RESCAL" reset block */
+#define CFG_FLG_HAS_PHY BIT(0)
+/* The SoC PCIe HW can dump to the console PCIe error info */
+#define CFG_FLG_HAS_ERR_REPORT BIT(1)
+/* SoC uses a Broadcom variant of the MIPS-1 ISA */
+#define CFG_FLG_IS_BMIPS BIT(2)
struct pcie_cfg_data {
const int *offsets;
- const enum pcie_soc_base soc_base;
- const bool has_phy;
- const u32 quirks;
+ enum pcie_soc_base soc_base;
+ u32 flags;
+ u32 quirks;
u8 num_inbound_wins;
int (*perst_set)(struct brcm_pcie *pcie, u32 val);
int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
int (*post_setup)(struct brcm_pcie *pcie);
- bool has_err_report;
};
struct subdev_regulators {
@@ -346,24 +370,19 @@ struct brcm_pcie {
spinlock_t bridge_lock;
};
-static inline bool is_bmips(const struct brcm_pcie *pcie)
-{
- return pcie->cfg->soc_base == BCM7435 || pcie->cfg->soc_base == BCM7425;
-}
-
static int brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
{
unsigned long flags;
int ret;
- if (pcie->cfg->has_err_report)
+ if (BFLAG(pcie, HAS_ERR_REPORT))
spin_lock_irqsave(&pcie->bridge_lock, flags);
ret = pcie->cfg->bridge_sw_init_set(pcie, val);
/* If we fail, assume the bridge is in reset (off) */
pcie->bridge_in_reset = ret ? true : val;
- if (pcie->cfg->has_err_report)
+ if (BFLAG(pcie, HAS_ERR_REPORT))
spin_unlock_irqrestore(&pcie->bridge_lock, flags);
return ret;
@@ -508,7 +527,7 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK);
writel(tmp, pcie->base + PCIE_MEM_WIN0_BASE_LIMIT(win));
- if (is_bmips(pcie))
+ if (BQUIRK(pcie, OB_WIN_32BIT_ADDR))
return;
/* Write the cpu & limit addr upper bits */
@@ -1144,8 +1163,8 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
if (ret)
return ret;
- /* Ensure that PERST# is asserted; some bootloaders may deassert it. */
- if (pcie->cfg->soc_base == BCM2711) {
+ if (BQUIRK(pcie, EARLY_PERST_ASSERT)) {
+ /* Ensure that PERST# is asserted; some bootloaders may deassert it. */
ret = pcie->cfg->perst_set(pcie, 1);
if (ret) {
pcie->cfg->bridge_sw_init_set(pcie, 0);
@@ -1161,7 +1180,7 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
return ret;
tmp = readl(base + HARD_DEBUG(pcie));
- if (is_bmips(pcie))
+ if (BFLAG(pcie, IS_BMIPS))
tmp &= ~PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK;
else
tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK;
@@ -1174,7 +1193,7 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
* is encoded as 0=128, 1=256, 2=512, 3=Rsvd, for BCM7278 it
* is encoded as 0=Rsvd, 1=128, 2=256, 3=512.
*/
- if (is_bmips(pcie))
+ if (BFLAG(pcie, IS_BMIPS))
burst = 0x1; /* 256 bytes */
else if (pcie->cfg->soc_base == BCM2711)
burst = 0x0; /* 128 bytes */
@@ -1281,11 +1300,11 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
return -EINVAL;
}
- if (is_bmips(pcie)) {
+ if (BQUIRK(pcie, OB_WIN_MAXSZ_128MB)) {
u64 start = res->start;
unsigned int j, nwins = resource_size(res) / SZ_128M;
- /* bmips PCIe outbound windows have a 128MB max size */
+ /* PCIe outbound windows have a 128MB max size */
if (nwins > BRCM_NUM_PCIE_OUT_WINS)
nwins = BRCM_NUM_PCIE_OUT_WINS;
for (j = 0; j < nwins; j++, start += SZ_128M)
@@ -1326,8 +1345,8 @@ static void brcm_extend_rbus_timeout(struct brcm_pcie *pcie)
const unsigned int REG_OFFSET = PCIE_RGR1_SW_INIT_1(pcie) - 8;
u32 timeout_us = 4000000; /* 4 seconds, our setting for L1SS */
- /* 7712 does not have this (RGR1) timer */
- if (pcie->cfg->soc_base == BCM7712)
+ /* Don't do access if there is no timer */
+ if (BQUIRK(pcie, NO_RGR1_TIMER))
return;
/* Each unit in timeout register is 1/216,000,000 seconds */
@@ -1589,12 +1608,12 @@ static int brcm_phy_cntl(struct brcm_pcie *pcie, const int start)
static inline int brcm_phy_start(struct brcm_pcie *pcie)
{
- return pcie->cfg->has_phy ? brcm_phy_cntl(pcie, 1) : 0;
+ return BFLAG(pcie, HAS_PHY) ? brcm_phy_cntl(pcie, 1) : 0;
}
static inline int brcm_phy_stop(struct brcm_pcie *pcie)
{
- return pcie->cfg->has_phy ? brcm_phy_cntl(pcie, 0) : 0;
+ return BFLAG(pcie, HAS_PHY) ? brcm_phy_cntl(pcie, 0) : 0;
}
static int brcm_pcie_turn_off(struct brcm_pcie *pcie)
@@ -1619,7 +1638,7 @@ static int brcm_pcie_turn_off(struct brcm_pcie *pcie)
u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
writel(tmp, base + HARD_DEBUG(pcie));
- if (!(pcie->cfg->quirks & CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN))
+ if (!(BQUIRK(pcie, AVOID_BRIDGE_SHUTDOWN)))
/* Shutdown PCIe bridge */
ret = brcm_pcie_bridge_sw_init_set(pcie, 1);
@@ -1898,7 +1917,7 @@ static void brcm_pcie_remove(struct platform_device *pdev)
pci_stop_root_bus(bridge->bus);
pci_remove_root_bus(bridge->bus);
pci_unlock_rescan_remove();
- if (pcie->cfg->has_err_report)
+ if (BFLAG(pcie, HAS_ERR_REPORT))
brcm_unregister_die_notifiers(pcie);
__brcm_pcie_remove(pcie);
@@ -1950,6 +1969,7 @@ static const struct pcie_cfg_data bcm2711_cfg = {
.perst_set = brcm_pcie_perst_set_generic,
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
.num_inbound_wins = 3,
+ .quirks = CFG_QUIRK_EARLY_PERST_ASSERT,
};
static const struct pcie_cfg_data bcm2712_cfg = {
@@ -1958,7 +1978,8 @@ static const struct pcie_cfg_data bcm2712_cfg = {
.perst_set = brcm_pcie_perst_set_7278,
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
.post_setup = brcm_pcie_post_setup_bcm2712,
- .quirks = CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN,
+ .quirks = CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN |
+ CFG_QUIRK_NO_RGR1_TIMER,
.num_inbound_wins = 10,
};
@@ -1968,6 +1989,7 @@ static const struct pcie_cfg_data bcm4908_cfg = {
.perst_set = brcm_pcie_perst_set_4908,
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
.num_inbound_wins = 3,
+ .quirks = CFG_QUIRK_PERST_PCIE_REV_CUTOFF,
};
static const struct pcie_cfg_data bcm7278_cfg = {
@@ -1984,6 +2006,9 @@ static const struct pcie_cfg_data bcm7425_cfg = {
.perst_set = brcm_pcie_perst_set_generic,
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
.num_inbound_wins = 3,
+ .quirks = CFG_QUIRK_OB_WIN_32BIT_ADDR
+ | CFG_QUIRK_OB_WIN_MAXSZ_128MB | CFG_QUIRK_32BIT_PCI_OPS,
+ .flags = CFG_FLG_IS_BMIPS,
};
static const struct pcie_cfg_data bcm7435_cfg = {
@@ -1992,6 +2017,9 @@ static const struct pcie_cfg_data bcm7435_cfg = {
.perst_set = brcm_pcie_perst_set_generic,
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
.num_inbound_wins = 3,
+ .quirks = CFG_QUIRK_OB_WIN_32BIT_ADDR
+ | CFG_QUIRK_OB_WIN_MAXSZ_128MB,
+ .flags = CFG_FLG_IS_BMIPS,
};
static const struct pcie_cfg_data bcm7216_cfg = {
@@ -1999,9 +2027,8 @@ static const struct pcie_cfg_data bcm7216_cfg = {
.soc_base = BCM7278,
.perst_set = brcm_pcie_perst_set_7278,
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_7278,
- .has_phy = true,
+ .flags = CFG_FLG_HAS_PHY | CFG_FLG_HAS_ERR_REPORT,
.num_inbound_wins = 3,
- .has_err_report = true,
};
static const struct pcie_cfg_data bcm7712_cfg = {
@@ -2010,6 +2037,7 @@ static const struct pcie_cfg_data bcm7712_cfg = {
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
.soc_base = BCM7712,
.num_inbound_wins = 10,
+ .quirks = CFG_QUIRK_NO_RGR1_TIMER,
};
static const struct of_device_id brcm_pcie_match[] = {
@@ -2034,7 +2062,7 @@ static struct pci_ops brcm_pcie_ops = {
.remove_bus = brcm_pcie_remove_bus,
};
-static struct pci_ops brcm7425_pcie_ops = {
+static struct pci_ops brcm_pcie_ops32 = {
.map_bus = brcm7425_pcie_map_bus,
.read = pci_generic_config_read32,
.write = pci_generic_config_write32,
@@ -2143,7 +2171,7 @@ static int brcm_pcie_probe(struct platform_device *pdev)
goto fail;
pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION);
- if (pcie->cfg->soc_base == BCM4908 &&
+ if (BQUIRK(pcie, PERST_PCIE_REV_CUTOFF) &&
pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) {
dev_err(pcie->dev, "hardware revision with unsupported PERST# setup\n");
ret = -ENODEV;
@@ -2164,8 +2192,8 @@ static int brcm_pcie_probe(struct platform_device *pdev)
}
}
- bridge->ops = pcie->cfg->soc_base == BCM7425 ?
- &brcm7425_pcie_ops : &brcm_pcie_ops;
+ bridge->ops = BQUIRK(pcie, 32BIT_PCI_OPS)
+ ? &brcm_pcie_ops32 : &brcm_pcie_ops;
bridge->sysdata = pcie;
platform_set_drvdata(pdev, pcie);
@@ -2179,7 +2207,7 @@ static int brcm_pcie_probe(struct platform_device *pdev)
return ret;
}
- if (pcie->cfg->has_err_report) {
+ if (BFLAG(pcie, HAS_ERR_REPORT)) {
spin_lock_init(&pcie->bridge_lock);
brcm_register_die_notifiers(pcie);
}