summaryrefslogtreecommitdiff
path: root/drivers/irqchip/irq-apple-aic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/irqchip/irq-apple-aic.c')
-rw-r--r--drivers/irqchip/irq-apple-aic.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c
index 032d66dceb8e..795b3db4554a 100644
--- a/drivers/irqchip/irq-apple-aic.c
+++ b/drivers/irqchip/irq-apple-aic.c
@@ -578,16 +578,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs)
}
if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) ==
- (FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) {
- int irq;
- if (cpumask_test_cpu(smp_processor_id(),
- &aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff))
- irq = AIC_CPU_PMU_P;
- else
- irq = AIC_CPU_PMU_E;
+ (FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT))
generic_handle_domain_irq(aic_irqc->hw_domain,
- AIC_FIQ_HWIRQ(irq));
- }
+ AIC_FIQ_HWIRQ(AIC_CPU_PMU_P));
if (static_branch_likely(&use_fast_ipi) &&
(FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ) &&
@@ -632,18 +625,7 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
handle_fasteoi_irq, NULL, NULL);
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
} else {
- int fiq = FIELD_GET(AIC_EVENT_NUM, 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);
- break;
- }
-
+ irq_set_percpu_devid(irq);
irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data,
handle_percpu_devid_irq, NULL, NULL);
}
@@ -651,6 +633,33 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
return 0;
}
+static int aic_irq_get_fwspec_info(struct irq_fwspec *fwspec, struct irq_fwspec_info *info)
+{
+ const struct cpumask *mask;
+ u32 intid;
+
+ info->flags = 0;
+ info->affinity = NULL;
+
+ if (fwspec->param[0] != AIC_FIQ)
+ return 0;
+
+ if (fwspec->param_count == 3)
+ intid = fwspec->param[1];
+ else
+ intid = fwspec->param[2];
+
+ if (aic_irqc->fiq_aff[intid])
+ mask = &aic_irqc->fiq_aff[intid]->aff;
+ else
+ mask = cpu_possible_mask;
+
+ info->affinity = mask;
+ info->flags = IRQ_FWSPEC_INFO_AFFINITY_VALID;
+
+ return 0;
+}
+
static int aic_irq_domain_translate(struct irq_domain *id,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
@@ -705,6 +714,10 @@ static int aic_irq_domain_translate(struct irq_domain *id,
break;
}
}
+
+ /* Merge the two PMUs on a single interrupt */
+ if (*hwirq == AIC_CPU_PMU_E)
+ *hwirq = AIC_CPU_PMU_P;
break;
default:
return -EINVAL;
@@ -750,9 +763,10 @@ static void aic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops aic_irq_domain_ops = {
- .translate = aic_irq_domain_translate,
- .alloc = aic_irq_domain_alloc,
- .free = aic_irq_domain_free,
+ .translate = aic_irq_domain_translate,
+ .alloc = aic_irq_domain_alloc,
+ .free = aic_irq_domain_free,
+ .get_fwspec_info = aic_irq_get_fwspec_info,
};
/*