mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support
@ 2026-07-28 20:20 Sai Krishna Musham
  2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
  2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
  0 siblings, 2 replies; 9+ messages in thread
From: Sai Krishna Musham @ 2026-07-28 20:20 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel
  Cc: linux-pci, devicetree, linux-kernel, michal.simek,
	bharat.kumar.gogada, thippeswamy.havalige, sai.krishna.musham,
	pranav.sanwal

Add support for the AMD Versal2 CPM6 PCIe host controller to the
AMD MDB PCIe driver.

Update the device-tree bindings, and add the CPM6 specific driver register
layout and interrupt handling while preserving MDB5 behavior.

Sai Krishna Musham (2):
  dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
  pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver

 .../bindings/pci/amd,versal2-mdb-host.yaml    | 111 +++++-
 .../devicetree/bindings/pci/snps,dw-pcie.yaml |   2 +
 drivers/pci/controller/dwc/pcie-amd-mdb.c     | 351 +++++++++++++++---
 3 files changed, 407 insertions(+), 57 deletions(-)


base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
-- 
2.44.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
  2026-07-28 20:20 [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support Sai Krishna Musham
@ 2026-07-28 20:20 ` Sai Krishna Musham
  2026-07-28 22:29   ` Bjorn Helgaas
  2026-07-29  9:54   ` Krzysztof Kozlowski
  2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
  1 sibling, 2 replies; 9+ messages in thread
From: Sai Krishna Musham @ 2026-07-28 20:20 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel
  Cc: linux-pci, devicetree, linux-kernel, michal.simek,
	bharat.kumar.gogada, thippeswamy.havalige, sai.krishna.musham,
	pranav.sanwal

The AMD CPM6 PCIe controller is based on the Synopsys DesignWare PCIe IP.
Add "intr" to snps,dw-pcie.yaml vendor-specific reg-names for the
per-controller interrupt register region used by CPM6.

Update amd,versal2-mdb-host.yaml with separate register definitions:
- MDB5: 4 regions (slcr, config, dbi, atu)
- CPM6: 5 regions (slcr, config, dbi, atu, intr)

Signed-off-by: Sai Krishna Musham <sai.krishna.musham@amd.com>
---
Changes in v2:
- Update the CPM6 device tree binding and example.

v1 https://lore.kernel.org/all/20260402180006.486229-2-sai.krishna.musham@amd.com/
---
 .../bindings/pci/amd,versal2-mdb-host.yaml    | 111 ++++++++++++++++--
 .../devicetree/bindings/pci/snps,dw-pcie.yaml |   2 +
 2 files changed, 102 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
index 406c15e1dee1..d22de24b41ca 100644
--- a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
+++ b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
@@ -12,24 +12,65 @@ maintainers:
 allOf:
   - $ref: /schemas/pci/pci-host-bridge.yaml#
   - $ref: /schemas/pci/snps,dw-pcie.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: amd,versal2-mdb-host
+    then:
+      properties:
+        reg:
+          items:
+            - description: MDB System Level Control and Status Register (SLCR) Base
+            - description: configuration region
+            - description: data bus interface
+            - description: address translation unit register
+        reg-names:
+          items:
+            - const: slcr
+            - const: config
+            - const: dbi
+            - const: atu
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - amd,versal2-cpm6-host
+              - amd,versal2-cpm6-host1
+    then:
+      properties:
+        reg:
+          minItems: 4
+          items:
+            - description: MDB System Level Control and Status Register (SLCR) Base
+            - description: configuration region
+            - description: data bus interface
+            - description: address translation unit register
+            - description: CPM6 PCIe error and event interrupt registers
+        reg-names:
+          minItems: 4
+          items:
+            - const: slcr
+            - const: config
+            - const: dbi
+            - const: atu
+            - const: intr
 
 properties:
   compatible:
-    const: amd,versal2-mdb-host
+    enum:
+      - amd,versal2-mdb-host
+      - amd,versal2-cpm6-host
+      - amd,versal2-cpm6-host1
 
   reg:
-    items:
-      - description: MDB System Level Control and Status Register (SLCR) Base
-      - description: configuration region
-      - description: data bus interface
-      - description: address translation unit register
+    minItems: 4
+    maxItems: 5
 
   reg-names:
-    items:
-      - const: slcr
-      - const: config
-      - const: dbi
-      - const: atu
+    minItems: 4
+    maxItems: 5
 
   ranges:
     maxItems: 2
@@ -141,3 +182,51 @@ examples:
             };
         };
     };
+
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        pcie@fcdd0000 {
+            compatible = "amd,versal2-cpm6-host";
+            reg = <0x0 0xfcdd0000 0x0 0x1000>,
+                  <0x6 0x100000 0x0 0xff00000>,
+                  <0x6 0x0 0x0 0x100000>,
+                  <0x0 0xfc280000 0x0 0x4000>,
+                  <0x0 0xfc840000 0x0 0x1000>;
+            reg-names = "slcr", "config", "dbi", "atu", "intr";
+            ranges = <0x2000000 0x00 0xe0000000 0x00 0xe0000000 0x00 0x8000000>,
+                     <0x43000000 0x80 0x00 0x80 0x00 0x20 0x00>;
+            interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-parent = <&gic>;
+            interrupt-map-mask = <0 0 0 7>;
+            interrupt-map = <0 0 0 1 &pcie_intc_1 0>,
+                            <0 0 0 2 &pcie_intc_1 1>,
+                            <0 0 0 3 &pcie_intc_1 2>,
+                            <0 0 0 4 &pcie_intc_1 3>;
+            msi-map = <0x0 &gic_its 0x00 0x10000>;
+            #address-cells = <3>;
+            #size-cells = <2>;
+            #interrupt-cells = <1>;
+            device_type = "pci";
+
+            pcie@0,0 {
+                device_type = "pci";
+                reg = <0x0 0x0 0x0 0x0 0x0>;
+                reset-gpios = <&gpio1 40 GPIO_ACTIVE_LOW>;
+                #address-cells = <3>;
+                #size-cells = <2>;
+                ranges;
+            };
+
+            pcie_intc_1: interrupt-controller {
+                #address-cells = <0>;
+                #interrupt-cells = <1>;
+                interrupt-controller;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
index b3216141881c..21f86609ddb6 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
@@ -117,6 +117,8 @@ properties:
               enum: [ ecam ]
             - description: AMD MDB PCIe SLCR region
               const: slcr
+            - description: AMD CPM6 PCIe error and event interrupt registers
+              const: intr
     allOf:
       - contains:
           enum: [ dbi, ctrl ]
-- 
2.44.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
  2026-07-28 20:20 [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support Sai Krishna Musham
  2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
@ 2026-07-28 20:20 ` Sai Krishna Musham
  2026-07-28 22:27   ` Bjorn Helgaas
  1 sibling, 1 reply; 9+ messages in thread
From: Sai Krishna Musham @ 2026-07-28 20:20 UTC (permalink / raw)
  To: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel
  Cc: linux-pci, devicetree, linux-kernel, michal.simek,
	bharat.kumar.gogada, thippeswamy.havalige, sai.krishna.musham,
	pranav.sanwal

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

Signed-off-by: Sai Krishna Musham <sai.krishna.musham@amd.com>
---
Changes in v2:
- Add CPM6 host controller interrupt support.

v1 https://lore.kernel.org/all/20260402180006.486229-3-sai.krishna.musham@amd.com/
---
 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 CPM SLCR
+ * region ("slcr") that holds the MERGED and PS severity registers they 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 MERGED
+ * 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 hwirq. */
+#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 == 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)			\
+	)
+
+/* 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 maps the
+ *             "intr" region holding the MISC_EVENT/PCIE_ERR registers; on MDB5
+ *             the interrupt registers live in the SLCR block, so it aliases
+ *             @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] = { __stringify(x), s }
+
+static const struct amd_mdb_intr_cause mdb5_intr_cause[32] = {
+	_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] = { __stringify(x), s }
+
+static const struct amd_mdb_intr_cause cpm6_intr_cause[32] = {
+	_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 == MDB5)
+		return;
+
+	/*
+	 * Clear this host's serviced contributions (MISC_EVENT0 and PCIE_ERR)
+	 * from MERGED.
+	 */
+	merged_mask = pcie->variant->version == 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 line
+	 * 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 = {
 };
 
@@ -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 = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
-			 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+	if (pcie->variant->version == MDB5)
+		val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
+				 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+	else
+		val = 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 = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
-			 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+	if (pcie->variant->version == MDB5)
+		val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
+				 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+	else
+		val = 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 = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
-	int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);
+	val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
 
-	for (i = 0; i < PCI_NUM_INTX; i++) {
-		if (int_status & AMD_MDB_PCIE_INTR_INTX_ASSERT(i))
+	if (pcie->variant->version == MDB5) {
+		int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);
+		for (i = 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-line status. */
+		if (!(val & pcie->variant->intx_mask))
+			return IRQ_NONE;
+		for (i = 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] = { __stringify(x), s }
-
-static const struct {
-	const char	*sym;
-	const char	*str;
-} intr_cause[32] = {
-	_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 = irq_data_get_irq_chip_data(d);
 	struct dw_pcie *pci = &pcie->pci;
 	struct dw_pcie_rp *port = &pci->pp;
 	unsigned long flags;
-	u32 val;
 
 	raw_spin_lock_irqsave(&port->lock, flags);
-	val = 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 = &pcie->pci;
 	struct dw_pcie_rp *port = &pci->pp;
 	unsigned long flags;
-	u32 val;
 
 	raw_spin_lock_irqsave(&port->lock, flags);
-	val = 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 = args;
 	unsigned long val;
+	u32 ev_raw, err;
 	int i;
 
-	val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
-	val &= ~readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_MASK_MISC);
+	ev_raw = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
+	val = ev_raw;
+	val &= ~readl_relaxed(pcie->intr_base + pcie->variant->misc_mask_reg);
+
+	if (pcie->variant->version == 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 &= 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. */
+	err = readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS);
+	err &= ~readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_MASK);
+	err &= 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 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 =
+			pcie->variant->version == MDB5 ?
+			mdb5_intr_cause : cpm6_intr_cause;
+		int i, irq;
+
+		for (i = 0; i < ARRAY_SIZE(mdb5_intr_cause); i++) {
+			if (!intr_cause[i].str)
+				continue;
+			irq = irq_find_mapping(pcie->mdb_domain, i);
+			if (irq) {
+				disable_irq(irq);
+				free_irq(irq, pcie);
+				irq_dispose_mapping(irq);
+			}
+		}
+		irq = 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 = 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 = 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 != MDB5)
+		writel_relaxed(AMD_CPM6_PCIE_ERR_MASK_ALL,
+			       pcie->intr_base + AMD_CPM6_PCIE_ERR_DISABLE);
 
 	/* Clear pending TLP interrupts. */
-	val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
-	val &= AMD_MDB_PCIE_IMR_ALL_MASK;
-	writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
+	val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg) &
+	      misc_mask_all;
+	writel_relaxed(val, pcie->intr_base + pcie->variant->misc_status_reg);
+
+	if (pcie->variant->version != MDB5) {
+		val = 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 != 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 = args;
+	const struct amd_mdb_intr_cause *intr_cause;
 	struct device *dev;
 	struct irq_data *d;
 
 	dev = pcie->pci.dev;
+	intr_cause = pcie->variant->version == MDB5 ?
+		     mdb5_intr_cause : cpm6_intr_cause;
 
 	/*
 	 * In the future, error reporting will be hooked to the AER subsystem.
@@ -351,15 +547,19 @@ static int amd_mdb_setup_irq(struct amd_mdb_pcie *pcie,
 	struct dw_pcie *pci = &pcie->pci;
 	struct dw_pcie_rp *pp = &pci->pp;
 	struct device *dev = &pdev->dev;
+	const struct amd_mdb_intr_cause *intr_cause;
 	int i, irq, err;
 
+	intr_cause = pcie->variant->version == MDB5 ?
+		     mdb5_intr_cause : cpm6_intr_cause;
+
 	amd_mdb_pcie_init_port(pcie);
 
 	pp->irq = platform_get_irq(pdev, 0);
 	if (pp->irq < 0)
 		return pp->irq;
 
-	for (i = 0; i < ARRAY_SIZE(intr_cause); i++) {
+	for (i = 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 = 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 == MDB5) {
+		pcie->intr_base = pcie->slcr;
+	} else {
+		pcie->intr_base = devm_platform_ioremap_resource_byname(pdev, "intr");
+		if (IS_ERR(pcie->intr_base))
+			return PTR_ERR(pcie->intr_base);
+	}
+
 	err = 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 = &pcie->pci;
 	pci->dev = dev;
+	pcie->variant = 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 = {
+	.version = CPM6,
+	.misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
+	.misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
+	.misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
+	.misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
+	.misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
+	.intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
+	.intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
+};
+
+static const struct amd_mdb_pcie_variant cpm6_host1 = {
+	.version = CPM6_HOST1,
+	.misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
+	.misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
+	.misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
+	.misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
+	.misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
+	.intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
+	.intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
+};
+
+static const struct amd_mdb_pcie_variant mdb5_host = {
+	.version = MDB5,
+	.misc_status_reg = AMD_MDB_TLP_IR_STATUS_MISC,
+	.misc_mask_reg = AMD_MDB_TLP_IR_MASK_MISC,
+	.misc_enable_reg = AMD_MDB_TLP_IR_ENABLE_MISC,
+	.misc_disable_reg = AMD_MDB_TLP_IR_DISABLE_MISC,
+	.misc_mask_all = AMD_MDB_PCIE_IMR_ALL_MASK,
+	.intx_hwirq = AMD_MDB_PCIE_INTR_INTX,
+	.intx_mask = AMD_MDB_TLP_PCIE_INTX_MASK,
+};
+
 static const struct of_device_id amd_mdb_pcie_of_match[] = {
 	{
 		.compatible = "amd,versal2-mdb-host",
+		.data = &mdb5_host,
+	},
+	{
+		.compatible = "amd,versal2-cpm6-host",
+		.data = &cpm6_host,
+	},
+	{
+		.compatible = "amd,versal2-cpm6-host1",
+		.data = &cpm6_host1,
 	},
 	{},
 };
-- 
2.44.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
  2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
@ 2026-07-28 22:27   ` Bjorn Helgaas
  2026-08-03 11:28     ` Musham, Sai Krishna
  0 siblings, 1 reply; 9+ messages in thread
From: Bjorn Helgaas @ 2026-07-28 22:27 UTC (permalink / raw)
  To: Sai Krishna Musham
  Cc: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel,
	linux-pci, devicetree, linux-kernel, michal.simek,
	bharat.kumar.gogada, thippeswamy.havalige, pranav.sanwal

Replace subject with something like this to match history:

  PCI: amd-mdb: Add CPM6 host controller support

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 existing
> 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 "== 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.

> Signed-off-by: Sai Krishna Musham <sai.krishna.musham@amd.com>
> ---
> Changes in v2:
> - Add CPM6 host controller interrupt support.
> 
> v1 https://lore.kernel.org/all/20260402180006.486229-3-sai.krishna.musham@amd.com/
> ---
>  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 CPM SLCR
> + * region ("slcr") that holds the MERGED and PS severity registers they 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 MERGED
> + * 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 hwirq. */
> +#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 == 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.

> +/* 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 maps the
> + *             "intr" region holding the MISC_EVENT/PCIE_ERR registers; on MDB5
> + *             the interrupt registers live in the SLCR block, so it aliases
> + *             @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] = { __stringify(x), s }
> +
> +static const struct amd_mdb_intr_cause mdb5_intr_cause[32] = {
> +	_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] = { __stringify(x), s }
> +
> +static const struct amd_mdb_intr_cause cpm6_intr_cause[32] = {
> +	_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 == MDB5)
> +		return;
> +
> +	/*
> +	 * Clear this host's serviced contributions (MISC_EVENT0 and PCIE_ERR)
> +	 * from MERGED.
> +	 */
> +	merged_mask = pcie->variant->version == 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 line
> +	 * 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 = {
>  };
>  
> @@ -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 = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> -			 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
> +	if (pcie->variant->version == MDB5)
> +		val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> +				 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
> +	else
> +		val = 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 = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> -			 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
> +	if (pcie->variant->version == MDB5)
> +		val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> +				 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
> +	else
> +		val = 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 = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> -	int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);
> +	val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
>  
> -	for (i = 0; i < PCI_NUM_INTX; i++) {
> -		if (int_status & AMD_MDB_PCIE_INTR_INTX_ASSERT(i))
> +	if (pcie->variant->version == MDB5) {
> +		int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);
> +		for (i = 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-line 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.

> +		if (!(val & pcie->variant->intx_mask))
> +			return IRQ_NONE;
> +		for (i = 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] = { __stringify(x), s }
> -
> -static const struct {
> -	const char	*sym;
> -	const char	*str;
> -} intr_cause[32] = {
> -	_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 = irq_data_get_irq_chip_data(d);
>  	struct dw_pcie *pci = &pcie->pci;
>  	struct dw_pcie_rp *port = &pci->pp;
>  	unsigned long flags;
> -	u32 val;
>  
>  	raw_spin_lock_irqsave(&port->lock, flags);
> -	val = 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 = &pcie->pci;
>  	struct dw_pcie_rp *port = &pci->pp;
>  	unsigned long flags;
> -	u32 val;
>  
>  	raw_spin_lock_irqsave(&port->lock, flags);
> -	val = 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 = args;
>  	unsigned long val;
> +	u32 ev_raw, err;
>  	int i;
>  
> -	val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> -	val &= ~readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_MASK_MISC);
> +	ev_raw = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
> +	val = ev_raw;
> +	val &= ~readl_relaxed(pcie->intr_base + pcie->variant->misc_mask_reg);
> +
> +	if (pcie->variant->version == 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 &= 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".

> +	err = readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS);
> +	err &= ~readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_MASK);
> +	err &= 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 IRQ re-fires. */

Shorten or multi-line.

> +	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 =
> +			pcie->variant->version == MDB5 ?
> +			mdb5_intr_cause : cpm6_intr_cause;
> +		int i, irq;
> +
> +		for (i = 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.

> +			if (!intr_cause[i].str)
> +				continue;
> +			irq = irq_find_mapping(pcie->mdb_domain, i);
> +			if (irq) {
> +				disable_irq(irq);
> +				free_irq(irq, pcie);
> +				irq_dispose_mapping(irq);
> +			}
> +		}
> +		irq = 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 = 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 = 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 != MDB5)
> +		writel_relaxed(AMD_CPM6_PCIE_ERR_MASK_ALL,
> +			       pcie->intr_base + AMD_CPM6_PCIE_ERR_DISABLE);
>  
>  	/* Clear pending TLP interrupts. */
> -	val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> -	val &= AMD_MDB_PCIE_IMR_ALL_MASK;
> -	writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> +	val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg) &
> +	      misc_mask_all;
> +	writel_relaxed(val, pcie->intr_base + pcie->variant->misc_status_reg);
> +
> +	if (pcie->variant->version != MDB5) {
> +		val = 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 != 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 = args;
> +	const struct amd_mdb_intr_cause *intr_cause;
>  	struct device *dev;
>  	struct irq_data *d;
>  
>  	dev = pcie->pci.dev;
> +	intr_cause = pcie->variant->version == MDB5 ?
> +		     mdb5_intr_cause : cpm6_intr_cause;
>  
>  	/*
>  	 * In the future, error reporting will be hooked to the AER subsystem.
> @@ -351,15 +547,19 @@ static int amd_mdb_setup_irq(struct amd_mdb_pcie *pcie,
>  	struct dw_pcie *pci = &pcie->pci;
>  	struct dw_pcie_rp *pp = &pci->pp;
>  	struct device *dev = &pdev->dev;
> +	const struct amd_mdb_intr_cause *intr_cause;
>  	int i, irq, err;
>  
> +	intr_cause = pcie->variant->version == MDB5 ?
> +		     mdb5_intr_cause : cpm6_intr_cause;
> +
>  	amd_mdb_pcie_init_port(pcie);
>  
>  	pp->irq = platform_get_irq(pdev, 0);
>  	if (pp->irq < 0)
>  		return pp->irq;
>  
> -	for (i = 0; i < ARRAY_SIZE(intr_cause); i++) {
> +	for (i = 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 = 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 == MDB5) {
> +		pcie->intr_base = pcie->slcr;
> +	} else {
> +		pcie->intr_base = devm_platform_ioremap_resource_byname(pdev, "intr");
> +		if (IS_ERR(pcie->intr_base))
> +			return PTR_ERR(pcie->intr_base);
> +	}
> +
>  	err = 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 = &pcie->pci;
>  	pci->dev = dev;
> +	pcie->variant = 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 = {
> +	.version = CPM6,
> +	.misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
> +	.misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
> +	.misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
> +	.misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
> +	.misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
> +	.intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
> +	.intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
> +};
> +
> +static const struct amd_mdb_pcie_variant cpm6_host1 = {
> +	.version = CPM6_HOST1,
> +	.misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
> +	.misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
> +	.misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
> +	.misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
> +	.misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
> +	.intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
> +	.intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
> +};
> +
> +static const struct amd_mdb_pcie_variant mdb5_host = {
> +	.version = MDB5,
> +	.misc_status_reg = AMD_MDB_TLP_IR_STATUS_MISC,
> +	.misc_mask_reg = AMD_MDB_TLP_IR_MASK_MISC,
> +	.misc_enable_reg = AMD_MDB_TLP_IR_ENABLE_MISC,
> +	.misc_disable_reg = AMD_MDB_TLP_IR_DISABLE_MISC,
> +	.misc_mask_all = AMD_MDB_PCIE_IMR_ALL_MASK,
> +	.intx_hwirq = AMD_MDB_PCIE_INTR_INTX,
> +	.intx_mask = AMD_MDB_TLP_PCIE_INTX_MASK,
> +};
> +
>  static const struct of_device_id amd_mdb_pcie_of_match[] = {
>  	{
>  		.compatible = "amd,versal2-mdb-host",
> +		.data = &mdb5_host,
> +	},
> +	{
> +		.compatible = "amd,versal2-cpm6-host",
> +		.data = &cpm6_host,
> +	},
> +	{
> +		.compatible = "amd,versal2-cpm6-host1",
> +		.data = &cpm6_host1,
>  	},
>  	{},
>  };
> -- 
> 2.44.4
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
  2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
@ 2026-07-28 22:29   ` Bjorn Helgaas
  2026-07-29  9:29     ` Musham, Sai Krishna
  2026-07-29  9:54   ` Krzysztof Kozlowski
  1 sibling, 1 reply; 9+ messages in thread
From: Bjorn Helgaas @ 2026-07-28 22:29 UTC (permalink / raw)
  To: Sai Krishna Musham
  Cc: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel,
	linux-pci, devicetree, linux-kernel, michal.simek,
	bharat.kumar.gogada, thippeswamy.havalige, pranav.sanwal

Replace subject:

  dt-bindings: PCI: amd-mdb: Add CPM6 support

to match history.  The prefix already tells us the "AMD MDB" part and
the "binding" part, so no need to repeat them.

On Wed, Jul 29, 2026 at 01:50:43AM +0530, Sai Krishna Musham wrote:
> The AMD CPM6 PCIe controller is based on the Synopsys DesignWare PCIe IP.
> Add "intr" to snps,dw-pcie.yaml vendor-specific reg-names for the
> per-controller interrupt register region used by CPM6.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
  2026-07-28 22:29   ` Bjorn Helgaas
@ 2026-07-29  9:29     ` Musham, Sai Krishna
  0 siblings, 0 replies; 9+ messages in thread
From: Musham, Sai Krishna @ 2026-07-29  9:29 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel,
	linux-pci, devicetree, linux-kernel, Simek, Michal, Gogada,
	Bharat Kumar, Havalige, Thippeswamy, Sanwal, Pranav

AMD General

Hi Bjorn,

> -----Original Message-----
> From: Bjorn Helgaas <helgaas@kernel.org>
> Sent: Wednesday, July 29, 2026 4:00 AM
> To: Musham, Sai Krishna <sai.krishna.musham@amd.com>
> Cc: bhelgaas@google.com; lpieralisi@kernel.org; kw@linux.com;
> mani@kernel.org; robh@kernel.org; krzk+dt@kernel.org;
> conor+dt@kernel.org; cassel@kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Simek, Michal
> <michal.simek@amd.com>; Gogada, Bharat Kumar
> <bharat.kumar.gogada@amd.com>; Havalige, Thippeswamy
> <thippeswamy.havalige@amd.com>; Sanwal, Pranav
> <Pranav.sanwal@amd.com>
> Subject: Re: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB
> PCIe binding
>
> Replace subject:
>
>   dt-bindings: PCI: amd-mdb: Add CPM6 support
>
> to match history.  The prefix already tells us the "AMD MDB" part and
> the "binding" part, so no need to repeat them.
>

Thanks for the review, sure I will update this in the next patch.

> On Wed, Jul 29, 2026 at 01:50:43AM +0530, Sai Krishna Musham wrote:
> > The AMD CPM6 PCIe controller is based on the Synopsys DesignWare PCIe
> IP.
> > Add "intr" to snps,dw-pcie.yaml vendor-specific reg-names for the
> > per-controller interrupt register region used by CPM6.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
  2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
  2026-07-28 22:29   ` Bjorn Helgaas
@ 2026-07-29  9:54   ` Krzysztof Kozlowski
  2026-07-29 15:49     ` Musham, Sai Krishna
  1 sibling, 1 reply; 9+ messages in thread
From: Krzysztof Kozlowski @ 2026-07-29  9:54 UTC (permalink / raw)
  To: Sai Krishna Musham, bhelgaas, lpieralisi, kw, mani, robh,
	krzk+dt, conor+dt, cassel
  Cc: linux-pci, devicetree, linux-kernel, michal.simek,
	bharat.kumar.gogada, thippeswamy.havalige, pranav.sanwal

On 28/07/2026 22:20, Sai Krishna Musham wrote:
> The AMD CPM6 PCIe controller is based on the Synopsys DesignWare PCIe IP.
> Add "intr" to snps,dw-pcie.yaml vendor-specific reg-names for the
> per-controller interrupt register region used by CPM6.
> 
> Update amd,versal2-mdb-host.yaml with separate register definitions:
> - MDB5: 4 regions (slcr, config, dbi, atu)
> - CPM6: 5 regions (slcr, config, dbi, atu, intr)
> 
> Signed-off-by: Sai Krishna Musham <sai.krishna.musham@amd.com>
> ---
> Changes in v2:
> - Update the CPM6 device tree binding and example.
> 
> v1 https://lore.kernel.org/all/20260402180006.486229-2-sai.krishna.musham@amd.com/
> ---
>  .../bindings/pci/amd,versal2-mdb-host.yaml    | 111 ++++++++++++++++--
>  .../devicetree/bindings/pci/snps,dw-pcie.yaml |   2 +
>  2 files changed, 102 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
> index 406c15e1dee1..d22de24b41ca 100644
> --- a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
> +++ b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
> @@ -12,24 +12,65 @@ maintainers:
>  allOf:
>    - $ref: /schemas/pci/pci-host-bridge.yaml#
>    - $ref: /schemas/pci/snps,dw-pcie.yaml#
> +  - if:

Move entire allOf to the end, after required: block.

> +      properties:
> +        compatible:
> +          contains:
> +            const: amd,versal2-mdb-host
> +    then:
> +      properties:
> +        reg:
> +          items:
> +            - description: MDB System Level Control and Status Register (SLCR) Base
> +            - description: configuration region
> +            - description: data bus interface
> +            - description: address translation unit register
> +        reg-names:
> +          items:
> +            - const: slcr
> +            - const: config
> +            - const: dbi
> +            - const: atu
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - amd,versal2-cpm6-host
> +              - amd,versal2-cpm6-host1
> +    then:
> +      properties:
> +        reg:
> +          minItems: 4
> +          items:
> +            - description: MDB System Level Control and Status Register (SLCR) Base
> +            - description: configuration region
> +            - description: data bus interface
> +            - description: address translation unit register
> +            - description: CPM6 PCIe error and event interrupt registers
> +        reg-names:
> +          minItems: 4
> +          items:
> +            - const: slcr
> +            - const: config
> +            - const: dbi
> +            - const: atu
> +            - const: intr
>  
>  properties:
>    compatible:
> -    const: amd,versal2-mdb-host
> +    enum:
> +      - amd,versal2-mdb-host
> +      - amd,versal2-cpm6-host
> +      - amd,versal2-cpm6-host1
>  
>    reg:
> -    items:
> -      - description: MDB System Level Control and Status Register (SLCR) Base
> -      - description: configuration region
> -      - description: data bus interface
> -      - description: address translation unit register
> +    minItems: 4
> +    maxItems: 5
>  
>    reg-names:
> -    items:
> -      - const: slcr
> -      - const: config
> -      - const: dbi
> -      - const: atu

Leave the list and extend it.

> +    minItems: 4

You need only this.

> +    maxItems: 5
>  
>    ranges:
>      maxItems: 2
> @@ -141,3 +182,51 @@ examples:
>              };
>          };
>      };
> +
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/gpio/gpio.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +        pcie@fcdd0000 {
> +            compatible = "amd,versal2-cpm6-hos

You do not need new example for one new property.

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
  2026-07-29  9:54   ` Krzysztof Kozlowski
@ 2026-07-29 15:49     ` Musham, Sai Krishna
  0 siblings, 0 replies; 9+ messages in thread
From: Musham, Sai Krishna @ 2026-07-29 15:49 UTC (permalink / raw)
  To: Krzysztof Kozlowski, bhelgaas, lpieralisi, kw, mani, robh,
	krzk+dt, conor+dt, cassel
  Cc: linux-pci, devicetree, linux-kernel, Simek, Michal, Gogada,
	Bharat Kumar, Havalige, Thippeswamy, Sanwal, Pranav

Public

Hi Krzysztof,

> -----Original Message-----
> From: Krzysztof Kozlowski <krzk@kernel.org>
> Sent: Wednesday, July 29, 2026 3:24 PM
> To: Musham, Sai Krishna <sai.krishna.musham@amd.com>;
> bhelgaas@google.com; lpieralisi@kernel.org; kw@linux.com;
> mani@kernel.org; robh@kernel.org; krzk+dt@kernel.org;
> conor+dt@kernel.org; cassel@kernel.org
> Cc: linux-pci@vger.kernel.org; devicetree@vger.kernel.org; linux-
> kernel@vger.kernel.org; Simek, Michal <michal.simek@amd.com>; Gogada,
> Bharat Kumar <bharat.kumar.gogada@amd.com>; Havalige, Thippeswamy
> <thippeswamy.havalige@amd.com>; Sanwal, Pranav
> <Pranav.sanwal@amd.com>
> Subject: Re: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB
> PCIe binding
>
> On 28/07/2026 22:20, Sai Krishna Musham wrote:
> > The AMD CPM6 PCIe controller is based on the Synopsys DesignWare PCIe
> IP.
> > Add "intr" to snps,dw-pcie.yaml vendor-specific reg-names for the
> > per-controller interrupt register region used by CPM6.
> >
> > Update amd,versal2-mdb-host.yaml with separate register definitions:
> > - MDB5: 4 regions (slcr, config, dbi, atu)
> > - CPM6: 5 regions (slcr, config, dbi, atu, intr)
> >
> > Signed-off-by: Sai Krishna Musham <sai.krishna.musham@amd.com>
> > ---
> > Changes in v2:
> > - Update the CPM6 device tree binding and example.
> >
> > v1 https://lore.kernel.org/all/20260402180006.486229-2-
> sai.krishna.musham@amd.com/
> > ---
> >  .../bindings/pci/amd,versal2-mdb-host.yaml    | 111 ++++++++++++++++--
> >  .../devicetree/bindings/pci/snps,dw-pcie.yaml |   2 +
> >  2 files changed, 102 insertions(+), 11 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-
> host.yaml b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-
> host.yaml
> > index 406c15e1dee1..d22de24b41ca 100644
> > --- a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
> > +++ b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
> > @@ -12,24 +12,65 @@ maintainers:
> >  allOf:
> >    - $ref: /schemas/pci/pci-host-bridge.yaml#
> >    - $ref: /schemas/pci/snps,dw-pcie.yaml#
> > +  - if:
>
> Move entire allOf to the end, after required: block.

Thanks for the review, I will move entire allOf block after required.

>
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            const: amd,versal2-mdb-host
> > +    then:
> > +      properties:
> > +        reg:
> > +          items:
> > +            - description: MDB System Level Control and Status Register (SLCR)
> Base
> > +            - description: configuration region
> > +            - description: data bus interface
> > +            - description: address translation unit register
> > +        reg-names:
> > +          items:
> > +            - const: slcr
> > +            - const: config
> > +            - const: dbi
> > +            - const: atu
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            enum:
> > +              - amd,versal2-cpm6-host
> > +              - amd,versal2-cpm6-host1
> > +    then:
> > +      properties:
> > +        reg:
> > +          minItems: 4
> > +          items:
> > +            - description: MDB System Level Control and Status Register (SLCR)
> Base
> > +            - description: configuration region
> > +            - description: data bus interface
> > +            - description: address translation unit register
> > +            - description: CPM6 PCIe error and event interrupt registers
> > +        reg-names:
> > +          minItems: 4
> > +          items:
> > +            - const: slcr
> > +            - const: config
> > +            - const: dbi
> > +            - const: atu
> > +            - const: intr
> >
> >  properties:
> >    compatible:
> > -    const: amd,versal2-mdb-host
> > +    enum:
> > +      - amd,versal2-mdb-host
> > +      - amd,versal2-cpm6-host
> > +      - amd,versal2-cpm6-host1
> >
> >    reg:
> > -    items:
> > -      - description: MDB System Level Control and Status Register (SLCR) Base
> > -      - description: configuration region
> > -      - description: data bus interface
> > -      - description: address translation unit register
> > +    minItems: 4
> > +    maxItems: 5
> >
> >    reg-names:
> > -    items:
> > -      - const: slcr
> > -      - const: config
> > -      - const: dbi
> > -      - const: atu
>
> Leave the list and extend it.

Thanks, I will extend the reg and reg-names.

>
> > +    minItems: 4
>
> You need only this.
>
> > +    maxItems: 5
> >
> >    ranges:
> >      maxItems: 2
> > @@ -141,3 +182,51 @@ examples:
> >              };
> >          };
> >      };
> > +
> > +  - |
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +    #include <dt-bindings/interrupt-controller/irq.h>
> > +    #include <dt-bindings/gpio/gpio.h>
> > +
> > +    soc {
> > +        #address-cells = <2>;
> > +        #size-cells = <2>;
> > +        pcie@fcdd0000 {
> > +            compatible = "amd,versal2-cpm6-hos
>
> You do not need new example for one new property.

Sure, I will remove this new example.

>
> Best regards,
> Krzysztof

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
  2026-07-28 22:27   ` Bjorn Helgaas
@ 2026-08-03 11:28     ` Musham, Sai Krishna
  0 siblings, 0 replies; 9+ messages in thread
From: Musham, Sai Krishna @ 2026-08-03 11:28 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel,
	linux-pci, devicetree, linux-kernel, Simek, Michal, Gogada,
	Bharat Kumar, Havalige, Thippeswamy, Sanwal, Pranav

Public

Hi Bjorn,

> -----Original Message-----
> From: Bjorn Helgaas <helgaas@kernel.org>
> Sent: Wednesday, July 29, 2026 3:57 AM
> To: Musham, Sai Krishna <sai.krishna.musham@amd.com>
> Cc: bhelgaas@google.com; lpieralisi@kernel.org; kw@linux.com;
> mani@kernel.org; robh@kernel.org; krzk+dt@kernel.org;
> conor+dt@kernel.org; cassel@kernel.org; linux-pci@vger.kernel.org;
> devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Simek, Michal
> <michal.simek@amd.com>; Gogada, Bharat Kumar
> <bharat.kumar.gogada@amd.com>; Havalige, Thippeswamy
> <thippeswamy.havalige@amd.com>; Sanwal, Pranav
> <Pranav.sanwal@amd.com>
> 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 existing
> > 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 "== 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 <sai.krishna.musham@amd.com>
> > ---
> > Changes in v2:
> > - Add CPM6 host controller interrupt support.
> >
> > v1 https://lore.kernel.org/all/20260402180006.486229-3-
> sai.krishna.musham@amd.com/
> > ---
> >  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 CPM
> SLCR
> > + * region ("slcr") that holds the MERGED and PS severity registers they 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 MERGED
> > + * 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 hwirq.
> */
> > +#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 == 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 maps
> the
> > + *             "intr" region holding the MISC_EVENT/PCIE_ERR registers; on
> MDB5
> > + *             the interrupt registers live in the SLCR block, so it aliases
> > + *             @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] = { __stringify(x), s }
> > +
> > +static const struct amd_mdb_intr_cause mdb5_intr_cause[32] = {
> > +   _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] = { __stringify(x), s }
> > +
> > +static const struct amd_mdb_intr_cause cpm6_intr_cause[32] = {
> > +   _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 == MDB5)
> > +           return;
> > +
> > +   /*
> > +    * Clear this host's serviced contributions (MISC_EVENT0 and
> PCIE_ERR)
> > +    * from MERGED.
> > +    */
> > +   merged_mask = pcie->variant->version == 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 line
> > +    * 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 = {
> >  };
> >
> > @@ -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 = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> > -                    AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
> > +   if (pcie->variant->version == MDB5)
> > +           val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> > +                            AMD_MDB_PCIE_INTR_INTX_ASSERT(data-
> >hwirq));
> > +   else
> > +           val = 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 = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> > -                    AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
> > +   if (pcie->variant->version == MDB5)
> > +           val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> > +                            AMD_MDB_PCIE_INTR_INTX_ASSERT(data-
> >hwirq));
> > +   else
> > +           val = 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 = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> > -   int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);
> > +   val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
> >
> > -   for (i = 0; i < PCI_NUM_INTX; i++) {
> > -           if (int_status & AMD_MDB_PCIE_INTR_INTX_ASSERT(i))
> > +   if (pcie->variant->version == MDB5) {
> > +           int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK,
> val);
> > +           for (i = 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-line
> 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 = 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] = { __stringify(x), s }
> > -
> > -static const struct {
> > -   const char      *sym;
> > -   const char      *str;
> > -} intr_cause[32] = {
> > -   _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 = irq_data_get_irq_chip_data(d);
> >     struct dw_pcie *pci = &pcie->pci;
> >     struct dw_pcie_rp *port = &pci->pp;
> >     unsigned long flags;
> > -   u32 val;
> >
> >     raw_spin_lock_irqsave(&port->lock, flags);
> > -   val = 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 = &pcie->pci;
> >     struct dw_pcie_rp *port = &pci->pp;
> >     unsigned long flags;
> > -   u32 val;
> >
> >     raw_spin_lock_irqsave(&port->lock, flags);
> > -   val = 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 = args;
> >     unsigned long val;
> > +   u32 ev_raw, err;
> >     int i;
> >
> > -   val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> > -   val &= ~readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_MASK_MISC);
> > +   ev_raw = readl_relaxed(pcie->intr_base + pcie->variant-
> >misc_status_reg);
> > +   val = ev_raw;
> > +   val &= ~readl_relaxed(pcie->intr_base + pcie->variant-
> >misc_mask_reg);
> > +
> > +   if (pcie->variant->version == 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 &= 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 = readl_relaxed(pcie->intr_base +
> AMD_CPM6_PCIE_ERR_STATUS);
> > +   err &= ~readl_relaxed(pcie->intr_base +
> AMD_CPM6_PCIE_ERR_MASK);
> > +   err &= 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 IRQ
> 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 =
> > +                   pcie->variant->version == MDB5 ?
> > +                   mdb5_intr_cause : cpm6_intr_cause;
> > +           int i, irq;
> > +
> > +           for (i = 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) ==
                  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 = irq_find_mapping(pcie->mdb_domain, i);
> > +                   if (irq) {
> > +                           disable_irq(irq);
> > +                           free_irq(irq, pcie);
> > +                           irq_dispose_mapping(irq);
> > +                   }
> > +           }
> > +           irq = 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 = 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 = 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 != MDB5)
> > +           writel_relaxed(AMD_CPM6_PCIE_ERR_MASK_ALL,
> > +                          pcie->intr_base +
> AMD_CPM6_PCIE_ERR_DISABLE);
> >
> >     /* Clear pending TLP interrupts. */
> > -   val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> > -   val &= AMD_MDB_PCIE_IMR_ALL_MASK;
> > -   writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> > +   val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg)
> &
> > +         misc_mask_all;
> > +   writel_relaxed(val, pcie->intr_base + pcie->variant->misc_status_reg);
> > +
> > +   if (pcie->variant->version != MDB5) {
> > +           val = 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 != 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 = args;
> > +   const struct amd_mdb_intr_cause *intr_cause;
> >     struct device *dev;
> >     struct irq_data *d;
> >
> >     dev = pcie->pci.dev;
> > +   intr_cause = pcie->variant->version == MDB5 ?
> > +                mdb5_intr_cause : cpm6_intr_cause;
> >
> >     /*
> >      * In the future, error reporting will be hooked to the AER subsystem.
> > @@ -351,15 +547,19 @@ static int amd_mdb_setup_irq(struct
> amd_mdb_pcie *pcie,
> >     struct dw_pcie *pci = &pcie->pci;
> >     struct dw_pcie_rp *pp = &pci->pp;
> >     struct device *dev = &pdev->dev;
> > +   const struct amd_mdb_intr_cause *intr_cause;
> >     int i, irq, err;
> >
> > +   intr_cause = pcie->variant->version == MDB5 ?
> > +                mdb5_intr_cause : cpm6_intr_cause;
> > +
> >     amd_mdb_pcie_init_port(pcie);
> >
> >     pp->irq = platform_get_irq(pdev, 0);
> >     if (pp->irq < 0)
> >             return pp->irq;
> >
> > -   for (i = 0; i < ARRAY_SIZE(intr_cause); i++) {
> > +   for (i = 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 = 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 == MDB5) {
> > +           pcie->intr_base = pcie->slcr;
> > +   } else {
> > +           pcie->intr_base =
> devm_platform_ioremap_resource_byname(pdev, "intr");
> > +           if (IS_ERR(pcie->intr_base))
> > +                   return PTR_ERR(pcie->intr_base);
> > +   }
> > +
> >     err = 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 = &pcie->pci;
> >     pci->dev = dev;
> > +   pcie->variant = 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 = {
> > +   .version = CPM6,
> > +   .misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
> > +   .misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
> > +   .misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
> > +   .misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
> > +   .misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
> > +   .intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
> > +   .intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
> > +};
> > +
> > +static const struct amd_mdb_pcie_variant cpm6_host1 = {
> > +   .version = CPM6_HOST1,
> > +   .misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
> > +   .misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
> > +   .misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
> > +   .misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
> > +   .misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
> > +   .intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
> > +   .intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
> > +};
> > +
> > +static const struct amd_mdb_pcie_variant mdb5_host = {
> > +   .version = MDB5,
> > +   .misc_status_reg = AMD_MDB_TLP_IR_STATUS_MISC,
> > +   .misc_mask_reg = AMD_MDB_TLP_IR_MASK_MISC,
> > +   .misc_enable_reg = AMD_MDB_TLP_IR_ENABLE_MISC,
> > +   .misc_disable_reg = AMD_MDB_TLP_IR_DISABLE_MISC,
> > +   .misc_mask_all = AMD_MDB_PCIE_IMR_ALL_MASK,
> > +   .intx_hwirq = AMD_MDB_PCIE_INTR_INTX,
> > +   .intx_mask = AMD_MDB_TLP_PCIE_INTX_MASK,
> > +};
> > +
> >  static const struct of_device_id amd_mdb_pcie_of_match[] = {
> >     {
> >             .compatible = "amd,versal2-mdb-host",
> > +           .data = &mdb5_host,
> > +   },
> > +   {
> > +           .compatible = "amd,versal2-cpm6-host",
> > +           .data = &cpm6_host,
> > +   },
> > +   {
> > +           .compatible = "amd,versal2-cpm6-host1",
> > +           .data = &cpm6_host1,
> >     },
> >     {},
> >  };
> > --
> > 2.44.4
> >

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-08-03 11:28 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-28 20:20 [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support Sai Krishna Musham
2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
2026-07-28 22:29   ` Bjorn Helgaas
2026-07-29  9:29     ` Musham, Sai Krishna
2026-07-29  9:54   ` Krzysztof Kozlowski
2026-07-29 15:49     ` Musham, Sai Krishna
2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
2026-07-28 22:27   ` Bjorn Helgaas
2026-08-03 11:28     ` Musham, Sai Krishna

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome