6060#define PLIC_DISABLE_THRESHOLD 0x7
6161#define PLIC_ENABLE_THRESHOLD 0
6262
63+ #define PLIC_QUIRK_EDGE_INTERRUPT 0
64+
6365struct plic_priv {
6466 struct cpumask lmask ;
6567 struct irq_domain * irqdomain ;
6668 void __iomem * regs ;
69+ unsigned long plic_quirks ;
6770};
6871
6972struct plic_handler {
@@ -81,6 +84,8 @@ static int plic_parent_irq __ro_after_init;
8184static bool plic_cpuhp_setup_done __ro_after_init ;
8285static DEFINE_PER_CPU (struct plic_handler , plic_handlers ) ;
8386
87+ static int plic_irq_set_type (struct irq_data * d , unsigned int type );
88+
8489static void __plic_toggle (void __iomem * enable_base , int hwirq , int enable )
8590{
8691 u32 __iomem * reg = enable_base + (hwirq / 32 ) * sizeof (u32 );
@@ -176,6 +181,17 @@ static void plic_irq_eoi(struct irq_data *d)
176181 }
177182}
178183
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+
179195static struct irq_chip plic_chip = {
180196 .name = "SiFive PLIC" ,
181197 .irq_mask = plic_irq_mask ,
@@ -184,8 +200,32 @@ static struct irq_chip plic_chip = {
184200#ifdef CONFIG_SMP
185201 .irq_set_affinity = plic_set_affinity ,
186202#endif
203+ .irq_set_type = plic_irq_set_type ,
187204};
188205
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+
189229static int plic_irqdomain_map (struct irq_domain * d , unsigned int irq ,
190230 irq_hw_number_t hwirq )
191231{
@@ -198,6 +238,19 @@ static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
198238 return 0 ;
199239}
200240
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+
201254static int plic_irq_domain_alloc (struct irq_domain * domain , unsigned int virq ,
202255 unsigned int nr_irqs , void * arg )
203256{
@@ -206,7 +259,7 @@ static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
206259 unsigned int type ;
207260 struct irq_fwspec * fwspec = arg ;
208261
209- ret = irq_domain_translate_onecell (domain , fwspec , & hwirq , & type );
262+ ret = plic_irq_domain_translate (domain , fwspec , & hwirq , & type );
210263 if (ret )
211264 return ret ;
212265
@@ -220,7 +273,7 @@ static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
220273}
221274
222275static const struct irq_domain_ops plic_irqdomain_ops = {
223- .translate = irq_domain_translate_onecell ,
276+ .translate = plic_irq_domain_translate ,
224277 .alloc = plic_irq_domain_alloc ,
225278 .free = irq_domain_free_irqs_top ,
226279};
@@ -281,8 +334,9 @@ static int plic_starting_cpu(unsigned int cpu)
281334 return 0 ;
282335}
283336
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 )
286340{
287341 int error = 0 , nr_contexts , nr_handlers = 0 , i ;
288342 u32 nr_irqs ;
@@ -293,6 +347,8 @@ static int __init plic_init(struct device_node *node,
293347 if (!priv )
294348 return - ENOMEM ;
295349
350+ priv -> plic_quirks = plic_quirks ;
351+
296352 priv -> regs = of_iomap (node , 0 );
297353 if (WARN_ON (!priv -> regs )) {
298354 error = - EIO ;
@@ -410,6 +466,20 @@ static int __init plic_init(struct device_node *node,
410466 return error ;
411467}
412468
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+
413475IRQCHIP_DECLARE (sifive_plic , "sifive,plic-1.0.0" , plic_init );
414476IRQCHIP_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