66
77#include <linux/acpi.h>
88#include <linux/sort.h>
9+ #include <linux/irq.h>
10+
11+ #include "init.h"
12+
13+ struct riscv_ext_intc_list {
14+ acpi_handle handle ;
15+ u32 gsi_base ;
16+ u32 nr_irqs ;
17+ u32 nr_idcs ;
18+ u32 id ;
19+ u32 type ;
20+ struct list_head list ;
21+ };
22+
23+ LIST_HEAD (ext_intc_list );
924
1025static int irqchip_cmp_func (const void * in0 , const void * in1 )
1126{
@@ -31,3 +46,135 @@ void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr)
3146 return ;
3247 sort (ape , nr , sizeof (* ape ), irqchip_cmp_func , NULL );
3348}
49+
50+ static acpi_status riscv_acpi_update_gsi_handle (u32 gsi_base , acpi_handle handle )
51+ {
52+ struct riscv_ext_intc_list * ext_intc_element ;
53+ struct list_head * i , * tmp ;
54+
55+ list_for_each_safe (i , tmp , & ext_intc_list ) {
56+ ext_intc_element = list_entry (i , struct riscv_ext_intc_list , list );
57+ if (gsi_base == ext_intc_element -> gsi_base ) {
58+ ext_intc_element -> handle = handle ;
59+ return AE_OK ;
60+ }
61+ }
62+
63+ return AE_NOT_FOUND ;
64+ }
65+
66+ int riscv_acpi_get_gsi_info (struct fwnode_handle * fwnode , u32 * gsi_base ,
67+ u32 * id , u32 * nr_irqs , u32 * nr_idcs )
68+ {
69+ struct riscv_ext_intc_list * ext_intc_element ;
70+ struct list_head * i ;
71+
72+ list_for_each (i , & ext_intc_list ) {
73+ ext_intc_element = list_entry (i , struct riscv_ext_intc_list , list );
74+ if (ext_intc_element -> handle == ACPI_HANDLE_FWNODE (fwnode )) {
75+ * gsi_base = ext_intc_element -> gsi_base ;
76+ * id = ext_intc_element -> id ;
77+ * nr_irqs = ext_intc_element -> nr_irqs ;
78+ if (nr_idcs )
79+ * nr_idcs = ext_intc_element -> nr_idcs ;
80+
81+ return 0 ;
82+ }
83+ }
84+
85+ return - ENODEV ;
86+ }
87+
88+ struct fwnode_handle * riscv_acpi_get_gsi_domain_id (u32 gsi )
89+ {
90+ struct riscv_ext_intc_list * ext_intc_element ;
91+ struct acpi_device * adev ;
92+ struct list_head * i ;
93+
94+ list_for_each (i , & ext_intc_list ) {
95+ ext_intc_element = list_entry (i , struct riscv_ext_intc_list , list );
96+ if (gsi >= ext_intc_element -> gsi_base &&
97+ gsi < (ext_intc_element -> gsi_base + ext_intc_element -> nr_irqs )) {
98+ adev = acpi_fetch_acpi_dev (ext_intc_element -> handle );
99+ if (!adev )
100+ return NULL ;
101+
102+ return acpi_fwnode_handle (adev );
103+ }
104+ }
105+
106+ return NULL ;
107+ }
108+
109+ static int __init riscv_acpi_register_ext_intc (u32 gsi_base , u32 nr_irqs , u32 nr_idcs ,
110+ u32 id , u32 type )
111+ {
112+ struct riscv_ext_intc_list * ext_intc_element ;
113+
114+ ext_intc_element = kzalloc (sizeof (* ext_intc_element ), GFP_KERNEL );
115+ if (!ext_intc_element )
116+ return - ENOMEM ;
117+
118+ ext_intc_element -> gsi_base = gsi_base ;
119+ ext_intc_element -> nr_irqs = nr_irqs ;
120+ ext_intc_element -> nr_idcs = nr_idcs ;
121+ ext_intc_element -> id = id ;
122+ list_add_tail (& ext_intc_element -> list , & ext_intc_list );
123+ return 0 ;
124+ }
125+
126+ static acpi_status __init riscv_acpi_create_gsi_map (acpi_handle handle , u32 level ,
127+ void * context , void * * return_value )
128+ {
129+ acpi_status status ;
130+ u64 gbase ;
131+
132+ if (!acpi_has_method (handle , "_GSB" )) {
133+ acpi_handle_err (handle , "_GSB method not found\n" );
134+ return AE_ERROR ;
135+ }
136+
137+ status = acpi_evaluate_integer (handle , "_GSB" , NULL , & gbase );
138+ if (ACPI_FAILURE (status )) {
139+ acpi_handle_err (handle , "failed to evaluate _GSB method\n" );
140+ return status ;
141+ }
142+
143+ status = riscv_acpi_update_gsi_handle ((u32 )gbase , handle );
144+ if (ACPI_FAILURE (status )) {
145+ acpi_handle_err (handle , "failed to find the GSI mapping entry\n" );
146+ return status ;
147+ }
148+
149+ return AE_OK ;
150+ }
151+
152+ static int __init riscv_acpi_aplic_parse_madt (union acpi_subtable_headers * header ,
153+ const unsigned long end )
154+ {
155+ struct acpi_madt_aplic * aplic = (struct acpi_madt_aplic * )header ;
156+
157+ return riscv_acpi_register_ext_intc (aplic -> gsi_base , aplic -> num_sources , aplic -> num_idcs ,
158+ aplic -> id , ACPI_RISCV_IRQCHIP_APLIC );
159+ }
160+
161+ static int __init riscv_acpi_plic_parse_madt (union acpi_subtable_headers * header ,
162+ const unsigned long end )
163+ {
164+ struct acpi_madt_plic * plic = (struct acpi_madt_plic * )header ;
165+
166+ return riscv_acpi_register_ext_intc (plic -> gsi_base , plic -> num_irqs , 0 ,
167+ plic -> id , ACPI_RISCV_IRQCHIP_PLIC );
168+ }
169+
170+ void __init riscv_acpi_init_gsi_mapping (void )
171+ {
172+ /* There can be either PLIC or APLIC */
173+ if (acpi_table_parse_madt (ACPI_MADT_TYPE_PLIC , riscv_acpi_plic_parse_madt , 0 ) > 0 ) {
174+ acpi_get_devices ("RSCV0001" , riscv_acpi_create_gsi_map , NULL , NULL );
175+ return ;
176+ }
177+
178+ if (acpi_table_parse_madt (ACPI_MADT_TYPE_APLIC , riscv_acpi_aplic_parse_madt , 0 ) > 0 )
179+ acpi_get_devices ("RSCV0002" , riscv_acpi_create_gsi_map , NULL , NULL );
180+ }
0 commit comments