mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
pci: brcmstb: Support different variants using a cfg struct
The Linux kernel driver already had support for multiple hardware variants when the bcm2712 was added (see e.g. linux commit 10dbedad3c818 which is the last in a longer set of changes). This patch brings in this required infrastructure and adds a differentiation between 2711 and 2712 register layouts on top. Signed-off-by: Torsten Duwe <duwe@suse.de> Co-authored-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com> Tested-by: Pedro Falcato <pfalcato@suse.de> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
This commit is contained in:
committed by
Peter Robinson
parent
b24c620e5e
commit
d0b2a1cb3f
@@ -70,6 +70,7 @@
|
||||
#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
|
||||
#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
|
||||
#define RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
|
||||
#define PCIE_MISC_PCIE_CTRL 0x4064
|
||||
#define PCIE_MISC_PCIE_STATUS 0x4068
|
||||
#define STATUS_PCIE_PORT_MASK 0x80
|
||||
#define STATUS_PCIE_PORT_SHIFT 7
|
||||
@@ -108,6 +109,10 @@
|
||||
|
||||
#define PCIE_RGR1_SW_INIT_1 0x9210
|
||||
#define PCIE_EXT_CFG_INDEX 0x9000
|
||||
#define RGR1_SW_INIT_1_PERST_MASK 0x1
|
||||
#define RGR1_SW_INIT_1_PERSTB_MASK 0x4
|
||||
#define RGR1_SW_INIT_1_INIT_MASK 0x2
|
||||
|
||||
/* A small window pointing at the ECAM of the device selected by CFG_INDEX */
|
||||
#define PCIE_EXT_CFG_DATA 0x8000
|
||||
|
||||
|
||||
@@ -49,6 +49,24 @@
|
||||
#define SSC_STATUS_PLL_LOCK_MASK 0x800
|
||||
#define SSC_STATUS_PLL_LOCK_SHIFT 11
|
||||
|
||||
enum {
|
||||
RGR1_SW_INIT_1,
|
||||
PCIE_HARD_DEBUG,
|
||||
};
|
||||
|
||||
enum brcm_pcie_type {
|
||||
BCM2711,
|
||||
BCM2712
|
||||
};
|
||||
|
||||
struct brcm_pcie;
|
||||
|
||||
struct brcm_pcie_cfg_data {
|
||||
const int *offsets;
|
||||
const enum brcm_pcie_type type;
|
||||
void (*perst_set)(struct brcm_pcie *pcie, u32 val);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcm_pcie - the PCIe controller state
|
||||
* @base: Base address of memory mapped IO registers of the controller
|
||||
@@ -61,6 +79,7 @@ struct brcm_pcie {
|
||||
|
||||
int gen;
|
||||
bool ssc;
|
||||
const struct brcm_pcie_cfg_data *pcie_cfg;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -104,6 +123,36 @@ static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
|
||||
return (val & STATUS_PCIE_PORT_MASK) >> STATUS_PCIE_PORT_SHIFT;
|
||||
}
|
||||
|
||||
static void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val)
|
||||
{
|
||||
if (val)
|
||||
setbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
|
||||
RGR1_SW_INIT_1_PERST_MASK);
|
||||
else
|
||||
clrbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
|
||||
RGR1_SW_INIT_1_PERST_MASK);
|
||||
}
|
||||
|
||||
static void brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
/* Perst bit has moved and assert value is 0 */
|
||||
tmp = readl(pcie->base + PCIE_MISC_PCIE_CTRL);
|
||||
u32p_replace_bits(&tmp, !val, RGR1_SW_INIT_1_PERSTB_MASK);
|
||||
writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL);
|
||||
}
|
||||
|
||||
static void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
|
||||
{
|
||||
if (val)
|
||||
setbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
|
||||
RGR1_SW_INIT_1_INIT_MASK);
|
||||
else
|
||||
clrbits_le32(pcie->base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
|
||||
RGR1_SW_INIT_1_INIT_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* brcm_pcie_link_up() - Check whether the PCIe link is up
|
||||
* @pcie: Pointer to the PCIe controller state
|
||||
@@ -365,8 +414,9 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
* e.g. BCM7278, the fundamental reset should not be asserted here.
|
||||
* This will need to be changed when support for other SoCs is added.
|
||||
*/
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1,
|
||||
PCIE_RGR1_SW_INIT_1_INIT_MASK | PCIE_RGR1_SW_INIT_1_PERST_MASK);
|
||||
brcm_pcie_bridge_sw_init_set(pcie, 1);
|
||||
if (pcie->pcie_cfg->type != BCM2712)
|
||||
pcie->pcie_cfg->perst_set(pcie, 1);
|
||||
/*
|
||||
* The delay is a safety precaution to preclude the reset signal
|
||||
* from looking like a glitch.
|
||||
@@ -374,9 +424,9 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
udelay(100);
|
||||
|
||||
/* Take the bridge out of reset */
|
||||
clrbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
|
||||
brcm_pcie_bridge_sw_init_set(pcie, 0);
|
||||
|
||||
clrbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
|
||||
clrbits_le32(base + pcie->pcie_cfg->offsets[PCIE_HARD_DEBUG],
|
||||
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
|
||||
|
||||
/* Wait for SerDes to be stable */
|
||||
@@ -426,8 +476,7 @@ static int brcm_pcie_probe(struct udevice *dev)
|
||||
brcm_pcie_set_gen(pcie, pcie->gen);
|
||||
|
||||
/* Unassert the fundamental reset */
|
||||
clrbits_le32(pcie->base + PCIE_RGR1_SW_INIT_1,
|
||||
PCIE_RGR1_SW_INIT_1_PERST_MASK);
|
||||
pcie->pcie_cfg->perst_set(pcie, 0);
|
||||
|
||||
/*
|
||||
* Wait for 100ms after PERST# deassertion; see PCIe CEM specification
|
||||
@@ -514,14 +563,25 @@ static int brcm_pcie_remove(struct udevice *dev)
|
||||
void __iomem *base = pcie->base;
|
||||
|
||||
/* Assert fundamental reset */
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_PERST_MASK);
|
||||
setbits_le32(base + pcie->pcie_cfg->offsets[RGR1_SW_INIT_1],
|
||||
PCIE_RGR1_SW_INIT_1_PERST_MASK);
|
||||
|
||||
/* Turn off SerDes */
|
||||
setbits_le32(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG,
|
||||
setbits_le32(base + pcie->pcie_cfg->offsets[PCIE_HARD_DEBUG],
|
||||
PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
|
||||
|
||||
/* Shutdown bridge */
|
||||
setbits_le32(base + PCIE_RGR1_SW_INIT_1, PCIE_RGR1_SW_INIT_1_INIT_MASK);
|
||||
brcm_pcie_bridge_sw_init_set(pcie, 1);
|
||||
|
||||
/*
|
||||
* For the controllers that are utilizing reset for bridge Sw init,
|
||||
* such as BCM2712, reset should be deasserted after assertion.
|
||||
* Leaving it in asserted state may lead to unexpected hangs in
|
||||
* the Linux Kernel driver because it do not perform reset initialization
|
||||
* and start accessing device memory.
|
||||
*/
|
||||
if (pcie->pcie_cfg->type == BCM2712)
|
||||
brcm_pcie_bridge_sw_init_set(pcie, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -546,6 +606,7 @@ static int brcm_pcie_of_to_plat(struct udevice *dev)
|
||||
else
|
||||
pcie->gen = max_link_speed;
|
||||
|
||||
pcie->pcie_cfg = (const struct brcm_pcie_cfg_data *)dev_get_driver_data(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -554,8 +615,31 @@ static const struct dm_pci_ops brcm_pcie_ops = {
|
||||
.write_config = brcm_pcie_write_config,
|
||||
};
|
||||
|
||||
static const int pcie_offsets[] = {
|
||||
[RGR1_SW_INIT_1] = 0x9210,
|
||||
[PCIE_HARD_DEBUG] = 0x4204,
|
||||
};
|
||||
|
||||
static const struct brcm_pcie_cfg_data bcm2711_cfg = {
|
||||
.offsets = pcie_offsets,
|
||||
.type = BCM2711,
|
||||
.perst_set = brcm_pcie_perst_set_generic,
|
||||
};
|
||||
|
||||
static const int pcie_offsets_bcm2712[] = {
|
||||
[RGR1_SW_INIT_1] = 0x0,
|
||||
[PCIE_HARD_DEBUG] = 0x4304,
|
||||
};
|
||||
|
||||
static const struct brcm_pcie_cfg_data bcm2712_cfg = {
|
||||
.offsets = pcie_offsets_bcm2712,
|
||||
.type = BCM2712,
|
||||
.perst_set = brcm_pcie_perst_set_2712,
|
||||
};
|
||||
|
||||
static const struct udevice_id brcm_pcie_ids[] = {
|
||||
{ .compatible = "brcm,bcm2711-pcie" },
|
||||
{ .compatible = "brcm,bcm2711-pcie", .data = (ulong)&bcm2711_cfg },
|
||||
{ .compatible = "brcm,bcm2712-pcie", .data = (ulong)&bcm2712_cfg },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user