Skip to content

Commit

Permalink
riscv: Add ACLINT SSWI support
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Xiaoguang Xing <[email protected]>
Signed-off-by: Guo Ren <[email protected]>
Signed-off-by: Guo Ren <[email protected]>
  • Loading branch information
guoren83 authored and RevySR committed Sep 6, 2024
1 parent 2aa129c commit a9e18e5
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
6 changes: 6 additions & 0 deletions arch/riscv/boot/dts/thead/th1520.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
44 changes: 41 additions & 3 deletions arch/riscv/kernel/sbi-ipi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,45 @@
* 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 <linux/cpu.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/sbi.h>

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);

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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);

0 comments on commit a9e18e5

Please sign in to comment.