6
6
7
7
#include <linux/acpi.h>
8
8
#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 );
9
24
10
25
static int irqchip_cmp_func (const void * in0 , const void * in1 )
11
26
{
@@ -31,3 +46,135 @@ void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr)
31
46
return ;
32
47
sort (ape , nr , sizeof (* ape ), irqchip_cmp_func , NULL );
33
48
}
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