[tip: irq/core] irqchip/apple-aic: Add a new "Global fast IPIs only" feature level

From: tip-bot2 for Nick Chan
Date: Wed Sep 04 2024 - 14:48:31 EST


The following commit has been merged into the irq/core branch of tip:

Commit-ID: a845342e6e5fb4937564f93cc88e00c732286fe3
Gitweb: https://git.kernel.org/tip/a845342e6e5fb4937564f93cc88e00c732286fe3
Author: Nick Chan <towinchenmi@xxxxxxxxx>
AuthorDate: Sun, 01 Sep 2024 11:40:06 +08:00
Committer: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
CommitterDate: Wed, 04 Sep 2024 20:43:30 +02:00

irqchip/apple-aic: Add a new "Global fast IPIs only" feature level

Starting with the A11 (T8015) SoC, Apple began using arm64 sysregs for
fast IPIs. However, on A11, there is no such things as "Local" fast IPIs,
as the SYS_IMP_APL_IPI_RR_LOCAL_EL1 register does not seem to exist.

Add a new feature level, used by the compatible "apple,t8015-aic",
controlled by a static branch key named use_local_fast_ipi. When
use_fast_ipi is true and use_local_fast_ipi is false, fast IPIs are used
but all IPIs goes through the register SYS_IMP_APL_IPI_RR_GLOBAL_EL1, as
"global" IPIs.

Signed-off-by: Nick Chan <towinchenmi@xxxxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Reviewed-by: Sven Peter <sven@xxxxxxxxxxxxx>
Link: https://lore.kernel.org/all/20240901034143.12731-4-towinchenmi@xxxxxxxxx

---
drivers/irqchip/irq-apple-aic.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c
index 8d81d5f..9012690 100644
--- a/drivers/irqchip/irq-apple-aic.c
+++ b/drivers/irqchip/irq-apple-aic.c
@@ -235,6 +235,8 @@ enum fiq_hwirq {
};

static DEFINE_STATIC_KEY_TRUE(use_fast_ipi);
+/* True if SYS_IMP_APL_IPI_RR_LOCAL_EL1 exists for local fast IPIs (M1+) */
+static DEFINE_STATIC_KEY_TRUE(use_local_fast_ipi);

struct aic_info {
int version;
@@ -252,6 +254,7 @@ struct aic_info {

/* Features */
bool fast_ipi;
+ bool local_fast_ipi;
};

static const struct aic_info aic1_info __initconst = {
@@ -270,17 +273,32 @@ static const struct aic_info aic1_fipi_info __initconst = {
.fast_ipi = true,
};

+static const struct aic_info aic1_local_fipi_info __initconst = {
+ .version = 1,
+
+ .event = AIC_EVENT,
+ .target_cpu = AIC_TARGET_CPU,
+
+ .fast_ipi = true,
+ .local_fast_ipi = true,
+};
+
static const struct aic_info aic2_info __initconst = {
.version = 2,

.irq_cfg = AIC2_IRQ_CFG,

.fast_ipi = true,
+ .local_fast_ipi = true,
};

static const struct of_device_id aic_info_match[] = {
{
.compatible = "apple,t8103-aic",
+ .data = &aic1_local_fipi_info,
+ },
+ {
+ .compatible = "apple,t8015-aic",
.data = &aic1_fipi_info,
},
{
@@ -750,12 +768,12 @@ static void aic_ipi_send_fast(int cpu)
u64 cluster = MPIDR_CLUSTER(mpidr);
u64 idx = MPIDR_CPU(mpidr);

- if (MPIDR_CLUSTER(my_mpidr) == cluster)
- write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx),
- SYS_IMP_APL_IPI_RR_LOCAL_EL1);
- else
+ if (static_branch_likely(&use_local_fast_ipi) && MPIDR_CLUSTER(my_mpidr) == cluster) {
+ write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx), SYS_IMP_APL_IPI_RR_LOCAL_EL1);
+ } else {
write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx) | FIELD_PREP(IPI_RR_CLUSTER, cluster),
SYS_IMP_APL_IPI_RR_GLOBAL_EL1);
+ }
isb();
}

@@ -990,6 +1008,9 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
if (!irqc->info.fast_ipi)
static_branch_disable(&use_fast_ipi);

+ if (!irqc->info.local_fast_ipi)
+ static_branch_disable(&use_local_fast_ipi);
+
irqc->info.die_stride = off - start_off;

irqc->hw_domain = irq_domain_create_tree(of_node_to_fwnode(node),