From a9e18e59adeafdb15d77d289f9184fef2e8912ea Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Wed, 4 Sep 2024 15:11:50 +0800 Subject: [PATCH] riscv: Add ACLINT SSWI support The SSWI device 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. The patch utilizes the feature to optimize IPI handling by avoiding Linux calls into firmware runtime, thus minimizing context switching expenses and removing the dependency on sbi-ipi. Co-developed-by: Xiaoguang Xing Signed-off-by: Xiaoguang Xing Signed-off-by: Guo Ren Signed-off-by: Guo Ren --- arch/riscv/boot/dts/thead/th1520.dtsi | 6 ++++ arch/riscv/kernel/sbi-ipi.c | 44 +++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi index 2ddbc3a6eb6a8..966b9b9ca0bb2 100644 --- a/arch/riscv/boot/dts/thead/th1520.dtsi +++ b/arch/riscv/boot/dts/thead/th1520.dtsi @@ -646,6 +646,12 @@ <&cpu3_intc 3>, <&cpu3_intc 7>; }; + aclint_sswi: aclint-sswi@ffdc00c000 { + compatible = "riscv,aclint-sswi"; + reg = <0xff 0xdc00c000 0x0 0x00010000>; + interrupt-controller; + }; + gmac0: ethernet@ffe7070000 { compatible = "xuantie,th1520-dwmac"; reg = <0xff 0xe7070000 0x0 0x2000>; diff --git a/arch/riscv/kernel/sbi-ipi.c b/arch/riscv/kernel/sbi-ipi.c index a4559695ce623..db296dc0fa967 100644 --- a/arch/riscv/kernel/sbi-ipi.c +++ b/arch/riscv/kernel/sbi-ipi.c @@ -3,18 +3,35 @@ * Multiplex several IPIs over a single HW IPI. * * Copyright (c) 2022 Ventana Micro Systems Inc. + * Copyright (C) 2024 Alibaba Group Holding Limited. */ #define pr_fmt(fmt) "riscv: " fmt #include #include #include +#include #include #include +#include +#include +#include #include static int sbi_ipi_virq; +static u32 __iomem *sswi_base; + +static void sswi_send_ipi(unsigned int cpu) +{ + writel(1, sswi_base + cpuid_to_hartid_map(cpu)); +} + +static void sswi_clear_ipi(void) +{ + writel(0, sswi_base + cpuid_to_hartid_map(smp_processor_id())); +} + static void sbi_ipi_handle(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); @@ -22,6 +39,9 @@ static void sbi_ipi_handle(struct irq_desc *desc) chained_irq_enter(chip, desc); csr_clear(CSR_IP, IE_SIE); + if (sswi_base) + sswi_clear_ipi(); + ipi_mux_process(); chained_irq_exit(chip, desc); @@ -54,7 +74,8 @@ void __init sbi_ipi_init(void) return; } - virq = ipi_mux_create(BITS_PER_BYTE, sbi_send_ipi); + virq = ipi_mux_create(BITS_PER_BYTE, sswi_base ? sswi_send_ipi + : sbi_send_ipi); if (virq <= 0) { pr_err("unable to create muxed IPIs\n"); irq_dispose_mapping(sbi_ipi_virq); @@ -69,9 +90,26 @@ void __init sbi_ipi_init(void) * via generic IPI-Mux */ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, + sswi_base ? + "irqchip/sswi-ipi:starting" : "irqchip/sbi-ipi:starting", sbi_ipi_starting_cpu, NULL); - riscv_ipi_set_virq_range(virq, BITS_PER_BYTE, false); - pr_info("providing IPIs using SBI IPI extension\n"); + riscv_ipi_set_virq_range(virq, BITS_PER_BYTE, + sswi_base ? true : false); + pr_info("providing IPIs using %s IPI extension\n", + sswi_base ? "ACLINT SSWI" : "SBI"); +} + +static int __init aclint_sswi_probe(struct device_node *node, + struct device_node *parent) +{ + sswi_base = of_iomap(node, 0); + if (!sswi_base) { + pr_err("RISC-V ACLINT SSWI device probe failure\n"); + return -ENODEV; + } + + return 0; } +IRQCHIP_DECLARE(riscv_aclint_sswi, "riscv,aclint-sswi", aclint_sswi_probe);