1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for IDT/Renesas 79RC3243x Interrupt Controller.
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include <linux/interrupt.h>
10 #include <linux/irqchip.h>
11 #include <linux/irqchip/chained_irq.h>
12 #include <linux/irqdomain.h>
13 #include <linux/of_address.h>
14 #include <linux/of_irq.h>
16 #define IDT_PIC_NR_IRQS 32
18 #define IDT_PIC_IRQ_PEND 0x00
19 #define IDT_PIC_IRQ_MASK 0x08
23 struct irq_domain
*irq_domain
;
24 struct irq_chip_generic
*gc
;
27 static void idt_irq_dispatch(struct irq_desc
*desc
)
29 struct idt_pic_data
*idtpic
= irq_desc_get_handler_data(desc
);
30 struct irq_chip
*host_chip
= irq_desc_get_chip(desc
);
33 chained_irq_enter(host_chip
, desc
);
35 pending
= irq_reg_readl(idtpic
->gc
, IDT_PIC_IRQ_PEND
);
36 pending
&= ~idtpic
->gc
->mask_cache
;
38 hwirq
= __fls(pending
);
39 generic_handle_domain_irq(idtpic
->irq_domain
, hwirq
);
40 pending
&= ~(1 << hwirq
);
43 chained_irq_exit(host_chip
, desc
);
46 static int idt_pic_init(struct device_node
*of_node
, struct device_node
*parent
)
48 struct irq_domain
*domain
;
49 struct idt_pic_data
*idtpic
;
50 struct irq_chip_generic
*gc
;
51 struct irq_chip_type
*ct
;
52 unsigned int parent_irq
;
55 idtpic
= kzalloc(sizeof(*idtpic
), GFP_KERNEL
);
61 parent_irq
= irq_of_parse_and_map(of_node
, 0);
63 pr_err("Failed to map parent IRQ!\n");
68 idtpic
->base
= of_iomap(of_node
, 0);
70 pr_err("Failed to map base address!\n");
75 domain
= irq_domain_add_linear(of_node
, IDT_PIC_NR_IRQS
,
76 &irq_generic_chip_ops
, NULL
);
78 pr_err("Failed to add irqdomain!\n");
82 idtpic
->irq_domain
= domain
;
84 ret
= irq_alloc_domain_generic_chips(domain
, 32, 1, "IDTPIC",
86 IRQ_NOPROBE
| IRQ_LEVEL
, 0);
88 goto out_domain_remove
;
90 gc
= irq_get_domain_generic_chip(domain
, 0);
91 gc
->reg_base
= idtpic
->base
;
95 ct
->regs
.mask
= IDT_PIC_IRQ_MASK
;
96 ct
->chip
.irq_mask
= irq_gc_mask_set_bit
;
97 ct
->chip
.irq_unmask
= irq_gc_mask_clr_bit
;
100 /* Mask interrupts. */
101 writel(0xffffffff, idtpic
->base
+ IDT_PIC_IRQ_MASK
);
102 gc
->mask_cache
= 0xffffffff;
104 irq_set_chained_handler_and_data(parent_irq
,
105 idt_irq_dispatch
, idtpic
);
110 irq_domain_remove(domain
);
112 iounmap(idtpic
->base
);
114 irq_dispose_mapping(parent_irq
);
118 pr_err("Failed to initialize! (errno = %d)\n", ret
);
122 IRQCHIP_DECLARE(idt_pic
, "idt,32434-pic", idt_pic_init
);