Skip to content

Commit c425060

Browse files
author
Marc Zyngier
committed
Merge branch irq/aic-pmu into irq/irqchip-next
* irq/aic-pmu: : . : Prefix branch for the M1 PMU support, adding the required : irqchip changes. Shared with the arm64 tree. : . irqchip/apple-aic: Fix cpumask allocation for FIQs irqchip/apple-aic: Move PMU-specific registers to their own include file arm64: dts: apple: Add t8303 PMU nodes arm64: dts: apple: Add t8103 PMU interrupt affinities irqchip/apple-aic: Wire PMU interrupts irqchip/apple-aic: Parse FIQ affinities from device-tree dt-bindings: apple,aic: Add affinity description for per-cpu pseudo-interrupts dt-bindings: apple,aic: Add CPU PMU per-cpu pseudo-interrupts dt-bindings: arm-pmu: Document Apple PMU compatible strings Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents 92af5d4 + dc29812 commit c425060

6 files changed

Lines changed: 150 additions & 22 deletions

File tree

Documentation/devicetree/bindings/arm/pmu.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ properties:
2020
items:
2121
- enum:
2222
- apm,potenza-pmu
23+
- apple,firestorm-pmu
24+
- apple,icestorm-pmu
2325
- arm,armv8-pmuv3 # Only for s/w models
2426
- arm,arm1136-pmu
2527
- arm,arm1176-pmu

Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ properties:
5656
- 1: virtual HV timer
5757
- 2: physical guest timer
5858
- 3: virtual guest timer
59+
- 4: 'efficient' CPU PMU
60+
- 5: 'performance' CPU PMU
5961
6062
The 3rd cell contains the interrupt flags. This is normally
6163
IRQ_TYPE_LEVEL_HIGH (4).
@@ -68,6 +70,35 @@ properties:
6870
power-domains:
6971
maxItems: 1
7072

73+
affinities:
74+
type: object
75+
additionalProperties: false
76+
description:
77+
FIQ affinity can be expressed as a single "affinities" node,
78+
containing a set of sub-nodes, one per FIQ with a non-default
79+
affinity.
80+
patternProperties:
81+
"^.+-affinity$":
82+
type: object
83+
additionalProperties: false
84+
properties:
85+
apple,fiq-index:
86+
description:
87+
The interrupt number specified as a FIQ, and for which
88+
the affinity is not the default.
89+
$ref: /schemas/types.yaml#/definitions/uint32
90+
maximum: 5
91+
92+
cpus:
93+
$ref: /schemas/types.yaml#/definitions/phandle-array
94+
description:
95+
Should be a list of phandles to CPU nodes (as described in
96+
Documentation/devicetree/bindings/arm/cpus.yaml).
97+
98+
required:
99+
- fiq-index
100+
- cpus
101+
71102
required:
72103
- compatible
73104
- '#interrupt-cells'

arch/arm64/boot/dts/apple/t8103.dtsi

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@
9797
<AIC_FIQ AIC_TMR_HV_VIRT IRQ_TYPE_LEVEL_HIGH>;
9898
};
9999

100+
pmu-e {
101+
compatible = "apple,icestorm-pmu";
102+
interrupt-parent = <&aic>;
103+
interrupts = <AIC_FIQ AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
104+
};
105+
106+
pmu-p {
107+
compatible = "apple,firestorm-pmu";
108+
interrupt-parent = <&aic>;
109+
interrupts = <AIC_FIQ AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
110+
};
111+
100112
clkref: clock-ref {
101113
compatible = "fixed-clock";
102114
#clock-cells = <0>;
@@ -213,6 +225,18 @@
213225
interrupt-controller;
214226
reg = <0x2 0x3b100000 0x0 0x8000>;
215227
power-domains = <&ps_aic>;
228+
229+
affinities {
230+
e-core-pmu-affinity {
231+
apple,fiq-index = <AIC_CPU_PMU_E>;
232+
cpus = <&cpu0 &cpu1 &cpu2 &cpu3>;
233+
};
234+
235+
p-core-pmu-affinity {
236+
apple,fiq-index = <AIC_CPU_PMU_P>;
237+
cpus = <&cpu4 &cpu5 &cpu6 &cpu7>;
238+
};
239+
};
216240
};
217241

218242
pmgr: power-management@23b700000 {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#ifndef __ASM_APPLE_M1_PMU_h
4+
#define __ASM_APPLE_M1_PMU_h
5+
6+
#include <linux/bits.h>
7+
#include <asm/sysreg.h>
8+
9+
/* Core PMC control register */
10+
#define SYS_IMP_APL_PMCR0_EL1 sys_reg(3, 1, 15, 0, 0)
11+
#define PMCR0_IMODE GENMASK(10, 8)
12+
#define PMCR0_IMODE_OFF 0
13+
#define PMCR0_IMODE_PMI 1
14+
#define PMCR0_IMODE_AIC 2
15+
#define PMCR0_IMODE_HALT 3
16+
#define PMCR0_IMODE_FIQ 4
17+
#define PMCR0_IACT BIT(11)
18+
19+
#endif /* __ASM_APPLE_M1_PMU_h */

drivers/irqchip/irq-apple-aic.c

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include <linux/limits.h>
5656
#include <linux/of_address.h>
5757
#include <linux/slab.h>
58+
#include <asm/apple_m1_pmu.h>
5859
#include <asm/exception.h>
5960
#include <asm/sysreg.h>
6061
#include <asm/virt.h>
@@ -109,16 +110,6 @@
109110
* Note: sysreg-based IPIs are not supported yet.
110111
*/
111112

112-
/* Core PMC control register */
113-
#define SYS_IMP_APL_PMCR0_EL1 sys_reg(3, 1, 15, 0, 0)
114-
#define PMCR0_IMODE GENMASK(10, 8)
115-
#define PMCR0_IMODE_OFF 0
116-
#define PMCR0_IMODE_PMI 1
117-
#define PMCR0_IMODE_AIC 2
118-
#define PMCR0_IMODE_HALT 3
119-
#define PMCR0_IMODE_FIQ 4
120-
#define PMCR0_IACT BIT(11)
121-
122113
/* IPI request registers */
123114
#define SYS_IMP_APL_IPI_RR_LOCAL_EL1 sys_reg(3, 5, 15, 0, 0)
124115
#define SYS_IMP_APL_IPI_RR_GLOBAL_EL1 sys_reg(3, 5, 15, 0, 1)
@@ -155,7 +146,7 @@
155146
#define SYS_IMP_APL_UPMSR_EL1 sys_reg(3, 7, 15, 6, 4)
156147
#define UPMSR_IACT BIT(0)
157148

158-
#define AIC_NR_FIQ 4
149+
#define AIC_NR_FIQ 6
159150
#define AIC_NR_SWIPI 32
160151

161152
/*
@@ -177,6 +168,9 @@ struct aic_irq_chip {
177168
void __iomem *base;
178169
struct irq_domain *hw_domain;
179170
struct irq_domain *ipi_domain;
171+
struct {
172+
cpumask_t aff;
173+
} *fiq_aff[AIC_NR_FIQ];
180174
int nr_hw;
181175
};
182176

@@ -412,16 +406,15 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs)
412406
aic_irqc->nr_hw + AIC_TMR_EL02_VIRT);
413407
}
414408

415-
if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) ==
416-
(FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) {
417-
/*
418-
* Not supported yet, let's figure out how to handle this when
419-
* we implement these proprietary performance counters. For now,
420-
* just mask it and move on.
421-
*/
422-
pr_err_ratelimited("PMC FIQ fired. Masking.\n");
423-
sysreg_clear_set_s(SYS_IMP_APL_PMCR0_EL1, PMCR0_IMODE | PMCR0_IACT,
424-
FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_OFF));
409+
if (read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & PMCR0_IACT) {
410+
int irq;
411+
if (cpumask_test_cpu(smp_processor_id(),
412+
&aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff))
413+
irq = AIC_CPU_PMU_P;
414+
else
415+
irq = AIC_CPU_PMU_E;
416+
generic_handle_domain_irq(aic_irqc->hw_domain,
417+
aic_irqc->nr_hw + irq);
425418
}
426419

427420
if (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ &&
@@ -461,7 +454,18 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
461454
handle_fasteoi_irq, NULL, NULL);
462455
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
463456
} else {
464-
irq_set_percpu_devid(irq);
457+
int fiq = hw - ic->nr_hw;
458+
459+
switch (fiq) {
460+
case AIC_CPU_PMU_P:
461+
case AIC_CPU_PMU_E:
462+
irq_set_percpu_devid_partition(irq, &ic->fiq_aff[fiq]->aff);
463+
break;
464+
default:
465+
irq_set_percpu_devid(irq);
466+
break;
467+
}
468+
465469
irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data,
466470
handle_percpu_devid_irq, NULL, NULL);
467471
}
@@ -793,12 +797,50 @@ static struct gic_kvm_info vgic_info __initdata = {
793797
.no_hw_deactivation = true,
794798
};
795799

800+
static void build_fiq_affinity(struct aic_irq_chip *ic, struct device_node *aff)
801+
{
802+
int i, n;
803+
u32 fiq;
804+
805+
if (of_property_read_u32(aff, "apple,fiq-index", &fiq) ||
806+
WARN_ON(fiq >= AIC_NR_FIQ) || ic->fiq_aff[fiq])
807+
return;
808+
809+
n = of_property_count_elems_of_size(aff, "cpus", sizeof(u32));
810+
if (WARN_ON(n < 0))
811+
return;
812+
813+
ic->fiq_aff[fiq] = kzalloc(sizeof(*ic->fiq_aff[fiq]), GFP_KERNEL);
814+
if (!ic->fiq_aff[fiq])
815+
return;
816+
817+
for (i = 0; i < n; i++) {
818+
struct device_node *cpu_node;
819+
u32 cpu_phandle;
820+
int cpu;
821+
822+
if (of_property_read_u32_index(aff, "cpus", i, &cpu_phandle))
823+
continue;
824+
825+
cpu_node = of_find_node_by_phandle(cpu_phandle);
826+
if (WARN_ON(!cpu_node))
827+
continue;
828+
829+
cpu = of_cpu_node_to_id(cpu_node);
830+
if (WARN_ON(cpu < 0))
831+
continue;
832+
833+
cpumask_set_cpu(cpu, &ic->fiq_aff[fiq]->aff);
834+
}
835+
}
836+
796837
static int __init aic_of_ic_init(struct device_node *node, struct device_node *parent)
797838
{
798839
int i;
799840
void __iomem *regs;
800841
u32 info;
801842
struct aic_irq_chip *irqc;
843+
struct device_node *affs;
802844

803845
regs = of_iomap(node, 0);
804846
if (WARN_ON(!regs))
@@ -832,6 +874,14 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
832874
return -ENODEV;
833875
}
834876

877+
affs = of_get_child_by_name(node, "affinities");
878+
if (affs) {
879+
struct device_node *chld;
880+
881+
for_each_child_of_node(affs, chld)
882+
build_fiq_affinity(irqc, chld);
883+
}
884+
835885
set_handle_irq(aic_handle_irq);
836886
set_handle_fiq(aic_handle_fiq);
837887

include/dt-bindings/interrupt-controller/apple-aic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@
1111
#define AIC_TMR_HV_VIRT 1
1212
#define AIC_TMR_GUEST_PHYS 2
1313
#define AIC_TMR_GUEST_VIRT 3
14+
#define AIC_CPU_PMU_E 4
15+
#define AIC_CPU_PMU_P 5
1416

1517
#endif

0 commit comments

Comments
 (0)