Hi, This patch series introduce support for A7-A11 SoCs into the AIC driver by if'ing out some features unavailable on them. For background information about these SoCs, see v1. Changes since v2: - Removed mention of the IPI-always-ack code path in aic_handle_fiq(). The patch to enable A7-A10 SoC to work is a bug fix to avoid accessing sysregs on configurations that do not provide them, and the rest of the message already explains what's going on. Changes since v1: - Corrected dt-binding issues pointed out by Rob, all of A7-M1 gets its own SoC compat, as well as the "apple,aic" generic fallback. - Order the AIC dt-bindings of the SoCs by release dates instead of alphabetical order: 's5l8960x' (A7) -> 't7000' (A8) -> 's8000' (A9) -> 't8010' (A10) -> 't8015' (A11) -> 't8103' (M1) - The patch to disallow local fast IPI on A11 now comes before the patch that enables to AIC driver to work on slow IPI systems. This ensures all IPI-always-ack code path in aic_handle_fiq() is removed by the slow IPI patch. - Keep local fast IPI enabled on AIC2, mistake in V1 - Describe the feature levels in the description of AIC. - Add new patch to remove unneccessary enablement of use_fast_ipi. - Do not try to enable use_local_fast_ipi, because it is enabled by default. In theory M1 can also get the apple,t8015-aic (A11) compatible. However, I do not see a point in doing that. Previous versions: v1: https://lore.kernel.org/asahi/20240829092610.89731-1-towinchenmi@gmail.com v2: https://lore.kernel.org/asahi/20240831055605.3542-1-towinchenmi@gmail.com Nick Chan Konrad Dybcio (1): irqchip/apple-aic: Only access system registers on SoCs which provide them Nick Chan (3): dt-bindings: apple,aic: Document A7-A11 compatibles irqchip/apple-aic: Skip unnecessary setting of use_fast_ipi irqchip/apple-aic: Add a new "Global fast IPIs only" feature level .../interrupt-controller/apple,aic.yaml | 14 ++++- drivers/irqchip/irq-apple-aic.c | 53 +++++++++++++------ 2 files changed, 49 insertions(+), 18 deletions(-) base-commit: 985bf40edf4343dcb04c33f58b40b4a85c1776d4 -- 2.46.0
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~postmarketos/upstreaming/patches/54812/mbox | git am -3Learn more about email & git
Document and describe the compatibles for Apple A7-A11 SoCs. There are three feature levels: - apple,aic: No fast IPI, for A7-A10 - apple,t8015-aic: fast IPI, global only, for A11 - apple,t8103-aic: fast IPI with local and global support, for M1 Each feature level is an extension of the previous, for example, M1 will also work with the A7 feature level. All of A7-M1 gets its own SoC-specific compatible, and the "apple,aic" compatible as a fallback. Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Reviewed-by: Sven Peter <sven@svenpeter.dev> Signed-off-by: Nick Chan <towinchenmi@gmail.com> --- .../bindings/interrupt-controller/apple,aic.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml index 698588e9aa86..4be9b596a790 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml @@ -31,13 +31,25 @@ description: | This device also represents the FIQ interrupt sources on platforms using AIC, which do not go through a discrete interrupt controller. + IPIs may be performed via MMIO registers on all variants of AIC. Starting + from A11, system registers may also be used for "fast" IPIs. Starting from + M1, even faster IPIs within the same cluster may be achieved by writing to + a "local" fast IPI register as opposed to using the "global" fast IPI + register. + allOf: - $ref: /schemas/interrupt-controller.yaml# properties: compatible: items: - - const: apple,t8103-aic + - enum: + - apple,s5l8960x-aic + - apple,t7000-aic + - apple,s8000-aic + - apple,t8010-aic + - apple,t8015-aic + - apple,t8103-aic - const: apple,aic interrupt-controller: true -- 2.46.0
use_fast_ipi is true by default and there is no need to "enable" it. Reviewed-by: Sven Peter <sven@svenpeter.dev> Signed-off-by: Nick Chan <towinchenmi@gmail.com> --- drivers/irqchip/irq-apple-aic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 5c534d9fd2b0..8d81d5fb3c50 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -987,9 +987,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p off += sizeof(u32) * (irqc->max_irq >> 5); /* MASK_CLR */ off += sizeof(u32) * (irqc->max_irq >> 5); /* HW_STATE */ - if (irqc->info.fast_ipi) - static_branch_enable(&use_fast_ipi); - else + if (!irqc->info.fast_ipi) static_branch_disable(&use_fast_ipi); irqc->info.die_stride = off - start_off; -- 2.46.0
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. Reviewed-by: Sven Peter <sven@svenpeter.dev> Signed-off-by: Nick Chan <towinchenmi@gmail.com> --- drivers/irqchip/irq-apple-aic.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 8d81d5fb3c50..01a3c79054f5 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,7 +768,8 @@ static void aic_ipi_send_fast(int cpu) u64 cluster = MPIDR_CLUSTER(mpidr); u64 idx = MPIDR_CPU(mpidr); - if (MPIDR_CLUSTER(my_mpidr) == cluster) + 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 @@ -990,6 +1009,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), -- 2.46.0
From: Konrad Dybcio <konrad.dybcio@somainline.org> Starting from the A11 (T8015) SoC, Apple introuced system registers for fast IPI and UNCORE PMC control. These sysregs do not exist on earlier A7-A10 SoCs and trying to access them results in an instant crash. Restrict sysreg access within the AIC driver to configurations where use_fast_ipi is true to allow AIC to function properly on A7-A10 SoCs. Reviewed-by: Sven Peter <sven@svenpeter.dev> Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org> Co-developed-by: Nick Chan <towinchenmi@gmail.com> Signed-off-by: Nick Chan <towinchenmi@gmail.com> --- drivers/irqchip/irq-apple-aic.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 01a3c79054f5..a6d812afb10d 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -234,6 +234,7 @@ enum fiq_hwirq { AIC_NR_FIQ }; +/* True if UNCORE/UNCORE2 and Sn_... IPI registers are present and used (A11+) */ 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); @@ -550,14 +551,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) * we check for everything here, even things we don't support yet. */ - if (read_sysreg_s(SYS_IMP_APL_IPI_SR_EL1) & IPI_SR_PENDING) { - if (static_branch_likely(&use_fast_ipi)) { - aic_handle_ipi(regs); - } else { - pr_err_ratelimited("Fast IPI fired. Acking.\n"); - write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); - } - } + if (static_branch_likely(&use_fast_ipi) && + (read_sysreg_s(SYS_IMP_APL_IPI_SR_EL1) & IPI_SR_PENDING)) + aic_handle_ipi(regs); if (TIMER_FIRING(read_sysreg(cntp_ctl_el0))) generic_handle_domain_irq(aic_irqc->hw_domain, @@ -592,8 +588,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) AIC_FIQ_HWIRQ(irq)); } - if (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ && - (read_sysreg_s(SYS_IMP_APL_UPMSR_EL1) & UPMSR_IACT)) { + if (static_branch_likely(&use_fast_ipi) && + (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ) && + (read_sysreg_s(SYS_IMP_APL_UPMSR_EL1) & UPMSR_IACT)) { /* Same story with uncore PMCs */ pr_err_ratelimited("Uncore PMC FIQ fired. Masking.\n"); sysreg_clear_set_s(SYS_IMP_APL_UPMCR0_EL1, UPMCR0_IMODE, @@ -830,7 +827,8 @@ static int aic_init_cpu(unsigned int cpu) /* Mask all hard-wired per-CPU IRQ/FIQ sources */ /* Pending Fast IPI FIQs */ - write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); + if (static_branch_likely(&use_fast_ipi)) + write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); /* Timer FIQs */ sysreg_clear_set(cntp_ctl_el0, 0, ARCH_TIMER_CTRL_IT_MASK); @@ -851,8 +849,9 @@ static int aic_init_cpu(unsigned int cpu) FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_OFF)); /* Uncore PMC FIQ */ - sysreg_clear_set_s(SYS_IMP_APL_UPMCR0_EL1, UPMCR0_IMODE, - FIELD_PREP(UPMCR0_IMODE, UPMCR0_IMODE_OFF)); + if (static_branch_likely(&use_fast_ipi)) + sysreg_clear_set_s(SYS_IMP_APL_UPMCR0_EL1, UPMCR0_IMODE, + FIELD_PREP(UPMCR0_IMODE, UPMCR0_IMODE_OFF)); /* Commit all of the above */ isb(); -- 2.46.0