60
60
#define PLIC_DISABLE_THRESHOLD 0x7
61
61
#define PLIC_ENABLE_THRESHOLD 0
62
62
63
+ #define PLIC_QUIRK_EDGE_INTERRUPT 0
64
+
63
65
struct plic_priv {
64
66
struct cpumask lmask ;
65
67
struct irq_domain * irqdomain ;
66
68
void __iomem * regs ;
69
+ unsigned long plic_quirks ;
67
70
};
68
71
69
72
struct plic_handler {
@@ -81,6 +84,8 @@ static int plic_parent_irq __ro_after_init;
81
84
static bool plic_cpuhp_setup_done __ro_after_init ;
82
85
static DEFINE_PER_CPU (struct plic_handler , plic_handlers ) ;
83
86
87
+ static int plic_irq_set_type (struct irq_data * d , unsigned int type );
88
+
84
89
static void __plic_toggle (void __iomem * enable_base , int hwirq , int enable )
85
90
{
86
91
u32 __iomem * reg = enable_base + (hwirq / 32 ) * sizeof (u32 );
@@ -176,6 +181,17 @@ static void plic_irq_eoi(struct irq_data *d)
176
181
}
177
182
}
178
183
184
+ static struct irq_chip plic_edge_chip = {
185
+ .name = "SiFive PLIC" ,
186
+ .irq_ack = plic_irq_eoi ,
187
+ .irq_mask = plic_irq_mask ,
188
+ .irq_unmask = plic_irq_unmask ,
189
+ #ifdef CONFIG_SMP
190
+ .irq_set_affinity = plic_set_affinity ,
191
+ #endif
192
+ .irq_set_type = plic_irq_set_type ,
193
+ };
194
+
179
195
static struct irq_chip plic_chip = {
180
196
.name = "SiFive PLIC" ,
181
197
.irq_mask = plic_irq_mask ,
@@ -184,8 +200,32 @@ static struct irq_chip plic_chip = {
184
200
#ifdef CONFIG_SMP
185
201
.irq_set_affinity = plic_set_affinity ,
186
202
#endif
203
+ .irq_set_type = plic_irq_set_type ,
187
204
};
188
205
206
+ static int plic_irq_set_type (struct irq_data * d , unsigned int type )
207
+ {
208
+ struct plic_priv * priv = irq_data_get_irq_chip_data (d );
209
+
210
+ if (!test_bit (PLIC_QUIRK_EDGE_INTERRUPT , & priv -> plic_quirks ))
211
+ return IRQ_SET_MASK_OK_NOCOPY ;
212
+
213
+ switch (type ) {
214
+ case IRQ_TYPE_EDGE_RISING :
215
+ irq_set_chip_handler_name_locked (d , & plic_edge_chip ,
216
+ handle_edge_irq , NULL );
217
+ break ;
218
+ case IRQ_TYPE_LEVEL_HIGH :
219
+ irq_set_chip_handler_name_locked (d , & plic_chip ,
220
+ handle_fasteoi_irq , NULL );
221
+ break ;
222
+ default :
223
+ return - EINVAL ;
224
+ }
225
+
226
+ return IRQ_SET_MASK_OK ;
227
+ }
228
+
189
229
static int plic_irqdomain_map (struct irq_domain * d , unsigned int irq ,
190
230
irq_hw_number_t hwirq )
191
231
{
@@ -198,6 +238,19 @@ static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
198
238
return 0 ;
199
239
}
200
240
241
+ static int plic_irq_domain_translate (struct irq_domain * d ,
242
+ struct irq_fwspec * fwspec ,
243
+ unsigned long * hwirq ,
244
+ unsigned int * type )
245
+ {
246
+ struct plic_priv * priv = d -> host_data ;
247
+
248
+ if (test_bit (PLIC_QUIRK_EDGE_INTERRUPT , & priv -> plic_quirks ))
249
+ return irq_domain_translate_twocell (d , fwspec , hwirq , type );
250
+
251
+ return irq_domain_translate_onecell (d , fwspec , hwirq , type );
252
+ }
253
+
201
254
static int plic_irq_domain_alloc (struct irq_domain * domain , unsigned int virq ,
202
255
unsigned int nr_irqs , void * arg )
203
256
{
@@ -206,7 +259,7 @@ static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
206
259
unsigned int type ;
207
260
struct irq_fwspec * fwspec = arg ;
208
261
209
- ret = irq_domain_translate_onecell (domain , fwspec , & hwirq , & type );
262
+ ret = plic_irq_domain_translate (domain , fwspec , & hwirq , & type );
210
263
if (ret )
211
264
return ret ;
212
265
@@ -220,7 +273,7 @@ static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
220
273
}
221
274
222
275
static const struct irq_domain_ops plic_irqdomain_ops = {
223
- .translate = irq_domain_translate_onecell ,
276
+ .translate = plic_irq_domain_translate ,
224
277
.alloc = plic_irq_domain_alloc ,
225
278
.free = irq_domain_free_irqs_top ,
226
279
};
@@ -281,8 +334,9 @@ static int plic_starting_cpu(unsigned int cpu)
281
334
return 0 ;
282
335
}
283
336
284
- static int __init plic_init (struct device_node * node ,
285
- struct device_node * parent )
337
+ static int __init __plic_init (struct device_node * node ,
338
+ struct device_node * parent ,
339
+ unsigned long plic_quirks )
286
340
{
287
341
int error = 0 , nr_contexts , nr_handlers = 0 , i ;
288
342
u32 nr_irqs ;
@@ -293,6 +347,8 @@ static int __init plic_init(struct device_node *node,
293
347
if (!priv )
294
348
return - ENOMEM ;
295
349
350
+ priv -> plic_quirks = plic_quirks ;
351
+
296
352
priv -> regs = of_iomap (node , 0 );
297
353
if (WARN_ON (!priv -> regs )) {
298
354
error = - EIO ;
@@ -410,6 +466,20 @@ static int __init plic_init(struct device_node *node,
410
466
return error ;
411
467
}
412
468
469
+ static int __init plic_init (struct device_node * node ,
470
+ struct device_node * parent )
471
+ {
472
+ return __plic_init (node , parent , 0 );
473
+ }
474
+
413
475
IRQCHIP_DECLARE (sifive_plic , "sifive,plic-1.0.0" , plic_init );
414
476
IRQCHIP_DECLARE (riscv_plic0 , "riscv,plic0" , plic_init ); /* for legacy systems */
415
- IRQCHIP_DECLARE (thead_c900_plic , "thead,c900-plic" , plic_init ); /* for firmware driver */
477
+
478
+ static int __init plic_edge_init (struct device_node * node ,
479
+ struct device_node * parent )
480
+ {
481
+ return __plic_init (node , parent , BIT (PLIC_QUIRK_EDGE_INTERRUPT ));
482
+ }
483
+
484
+ IRQCHIP_DECLARE (andestech_nceplic100 , "andestech,nceplic100" , plic_edge_init );
485
+ IRQCHIP_DECLARE (thead_c900_plic , "thead,c900-plic" , plic_edge_init );
0 commit comments