mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
irqchip/apple-aic: Only access system registers on SoCs which provide them
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. Co-developed-by: Nick Chan <towinchenmi@gmail.com> Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org> Signed-off-by: Nick Chan <towinchenmi@gmail.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Sven Peter <sven@svenpeter.dev> Link: https://lore.kernel.org/all/20240901034143.12731-5-towinchenmi@gmail.com
This commit is contained in:
parent
a845342e6e
commit
59fc20ba70
@ -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,
|
||||
@ -829,7 +826,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);
|
||||
@ -850,8 +848,10 @@ 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();
|
||||
|
Loading…
Reference in New Issue
Block a user