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>
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)
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+
796837static 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
0 commit comments