]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
irqchip/thead-c900-aclint-sswi: Generalize aclint-sswi driver and add MIPS P800 support
authorVladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Thu, 12 Jun 2025 14:39:08 +0000 (17:39 +0300)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 26 Jun 2025 14:06:40 +0000 (16:06 +0200)
Refactor the Thead specific implementation of the ACLINT-SSWI irqchip:

 - Rename the source file and related details to reflect the generic nature
   of the driver

 - Factor out the generic code that serves both Thead and MIPS variants.
   This generic part is compliant with the RISC-V draft spec [1]

 - Provide generic and Thead specific initialization functions

Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250612143911.3224046-5-vladimir.kondratiev@mobileye.com
Link: https://github.com/riscvarchive/riscv-aclint
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/irq-aclint-sswi.c [moved from drivers/irqchip/irq-thead-c900-aclint-sswi.c with 68% similarity]
include/linux/cpuhotplug.h

index 0d196e44714266f8ea91e5d72951ef16af44a5df..39f6f421fc75f8738b0e3104c833a0fb4854e214 100644 (file)
@@ -634,18 +634,25 @@ config STARFIVE_JH8100_INTC
 
          If you don't know what to do here, say Y.
 
-config THEAD_C900_ACLINT_SSWI
-       bool "THEAD C9XX ACLINT S-mode IPI Interrupt Controller"
+config ACLINT_SSWI
+       bool "RISC-V ACLINT S-mode IPI Interrupt Controller"
        depends on RISCV
        depends on SMP
        select IRQ_DOMAIN_HIERARCHY
        select GENERIC_IRQ_IPI_MUX
        help
-         This enables support for T-HEAD specific ACLINT SSWI device
-         support.
+         This enables support for variants of the RISC-V ACLINT-SSWI device.
+         Supported variants are:
+         - T-HEAD, with compatible "thead,c900-aclint-sswi"
+         - MIPS P8700, with compatible "mips,p8700-aclint-sswi"
 
          If you don't know what to do here, say Y.
 
+# Backwards compatibility so oldconfig does not drop it.
+config THEAD_C900_ACLINT_SSWI
+       bool
+       select ACLINT_SSWI
+
 config EXYNOS_IRQ_COMBINER
        bool "Samsung Exynos IRQ combiner support" if COMPILE_TEST
        depends on (ARCH_EXYNOS && ARM) || COMPILE_TEST
index 23ca4959e6ced015fa1a576a3e3524947c75dcc8..0458d6c5d1619b6dd51fa954fb59d07afadfedb6 100644 (file)
@@ -105,7 +105,7 @@ obj-$(CONFIG_RISCV_APLIC_MSI)               += irq-riscv-aplic-msi.o
 obj-$(CONFIG_RISCV_IMSIC)              += irq-riscv-imsic-state.o irq-riscv-imsic-early.o irq-riscv-imsic-platform.o
 obj-$(CONFIG_SIFIVE_PLIC)              += irq-sifive-plic.o
 obj-$(CONFIG_STARFIVE_JH8100_INTC)     += irq-starfive-jh8100-intc.o
-obj-$(CONFIG_THEAD_C900_ACLINT_SSWI)   += irq-thead-c900-aclint-sswi.o
+obj-$(CONFIG_ACLINT_SSWI)              += irq-aclint-sswi.o
 obj-$(CONFIG_IMX_IRQSTEER)             += irq-imx-irqsteer.o
 obj-$(CONFIG_IMX_INTMUX)               += irq-imx-intmux.o
 obj-$(CONFIG_IMX_MU_MSI)               += irq-imx-mu-msi.o
similarity index 68%
rename from drivers/irqchip/irq-thead-c900-aclint-sswi.c
rename to drivers/irqchip/irq-aclint-sswi.c
index 8ff6e7a1363bd25e823d8636c9a0031c26215cc5..0131194d4847b1a46b21e3ebbbd0351ea6751c3d 100644 (file)
@@ -3,7 +3,8 @@
  * Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com>
  */
 
-#define pr_fmt(fmt) "thead-c900-aclint-sswi: " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <asm/sbi.h>
 #include <asm/vendorid_list.h>
 
-#define THEAD_ACLINT_xSWI_REGISTER_SIZE                4
-
-#define THEAD_C9XX_CSR_SXSTATUS                        0x5c0
-#define THEAD_C9XX_SXSTATUS_CLINTEE            BIT(17)
-
 static int sswi_ipi_virq __ro_after_init;
 static DEFINE_PER_CPU(void __iomem *, sswi_cpu_regs);
 
-static void thead_aclint_sswi_ipi_send(unsigned int cpu)
+static void aclint_sswi_ipi_send(unsigned int cpu)
 {
        writel(0x1, per_cpu(sswi_cpu_regs, cpu));
 }
 
-static void thead_aclint_sswi_ipi_clear(void)
+static void aclint_sswi_ipi_clear(void)
 {
        writel_relaxed(0x0, this_cpu_read(sswi_cpu_regs));
 }
 
-static void thead_aclint_sswi_ipi_handle(struct irq_desc *desc)
+static void aclint_sswi_ipi_handle(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
 
        chained_irq_enter(chip, desc);
 
        csr_clear(CSR_IP, IE_SIE);
-       thead_aclint_sswi_ipi_clear();
+       aclint_sswi_ipi_clear();
 
        ipi_mux_process();
 
        chained_irq_exit(chip, desc);
 }
 
-static int thead_aclint_sswi_starting_cpu(unsigned int cpu)
+static int aclint_sswi_starting_cpu(unsigned int cpu)
 {
        enable_percpu_irq(sswi_ipi_virq, irq_get_trigger_type(sswi_ipi_virq));
 
        return 0;
 }
 
-static int thead_aclint_sswi_dying_cpu(unsigned int cpu)
+static int aclint_sswi_dying_cpu(unsigned int cpu)
 {
-       thead_aclint_sswi_ipi_clear();
+       aclint_sswi_ipi_clear();
 
        disable_percpu_irq(sswi_ipi_virq);
 
        return 0;
 }
 
-static int __init thead_aclint_sswi_parse_irq(struct fwnode_handle *fwnode,
-                                             void __iomem *reg)
+static int __init aclint_sswi_parse_irq(struct fwnode_handle *fwnode, void __iomem *reg)
 {
        struct of_phandle_args parent;
        unsigned long hartid;
@@ -97,7 +92,7 @@ static int __init thead_aclint_sswi_parse_irq(struct fwnode_handle *fwnode,
 
                cpu = riscv_hartid_to_cpuid(hartid);
 
-               per_cpu(sswi_cpu_regs, cpu) = reg + i * THEAD_ACLINT_xSWI_REGISTER_SIZE;
+               per_cpu(sswi_cpu_regs, cpu) = reg + hart_index * 4;
        }
 
        pr_info("%pfwP: register %u CPU%s\n", fwnode, contexts, str_plural(contexts));
@@ -105,17 +100,12 @@ static int __init thead_aclint_sswi_parse_irq(struct fwnode_handle *fwnode,
        return 0;
 }
 
-static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode)
+static int __init aclint_sswi_probe(struct fwnode_handle *fwnode)
 {
        struct irq_domain *domain;
        void __iomem *reg;
        int virq, rc;
 
-       /* If it is T-HEAD CPU, check whether SSWI is enabled */
-       if (riscv_cached_mvendorid(0) == THEAD_VENDOR_ID &&
-           !(csr_read(THEAD_C9XX_CSR_SXSTATUS) & THEAD_C9XX_SXSTATUS_CLINTEE))
-               return -ENOTSUPP;
-
        if (!is_of_node(fwnode))
                return -EINVAL;
 
@@ -124,7 +114,7 @@ static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode)
                return -ENOMEM;
 
        /* Parse SSWI setting */
-       rc = thead_aclint_sswi_parse_irq(fwnode, reg);
+       rc = aclint_sswi_parse_irq(fwnode, reg);
        if (rc < 0)
                return rc;
 
@@ -146,22 +136,64 @@ static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode)
        }
 
        /* Register SSWI irq and handler */
-       virq = ipi_mux_create(BITS_PER_BYTE, thead_aclint_sswi_ipi_send);
+       virq = ipi_mux_create(BITS_PER_BYTE, aclint_sswi_ipi_send);
        if (virq <= 0) {
                pr_err("unable to create muxed IPIs\n");
                irq_dispose_mapping(sswi_ipi_virq);
                return virq < 0 ? virq : -ENOMEM;
        }
 
-       irq_set_chained_handler(sswi_ipi_virq, thead_aclint_sswi_ipi_handle);
+       irq_set_chained_handler(sswi_ipi_virq, aclint_sswi_ipi_handle);
 
-       cpuhp_setup_state(CPUHP_AP_IRQ_THEAD_ACLINT_SSWI_STARTING,
-                         "irqchip/thead-aclint-sswi:starting",
-                         thead_aclint_sswi_starting_cpu,
-                         thead_aclint_sswi_dying_cpu);
+       cpuhp_setup_state(CPUHP_AP_IRQ_ACLINT_SSWI_STARTING,
+                         "irqchip/aclint-sswi:starting",
+                         aclint_sswi_starting_cpu,
+                         aclint_sswi_dying_cpu);
 
        riscv_ipi_set_virq_range(virq, BITS_PER_BYTE);
 
+       return 0;
+}
+
+/* generic/MIPS variant */
+static int __init generic_aclint_sswi_probe(struct fwnode_handle *fwnode)
+{
+       int rc;
+
+       rc = aclint_sswi_probe(fwnode);
+       if (rc)
+               return rc;
+
+       /* Announce that SSWI is providing IPIs */
+       pr_info("providing IPIs using ACLINT SSWI\n");
+
+       return 0;
+}
+
+static int __init generic_aclint_sswi_early_probe(struct device_node *node,
+                                                 struct device_node *parent)
+{
+       return generic_aclint_sswi_probe(&node->fwnode);
+}
+IRQCHIP_DECLARE(generic_aclint_sswi, "mips,p8700-aclint-sswi", generic_aclint_sswi_early_probe);
+
+/* THEAD variant */
+#define THEAD_C9XX_CSR_SXSTATUS                        0x5c0
+#define THEAD_C9XX_SXSTATUS_CLINTEE            BIT(17)
+
+static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode)
+{
+       int rc;
+
+       /* If it is T-HEAD CPU, check whether SSWI is enabled */
+       if (riscv_cached_mvendorid(0) == THEAD_VENDOR_ID &&
+           !(csr_read(THEAD_C9XX_CSR_SXSTATUS) & THEAD_C9XX_SXSTATUS_CLINTEE))
+               return -ENOTSUPP;
+
+       rc = aclint_sswi_probe(fwnode);
+       if (rc)
+               return rc;
+
        /* Announce that SSWI is providing IPIs */
        pr_info("providing IPIs using THEAD ACLINT SSWI\n");
 
index df366ee15456bba56c581d482f98a5b9d26211d5..d381420bbd5f8f8f8dff5e6e36bfe5b7327de61e 100644 (file)
@@ -145,7 +145,7 @@ enum cpuhp_state {
        CPUHP_AP_IRQ_EIOINTC_STARTING,
        CPUHP_AP_IRQ_AVECINTC_STARTING,
        CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
-       CPUHP_AP_IRQ_THEAD_ACLINT_SSWI_STARTING,
+       CPUHP_AP_IRQ_ACLINT_SSWI_STARTING,
        CPUHP_AP_IRQ_RISCV_IMSIC_STARTING,
        CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING,
        CPUHP_AP_ARM_MVEBU_COHERENCY,