RE: [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
"Musham, Sai Krishna" <[email protected]> Mon, 3 Aug 2026 11:28:16 +0000
| Newsgroups | org.kernel.vger.linux-pci,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <IA4PR12MB9810D1085E98AD602AABEA3DCDD52@IA4PR12MB9810.namprd12.prod.outlook.com> |
Public Hi Bjorn, > -----Original Message----- > From: Bjorn Helgaas <[email protected]> > Sent: Wednesday, July 29, 2026 3:57 AM > To: Musham, Sai Krishna <[email protected]> > Cc: [email protected]; [email protected]; [email protected]; > [email protected]; [email protected]; [email protected]; > [email protected]; [email protected]; [email protected]; > [email protected]; [email protected]; Simek, Michal > <[email protected]>; Gogada, Bharat Kumar > <[email protected]>; Havalige, Thippeswamy > <[email protected]>; Sanwal, Pranav > <[email protected]> > Subject: Re: [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to > AMD MDB PCIe driver > > Replace subject with something like this to match history: > > PCI: amd-mdb: Add CPM6 host controller support > I renamed subject to match history and will send in next patch. > On Wed, Jul 29, 2026 at 01:50:44AM +0530, Sai Krishna Musham wrote: > > Extend the AMD MDB PCIe driver to support AMD Versal2 CPM6 variants > > (amd,versal2-cpm6-host and amd,versal2-cpm6-host1). Like MDB5, CPM6 is > > based on the Synopsys DesignWare PCIe controller and reuses the existin= g > > DesignWare host support; only the interrupt architecture differs: > > - The per-controller interrupt registers (MISC_EVENT, PCIE_ERR) are in = a > > dedicated "intr" region instead of the shared SLCR > > - The aggregation layer (MERGED, PS_MISC) is shared and sticky; it > > requires an explicit W1C-clear after servicing to prevent IRQ storms > > - The completion timeout is reported via PCIE_ERR instead of MISC_EVENT > > > > Add variant-specific register layout and implement aggregator clearing > > that, after every interrupt pass, clears this host's contribution from > > the MERGED register and the corresponding bit in the PS_MISC severity > > register. > > I don't know if it's worth it, but I think this part could be split > into a preparatory patch that just reworks the MDB5 support, e.g., > moves the _IC stuff, adds the register layout pointers and mdb5_host, > sets up pcie->variant and tests it for "=3D=3D MDB5", etc. > > Some of the generic things Sashiko pointed out could also be fixed in > separate preparatory patches where they would be easier to backport to > kernels where only MDB5 support is needed. > > Then this patch would be purely CPM6-related things. > Sure, since there is no functional change. I will split this in v4: 1. MDB5 rework: move the _IC tables, add the register-layout pointers + mdb5_host, and route register access through pcie->variant. 2. Pre-existing MDB5 fixes Sashiko flagged, as standalone backportable patches. 3. CPM6-only additions. > > Signed-off-by: Sai Krishna Musham <[email protected]> > > --- > > Changes in v2: > > - Add CPM6 host controller interrupt support. > > > > v1 https://lore.kernel.org/all/20260402180006.486229-3- > [email protected]/ > > --- > > drivers/pci/controller/dwc/pcie-amd-mdb.c | 351 +++++++++++++++++++--- > > 1 file changed, 305 insertions(+), 46 deletions(-) > > > > diff --git a/drivers/pci/controller/dwc/pcie-amd-mdb.c > b/drivers/pci/controller/dwc/pcie-amd-mdb.c > > index dee295f281a3..dbf36ce9902c 100644 > > --- a/drivers/pci/controller/dwc/pcie-amd-mdb.c > > +++ b/drivers/pci/controller/dwc/pcie-amd-mdb.c > > @@ -21,6 +21,23 @@ > > #include "../../pci.h" > > #include "pcie-designware.h" > > > > +/* > > + * On CPM6 the per-controller PCIe interrupt registers (MISC_EVENT and > > + * PCIE_ERR) live in a dedicated region ("intr"), separate from the CP= M > SLCR > > + * region ("slcr") that holds the MERGED and PS severity registers the= y feed > > + * into. Each has a sticky W1C STATUS, a read-only MASK, and write-1 > > + * ENABLE/DISABLE register. > > + */ > > +#define AMD_CPM6_PCIE_ERR_STATUS 0x500 > > +#define AMD_CPM6_PCIE_ERR_MASK 0x504 > > +#define AMD_CPM6_PCIE_ERR_ENABLE 0x508 > > +#define AMD_CPM6_PCIE_ERR_DISABLE 0x50C > > + > > +#define AMD_CPM6_MISC_EVENT_STATUS 0x514 > > +#define AMD_CPM6_MISC_EVENT_MASK 0x518 > > +#define AMD_CPM6_MISC_EVENT_ENABLE 0x51C > > +#define AMD_CPM6_MISC_EVENT_DISABLE 0x520 > > + > > #define AMD_MDB_TLP_IR_STATUS_MISC 0x4C0 > > #define AMD_MDB_TLP_IR_MASK_MISC 0x4C4 > > #define AMD_MDB_TLP_IR_ENABLE_MISC 0x4C8 > > @@ -30,7 +47,22 @@ > > > > #define AMD_MDB_PCIE_INTR_INTX_ASSERT(x) BIT((x) * 2) > > > > -/* Interrupt registers definitions. */ > > +#define AMD_CPM6_MERGED_STATUS 0x648 > > + > > +/* MERGED input bits for the MISC_EVENT/PCIE_ERR sources this driver > handles. */ > > +#define AMD_CPM6_MERGED_PCIE_ERR_HOST0 13 > > +#define AMD_CPM6_MERGED_MISC_EVENT_HOST0 14 > > +#define AMD_CPM6_MERGED_PCIE_ERR_HOST1 16 > > +#define AMD_CPM6_MERGED_MISC_EVENT_HOST1 17 > > + > > +/* > > + * The PS_MISC severity register feeds the misc/OR GIC line. The MERGE= D > > + * aggregator appears as bit 21 within it. > > + */ > > +#define AMD_CPM6_PS_MISC_IR_STATUS 0x340 > > +#define AMD_CPM6_PS_IR_MERGED BIT(21) > > + > > +/* MDB5 interrupt register definitions. */ > > #define AMD_MDB_PCIE_INTR_CMPL_TIMEOUT 15 > > #define AMD_MDB_PCIE_INTR_INTX 16 > > #define AMD_MDB_PCIE_INTR_PM_PME_RCVD 24 > > @@ -39,6 +71,9 @@ > > #define AMD_MDB_PCIE_INTR_NONFATAL 27 > > #define AMD_MDB_PCIE_INTR_FATAL 28 > > > > +/* Completion timeout lives in PCIE_ERR_STATUS; give it a dedicated hw= irq. > */ > > +#define AMD_CPM6_PCIE_ERR_CMPL_RADM 20 > > + > > #define IMR(x) BIT(AMD_MDB_PCIE_INTR_ ##x) > > #define AMD_MDB_PCIE_IMR_ALL_MASK \ > > ( \ > > @@ -51,10 +86,58 @@ > > AMD_MDB_TLP_PCIE_INTX_MASK \ > > ) > > > > +/* CPM6 hwirq mapping (hwirq =3D=3D MISC_EVENT status bit). */ > > +#define AMD_CPM6_PCIE_INTR_FATAL 17 > > +#define AMD_CPM6_PCIE_INTR_NONFATAL 18 > > +#define AMD_CPM6_PCIE_INTR_MISC_CORRECTABLE 19 > > +#define AMD_CPM6_PCIE_INTR_PME_TO_ACK_RCVD 20 > > +#define AMD_CPM6_PCIE_INTR_PM_PME_RCVD 21 > > +#define AMD_CPM6_PCIE_INTR_INTX 22 > > + > > +#define AMD_CPM6_MISC_EVENT_MASK_ALL \ > > + ( \ > > + BIT(AMD_CPM6_PCIE_INTR_FATAL) | \ > > + BIT(AMD_CPM6_PCIE_INTR_NONFATAL) | \ > > + BIT(AMD_CPM6_PCIE_INTR_MISC_CORRECTABLE) |\ > > + BIT(AMD_CPM6_PCIE_INTR_PME_TO_ACK_RCVD) |\ > > + BIT(AMD_CPM6_PCIE_INTR_PM_PME_RCVD) | \ > > + BIT(AMD_CPM6_PCIE_INTR_INTX) \ > > + ) > > Line up the backslashes as in AMD_MDB_PCIE_IMR_ALL_MASK. > Backslashes lined up for AMD_CPM6_MISC_EVENT_MASK_ALL. Will be fixed in the next patch. > > +/* Sources handled in the PCIE_ERR register. */ > > +#define AMD_CPM6_PCIE_ERR_MASK_ALL > BIT(AMD_CPM6_PCIE_ERR_CMPL_RADM) > > + > > +enum amd_mdb_pcie_version { > > + MDB5, > > + CPM6, > > + CPM6_HOST1, > > +}; > > + > > +struct amd_mdb_intr_cause { > > + const char *sym; > > + const char *str; > > +}; > > + > > +struct amd_mdb_pcie_variant { > > + enum amd_mdb_pcie_version version; > > + u32 misc_status_reg; > > + u32 misc_mask_reg; > > + u32 misc_enable_reg; > > + u32 misc_disable_reg; > > + u32 misc_mask_all; > > + u32 intx_hwirq; > > + u32 intx_mask; > > +}; > > + > > /** > > * struct amd_mdb_pcie - PCIe port information > > * @pci: DesignWare PCIe controller structure > > * @slcr: MDB System Level Control and Status Register (SLCR) base > > + * @intr_base: Per-controller interrupt register base. On CPM6 this ma= ps > the > > + * "intr" region holding the MISC_EVENT/PCIE_ERR registers= ; on > MDB5 > > + * the interrupt registers live in the SLCR block, so it a= liases > > + * @slcr. > > + * @variant: Interrupt layout data for the matched platform compatible > > * @intx_domain: INTx IRQ domain pointer > > * @mdb_domain: MDB IRQ domain pointer > > * @perst_gpio: GPIO descriptor for PERST# signal handling > > @@ -63,12 +146,62 @@ > > struct amd_mdb_pcie { > > struct dw_pcie pci; > > void __iomem *slcr; > > + void __iomem *intr_base; > > + const struct amd_mdb_pcie_variant *variant; > > struct irq_domain *intx_domain; > > struct irq_domain *mdb_domain; > > struct gpio_desc *perst_gpio; > > int intx_irq; > > }; > > > > +#define _IC(x, s)[AMD_MDB_PCIE_INTR_ ## x] =3D { __stringify(x), s } > > + > > +static const struct amd_mdb_intr_cause mdb5_intr_cause[32] =3D { > > + _IC(CMPL_TIMEOUT, "Completion timeout"), > > + _IC(PM_PME_RCVD, "PM_PME message received"), > > + _IC(PME_TO_ACK_RCVD, "PME_TO_ACK message received"), > > + _IC(MISC_CORRECTABLE, "Correctable error message"), > > + _IC(NONFATAL, "Non fatal error message"), > > + _IC(FATAL, "Fatal error message"), > > +}; > > + > > +#define _IC6(x, s)[AMD_CPM6_PCIE_INTR_ ## x] =3D { __stringify(x), s } > > + > > +static const struct amd_mdb_intr_cause cpm6_intr_cause[32] =3D { > > + _IC6(PM_PME_RCVD, "PM_PME message received"), > > + _IC6(PME_TO_ACK_RCVD, "PME_TO_ACK message received"), > > + _IC6(MISC_CORRECTABLE, "Correctable error message"), > > + _IC6(NONFATAL, "Non fatal error message"), > > + _IC6(FATAL, "Fatal error message"), > > +}; > > + > > +static void amd_mdb_pcie_clear_aggregators(struct amd_mdb_pcie *pcie) > > +{ > > + u32 merged_mask; > > + > > + if (pcie->variant->version =3D=3D MDB5) > > + return; > > + > > + /* > > + * Clear this host's serviced contributions (MISC_EVENT0 and > PCIE_ERR) > > + * from MERGED. > > + */ > > + merged_mask =3D pcie->variant->version =3D=3D CPM6 ? > > + BIT(AMD_CPM6_MERGED_MISC_EVENT_HOST0) | > > + BIT(AMD_CPM6_MERGED_PCIE_ERR_HOST0) : > > + BIT(AMD_CPM6_MERGED_MISC_EVENT_HOST1) | > > + BIT(AMD_CPM6_MERGED_PCIE_ERR_HOST1); > > + > > + writel_relaxed(merged_mask, pcie->slcr + > AMD_CPM6_MERGED_STATUS); > > + > > + /* > > + * Clear MERGED in the PS_MISC severity register so the misc GIC li= ne > > + * de-asserts. > > + */ > > + writel_relaxed(AMD_CPM6_PS_IR_MERGED, > > + pcie->slcr + AMD_CPM6_PS_MISC_IR_STATUS); > > +} > > + > > static const struct dw_pcie_host_ops amd_mdb_pcie_host_ops =3D { > > }; > > > > @@ -81,14 +214,17 @@ static void amd_mdb_intx_irq_mask(struct > irq_data *data) > > u32 val; > > > > raw_spin_lock_irqsave(&port->lock, flags); > > - val =3D FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK, > > - AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq)); > > + if (pcie->variant->version =3D=3D MDB5) > > + val =3D FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK, > > + AMD_MDB_PCIE_INTR_INTX_ASSERT(data- > >hwirq)); > > + else > > + val =3D pcie->variant->intx_mask; > > > > /* > > * Writing '1' to a bit in AMD_MDB_TLP_IR_DISABLE_MISC disables > that > > * interrupt, writing '0' has no effect. > > */ > > - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); > > + writel_relaxed(val, pcie->intr_base + pcie->variant- > >misc_disable_reg); > > raw_spin_unlock_irqrestore(&port->lock, flags); > > } > > > > @@ -101,14 +237,17 @@ static void amd_mdb_intx_irq_unmask(struct > irq_data *data) > > u32 val; > > > > raw_spin_lock_irqsave(&port->lock, flags); > > - val =3D FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK, > > - AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq)); > > + if (pcie->variant->version =3D=3D MDB5) > > + val =3D FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK, > > + AMD_MDB_PCIE_INTR_INTX_ASSERT(data- > >hwirq)); > > + else > > + val =3D pcie->variant->intx_mask; > > > > /* > > * Writing '1' to a bit in AMD_MDB_TLP_IR_ENABLE_MISC enables > that > > * interrupt, writing '0' has no effect. > > */ > > - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); > > + writel_relaxed(val, pcie->intr_base + pcie->variant- > >misc_enable_reg); > > raw_spin_unlock_irqrestore(&port->lock, flags); > > } > > > > @@ -148,42 +287,34 @@ static irqreturn_t dw_pcie_rp_intx(int irq, void > *args) > > unsigned long val; > > int i, int_status; > > > > - val =3D readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); > > - int_status =3D FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val); > > + val =3D readl_relaxed(pcie->intr_base + pcie->variant->misc_status_= reg); > > > > - for (i =3D 0; i < PCI_NUM_INTX; i++) { > > - if (int_status & AMD_MDB_PCIE_INTR_INTX_ASSERT(i)) > > + if (pcie->variant->version =3D=3D MDB5) { > > + int_status =3D FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, > val); > > + for (i =3D 0; i < PCI_NUM_INTX; i++) { > > + if (int_status & > AMD_MDB_PCIE_INTR_INTX_ASSERT(i)) > > + generic_handle_domain_irq(pcie- > >intx_domain, i); > > + } > > + } else { > > + /* CPM6 exposes only aggregate INTx indication, not per-lin= e > status. */ > > Shorten or wrap into a multi-line comment that fits in 80 columns like > the rest of the file. Omit the period at end if that helps. > Thanks, I will shorten it to 80 columns. > > + if (!(val & pcie->variant->intx_mask)) > > + return IRQ_NONE; > > + for (i =3D 0; i < PCI_NUM_INTX; i++) > > generic_handle_domain_irq(pcie->intx_domain, i); > > } > > > > return IRQ_HANDLED; > > } > > > > -#define _IC(x, s)[AMD_MDB_PCIE_INTR_ ## x] =3D { __stringify(x), s } > > - > > -static const struct { > > - const char *sym; > > - const char *str; > > -} intr_cause[32] =3D { > > - _IC(CMPL_TIMEOUT, "Completion timeout"), > > - _IC(PM_PME_RCVD, "PM_PME message received"), > > - _IC(PME_TO_ACK_RCVD, "PME_TO_ACK message received"), > > - _IC(MISC_CORRECTABLE, "Correctable error message"), > > - _IC(NONFATAL, "Non fatal error message"), > > - _IC(FATAL, "Fatal error message"), > > -}; > > - > > static void amd_mdb_event_irq_mask(struct irq_data *d) > > { > > struct amd_mdb_pcie *pcie =3D irq_data_get_irq_chip_data(d); > > struct dw_pcie *pci =3D &pcie->pci; > > struct dw_pcie_rp *port =3D &pci->pp; > > unsigned long flags; > > - u32 val; > > > > raw_spin_lock_irqsave(&port->lock, flags); > > - val =3D BIT(d->hwirq); > > - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); > > + writel_relaxed(BIT(d->hwirq), pcie->intr_base + pcie->variant- > >misc_disable_reg); > > raw_spin_unlock_irqrestore(&port->lock, flags); > > } > > > > @@ -193,11 +324,9 @@ static void amd_mdb_event_irq_unmask(struct > irq_data *d) > > struct dw_pcie *pci =3D &pcie->pci; > > struct dw_pcie_rp *port =3D &pci->pp; > > unsigned long flags; > > - u32 val; > > > > raw_spin_lock_irqsave(&port->lock, flags); > > - val =3D BIT(d->hwirq); > > - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); > > + writel_relaxed(BIT(d->hwirq), pcie->intr_base + pcie->variant- > >misc_enable_reg); > > raw_spin_unlock_irqrestore(&port->lock, flags); > > } > > > > @@ -226,13 +355,39 @@ static irqreturn_t amd_mdb_pcie_event(int irq, > void *args) > > { > > struct amd_mdb_pcie *pcie =3D args; > > unsigned long val; > > + u32 ev_raw, err; > > int i; > > > > - val =3D readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); > > - val &=3D ~readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_MASK_MISC); > > + ev_raw =3D readl_relaxed(pcie->intr_base + pcie->variant- > >misc_status_reg); > > + val =3D ev_raw; > > + val &=3D ~readl_relaxed(pcie->intr_base + pcie->variant- > >misc_mask_reg); > > + > > + if (pcie->variant->version =3D=3D MDB5) { > > + for_each_set_bit(i, &val, 32) > > + generic_handle_domain_irq(pcie->mdb_domain, i); > > + writel_relaxed(val, pcie->intr_base + pcie->variant- > >misc_status_reg); > > + return IRQ_HANDLED; > > + } > > + > > + val &=3D pcie->variant->misc_mask_all; > > + > > for_each_set_bit(i, &val, 32) > > generic_handle_domain_irq(pcie->mdb_domain, i); > > - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); > > + > > + /* Clear handled + any unhandled sticky bits to avoid IRQ storms. *= / > > + writel_relaxed(ev_raw, pcie->intr_base + pcie->variant- > >misc_status_reg); > > + > > + /* On CPM6 the completion timeout is reported via the PCIE_ERR > register. */ > > Shorten, e.g., drop "the". > Thanks, shortened to "On CPM6 completion timeout is reported via PCIE_ERR.". > > + err =3D readl_relaxed(pcie->intr_base + > AMD_CPM6_PCIE_ERR_STATUS); > > + err &=3D ~readl_relaxed(pcie->intr_base + > AMD_CPM6_PCIE_ERR_MASK); > > + err &=3D AMD_CPM6_PCIE_ERR_MASK_ALL; > > + if (err) { > > + dev_warn(pcie->pci.dev, "Completion timeout\n"); > > + writel_relaxed(err, pcie->intr_base + > AMD_CPM6_PCIE_ERR_STATUS); > > + } > > + > > + /* Aggregation bits are sticky; clear them each pass or the level I= RQ > re-fires. */ > > Shorten or multi-line. > Thanks, shortened to "Sticky aggregation bits; clear each pass or the IRQ re-fires" > > + amd_mdb_pcie_clear_aggregators(pcie); > > > > return IRQ_HANDLED; > > } > > @@ -245,29 +400,67 @@ static void > amd_mdb_pcie_free_irq_domains(struct amd_mdb_pcie *pcie) > > } > > > > if (pcie->mdb_domain) { > > + const struct amd_mdb_intr_cause *intr_cause =3D > > + pcie->variant->version =3D=3D MDB5 ? > > + mdb5_intr_cause : cpm6_intr_cause; > > + int i, irq; > > + > > + for (i =3D 0; i < ARRAY_SIZE(mdb5_intr_cause); i++) { > > It looks wrong to use ARRAY_SIZE(mdb5_intr_cause) in these loops when > "intr_cause" might be cpm6_intr_cause, which may be a different size > than mdb5_intr_cause. > Thanks, I will fix both cause tables [32], and I will add static_assert(ARRAY_SIZE(mdb5_intr_cause) =3D=3D ARRAY_SIZE(cpm6_intr_cause)); so the shared loop bound is guaranteed correct. I will send in next patch. > > + if (!intr_cause[i].str) > > + continue; > > + irq =3D irq_find_mapping(pcie->mdb_domain, i); > > + if (irq) { > > + disable_irq(irq); > > + free_irq(irq, pcie); > > + irq_dispose_mapping(irq); > > + } > > + } > > + irq =3D irq_find_mapping(pcie->mdb_domain, > > + pcie->variant->intx_hwirq); > > + if (irq) { > > + disable_irq(irq); > > + free_irq(irq, pcie); > > + irq_dispose_mapping(irq); > > + } > > + > > irq_domain_remove(pcie->mdb_domain); > > pcie->mdb_domain =3D NULL; > > } > > } > > > > -static int amd_mdb_pcie_init_port(struct amd_mdb_pcie *pcie) > > +static void amd_mdb_pcie_init_port(struct amd_mdb_pcie *pcie) > > { > > - unsigned long val; > > + u32 misc_mask_all; > > + u32 val; > > + > > + misc_mask_all =3D pcie->variant->misc_mask_all; > > > > /* Disable all TLP interrupts. */ > > - writel_relaxed(AMD_MDB_PCIE_IMR_ALL_MASK, > > - pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC); > > + writel_relaxed(misc_mask_all, > > + pcie->intr_base + pcie->variant->misc_disable_reg); > > + > > + if (pcie->variant->version !=3D MDB5) > > + writel_relaxed(AMD_CPM6_PCIE_ERR_MASK_ALL, > > + pcie->intr_base + > AMD_CPM6_PCIE_ERR_DISABLE); > > > > /* Clear pending TLP interrupts. */ > > - val =3D readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); > > - val &=3D AMD_MDB_PCIE_IMR_ALL_MASK; > > - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC); > > + val =3D readl_relaxed(pcie->intr_base + pcie->variant->misc_status_= reg) > & > > + misc_mask_all; > > + writel_relaxed(val, pcie->intr_base + pcie->variant->misc_status_re= g); > > + > > + if (pcie->variant->version !=3D MDB5) { > > + val =3D readl_relaxed(pcie->intr_base + > AMD_CPM6_PCIE_ERR_STATUS) & > > + AMD_CPM6_PCIE_ERR_MASK_ALL; > > + writel_relaxed(val, pcie->intr_base + > AMD_CPM6_PCIE_ERR_STATUS); > > + } > > > > /* Enable all TLP interrupts. */ > > - writel_relaxed(AMD_MDB_PCIE_IMR_ALL_MASK, > > - pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC); > > + writel_relaxed(misc_mask_all, > > + pcie->intr_base + pcie->variant->misc_enable_reg); > > > > - return 0; > > + if (pcie->variant->version !=3D MDB5) > > + writel_relaxed(AMD_CPM6_PCIE_ERR_MASK_ALL, > > + pcie->intr_base + > AMD_CPM6_PCIE_ERR_ENABLE); > > } > > > > /** > > @@ -327,10 +520,13 @@ static int amd_mdb_pcie_init_irq_domains(struct > amd_mdb_pcie *pcie, > > static irqreturn_t amd_mdb_pcie_intr_handler(int irq, void *args) > > { > > struct amd_mdb_pcie *pcie =3D args; > > + const struct amd_mdb_intr_cause *intr_cause; > > struct device *dev; > > struct irq_data *d; > > > > dev =3D pcie->pci.dev; > > + intr_cause =3D pcie->variant->version =3D=3D MDB5 ? > > + mdb5_intr_cause : cpm6_intr_cause; > > > > /* > > * In the future, error reporting will be hooked to the AER subsyst= em. > > @@ -351,15 +547,19 @@ static int amd_mdb_setup_irq(struct > amd_mdb_pcie *pcie, > > struct dw_pcie *pci =3D &pcie->pci; > > struct dw_pcie_rp *pp =3D &pci->pp; > > struct device *dev =3D &pdev->dev; > > + const struct amd_mdb_intr_cause *intr_cause; > > int i, irq, err; > > > > + intr_cause =3D pcie->variant->version =3D=3D MDB5 ? > > + mdb5_intr_cause : cpm6_intr_cause; > > + > > amd_mdb_pcie_init_port(pcie); > > > > pp->irq =3D platform_get_irq(pdev, 0); > > if (pp->irq < 0) > > return pp->irq; > > > > - for (i =3D 0; i < ARRAY_SIZE(intr_cause); i++) { > > + for (i =3D 0; i < ARRAY_SIZE(mdb5_intr_cause); i++) { > > if (!intr_cause[i].str) > > continue; > > > > @@ -379,7 +579,7 @@ static int amd_mdb_setup_irq(struct > amd_mdb_pcie *pcie, > > } > > > > pcie->intx_irq =3D irq_create_mapping(pcie->mdb_domain, > > - AMD_MDB_PCIE_INTR_INTX); > > + pcie->variant->intx_hwirq); > > if (!pcie->intx_irq) { > > dev_err(dev, "Failed to map INTx interrupt\n"); > > return -ENXIO; > > @@ -439,6 +639,20 @@ static int amd_mdb_add_pcie_port(struct > amd_mdb_pcie *pcie, > > if (IS_ERR(pcie->slcr)) > > return PTR_ERR(pcie->slcr); > > > > + /* > > + * On MDB5 all interrupt registers live in the SLCR block, so the > > + * interrupt-register base simply aliases @slcr. CPM6 moves the > > + * MISC_EVENT/PCIE_ERR registers into a separate per-controller > region > > + * mapped by name as "intr". > > + */ > > + if (pcie->variant->version =3D=3D MDB5) { > > + pcie->intr_base =3D pcie->slcr; > > + } else { > > + pcie->intr_base =3D > devm_platform_ioremap_resource_byname(pdev, "intr"); > > + if (IS_ERR(pcie->intr_base)) > > + return PTR_ERR(pcie->intr_base); > > + } > > + > > err =3D amd_mdb_pcie_init_irq_domains(pcie, pdev); > > if (err) > > return err; > > @@ -483,6 +697,9 @@ static int amd_mdb_pcie_probe(struct > platform_device *pdev) > > > > pci =3D &pcie->pci; > > pci->dev =3D dev; > > + pcie->variant =3D of_device_get_match_data(dev); > > + if (!pcie->variant) > > + return -EINVAL; > > > > platform_set_drvdata(pdev, pcie); > > > > @@ -514,9 +731,51 @@ static void amd_mdb_pcie_shutdown(struct > platform_device *pdev) > > gpiod_set_value_cansleep(pcie->perst_gpio, 1); > > } > > > > +static const struct amd_mdb_pcie_variant cpm6_host =3D { > > + .version =3D CPM6, > > + .misc_status_reg =3D AMD_CPM6_MISC_EVENT_STATUS, > > + .misc_mask_reg =3D AMD_CPM6_MISC_EVENT_MASK, > > + .misc_enable_reg =3D AMD_CPM6_MISC_EVENT_ENABLE, > > + .misc_disable_reg =3D AMD_CPM6_MISC_EVENT_DISABLE, > > + .misc_mask_all =3D AMD_CPM6_MISC_EVENT_MASK_ALL, > > + .intx_hwirq =3D AMD_CPM6_PCIE_INTR_INTX, > > + .intx_mask =3D BIT(AMD_CPM6_PCIE_INTR_INTX), > > +}; > > + > > +static const struct amd_mdb_pcie_variant cpm6_host1 =3D { > > + .version =3D CPM6_HOST1, > > + .misc_status_reg =3D AMD_CPM6_MISC_EVENT_STATUS, > > + .misc_mask_reg =3D AMD_CPM6_MISC_EVENT_MASK, > > + .misc_enable_reg =3D AMD_CPM6_MISC_EVENT_ENABLE, > > + .misc_disable_reg =3D AMD_CPM6_MISC_EVENT_DISABLE, > > + .misc_mask_all =3D AMD_CPM6_MISC_EVENT_MASK_ALL, > > + .intx_hwirq =3D AMD_CPM6_PCIE_INTR_INTX, > > + .intx_mask =3D BIT(AMD_CPM6_PCIE_INTR_INTX), > > +}; > > + > > +static const struct amd_mdb_pcie_variant mdb5_host =3D { > > + .version =3D MDB5, > > + .misc_status_reg =3D AMD_MDB_TLP_IR_STATUS_MISC, > > + .misc_mask_reg =3D AMD_MDB_TLP_IR_MASK_MISC, > > + .misc_enable_reg =3D AMD_MDB_TLP_IR_ENABLE_MISC, > > + .misc_disable_reg =3D AMD_MDB_TLP_IR_DISABLE_MISC, > > + .misc_mask_all =3D AMD_MDB_PCIE_IMR_ALL_MASK, > > + .intx_hwirq =3D AMD_MDB_PCIE_INTR_INTX, > > + .intx_mask =3D AMD_MDB_TLP_PCIE_INTX_MASK, > > +}; > > + > > static const struct of_device_id amd_mdb_pcie_of_match[] =3D { > > { > > .compatible =3D "amd,versal2-mdb-host", > > + .data =3D &mdb5_host, > > + }, > > + { > > + .compatible =3D "amd,versal2-cpm6-host", > > + .data =3D &cpm6_host, > > + }, > > + { > > + .compatible =3D "amd,versal2-cpm6-host1", > > + .data =3D &cpm6_host1, > > }, > > {}, > > }; > > -- > > 2.44.4 > >