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
> >