Add the amd,versal2-cpm6-host1 compatible to support the second CPM6 PCIe host controller, alongside the existing MDB5 and CPM6 host0.
On init, disable and clear pending interrupts. Signed-off-by: Pranav Sanwal <[email protected]> Message-ID: <1d855c8127c24e3423e62671a4a5c08a9e4a6e32.1789111144.git.pranav.san...@amd.com> --- drivers/pci/pcie_dw_amd.c | 116 ++++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 18 deletions(-) diff --git a/drivers/pci/pcie_dw_amd.c b/drivers/pci/pcie_dw_amd.c index 944458e668c..9e545d6ec7e 100644 --- a/drivers/pci/pcie_dw_amd.c +++ b/drivers/pci/pcie_dw_amd.c @@ -19,14 +19,23 @@ #include "pcie_dw_common.h" -/* - * SLCR (System Level Control Register) Interrupt Register Offsets - * These are relative to the SLCR base address from device tree - */ +/* MDB5 SLCR (System Level Control Register) interrupt register offsets */ #define AMD_DW_TLP_IR_STATUS_MISC 0x4c0 #define AMD_DW_TLP_IR_DISABLE_MISC 0x4cc -/* Interrupt bit definitions */ +/* CPM6 per-host MISC_EVENT registers, in the separate "intr" region */ +#define AMD_CPM6_MISC_EVENT_STATUS 0x514 +#define AMD_CPM6_MISC_EVENT_DISABLE 0x520 + +/* CPM6 shared aggregators in the "slcr" region, common to both hosts */ +#define AMD_CPM6_PS_MISC_IR_STATUS 0x340 +#define AMD_CPM6_PS_IR_MERGED BIT(21) +#define AMD_CPM6_MERGED_STATUS 0x648 +#define AMD_CPM6_MERGED_DISABLE 0x654 +#define AMD_CPM6_MERGED_MISC_EVENT_HOST0 14 +#define AMD_CPM6_MERGED_MISC_EVENT_HOST1 17 + +/* MDB5 TLP_IR interrupt bit definitions */ #define AMD_DW_PCIE_INTR_CMPL_TIMEOUT 15 #define AMD_DW_PCIE_INTR_PM_PME_RCVD 24 #define AMD_DW_PCIE_INTR_PME_TO_ACK_RCVD 25 @@ -45,6 +54,8 @@ BIT(AMD_DW_PCIE_INTR_FATAL) | \ AMD_DW_PCIE_INTR_INTX_MASK) +#define AMD_CPM6_PCIE_INTR_MASK BIT(22) + /* DW PCIe Debug Registers (in DBI space) */ #define AMD_DW_PCIE_PORT_DEBUG1 0x72c #define AMD_DW_PCIE_PORT_DEBUG1_LINK_UP BIT(4) @@ -58,31 +69,88 @@ #define PCIE_RESET_CONFIG_WAIT_MS 100 #define PCIE_T_PERST_WAIT_MS 1 +/** + * enum amd_dw_pcie_version - AMD DesignWare PCIe controller variant + * @AMD_DW_PCIE_MDB5: amd,versal2-mdb-host + * @AMD_DW_PCIE_CPM6_HOST0: amd,versal2-cpm6-host + * @AMD_DW_PCIE_CPM6_HOST1: amd,versal2-cpm6-host1 + */ +enum amd_dw_pcie_version { + AMD_DW_PCIE_MDB5, + AMD_DW_PCIE_CPM6_HOST0, + AMD_DW_PCIE_CPM6_HOST1, +}; + /** * struct amd_dw_pcie - AMD DesignWare PCIe controller private data * @dw: DesignWare PCIe common structure - * @slcr_base: System Level Control Register base (for interrupts) + * @slcr_base: System Level Control Register base (IR block on MDB5, MERGED aggregator on CPM6) + * @intr_base: Per-host interrupt register base (aliases @slcr_base on MDB5) + * @version: Matched compatible variant */ struct amd_dw_pcie { struct pcie_dw dw; void __iomem *slcr_base; + void __iomem *intr_base; + enum amd_dw_pcie_version version; }; -static void amd_dw_pcie_init_port(struct amd_dw_pcie *pcie) +static void amd_dw_pcie_init_port_mdb5(struct amd_dw_pcie *pcie) { u32 val; - if (!pcie->slcr_base) - return; - /* Disable all TLP interrupts */ writel(AMD_DW_PCIE_IMR_ALL_MASK, - pcie->slcr_base + AMD_DW_TLP_IR_DISABLE_MISC); + pcie->intr_base + AMD_DW_TLP_IR_DISABLE_MISC); /* Clear any pending TLP interrupts */ - val = readl(pcie->slcr_base + AMD_DW_TLP_IR_STATUS_MISC); + val = readl(pcie->intr_base + AMD_DW_TLP_IR_STATUS_MISC); val &= AMD_DW_PCIE_IMR_ALL_MASK; - writel(val, pcie->slcr_base + AMD_DW_TLP_IR_STATUS_MISC); + writel(val, pcie->intr_base + AMD_DW_TLP_IR_STATUS_MISC); +} + +static void amd_dw_pcie_init_port_cpm6(struct amd_dw_pcie *pcie) +{ + u32 host_bit; + u32 val; + + writel(AMD_CPM6_PCIE_INTR_MASK, + pcie->intr_base + AMD_CPM6_MISC_EVENT_DISABLE); + + /* Clear every pending MISC_EVENT bit, not just the ones this driver knows */ + val = readl(pcie->intr_base + AMD_CPM6_MISC_EVENT_STATUS); + writel(val, pcie->intr_base + AMD_CPM6_MISC_EVENT_STATUS); + + if (!pcie->slcr_base) + return; + + switch (pcie->version) { + case AMD_DW_PCIE_CPM6_HOST1: + host_bit = AMD_CPM6_MERGED_MISC_EVENT_HOST1; + break; + default: + host_bit = AMD_CPM6_MERGED_MISC_EVENT_HOST0; + break; + } + + /* Mask this host's bit in the shared MERGED aggregator */ + writel(BIT(host_bit), pcie->slcr_base + AMD_CPM6_MERGED_DISABLE); + + /* Clear the latched aggregate: this host's MERGED bit and PS_MISC's MERGED bit */ + writel(BIT(host_bit), pcie->slcr_base + AMD_CPM6_MERGED_STATUS); + writel(AMD_CPM6_PS_IR_MERGED, + pcie->slcr_base + AMD_CPM6_PS_MISC_IR_STATUS); +} + +static void amd_dw_pcie_init_port(struct amd_dw_pcie *pcie) +{ + if (!pcie->intr_base) + return; + + if (pcie->version == AMD_DW_PCIE_MDB5) + amd_dw_pcie_init_port_mdb5(pcie); + else + amd_dw_pcie_init_port_cpm6(pcie); } static void amd_dw_pcie_start_link(struct amd_dw_pcie *pcie) @@ -179,9 +247,20 @@ static int amd_dw_pcie_of_to_plat(struct udevice *dev) pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; } + pcie->version = (enum amd_dw_pcie_version)dev_get_driver_data(dev); + pcie->slcr_base = dev_read_addr_name_ptr(dev, "slcr"); if (!pcie->slcr_base) - dev_dbg(dev, "No 'slcr' region, interrupt features disabled\n"); + dev_dbg(dev, "No 'slcr' region available\n"); + + if (pcie->version == AMD_DW_PCIE_MDB5) { + /* MDB5 has no separate 'intr' region; it aliases 'slcr' */ + pcie->intr_base = pcie->slcr_base; + } else { + pcie->intr_base = dev_read_addr_name_ptr(dev, "intr"); + if (!pcie->intr_base) + dev_dbg(dev, "No 'intr' region, interrupt features disabled\n"); + } ret = pci_get_regions(dev, &io_region, &mem_region, &pref_region); if (ret < 0) { @@ -222,9 +301,9 @@ static int amd_dw_pcie_probe(struct udevice *dev) dev_warn(dev, "No MEM region configured!\n"); } - dev_dbg(dev, "dbi: 0x%lx | config: 0x%lx | atu: 0x%lx | slcr: 0x%lx\n", + dev_dbg(dev, "dbi: 0x%lx | config: 0x%lx | atu: 0x%lx | slcr: 0x%lx | intr: 0x%lx\n", (long)pci->dbi_base, (long)pci->cfg_base, - (long)pci->atu_base, (long)pcie->slcr_base); + (long)pci->atu_base, (long)pcie->slcr_base, (long)pcie->intr_base); return 0; } @@ -235,8 +314,9 @@ static const struct dm_pci_ops amd_dw_pcie_ops = { }; static const struct udevice_id amd_dw_pcie_ids[] = { - { .compatible = "amd,versal2-mdb-host" }, - { .compatible = "amd,versal2-cpm6-host" }, + { .compatible = "amd,versal2-mdb-host", .data = AMD_DW_PCIE_MDB5 }, + { .compatible = "amd,versal2-cpm6-host", .data = AMD_DW_PCIE_CPM6_HOST0 }, + { .compatible = "amd,versal2-cpm6-host1", .data = AMD_DW_PCIE_CPM6_HOST1 }, { } }; -- 2.43.7
