6
6
*/
7
7
8
8
#define pr_fmt (fmt ) "riscv-intc: " fmt
9
+ #include <linux/acpi.h>
9
10
#include <linux/atomic.h>
10
11
#include <linux/bits.h>
11
12
#include <linux/cpu.h>
@@ -112,6 +113,30 @@ static struct fwnode_handle *riscv_intc_hwnode(void)
112
113
return intc_domain -> fwnode ;
113
114
}
114
115
116
+ static int __init riscv_intc_init_common (struct fwnode_handle * fn )
117
+ {
118
+ int rc ;
119
+
120
+ intc_domain = irq_domain_create_linear (fn , BITS_PER_LONG ,
121
+ & riscv_intc_domain_ops , NULL );
122
+ if (!intc_domain ) {
123
+ pr_err ("unable to add IRQ domain\n" );
124
+ return - ENXIO ;
125
+ }
126
+
127
+ rc = set_handle_irq (& riscv_intc_irq );
128
+ if (rc ) {
129
+ pr_err ("failed to set irq handler\n" );
130
+ return rc ;
131
+ }
132
+
133
+ riscv_set_intc_hwnode_fn (riscv_intc_hwnode );
134
+
135
+ pr_info ("%d local interrupts mapped\n" , BITS_PER_LONG );
136
+
137
+ return 0 ;
138
+ }
139
+
115
140
static int __init riscv_intc_init (struct device_node * node ,
116
141
struct device_node * parent )
117
142
{
@@ -133,24 +158,39 @@ static int __init riscv_intc_init(struct device_node *node,
133
158
if (riscv_hartid_to_cpuid (hartid ) != smp_processor_id ())
134
159
return 0 ;
135
160
136
- intc_domain = irq_domain_add_linear (node , BITS_PER_LONG ,
137
- & riscv_intc_domain_ops , NULL );
138
- if (!intc_domain ) {
139
- pr_err ("unable to add IRQ domain\n" );
140
- return - ENXIO ;
141
- }
161
+ return riscv_intc_init_common (of_node_to_fwnode (node ));
162
+ }
142
163
143
- rc = set_handle_irq (& riscv_intc_irq );
144
- if (rc ) {
145
- pr_err ("failed to set irq handler\n" );
146
- return rc ;
147
- }
164
+ IRQCHIP_DECLARE (riscv , "riscv,cpu-intc" , riscv_intc_init );
148
165
149
- riscv_set_intc_hwnode_fn ( riscv_intc_hwnode );
166
+ #ifdef CONFIG_ACPI
150
167
151
- pr_info ("%d local interrupts mapped\n" , BITS_PER_LONG );
168
+ static int __init riscv_intc_acpi_init (union acpi_subtable_headers * header ,
169
+ const unsigned long end )
170
+ {
171
+ struct fwnode_handle * fn ;
172
+ struct acpi_madt_rintc * rintc ;
152
173
153
- return 0 ;
174
+ rintc = (struct acpi_madt_rintc * )header ;
175
+
176
+ /*
177
+ * The ACPI MADT will have one INTC for each CPU (or HART)
178
+ * so riscv_intc_acpi_init() function will be called once
179
+ * for each INTC. We only do INTC initialization
180
+ * for the INTC belonging to the boot CPU (or boot HART).
181
+ */
182
+ if (riscv_hartid_to_cpuid (rintc -> hart_id ) != smp_processor_id ())
183
+ return 0 ;
184
+
185
+ fn = irq_domain_alloc_named_fwnode ("RISCV-INTC" );
186
+ if (!fn ) {
187
+ pr_err ("unable to allocate INTC FW node\n" );
188
+ return - ENOMEM ;
189
+ }
190
+
191
+ return riscv_intc_init_common (fn );
154
192
}
155
193
156
- IRQCHIP_DECLARE (riscv , "riscv,cpu-intc" , riscv_intc_init );
194
+ IRQCHIP_ACPI_DECLARE (riscv_intc , ACPI_MADT_TYPE_RINTC , NULL ,
195
+ ACPI_MADT_RINTC_VERSION_V1 , riscv_intc_acpi_init );
196
+ #endif
0 commit comments