@@ -579,16 +579,36 @@ static __always_inline int gicv5_irq_domain_translate(struct irq_domain *d,
579579 unsigned int * type ,
580580 const u8 hwirq_type )
581581{
582- if (! is_of_node ( fwspec -> fwnode ))
583- return - EINVAL ;
582+ unsigned int hwirq_trigger ;
583+ u8 fwspec_irq_type ;
584584
585- if (fwspec -> param_count < 3 )
586- return - EINVAL ;
585+ if (is_of_node (fwspec -> fwnode )) {
587586
588- if (fwspec -> param [0 ] != hwirq_type )
589- return - EINVAL ;
587+ if (fwspec -> param_count < 3 )
588+ return - EINVAL ;
589+
590+ fwspec_irq_type = fwspec -> param [0 ];
591+
592+ if (fwspec -> param [0 ] != hwirq_type )
593+ return - EINVAL ;
594+
595+ * hwirq = fwspec -> param [1 ];
596+ hwirq_trigger = fwspec -> param [2 ];
597+ }
598+
599+ if (is_fwnode_irqchip (fwspec -> fwnode )) {
600+
601+ if (fwspec -> param_count != 2 )
602+ return - EINVAL ;
590603
591- * hwirq = fwspec -> param [1 ];
604+ fwspec_irq_type = FIELD_GET (GICV5_HWIRQ_TYPE , fwspec -> param [0 ]);
605+
606+ if (fwspec_irq_type != hwirq_type )
607+ return - EINVAL ;
608+
609+ * hwirq = FIELD_GET (GICV5_HWIRQ_ID , fwspec -> param [0 ]);
610+ hwirq_trigger = fwspec -> param [1 ];
611+ }
592612
593613 switch (hwirq_type ) {
594614 case GICV5_HWIRQ_TYPE_PPI :
@@ -600,7 +620,7 @@ static __always_inline int gicv5_irq_domain_translate(struct irq_domain *d,
600620 IRQ_TYPE_EDGE_RISING ;
601621 break ;
602622 case GICV5_HWIRQ_TYPE_SPI :
603- * type = fwspec -> param [ 2 ] & IRQ_TYPE_SENSE_MASK ;
623+ * type = hwirq_trigger & IRQ_TYPE_SENSE_MASK ;
604624 break ;
605625 default :
606626 BUILD_BUG_ON (1 );
@@ -660,10 +680,18 @@ static void gicv5_irq_domain_free(struct irq_domain *domain, unsigned int virq,
660680static int gicv5_irq_ppi_domain_select (struct irq_domain * d , struct irq_fwspec * fwspec ,
661681 enum irq_domain_bus_token bus_token )
662682{
683+ u32 hwirq_type ;
684+
663685 if (fwspec -> fwnode != d -> fwnode )
664686 return 0 ;
665687
666- if (fwspec -> param [0 ] != GICV5_HWIRQ_TYPE_PPI )
688+ if (is_of_node (fwspec -> fwnode ))
689+ hwirq_type = fwspec -> param [0 ];
690+
691+ if (is_fwnode_irqchip (fwspec -> fwnode ))
692+ hwirq_type = FIELD_GET (GICV5_HWIRQ_TYPE , fwspec -> param [0 ]);
693+
694+ if (hwirq_type != GICV5_HWIRQ_TYPE_PPI )
667695 return 0 ;
668696
669697 return (d == gicv5_global_data .ppi_domain );
@@ -718,10 +746,18 @@ static int gicv5_irq_spi_domain_alloc(struct irq_domain *domain, unsigned int vi
718746static int gicv5_irq_spi_domain_select (struct irq_domain * d , struct irq_fwspec * fwspec ,
719747 enum irq_domain_bus_token bus_token )
720748{
749+ u32 hwirq_type ;
750+
721751 if (fwspec -> fwnode != d -> fwnode )
722752 return 0 ;
723753
724- if (fwspec -> param [0 ] != GICV5_HWIRQ_TYPE_SPI )
754+ if (is_of_node (fwspec -> fwnode ))
755+ hwirq_type = fwspec -> param [0 ];
756+
757+ if (is_fwnode_irqchip (fwspec -> fwnode ))
758+ hwirq_type = FIELD_GET (GICV5_HWIRQ_TYPE , fwspec -> param [0 ]);
759+
760+ if (hwirq_type != GICV5_HWIRQ_TYPE_SPI )
725761 return 0 ;
726762
727763 return (d == gicv5_global_data .spi_domain );
@@ -1082,16 +1118,12 @@ static inline void __init gic_of_setup_kvm_info(struct device_node *node)
10821118}
10831119#endif // CONFIG_KVM
10841120
1085- static int __init gicv5_of_init (struct device_node * node , struct device_node * parent )
1121+ static int __init gicv5_init_common (struct fwnode_handle * parent_domain )
10861122{
1087- int ret = gicv5_irs_of_probe ( node );
1123+ int ret = gicv5_init_domains ( parent_domain );
10881124 if (ret )
10891125 return ret ;
10901126
1091- ret = gicv5_init_domains (of_fwnode_handle (node ));
1092- if (ret )
1093- goto out_irs ;
1094-
10951127 gicv5_set_cpuif_pribits ();
10961128 gicv5_set_cpuif_idbits ();
10971129
@@ -1113,18 +1145,82 @@ static int __init gicv5_of_init(struct device_node *node, struct device_node *pa
11131145 gicv5_smp_init ();
11141146
11151147 gicv5_irs_its_probe ();
1116-
1117- gic_of_setup_kvm_info (node );
1118-
11191148 return 0 ;
11201149
11211150out_int :
11221151 gicv5_cpu_disable_interrupts ();
11231152out_dom :
11241153 gicv5_free_domains ();
1154+ return ret ;
1155+ }
1156+
1157+ static int __init gicv5_of_init (struct device_node * node , struct device_node * parent )
1158+ {
1159+ int ret = gicv5_irs_of_probe (node );
1160+ if (ret )
1161+ return ret ;
1162+
1163+ ret = gicv5_init_common (of_fwnode_handle (node ));
1164+ if (ret )
1165+ goto out_irs ;
1166+
1167+ gic_of_setup_kvm_info (node );
1168+
1169+ return 0 ;
11251170out_irs :
11261171 gicv5_irs_remove ();
11271172
11281173 return ret ;
11291174}
11301175IRQCHIP_DECLARE (gic_v5 , "arm,gic-v5" , gicv5_of_init );
1176+
1177+ #ifdef CONFIG_ACPI
1178+ static bool __init acpi_validate_gic_table (struct acpi_subtable_header * header ,
1179+ struct acpi_probe_entry * ape )
1180+ {
1181+ struct acpi_madt_gicv5_irs * irs = (struct acpi_madt_gicv5_irs * )header ;
1182+
1183+ return (irs -> version == ape -> driver_data );
1184+ }
1185+
1186+ static struct fwnode_handle * gsi_domain_handle ;
1187+
1188+ static struct fwnode_handle * gic_v5_get_gsi_domain_id (u32 gsi )
1189+ {
1190+ return gsi_domain_handle ;
1191+ }
1192+
1193+ static int __init gic_acpi_init (union acpi_subtable_headers * header , const unsigned long end )
1194+ {
1195+ struct acpi_madt_gicv5_irs * irs = (struct acpi_madt_gicv5_irs * )header ;
1196+ int ret ;
1197+
1198+ if (gsi_domain_handle )
1199+ return 0 ;
1200+
1201+ gsi_domain_handle = irq_domain_alloc_fwnode (& irs -> config_base_address );
1202+ if (!gsi_domain_handle )
1203+ return - ENOMEM ;
1204+
1205+ ret = gicv5_irs_acpi_probe ();
1206+ if (ret )
1207+ goto out_fwnode ;
1208+
1209+ ret = gicv5_init_common (gsi_domain_handle );
1210+ if (ret )
1211+ goto out_irs ;
1212+
1213+ acpi_set_irq_model (ACPI_IRQ_MODEL_GIC_V5 , gic_v5_get_gsi_domain_id );
1214+
1215+ return 0 ;
1216+
1217+ out_irs :
1218+ gicv5_irs_remove ();
1219+ out_fwnode :
1220+ irq_domain_free_fwnode (gsi_domain_handle );
1221+ return ret ;
1222+ }
1223+ IRQCHIP_ACPI_DECLARE (gic_v5 , ACPI_MADT_TYPE_GICV5_IRS ,
1224+ acpi_validate_gic_table , ACPI_MADT_GIC_VERSION_V5 ,
1225+ gic_acpi_init );
1226+ #endif
0 commit comments