1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2015-2016 Vladimir Zapolskiy <vz@mleia.com>
6 #define pr_fmt(fmt) "%s: " fmt, __func__
9 #include <linux/irqchip.h>
10 #include <linux/irqchip/chained_irq.h>
11 #include <linux/of_address.h>
12 #include <linux/of_irq.h>
13 #include <linux/of_platform.h>
14 #include <linux/slab.h>
15 #include <asm/exception.h>
17 #define LPC32XX_INTC_MASK 0x00
18 #define LPC32XX_INTC_RAW 0x04
19 #define LPC32XX_INTC_STAT 0x08
20 #define LPC32XX_INTC_POL 0x0C
21 #define LPC32XX_INTC_TYPE 0x10
22 #define LPC32XX_INTC_FIQ 0x14
24 #define NR_LPC32XX_IC_IRQS 32
26 struct lpc32xx_irq_chip
{
28 struct irq_domain
*domain
;
32 static struct lpc32xx_irq_chip
*lpc32xx_mic_irqc
;
34 static inline u32
lpc32xx_ic_read(struct lpc32xx_irq_chip
*ic
, u32 reg
)
36 return readl_relaxed(ic
->base
+ reg
);
39 static inline void lpc32xx_ic_write(struct lpc32xx_irq_chip
*ic
,
42 writel_relaxed(val
, ic
->base
+ reg
);
45 static void lpc32xx_irq_mask(struct irq_data
*d
)
47 struct lpc32xx_irq_chip
*ic
= irq_data_get_irq_chip_data(d
);
48 u32 val
, mask
= BIT(d
->hwirq
);
50 val
= lpc32xx_ic_read(ic
, LPC32XX_INTC_MASK
) & ~mask
;
51 lpc32xx_ic_write(ic
, LPC32XX_INTC_MASK
, val
);
54 static void lpc32xx_irq_unmask(struct irq_data
*d
)
56 struct lpc32xx_irq_chip
*ic
= irq_data_get_irq_chip_data(d
);
57 u32 val
, mask
= BIT(d
->hwirq
);
59 val
= lpc32xx_ic_read(ic
, LPC32XX_INTC_MASK
) | mask
;
60 lpc32xx_ic_write(ic
, LPC32XX_INTC_MASK
, val
);
63 static void lpc32xx_irq_ack(struct irq_data
*d
)
65 struct lpc32xx_irq_chip
*ic
= irq_data_get_irq_chip_data(d
);
66 u32 mask
= BIT(d
->hwirq
);
68 lpc32xx_ic_write(ic
, LPC32XX_INTC_RAW
, mask
);
71 static int lpc32xx_irq_set_type(struct irq_data
*d
, unsigned int type
)
73 struct lpc32xx_irq_chip
*ic
= irq_data_get_irq_chip_data(d
);
74 u32 val
, mask
= BIT(d
->hwirq
);
78 case IRQ_TYPE_EDGE_RISING
:
82 case IRQ_TYPE_EDGE_FALLING
:
86 case IRQ_TYPE_LEVEL_HIGH
:
90 case IRQ_TYPE_LEVEL_LOW
:
95 pr_info("unsupported irq type %d\n", type
);
99 irqd_set_trigger_type(d
, type
);
101 val
= lpc32xx_ic_read(ic
, LPC32XX_INTC_POL
);
106 lpc32xx_ic_write(ic
, LPC32XX_INTC_POL
, val
);
108 val
= lpc32xx_ic_read(ic
, LPC32XX_INTC_TYPE
);
111 irq_set_handler_locked(d
, handle_edge_irq
);
114 irq_set_handler_locked(d
, handle_level_irq
);
116 lpc32xx_ic_write(ic
, LPC32XX_INTC_TYPE
, val
);
121 static void __exception_irq_entry
lpc32xx_handle_irq(struct pt_regs
*regs
)
123 struct lpc32xx_irq_chip
*ic
= lpc32xx_mic_irqc
;
124 u32 hwirq
= lpc32xx_ic_read(ic
, LPC32XX_INTC_STAT
), irq
;
129 handle_domain_irq(lpc32xx_mic_irqc
->domain
, irq
, regs
);
133 static void lpc32xx_sic_handler(struct irq_desc
*desc
)
135 struct lpc32xx_irq_chip
*ic
= irq_desc_get_handler_data(desc
);
136 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
137 u32 hwirq
= lpc32xx_ic_read(ic
, LPC32XX_INTC_STAT
), irq
;
139 chained_irq_enter(chip
, desc
);
144 generic_handle_irq(irq_find_mapping(ic
->domain
, irq
));
147 chained_irq_exit(chip
, desc
);
150 static int lpc32xx_irq_domain_map(struct irq_domain
*id
, unsigned int virq
,
153 struct lpc32xx_irq_chip
*ic
= id
->host_data
;
155 irq_set_chip_data(virq
, ic
);
156 irq_set_chip_and_handler(virq
, &ic
->chip
, handle_level_irq
);
157 irq_set_status_flags(virq
, IRQ_LEVEL
);
158 irq_set_noprobe(virq
);
163 static void lpc32xx_irq_domain_unmap(struct irq_domain
*id
, unsigned int virq
)
165 irq_set_chip_and_handler(virq
, NULL
, NULL
);
168 static const struct irq_domain_ops lpc32xx_irq_domain_ops
= {
169 .map
= lpc32xx_irq_domain_map
,
170 .unmap
= lpc32xx_irq_domain_unmap
,
171 .xlate
= irq_domain_xlate_twocell
,
174 static int __init
lpc32xx_of_ic_init(struct device_node
*node
,
175 struct device_node
*parent
)
177 struct lpc32xx_irq_chip
*irqc
;
178 bool is_mic
= of_device_is_compatible(node
, "nxp,lpc3220-mic");
179 const __be32
*reg
= of_get_property(node
, "reg", NULL
);
180 u32 parent_irq
, i
, addr
= reg
? be32_to_cpu(*reg
) : 0;
182 irqc
= kzalloc(sizeof(*irqc
), GFP_KERNEL
);
186 irqc
->base
= of_iomap(node
, 0);
188 pr_err("%pOF: unable to map registers\n", node
);
193 irqc
->chip
.irq_ack
= lpc32xx_irq_ack
;
194 irqc
->chip
.irq_mask
= lpc32xx_irq_mask
;
195 irqc
->chip
.irq_unmask
= lpc32xx_irq_unmask
;
196 irqc
->chip
.irq_set_type
= lpc32xx_irq_set_type
;
198 irqc
->chip
.name
= kasprintf(GFP_KERNEL
, "%08x.mic", addr
);
200 irqc
->chip
.name
= kasprintf(GFP_KERNEL
, "%08x.sic", addr
);
202 irqc
->domain
= irq_domain_add_linear(node
, NR_LPC32XX_IC_IRQS
,
203 &lpc32xx_irq_domain_ops
, irqc
);
205 pr_err("unable to add irq domain\n");
207 kfree(irqc
->chip
.name
);
213 lpc32xx_mic_irqc
= irqc
;
214 set_handle_irq(lpc32xx_handle_irq
);
216 for (i
= 0; i
< of_irq_count(node
); i
++) {
217 parent_irq
= irq_of_parse_and_map(node
, i
);
219 irq_set_chained_handler_and_data(parent_irq
,
220 lpc32xx_sic_handler
, irqc
);
224 lpc32xx_ic_write(irqc
, LPC32XX_INTC_MASK
, 0x00);
225 lpc32xx_ic_write(irqc
, LPC32XX_INTC_POL
, 0x00);
226 lpc32xx_ic_write(irqc
, LPC32XX_INTC_TYPE
, 0x00);
231 IRQCHIP_DECLARE(nxp_lpc32xx_mic
, "nxp,lpc3220-mic", lpc32xx_of_ic_init
);
232 IRQCHIP_DECLARE(nxp_lpc32xx_sic
, "nxp,lpc3220-sic", lpc32xx_of_ic_init
);