irqchip/apple-aic: Wire PMU interrupts

Add the necessary code to configure and P and E-core PMU interrupts
with their respective affinities. When such an interrupt fires, map
it onto the right pseudo-interrupt.

Reviewed-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
Marc Zyngier 2021-11-01 19:59:20 +00:00
parent a5e8801202
commit c7708816c9
1 changed files with 22 additions and 12 deletions

View File

@ -155,7 +155,7 @@
#define SYS_IMP_APL_UPMSR_EL1 sys_reg(3, 7, 15, 6, 4) #define SYS_IMP_APL_UPMSR_EL1 sys_reg(3, 7, 15, 6, 4)
#define UPMSR_IACT BIT(0) #define UPMSR_IACT BIT(0)
#define AIC_NR_FIQ 4 #define AIC_NR_FIQ 6
#define AIC_NR_SWIPI 32 #define AIC_NR_SWIPI 32
/* /*
@ -415,16 +415,15 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs)
aic_irqc->nr_hw + AIC_TMR_EL02_VIRT); aic_irqc->nr_hw + AIC_TMR_EL02_VIRT);
} }
if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) == if (read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & PMCR0_IACT) {
(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) { int irq;
/* if (cpumask_test_cpu(smp_processor_id(),
* Not supported yet, let's figure out how to handle this when &aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff))
* we implement these proprietary performance counters. For now, irq = AIC_CPU_PMU_P;
* just mask it and move on. else
*/ irq = AIC_CPU_PMU_E;
pr_err_ratelimited("PMC FIQ fired. Masking.\n"); generic_handle_domain_irq(aic_irqc->hw_domain,
sysreg_clear_set_s(SYS_IMP_APL_PMCR0_EL1, PMCR0_IMODE | PMCR0_IACT, aic_irqc->nr_hw + irq);
FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_OFF));
} }
if (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ && if (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ &&
@ -464,7 +463,18 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
handle_fasteoi_irq, NULL, NULL); handle_fasteoi_irq, NULL, NULL);
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
} else { } else {
int fiq = hw - ic->nr_hw;
switch (fiq) {
case AIC_CPU_PMU_P:
case AIC_CPU_PMU_E:
irq_set_percpu_devid_partition(irq, &ic->fiq_aff[fiq]->aff);
break;
default:
irq_set_percpu_devid(irq); irq_set_percpu_devid(irq);
break;
}
irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data, irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data,
handle_percpu_devid_irq, NULL, NULL); handle_percpu_devid_irq, NULL, NULL);
} }