irqchip/apple-aic: Parse FIQ affinities from device-tree
authorMarc Zyngier <maz@kernel.org>
Wed, 3 Nov 2021 13:35:25 +0000 (13:35 +0000)
committerMarc Zyngier <maz@kernel.org>
Mon, 7 Feb 2022 16:00:42 +0000 (16:00 +0000)
In order to be able to tell the core IRQ code about the affinity
of the PMU interrupt in later patches, parse the affinities kindly
provided in the device-tree.

Signed-off-by: Marc Zyngier <maz@kernel.org>
drivers/irqchip/irq-apple-aic.c

index 38091ebb940330675c306df56c1e5adc4a893682..22d9b2058612b3d87697d616a8431289211b999f 100644 (file)
@@ -177,6 +177,9 @@ struct aic_irq_chip {
        void __iomem *base;
        struct irq_domain *hw_domain;
        struct irq_domain *ipi_domain;
+       struct {
+               cpumask_t aff;
+       } *fiq_aff[AIC_NR_FIQ];
        int nr_hw;
 };
 
@@ -793,12 +796,50 @@ static struct gic_kvm_info vgic_info __initdata = {
        .no_hw_deactivation     = true,
 };
 
+static void build_fiq_affinity(struct aic_irq_chip *ic, struct device_node *aff)
+{
+       int i, n;
+       u32 fiq;
+
+       if (of_property_read_u32(aff, "apple,fiq-index", &fiq) ||
+           WARN_ON(fiq >= AIC_NR_FIQ) || ic->fiq_aff[fiq])
+               return;
+
+       n = of_property_count_elems_of_size(aff, "cpus", sizeof(u32));
+       if (WARN_ON(n < 0))
+               return;
+
+       ic->fiq_aff[fiq] = kzalloc(sizeof(ic->fiq_aff[fiq]), GFP_KERNEL);
+       if (!ic->fiq_aff[fiq])
+               return;
+
+       for (i = 0; i < n; i++) {
+               struct device_node *cpu_node;
+               u32 cpu_phandle;
+               int cpu;
+
+               if (of_property_read_u32_index(aff, "cpus", i, &cpu_phandle))
+                       continue;
+
+               cpu_node = of_find_node_by_phandle(cpu_phandle);
+               if (WARN_ON(!cpu_node))
+                       continue;
+
+               cpu = of_cpu_node_to_id(cpu_node);
+               if (WARN_ON(cpu < 0))
+                       continue;
+
+               cpumask_set_cpu(cpu, &ic->fiq_aff[fiq]->aff);
+       }
+}
+
 static int __init aic_of_ic_init(struct device_node *node, struct device_node *parent)
 {
        int i;
        void __iomem *regs;
        u32 info;
        struct aic_irq_chip *irqc;
+       struct device_node *affs;
 
        regs = of_iomap(node, 0);
        if (WARN_ON(!regs))
@@ -832,6 +873,14 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
                return -ENODEV;
        }
 
+       affs = of_get_child_by_name(node, "affinities");
+       if (affs) {
+               struct device_node *chld;
+
+               for_each_child_of_node(affs, chld)
+                       build_fiq_affinity(irqc, chld);
+       }
+
        set_handle_irq(aic_handle_irq);
        set_handle_fiq(aic_handle_fiq);