From 4eea7596b8fb5c204f7a454a5166ebdcb6b6c72a Mon Sep 17 00:00:00 2001 From: Thippeswamy Havalige Date: Sun, 22 Sep 2024 11:43:18 +0530 Subject: [PATCH] PCI: xilinx-cpm: Add support for Versal CPM5 Root Port Controller 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Krzysztof WilczyƄski Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/pcie-xilinx-cpm.c | 50 ++++++++++++++++++------ 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/pci/controller/pcie-xilinx-cpm.c b/drivers/pci/controller/pcie-xilinx-cpm.c index a0f5e1d67b04c..81e8bfae53d00 100644 --- a/drivers/pci/controller/pcie-xilinx-cpm.c +++ b/drivers/pci/controller/pcie-xilinx-cpm.c @@ -30,11 +30,14 @@ #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) @@ -80,14 +83,21 @@ 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 @@ static int xilinx_cpm_pcie_probe(struct platform_device *pdev) 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, + }, {} };