]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: xilinx-cpm: Add support for Versal CPM5 Root Port Controller 1
authorThippeswamy Havalige <thippesw@amd.com>
Sun, 22 Sep 2024 06:13:18 +0000 (11:43 +0530)
committerKrzysztof Wilczyński <kwilczynski@kernel.org>
Wed, 18 Dec 2024 23:22:00 +0000 (23:22 +0000)
Add support for the Xilinx Versal CPM5 Root Port Controller 1. The key
difference between Controller 0 and Controller 1 lies in the
platform-specific error interrupt bits, which are located at different
register offsets.

To handle these differences, updated variant structure to hold the
following platform-specific details:

- Interrupt status register offset (ir_status)
- Interrupt enable register offset (ir_enable)
- Miscellaneous interrupt values (ir_misc_value)

The driver differentiates between Controller 0 and Controller 1 using the
compatible string in the device tree. This ensures that the appropriate
register offsets are used for each controller, allowing for correct
handling of platform-specific interrupts and initialization.

Link: https://lore.kernel.org/r/20240922061318.2653503-3-thippesw@amd.com
Signed-off-by: Thippeswamy Havalige <thippesw@amd.com>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/pci/controller/pcie-xilinx-cpm.c

index a0f5e1d67b04c63924d7973f492c12c94539e4ae..81e8bfae53d0067711702d9b06aa1dc0698aa48b 100644 (file)
 #define XILINX_CPM_PCIE_REG_IDRN_MASK  0x00000E3C
 #define XILINX_CPM_PCIE_MISC_IR_STATUS 0x00000340
 #define XILINX_CPM_PCIE_MISC_IR_ENABLE 0x00000348
-#define XILINX_CPM_PCIE_MISC_IR_LOCAL  BIT(1)
+#define XILINX_CPM_PCIE0_MISC_IR_LOCAL BIT(1)
+#define XILINX_CPM_PCIE1_MISC_IR_LOCAL BIT(2)
 
-#define XILINX_CPM_PCIE_IR_STATUS       0x000002A0
-#define XILINX_CPM_PCIE_IR_ENABLE       0x000002A8
-#define XILINX_CPM_PCIE_IR_LOCAL        BIT(0)
+#define XILINX_CPM_PCIE0_IR_STATUS     0x000002A0
+#define XILINX_CPM_PCIE1_IR_STATUS     0x000002B4
+#define XILINX_CPM_PCIE0_IR_ENABLE     0x000002A8
+#define XILINX_CPM_PCIE1_IR_ENABLE     0x000002BC
+#define XILINX_CPM_PCIE_IR_LOCAL       BIT(0)
 
 #define IMR(x) BIT(XILINX_PCIE_INTR_ ##x)
 
 enum xilinx_cpm_version {
        CPM,
        CPM5,
+       CPM5_HOST1,
 };
 
 /**
  * struct xilinx_cpm_variant - CPM variant information
  * @version: CPM version
+ * @ir_status: Offset for the error interrupt status register
+ * @ir_enable: Offset for the CPM5 local error interrupt enable register
+ * @ir_misc_value: A bitmask for the miscellaneous interrupt status
  */
 struct xilinx_cpm_variant {
        enum xilinx_cpm_version version;
+       u32 ir_status;
+       u32 ir_enable;
+       u32 ir_misc_value;
 };
 
 /**
@@ -269,6 +279,7 @@ static void xilinx_cpm_pcie_event_flow(struct irq_desc *desc)
 {
        struct xilinx_cpm_pcie *port = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
+       const struct xilinx_cpm_variant *variant = port->variant;
        unsigned long val;
        int i;
 
@@ -279,11 +290,11 @@ static void xilinx_cpm_pcie_event_flow(struct irq_desc *desc)
                generic_handle_domain_irq(port->cpm_domain, i);
        pcie_write(port, val, XILINX_CPM_PCIE_REG_IDR);
 
-       if (port->variant->version == CPM5) {
-               val = readl_relaxed(port->cpm_base + XILINX_CPM_PCIE_IR_STATUS);
+       if (variant->ir_status) {
+               val = readl_relaxed(port->cpm_base + variant->ir_status);
                if (val)
                        writel_relaxed(val, port->cpm_base +
-                                           XILINX_CPM_PCIE_IR_STATUS);
+                                      variant->ir_status);
        }
 
        /*
@@ -465,6 +476,8 @@ static int xilinx_cpm_setup_irq(struct xilinx_cpm_pcie *port)
  */
 static void xilinx_cpm_pcie_init_port(struct xilinx_cpm_pcie *port)
 {
+       const struct xilinx_cpm_variant *variant = port->variant;
+
        if (cpm_pcie_link_up(port))
                dev_info(port->dev, "PCIe Link is UP\n");
        else
@@ -483,15 +496,15 @@ static void xilinx_cpm_pcie_init_port(struct xilinx_cpm_pcie *port)
         * XILINX_CPM_PCIE_MISC_IR_ENABLE register is mapped to
         * CPM SLCR block.
         */
-       writel(XILINX_CPM_PCIE_MISC_IR_LOCAL,
+       writel(variant->ir_misc_value,
               port->cpm_base + XILINX_CPM_PCIE_MISC_IR_ENABLE);
 
-       if (port->variant->version == CPM5) {
+       if (variant->ir_enable) {
                writel(XILINX_CPM_PCIE_IR_LOCAL,
-                      port->cpm_base + XILINX_CPM_PCIE_IR_ENABLE);
+                      port->cpm_base + variant->ir_enable);
        }
 
-       /* Enable the Bridge enable bit */
+       /* Set Bridge enable bit */
        pcie_write(port, pcie_read(port, XILINX_CPM_PCIE_REG_RPSC) |
                   XILINX_CPM_PCIE_REG_RPSC_BEN,
                   XILINX_CPM_PCIE_REG_RPSC);
@@ -609,10 +622,21 @@ err_parse_dt:
 
 static const struct xilinx_cpm_variant cpm_host = {
        .version = CPM,
+       .ir_misc_value = XILINX_CPM_PCIE0_MISC_IR_LOCAL,
 };
 
 static const struct xilinx_cpm_variant cpm5_host = {
        .version = CPM5,
+       .ir_misc_value = XILINX_CPM_PCIE0_MISC_IR_LOCAL,
+       .ir_status = XILINX_CPM_PCIE0_IR_STATUS,
+       .ir_enable = XILINX_CPM_PCIE0_IR_ENABLE,
+};
+
+static const struct xilinx_cpm_variant cpm5_host1 = {
+       .version = CPM5_HOST1,
+       .ir_misc_value = XILINX_CPM_PCIE1_MISC_IR_LOCAL,
+       .ir_status = XILINX_CPM_PCIE1_IR_STATUS,
+       .ir_enable = XILINX_CPM_PCIE1_IR_ENABLE,
 };
 
 static const struct of_device_id xilinx_cpm_pcie_of_match[] = {
@@ -624,6 +648,10 @@ static const struct of_device_id xilinx_cpm_pcie_of_match[] = {
                .compatible = "xlnx,versal-cpm5-host",
                .data = &cpm5_host,
        },
+       {
+               .compatible = "xlnx,versal-cpm5-host1",
+               .data = &cpm5_host1,
+       },
        {}
 };