riscv: interrupt-controller: Add T-HEAD C900 ACLINT SSWI
Subsystems (4)
v2 cover riscv: interrupt-controller: Add T-HEAD C900 ACLINT SSWI
New version of T-HEAD C920 implement a fully featured ACLINT[1] device (This core is used by Sophgo SG2044). This ACLINT device provides a SSWI field to support fast S-mode IPI. This SSWI device is like the MSWI device in CLINT/ACLINT, but for S-mode. The only thing is different from the draft is that the T-HEAD version SSWI needs to write 0 on the SSWI address to clear the IPI.
Add full support for T-HEAD C900 SSWI device.
[1] https://github.com/riscv/riscv-aclint
Change from v1:
1. patch 2: use computed reg offset to avoid uncessary reg additions when setting/clearing irq.
2. patch 2: fix mulitple format issues and improve some comments.
3. patch 2: disable cpu irq when CPU is stopped.
Inochi Amaoto (3):
dt-bindings: interrupt-controller: Add Sophgo SG2044 ACLINT SSWI
irqchip: add T-HEAD C900 ACLINT SSWI driver
riscv: defconfig: Enable T-HEAD C900 ACLINT SSWI drivers
.../thead,c900-aclint-sswi.yaml | 58 ++++++ arch/riscv/configs/defconfig | 1 + drivers/irqchip/Kconfig | 10 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-thead-c900-aclint-sswi.c | 166 ++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 6 files changed, 237 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml create mode 100644 drivers/irqchip/irq-thead-c900-aclint-sswi.c
--
2.47.0
PATCH v2 1/3 dt-bindings: interrupt-controller: Add Sophgo SG2044 ACLINT SSWI
Sophgo SG2044 has a new version of T-HEAD C920, which implement a fully featured ACLINT device. This ACLINT has an extra SSWI field to support fast S-mode IPI.
Add necessary compatible string for the T-HEAD ACLINT sswi device.
--- .../thead,c900-aclint-sswi.yaml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml
Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml new file +58 -0
@@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/thead,c900-aclint-sswi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sophgo sg2044 ACLINT Supervisor-level Software Interrupt Device + +maintainers: + - Inochi Amaoto <[email protected]> + +description: + The SSWI device is a part of the riscv ACLINT device. It provides + supervisor-level IPI functionality for a set of HARTs on a RISC-V + platform. It provides a register to set an IPI (SETSSIP) for each + HART connected to the SSWI device. + +properties: + compatible: + items: + - enum: + - sophgo,sg2044-aclint-sswi + - const: thead,c900-aclint-sswi + + reg: + maxItems: 1 + + "#interrupt-cells": + const: 0 + + interrupt-controller: true + + interrupts-extended: + minItems: 1 + maxItems: 4095 + +additionalProperties: false + +required: + - compatible + - reg + - "#interrupt-cells" + - interrupt-controller + - interrupts-extended + +examples: + - | + interrupt-controller@94000000 { + compatible = "sophgo,sg2044-aclint-sswi", "thead,c900-aclint-sswi"; + reg = <0x94000000 0x00004000>; + #interrupt-cells = <0>; + interrupt-controller; + interrupts-extended = <&cpu1intc 1>, + <&cpu2intc 1>, + <&cpu3intc 1>, + <&cpu4intc 1>; + }; +...
Signature · 1 line
2.47.0
Re: [PATCH v2 1/3] dt-bindings: interrupt-controller: Add Sophgo SG2044 ACLINT SSWI
Quoted 7 lines · Inochi Amaoto
Sophgo SG2044 has a new version of T-HEAD C920, which implement a fully featured ACLINT device. This ACLINT has an extra SSWI field to support fast S-mode IPI.
Add necessary compatible string for the T-HEAD ACLINT sswi device.
Signed-off-by Inochi Amaoto <[email protected]>
This is not a complaint about speed of reposting, but I do have outstanding thoughts on the previous version of the patch. I've just been really busy with work this week and not yet had a chance to get back to you on it. I'll, hopefully, get there tomorrow.
Re: [PATCH v2 1/3] dt-bindings: interrupt-controller: Add Sophgo SG2044 ACLINT SSWI
In reply to Inochi AmaotoQuoted 7 lines · Inochi Amaoto
Sophgo SG2044 has a new version of T-HEAD C920, which implement a fully featured ACLINT device. This ACLINT has an extra SSWI field to support fast S-mode IPI.
Add necessary compatible string for the T-HEAD ACLINT sswi device.
Signed-off-by Inochi Amaoto <[email protected]>
PATCH v2 2/3 irqchip: add T-HEAD C900 ACLINT SSWI driver
In reply to Inochi AmaotoAdd a driver for the T-HEAD C900 ACLINT SSWI device, which is an enhanced implementation of the RISC-V ACLINT SSWI specification. This device allows the system to send ipi via fast device interface.
--- drivers/irqchip/Kconfig | 10 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-thead-c900-aclint-sswi.c | 166 +++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 4 files changed, 178 insertions(+) create mode 100644 drivers/irqchip/irq-thead-c900-aclint-sswi.c
drivers/irqchip/Kconfig +10 -0
@@ -611,6 +611,16 @@ 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" + depends on RISCV + select IRQ_DOMAIN_HIERARCHY + help + This enables support for T-HEAD specific ACLINT SSWI device + support. + + If you don't know what to do here, say Y. + config EXYNOS_IRQ_COMBINER bool "Samsung Exynos IRQ combiner support" if COMPILE_TEST depends on (ARCH_EXYNOS && ARM) || COMPILE_TEST
drivers/irqchip/Makefile +1 -0
@@ -101,6 +101,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_IMX_IRQSTEER) += irq-imx-irqsteer.o obj-$(CONFIG_IMX_INTMUX) += irq-imx-intmux.o obj-$(CONFIG_IMX_MU_MSI) += irq-imx-mu-msi.o
drivers/irqchip/irq-thead-c900-aclint-sswi.c new file +166 -0
166 lines not on this page · raw message
include/linux/cpuhotplug.h +1 -0
@@ -147,6 +147,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_RISCV_IMSIC_STARTING ,CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING , CPUHP_AP_ARM_MVEBU_COHERENCY,
Signature · 1 line
2.47.0
kernel test robot
build botRe: [PATCH v2 2/3] irqchip: add T-HEAD C900 ACLINT SSWI driver
kernel test robot noticed the following build errors:
Hi Inochi,
kernel test robot noticed the following build errors:
[auto build test ERROR on tip/irq/core]
[also build test ERROR on robh/for-next tip/smp/core linus/master v6.12-rc2 next-20241011] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Inochi-Amaoto/dt-bindings-interrupt-controller-Add-Sophgo-SG2044-ACLINT-SSWI/20241010-064628 base: tip/irq/core patch link: https://lore.kernel.org/r/20241009224410.53188-3-inochiama%40gmail.com patch subject: [PATCH v2 2/3] irqchip: add T-HEAD C900 ACLINT SSWI driver config: riscv-randconfig-r054-20241013 (https://download.01.org/0day-ci/archive/20241014/[email protected]/config) compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241014/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
>> ld.lld: error: undefined symbol: ipi_mux_process >>> referenced by irq-thead-c900-aclint-sswi.c:38 (drivers/irqchip/irq-thead-c900-aclint-sswi.c:38) >>> drivers/irqchip/irq-thead-c900-aclint-sswi.o:(thead_aclint_sswi_ipi_handle) in archive vmlinux.a -- >> ld.lld: error: undefined symbol: ipi_mux_create >>> referenced by err.h:81 (include/linux/err.h:81) >>> drivers/irqchip/irq-thead-c900-aclint-sswi.o:(aclint_sswi_probe) in archive vmlinux.a
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Re: [PATCH v2 2/3] irqchip: add T-HEAD C900 ACLINT SSWI driver
In reply to Inochi Amaotodrivers/irqchip/Kconfig config STARFIVE_JH8100_INTC · line 617
Quoted 4 lines · Inochi Amaoto
drivers/irqchip/Kconfig +4
-0+config THEAD_C900_ACLINT_SSWI + bool "THEAD C9XX ACLINT S-mode IPI Interrupt Controller" + depends on RISCV + select IRQ_DOMAIN_HIERARCHY
Lacks
select GENERIC_IRQ_IPI_MUX
Other than that this looks good.
Thanks,
tglx
Re: [PATCH v2 2/3] irqchip: add T-HEAD C900 ACLINT SSWI driver
Quoted 9 lines · Thomas Gleixner
drivers/irqchip/Kconfig config STARFIVE_JH8100_INTC · line 617
Quoted 4 lines · Inochi Amaoto
drivers/irqchip/Kconfig +4
-0+config THEAD_C900_ACLINT_SSWI + bool "THEAD C9XX ACLINT S-mode IPI Interrupt Controller" + depends on RISCV + select IRQ_DOMAIN_HIERARCHYLacks
selectGENERIC_IRQ_IPI_MUX
Quoted 5 lines
Other than that this looks good.
Thanks,
tglx
Thanks, I will update it.
Regards,
Inochi
Re: [PATCH v2 2/3] irqchip: add T-HEAD C900 ACLINT SSWI driver
In reply to Inochi AmaotoHi Inochi,
Quoted 76 lines · Inochi Amaoto
Add a driver for the T-HEAD C900 ACLINT SSWI device, which is an enhanced implementation of the RISC-V ACLINT SSWI specification. This device allows the system to send ipi via fast device interface.
Signed-off-by Inochi Amaoto <[email protected]>--- drivers/irqchip/Kconfig | 10 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-thead-c900-aclint-sswi.c | 166 +++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 4 files changed, 178 insertions(+) create mode 100644 drivers/irqchip/irq-thead-c900-aclint-sswi.cdrivers/irqchip/Kconfig +10
-0@@ -611,6 +611,16 @@ 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" + depends on RISCV + select IRQ_DOMAIN_HIERARCHY + help + This enables support for T-HEAD specific ACLINT SSWI device + support. + + If you don't know what to do here, say Y. + config EXYNOS_IRQ_COMBINER bool "Samsung Exynos IRQ combiner support" if COMPILE_TEST depends on (ARCH_EXYNOS && ARM) || COMPILE_TESTdrivers/irqchip/Makefile +1
-0@@ -101,6 +101,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_IMX_IRQSTEER) += irq-imx-irqsteer.o obj-$(CONFIG_IMX_INTMUX) += irq-imx-intmux.o obj-$(CONFIG_IMX_MU_MSI) += irq-imx-mu-msi.odrivers/irqchip/irq-thead-c900-aclint-sswi.c new file +24
-0@@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (C) 2024 Inochi Amaoto <[email protected]> +*/ + +#define pr_fmt (fmt) "thead-c900-aclint-sswi: " fmt +#include <linux/cpu.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/string_choices.h> + +#define ACLINT_xSWI_REGISTER_SIZE 4 + +static int sswi_ipi_virq__ro_after_init ;
drivers/irqchip/irq-thead-c900-aclint-sswi.c line 34
Quoted 10 lines
drivers/irqchip/irq-thead-c900-aclint-sswi.c new file +10
-0+static DEFINE_PER_CPU(void __iomem *, sswi_cpu_regs); + +static void thead_aclint_sswi_ipi_send (unsigned int cpu) +{ +writel_relaxed (0x1 ,per_cpu (sswi_cpu_regs, cpu)); +} + +static void thead_aclint_sswi_ipi_clear (void ) +{ +writel_relaxed (0x0 ,this_cpu_read (sswi_cpu_regs));
This isn't quite compliant with the ACLINT spec[1], which states: "Writing 0 to the least significant bit of a SETSSIP register has no effect". In a RISC-V ACLINT, only the CSR write is required to clear the interrupt.
This implementation does match the behavior of the T-HEAD CLINT extensions which are also present in C906/C910[2][3][4].
This raises the question: in the older CPUs, using this functionality requires setting the mxstatus.CLINTEE bit from M-mode. Is this still the case for the C920 CPU in SG2044? If so, the driver should check sxstatus.CLINTEE when probing.
It would also be ideal if we could support the other SoCs that use this same IP block, but with the other CLINT binding.
Regards,
Samuel
[1]: https://github.com/riscv/riscv-aclint/blob/main/riscv-aclint.adoc
[2]:
https://occ-intl-prod.oss-ap-southeast-1.aliyuncs.com/resource/XuanTie-OpenC906-UserManual.pdf
[3]:
https://github.com/XUANTIE-RV/openc906/blob/main/C906_RTL_FACTORY/gen_rtl/clint/rtl/clint_func.v#L285
[4]:
https://github.com/XUANTIE-RV/openc906/blob/main/C906_RTL_FACTORY/gen_rtl/cp0/rtl/aq_cp0_trap_csr.v#L1240
Quoted 144 lines
drivers/irqchip/irq-thead-c900-aclint-sswi.c new file +132
-0+} + +static void thead_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 (); + +ipi_mux_process (); + +chained_irq_exit (chip, desc); +} + +static int thead_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) +{ +thead_aclint_sswi_ipi_clear (); + +disable_percpu_irq (sswi_ipi_virq); + +return 0 ; +} + +static int __init aclint_sswi_parse_irq (struct fwnode_handle *fwnode, +void __iomem *reg) +{ +struct of_phandle_args parent; +unsigned long hartid; +u32 contexts, i; +int rc, cpu; + + contexts =of_irq_count (to_of_node (fwnode)); +if (!(contexts)) { +pr_err ("%pfwP: no ACLINT SSWI context available\n" , fwnode); +return -EINVAL ; + } + +for (i =0 ; i < contexts; i++) { + rc =of_irq_parse_one (to_of_node (fwnode), i, &parent); +if (rc) +return rc; + + rc =riscv_of_parent_hartid (parent.np, &hartid); +if (rc) +return rc; + +if (parent.args[0 ] !=RV_IRQ_SOFT ) +return -ENOTSUPP ; + + cpu =riscv_hartid_to_cpuid (hartid); + +per_cpu (sswi_cpu_regs, cpu) = reg + i * ACLINT_xSWI_REGISTER_SIZE; + } + +pr_info ("%pfwP: register %u CPU%s\n" , fwnode, contexts,str_plural (contexts)); + +return 0 ; +} + +static int __init aclint_sswi_probe (struct fwnode_handle *fwnode) +{ +struct irq_domain *domain; +void __iomem *reg; +int virq, rc; + +if (!is_of_node (fwnode)) +return -EINVAL ; + + reg =of_iomap (to_of_node (fwnode),0 ); +if (!reg) +return -ENOMEM ; + +/* Parse SSWI setting */ + rc =aclint_sswi_parse_irq (fwnode, reg); +if (rc <0 ) +return rc; + +/* If mulitple SSWI devices are present, do not register irq again */ +if (sswi_ipi_virq) +return 0 ; + +/* Find riscv intc domain and create IPI irq mapping */ + domain =irq_find_matching_fwnode (riscv_get_intc_hwnode (),DOMAIN_BUS_ANY ); +if (!domain) { +pr_err ("%pfwP: Failed to find INTC domain\n" , fwnode); +return -ENOENT ; + } + + sswi_ipi_virq =irq_create_mapping (domain,RV_IRQ_SOFT ); +if (!sswi_ipi_virq) { +pr_err ("unable to create ACLINT SSWI IRQ mapping\n" ); +return -ENOMEM ; + } + +/* Register SSWI irq and handler */ + virq =ipi_mux_create (BITS_PER_BYTE , thead_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); + +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); + +riscv_ipi_set_virq_range (virq,BITS_PER_BYTE ); + +/* Announce that SSWI is providing IPIs */ +pr_info ("providing IPIs using THEAD ACLINT SSWI\n" ); + +return 0 ; +} + +static int __init aclint_sswi_early_probe (struct device_node *node, +struct device_node *parent) +{ +return aclint_sswi_probe (&node->fwnode); +} +IRQCHIP_DECLARE (thead_aclint_sswi,"thead,c900-aclint-sswi" , aclint_sswi_early_probe);include/linux/cpuhotplug.h +1
-0@@ -147,6 +147,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_RISCV_IMSIC_STARTING ,CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING , CPUHP_AP_ARM_MVEBU_COHERENCY,
Re: [PATCH v2 2/3] irqchip: add T-HEAD C900 ACLINT SSWI driver
Quoted 94 lines · Samuel Holland
Hi Inochi,
Quoted 76 lines · Inochi Amaoto
Add a driver for the T-HEAD C900 ACLINT SSWI device, which is an enhanced implementation of the RISC-V ACLINT SSWI specification. This device allows the system to send ipi via fast device interface.
Signed-off-by Inochi Amaoto <[email protected]>--- drivers/irqchip/Kconfig | 10 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-thead-c900-aclint-sswi.c | 166 +++++++++++++++++++ include/linux/cpuhotplug.h | 1 + 4 files changed, 178 insertions(+) create mode 100644 drivers/irqchip/irq-thead-c900-aclint-sswi.cdrivers/irqchip/Kconfig +10
-0@@ -611,6 +611,16 @@ 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" + depends on RISCV + select IRQ_DOMAIN_HIERARCHY + help + This enables support for T-HEAD specific ACLINT SSWI device + support. + + If you don't know what to do here, say Y. + config EXYNOS_IRQ_COMBINER bool "Samsung Exynos IRQ combiner support" if COMPILE_TEST depends on (ARCH_EXYNOS && ARM) || COMPILE_TESTdrivers/irqchip/Makefile +1
-0@@ -101,6 +101,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_IMX_IRQSTEER) += irq-imx-irqsteer.o obj-$(CONFIG_IMX_INTMUX) += irq-imx-intmux.o obj-$(CONFIG_IMX_MU_MSI) += irq-imx-mu-msi.odrivers/irqchip/irq-thead-c900-aclint-sswi.c new file +24
-0@@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (C) 2024 Inochi Amaoto <[email protected]> +*/ + +#define pr_fmt (fmt) "thead-c900-aclint-sswi: " fmt +#include <linux/cpu.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/pci.h> +#include <linux/spinlock.h> +#include <linux/smp.h> +#include <linux/string_choices.h> + +#define ACLINT_xSWI_REGISTER_SIZE 4 + +static int sswi_ipi_virq__ro_after_init ;drivers/irqchip/irq-thead-c900-aclint-sswi.c line 34
Quoted 10 lines
drivers/irqchip/irq-thead-c900-aclint-sswi.c new file +10
-0+static DEFINE_PER_CPU(void __iomem *, sswi_cpu_regs); + +static void thead_aclint_sswi_ipi_send (unsigned int cpu) +{ +writel_relaxed (0x1 ,per_cpu (sswi_cpu_regs, cpu)); +} + +static void thead_aclint_sswi_ipi_clear (void ) +{ +writel_relaxed (0x0 ,this_cpu_read (sswi_cpu_regs));This isn't quite compliant with the ACLINT spec[1], which states: "Writing 0 to the least significant bit of a SETSSIP register has no effect". In a RISC-V ACLINT, only the CSR write is required to clear the interrupt.
Quoted 3 lines
This implementation does match the behavior of the T-HEAD CLINT extensions which are also present in C906/C910[2][3][4].
Yes, this is T-HEAD specific one, it does not match the spec exactly. This is why I add "thead" prefix.
Quoted 4 lines
This raises the question: in the older CPUs, using this functionality requires setting the mxstatus.CLINTEE bit from M-mode. Is this still the case for the C920 CPU in SG2044? If so, the driver should check sxstatus.CLINTEE when probing.
It seems that I forgot this. The SG2044 also needs to check the CLINTEE bit when probing, it just set this bit in its zsbl. I will fix this in the next version. Thanks for points it.
Quoted 159 lines
It would also be ideal if we could support the other SoCs that use this same IP block, but with the other CLINT binding.
Regards,
Samuel[1]: https://github.com/riscv/riscv-aclint/blob/main/riscv-aclint.adoc
[2]:
https://occ-intl-prod.oss-ap-southeast-1.aliyuncs.com/resource/XuanTie-OpenC906-UserManual.pdf
[3]:
https://github.com/XUANTIE-RV/openc906/blob/main/C906_RTL_FACTORY/gen_rtl/clint/rtl/clint_func.v#L285
[4]:
https://github.com/XUANTIE-RV/openc906/blob/main/C906_RTL_FACTORY/gen_rtl/cp0/rtl/aq_cp0_trap_csr.v#L1240Quoted 144 lines
drivers/irqchip/irq-thead-c900-aclint-sswi.c new file +132
-0+} + +static void thead_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 (); + +ipi_mux_process (); + +chained_irq_exit (chip, desc); +} + +static int thead_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) +{ +thead_aclint_sswi_ipi_clear (); + +disable_percpu_irq (sswi_ipi_virq); + +return 0 ; +} + +static int __init aclint_sswi_parse_irq (struct fwnode_handle *fwnode, +void __iomem *reg) +{ +struct of_phandle_args parent; +unsigned long hartid; +u32 contexts, i; +int rc, cpu; + + contexts =of_irq_count (to_of_node (fwnode)); +if (!(contexts)) { +pr_err ("%pfwP: no ACLINT SSWI context available\n" , fwnode); +return -EINVAL ; + } + +for (i =0 ; i < contexts; i++) { + rc =of_irq_parse_one (to_of_node (fwnode), i, &parent); +if (rc) +return rc; + + rc =riscv_of_parent_hartid (parent.np, &hartid); +if (rc) +return rc; + +if (parent.args[0 ] !=RV_IRQ_SOFT ) +return -ENOTSUPP ; + + cpu =riscv_hartid_to_cpuid (hartid); + +per_cpu (sswi_cpu_regs, cpu) = reg + i * ACLINT_xSWI_REGISTER_SIZE; + } + +pr_info ("%pfwP: register %u CPU%s\n" , fwnode, contexts,str_plural (contexts)); + +return 0 ; +} + +static int __init aclint_sswi_probe (struct fwnode_handle *fwnode) +{ +struct irq_domain *domain; +void __iomem *reg; +int virq, rc; + +if (!is_of_node (fwnode)) +return -EINVAL ; + + reg =of_iomap (to_of_node (fwnode),0 ); +if (!reg) +return -ENOMEM ; + +/* Parse SSWI setting */ + rc =aclint_sswi_parse_irq (fwnode, reg); +if (rc <0 ) +return rc; + +/* If mulitple SSWI devices are present, do not register irq again */ +if (sswi_ipi_virq) +return 0 ; + +/* Find riscv intc domain and create IPI irq mapping */ + domain =irq_find_matching_fwnode (riscv_get_intc_hwnode (),DOMAIN_BUS_ANY ); +if (!domain) { +pr_err ("%pfwP: Failed to find INTC domain\n" , fwnode); +return -ENOENT ; + } + + sswi_ipi_virq =irq_create_mapping (domain,RV_IRQ_SOFT ); +if (!sswi_ipi_virq) { +pr_err ("unable to create ACLINT SSWI IRQ mapping\n" ); +return -ENOMEM ; + } + +/* Register SSWI irq and handler */ + virq =ipi_mux_create (BITS_PER_BYTE , thead_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); + +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); + +riscv_ipi_set_virq_range (virq,BITS_PER_BYTE ); + +/* Announce that SSWI is providing IPIs */ +pr_info ("providing IPIs using THEAD ACLINT SSWI\n" ); + +return 0 ; +} + +static int __init aclint_sswi_early_probe (struct device_node *node, +struct device_node *parent) +{ +return aclint_sswi_probe (&node->fwnode); +} +IRQCHIP_DECLARE (thead_aclint_sswi,"thead,c900-aclint-sswi" , aclint_sswi_early_probe);include/linux/cpuhotplug.h +1
-0@@ -147,6 +147,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_RISCV_IMSIC_STARTING ,CPUHP_AP_IRQ_RISCV_SBI_IPI_STARTING , CPUHP_AP_ARM_MVEBU_COHERENCY,
PATCH v2 3/3 riscv: defconfig: Enable T-HEAD C900 ACLINT SSWI drivers
In reply to Inochi AmaotoAdd support for T-HEAD C900 ACLINT SSWI irqchip.
--- arch/riscv/configs/defconfig | 1 + 1 file changed, 1 insertion(+)
arch/riscv/configs/defconfig +1 -0
@@ -256,6 +256,7 @@ CONFIG_RPMSG_CTRL=y CONFIG_RPMSG_VIRTIO=y CONFIG_PM_DEVFREQ=y CONFIG_IIO=y +CONFIG_THEAD_C900_ACLINT_SSWI=y CONFIG_PHY_SUN4I_USB=m CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=m CONFIG_PHY_STARFIVE_JH7110_PCIE=m
Signature · 1 line
2.47.0