Skip to content

Commit 377bced

Browse files
Stanimir Varbanovkwilczynski
authored andcommitted
PCI: brcmstb: Add BCM2712 support
Add a bare minimum amount of changes in order to support PCIe Root Complex hardware IP found on RPi5. The PCIe controller on BCM2712 is based on BCM7712 and as such it inherits register offsets, PERST# assertion, bridge_reset ops, and inbound windows count. Although, the implementation for BCM2712 needs a workaround related to the control of the bridge_reset where turning off of the Root Port must not shutdown the bridge_reset and this must be avoided. To implement this workaround a quirks field is introduced in pcie_cfg_data struct. The controller also needs adjustment of PHY PLL setup to use a 54MHz input refclk. The default input reference clock for the PHY PLL is 100Mhz, except for some devices where it is 54Mhz like BCM2712C1 and BCM2712D0. To implement those adjustments introduce a new .post_setup op in pcie_cfg_data and call it at the end of brcm_pcie_setup function. The BCM2712 .post_setup callback implements the required MDIO writes that switch the PLL refclk and also change PHY PM clock period. Without this RPi5 PCIex1 is unable to enumerate endpoint devices on the expansion connector. Signed-off-by: Stanimir Varbanov <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Reviewed-by: Jim Quinlan <[email protected]> Tested-by: Ivan T. Ivanov <[email protected]> Link: https://lore.kernel.org/r/[email protected] [commit log] Signed-off-by: Krzysztof Wilczyński <[email protected]>
1 parent 25a98c7 commit 377bced

File tree

1 file changed

+67
-2
lines changed

1 file changed

+67
-2
lines changed

drivers/pci/controller/pcie-brcmstb.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
5656
#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
5757

58+
#define PCIE_RC_PL_PHY_CTL_15 0x184c
59+
#define PCIE_RC_PL_PHY_CTL_15_DIS_PLL_PD_MASK 0x400000
60+
#define PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK 0xff
61+
5862
#define PCIE_MISC_MISC_CTRL 0x4008
5963
#define PCIE_MISC_MISC_CTRL_PCIE_RCB_64B_MODE_MASK 0x80
6064
#define PCIE_MISC_MISC_CTRL_PCIE_RCB_MPS_MODE_MASK 0x400
@@ -234,13 +238,24 @@ struct inbound_win {
234238
u64 cpu_addr;
235239
};
236240

241+
/*
242+
* The RESCAL block is tied to PCIe controller #1, regardless of the number of
243+
* controllers, and turning off PCIe controller #1 prevents access to the RESCAL
244+
* register blocks, therefore no other controller can access this register
245+
* space, and depending upon the bus fabric we may get a timeout (UBUS/GISB),
246+
* or a hang (AXI).
247+
*/
248+
#define CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN BIT(0)
249+
237250
struct pcie_cfg_data {
238251
const int *offsets;
239252
const enum pcie_soc_base soc_base;
240253
const bool has_phy;
254+
const u32 quirks;
241255
u8 num_inbound_wins;
242256
int (*perst_set)(struct brcm_pcie *pcie, u32 val);
243257
int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
258+
int (*post_setup)(struct brcm_pcie *pcie);
244259
};
245260

246261
struct subdev_regulators {
@@ -816,6 +831,38 @@ static int brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val)
816831
return 0;
817832
}
818833

834+
static int brcm_pcie_post_setup_bcm2712(struct brcm_pcie *pcie)
835+
{
836+
const u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 };
837+
const u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e };
838+
int ret, i;
839+
u32 tmp;
840+
841+
/* Allow a 54MHz (xosc) refclk source */
842+
ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET, 0x1600);
843+
if (ret < 0)
844+
return ret;
845+
846+
for (i = 0; i < ARRAY_SIZE(regs); i++) {
847+
ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]);
848+
if (ret < 0)
849+
return ret;
850+
}
851+
852+
usleep_range(100, 200);
853+
854+
/*
855+
* Set L1SS sub-state timers to avoid lengthy state transitions,
856+
* PM clock period is 18.52ns (1/54MHz, round down).
857+
*/
858+
tmp = readl(pcie->base + PCIE_RC_PL_PHY_CTL_15);
859+
tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK;
860+
tmp |= 0x12;
861+
writel(tmp, pcie->base + PCIE_RC_PL_PHY_CTL_15);
862+
863+
return 0;
864+
}
865+
819866
static void add_inbound_win(struct inbound_win *b, u8 *count, u64 size,
820867
u64 cpu_addr, u64 pci_offset)
821868
{
@@ -1179,6 +1226,12 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
11791226
PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
11801227
writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
11811228

1229+
if (pcie->cfg->post_setup) {
1230+
ret = pcie->cfg->post_setup(pcie);
1231+
if (ret < 0)
1232+
return ret;
1233+
}
1234+
11821235
return 0;
11831236
}
11841237

@@ -1488,8 +1541,9 @@ static int brcm_pcie_turn_off(struct brcm_pcie *pcie)
14881541
u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
14891542
writel(tmp, base + HARD_DEBUG(pcie));
14901543

1491-
/* Shutdown PCIe bridge */
1492-
ret = pcie->cfg->bridge_sw_init_set(pcie, 1);
1544+
if (!(pcie->cfg->quirks & CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN))
1545+
/* Shutdown PCIe bridge */
1546+
ret = pcie->cfg->bridge_sw_init_set(pcie, 1);
14931547

14941548
return ret;
14951549
}
@@ -1699,6 +1753,16 @@ static const struct pcie_cfg_data bcm2711_cfg = {
16991753
.num_inbound_wins = 3,
17001754
};
17011755

1756+
static const struct pcie_cfg_data bcm2712_cfg = {
1757+
.offsets = pcie_offsets_bcm7712,
1758+
.soc_base = BCM7712,
1759+
.perst_set = brcm_pcie_perst_set_7278,
1760+
.bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic,
1761+
.post_setup = brcm_pcie_post_setup_bcm2712,
1762+
.quirks = CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN,
1763+
.num_inbound_wins = 10,
1764+
};
1765+
17021766
static const struct pcie_cfg_data bcm4908_cfg = {
17031767
.offsets = pcie_offsets,
17041768
.soc_base = BCM4908,
@@ -1750,6 +1814,7 @@ static const struct pcie_cfg_data bcm7712_cfg = {
17501814

17511815
static const struct of_device_id brcm_pcie_match[] = {
17521816
{ .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg },
1817+
{ .compatible = "brcm,bcm2712-pcie", .data = &bcm2712_cfg },
17531818
{ .compatible = "brcm,bcm4908-pcie", .data = &bcm4908_cfg },
17541819
{ .compatible = "brcm,bcm7211-pcie", .data = &generic_cfg },
17551820
{ .compatible = "brcm,bcm7216-pcie", .data = &bcm7216_cfg },

0 commit comments

Comments
 (0)