2 * Copyright (C) Maxime Coquelin 2015
3 * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
4 * License terms: GNU General Public License (GPL), version 2
7 #include <linux/bitops.h>
8 #include <linux/interrupt.h>
10 #include <linux/irq.h>
11 #include <linux/irqchip.h>
12 #include <linux/irqchip/chained_irq.h>
13 #include <linux/irqdomain.h>
14 #include <linux/of_address.h>
15 #include <linux/of_irq.h>
21 #define EXTI_SWIER 0x10
24 static void stm32_irq_handler(struct irq_desc
*desc
)
26 struct irq_domain
*domain
= irq_desc_get_handler_data(desc
);
27 struct irq_chip_generic
*gc
= domain
->gc
->gc
[0];
28 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
29 unsigned long pending
;
32 chained_irq_enter(chip
, desc
);
34 while ((pending
= irq_reg_readl(gc
, EXTI_PR
))) {
35 for_each_set_bit(n
, &pending
, BITS_PER_LONG
) {
36 generic_handle_irq(irq_find_mapping(domain
, n
));
37 irq_reg_writel(gc
, BIT(n
), EXTI_PR
);
41 chained_irq_exit(chip
, desc
);
44 static int stm32_irq_set_type(struct irq_data
*data
, unsigned int type
)
46 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(data
);
47 int pin
= data
->hwirq
;
52 rtsr
= irq_reg_readl(gc
, EXTI_RTSR
);
53 ftsr
= irq_reg_readl(gc
, EXTI_FTSR
);
56 case IRQ_TYPE_EDGE_RISING
:
60 case IRQ_TYPE_EDGE_FALLING
:
64 case IRQ_TYPE_EDGE_BOTH
:
73 irq_reg_writel(gc
, rtsr
, EXTI_RTSR
);
74 irq_reg_writel(gc
, ftsr
, EXTI_FTSR
);
81 static int stm32_irq_set_wake(struct irq_data
*data
, unsigned int on
)
83 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(data
);
84 int pin
= data
->hwirq
;
89 emr
= irq_reg_readl(gc
, EXTI_EMR
);
94 irq_reg_writel(gc
, emr
, EXTI_EMR
);
101 static int stm32_exti_alloc(struct irq_domain
*d
, unsigned int virq
,
102 unsigned int nr_irqs
, void *data
)
104 struct irq_chip_generic
*gc
= d
->gc
->gc
[0];
105 struct irq_fwspec
*fwspec
= data
;
106 irq_hw_number_t hwirq
;
108 hwirq
= fwspec
->param
[0];
110 irq_map_generic_chip(d
, virq
, hwirq
);
111 irq_domain_set_info(d
, virq
, hwirq
, &gc
->chip_types
->chip
, gc
,
112 handle_simple_irq
, NULL
, NULL
);
117 static void stm32_exti_free(struct irq_domain
*d
, unsigned int virq
,
118 unsigned int nr_irqs
)
120 struct irq_data
*data
= irq_domain_get_irq_data(d
, virq
);
122 irq_domain_reset_irq_data(data
);
125 struct irq_domain_ops irq_exti_domain_ops
= {
126 .map
= irq_map_generic_chip
,
127 .xlate
= irq_domain_xlate_onetwocell
,
128 .alloc
= stm32_exti_alloc
,
129 .free
= stm32_exti_free
,
132 static int __init
stm32_exti_init(struct device_node
*node
,
133 struct device_node
*parent
)
135 unsigned int clr
= IRQ_NOREQUEST
| IRQ_NOPROBE
| IRQ_NOAUTOEN
;
136 int nr_irqs
, nr_exti
, ret
, i
;
137 struct irq_chip_generic
*gc
;
138 struct irq_domain
*domain
;
141 base
= of_iomap(node
, 0);
143 pr_err("%s: Unable to map registers\n", node
->full_name
);
147 /* Determine number of irqs supported */
148 writel_relaxed(~0UL, base
+ EXTI_RTSR
);
149 nr_exti
= fls(readl_relaxed(base
+ EXTI_RTSR
));
150 writel_relaxed(0, base
+ EXTI_RTSR
);
152 pr_info("%s: %d External IRQs detected\n", node
->full_name
, nr_exti
);
154 domain
= irq_domain_add_linear(node
, nr_exti
,
155 &irq_exti_domain_ops
, NULL
);
157 pr_err("%s: Could not register interrupt domain.\n",
163 ret
= irq_alloc_domain_generic_chips(domain
, nr_exti
, 1, "exti",
164 handle_edge_irq
, clr
, 0, 0);
166 pr_err("%s: Could not allocate generic interrupt chip.\n",
168 goto out_free_domain
;
171 gc
= domain
->gc
->gc
[0];
173 gc
->chip_types
->type
= IRQ_TYPE_EDGE_BOTH
;
174 gc
->chip_types
->chip
.name
= gc
->chip_types
[0].chip
.name
;
175 gc
->chip_types
->chip
.irq_ack
= irq_gc_ack_set_bit
;
176 gc
->chip_types
->chip
.irq_mask
= irq_gc_mask_clr_bit
;
177 gc
->chip_types
->chip
.irq_unmask
= irq_gc_mask_set_bit
;
178 gc
->chip_types
->chip
.irq_set_type
= stm32_irq_set_type
;
179 gc
->chip_types
->chip
.irq_set_wake
= stm32_irq_set_wake
;
180 gc
->chip_types
->regs
.ack
= EXTI_PR
;
181 gc
->chip_types
->regs
.mask
= EXTI_IMR
;
182 gc
->chip_types
->handler
= handle_edge_irq
;
184 nr_irqs
= of_irq_count(node
);
185 for (i
= 0; i
< nr_irqs
; i
++) {
186 unsigned int irq
= irq_of_parse_and_map(node
, i
);
188 irq_set_handler_data(irq
, domain
);
189 irq_set_chained_handler(irq
, stm32_irq_handler
);
195 irq_domain_remove(domain
);
201 IRQCHIP_DECLARE(stm32_exti
, "st,stm32-exti", stm32_exti_init
);