summaryrefslogtreecommitdiffstats
path: root/drivers/irqchip/irq-stm32-exti.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-13 20:33:11 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-13 20:33:11 -0500
commit670310dfbae0eefe7318ff6a61e29e67a7a7bbce (patch)
treeeb3ce3aa3e6786a64fec93d410bb6f0b9a56be77 /drivers/irqchip/irq-stm32-exti.c
parent43ff2f4db9d0f76452b77cfa645f02b471143b24 (diff)
parentffc661c99f621152d5fdcf53f9df0d48c326318b (diff)
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq core updates from Thomas Gleixner: "A rather large update for the interrupt core code and the irq chip drivers: - Add a new bitmap matrix allocator and supporting changes, which is used to replace the x86 vector allocator which comes with separate pull request. This allows to replace the convoluted nested loop allocation function in x86 with a facility which supports the recently added property of managed interrupts proper and allows to switch to a best effort vector reservation scheme, which addresses problems with vector exhaustion. - A large update to the ARM GIC-V3-ITS driver adding support for range selectors. - New interrupt controllers: - Meson and Meson8 GPIO - BCM7271 L2 - Socionext EXIU If you expected that this will stop at some point, I have to disappoint you. There are new ones posted already. Sigh! - STM32 interrupt controller support for new platforms. - A pile of fixes, cleanups and updates to the MIPS GIC driver - The usual small fixes, cleanups and updates all over the place. Most visible one is to move the irq chip drivers Kconfig switches into a separate Kconfig menu" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (70 commits) genirq: Fix type of shifting literal 1 in __setup_irq() irqdomain: Drop pointless NULL check in virq_debug_show_one genirq/proc: Return proper error code when irq_set_affinity() fails irq/work: Use llist_for_each_entry_safe irqchip: mips-gic: Print warning if inherited GIC base is used irqchip/mips-gic: Add pr_fmt and reword pr_* messages irqchip/stm32: Move the wakeup on interrupt mask irqchip/stm32: Fix initial values irqchip/stm32: Add stm32h7 support dt-bindings/interrupt-controllers: Add compatible string for stm32h7 irqchip/stm32: Add multi-bank management irqchip/stm32: Select GENERIC_IRQ_CHIP irqchip/exiu: Add support for Socionext Synquacer EXIU controller dt-bindings: Add description of Socionext EXIU interrupt controller irqchip/gic-v3-its: Fix VPE activate callback return value irqchip: mips-gic: Make IPI bitmaps static irqchip: mips-gic: Share register writes in gic_set_type() irqchip: mips-gic: Remove gic_vpes variable irqchip: mips-gic: Use num_possible_cpus() to reserve IPIs irqchip: mips-gic: Configure EIC when CPUs come online ...
Diffstat (limited to 'drivers/irqchip/irq-stm32-exti.c')
-rw-r--r--drivers/irqchip/irq-stm32-exti.c206
1 files changed, 157 insertions, 49 deletions
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 45363ff8d06f..31ab0dee2ce7 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -14,27 +14,99 @@
14#include <linux/of_address.h> 14#include <linux/of_address.h>
15#include <linux/of_irq.h> 15#include <linux/of_irq.h>
16 16
17#define EXTI_IMR 0x0 17#define IRQS_PER_BANK 32
18#define EXTI_EMR 0x4 18
19#define EXTI_RTSR 0x8 19struct stm32_exti_bank {
20#define EXTI_FTSR 0xc 20 u32 imr_ofst;
21#define EXTI_SWIER 0x10 21 u32 emr_ofst;
22#define EXTI_PR 0x14 22 u32 rtsr_ofst;
23 u32 ftsr_ofst;
24 u32 swier_ofst;
25 u32 pr_ofst;
26};
27
28static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
29 .imr_ofst = 0x00,
30 .emr_ofst = 0x04,
31 .rtsr_ofst = 0x08,
32 .ftsr_ofst = 0x0C,
33 .swier_ofst = 0x10,
34 .pr_ofst = 0x14,
35};
36
37static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
38 &stm32f4xx_exti_b1,
39};
40
41static const struct stm32_exti_bank stm32h7xx_exti_b1 = {
42 .imr_ofst = 0x80,
43 .emr_ofst = 0x84,
44 .rtsr_ofst = 0x00,
45 .ftsr_ofst = 0x04,
46 .swier_ofst = 0x08,
47 .pr_ofst = 0x88,
48};
49
50static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
51 .imr_ofst = 0x90,
52 .emr_ofst = 0x94,
53 .rtsr_ofst = 0x20,
54 .ftsr_ofst = 0x24,
55 .swier_ofst = 0x28,
56 .pr_ofst = 0x98,
57};
58
59static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
60 .imr_ofst = 0xA0,
61 .emr_ofst = 0xA4,
62 .rtsr_ofst = 0x40,
63 .ftsr_ofst = 0x44,
64 .swier_ofst = 0x48,
65 .pr_ofst = 0xA8,
66};
67
68static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
69 &stm32h7xx_exti_b1,
70 &stm32h7xx_exti_b2,
71 &stm32h7xx_exti_b3,
72};
73
74static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
75{
76 const struct stm32_exti_bank *stm32_bank = gc->private;
77
78 return irq_reg_readl(gc, stm32_bank->pr_ofst);
79}
80
81static void stm32_exti_irq_ack(struct irq_chip_generic *gc, u32 mask)
82{
83 const struct stm32_exti_bank *stm32_bank = gc->private;
84
85 irq_reg_writel(gc, mask, stm32_bank->pr_ofst);
86}
23 87
24static void stm32_irq_handler(struct irq_desc *desc) 88static void stm32_irq_handler(struct irq_desc *desc)
25{ 89{
26 struct irq_domain *domain = irq_desc_get_handler_data(desc); 90 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); 91 struct irq_chip *chip = irq_desc_get_chip(desc);
92 unsigned int virq, nbanks = domain->gc->num_chips;
93 struct irq_chip_generic *gc;
94 const struct stm32_exti_bank *stm32_bank;
29 unsigned long pending; 95 unsigned long pending;
30 int n; 96 int n, i, irq_base = 0;
31 97
32 chained_irq_enter(chip, desc); 98 chained_irq_enter(chip, desc);
33 99
34 while ((pending = irq_reg_readl(gc, EXTI_PR))) { 100 for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
35 for_each_set_bit(n, &pending, BITS_PER_LONG) { 101 gc = irq_get_domain_generic_chip(domain, irq_base);
36 generic_handle_irq(irq_find_mapping(domain, n)); 102 stm32_bank = gc->private;
37 irq_reg_writel(gc, BIT(n), EXTI_PR); 103
104 while ((pending = stm32_exti_pending(gc))) {
105 for_each_set_bit(n, &pending, IRQS_PER_BANK) {
106 virq = irq_find_mapping(domain, irq_base + n);
107 generic_handle_irq(virq);
108 stm32_exti_irq_ack(gc, BIT(n));
109 }
38 } 110 }
39 } 111 }
40 112
@@ -44,13 +116,14 @@ static void stm32_irq_handler(struct irq_desc *desc)
44static int stm32_irq_set_type(struct irq_data *data, unsigned int type) 116static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
45{ 117{
46 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); 118 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
47 int pin = data->hwirq; 119 const struct stm32_exti_bank *stm32_bank = gc->private;
120 int pin = data->hwirq % IRQS_PER_BANK;
48 u32 rtsr, ftsr; 121 u32 rtsr, ftsr;
49 122
50 irq_gc_lock(gc); 123 irq_gc_lock(gc);
51 124
52 rtsr = irq_reg_readl(gc, EXTI_RTSR); 125 rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
53 ftsr = irq_reg_readl(gc, EXTI_FTSR); 126 ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
54 127
55 switch (type) { 128 switch (type) {
56 case IRQ_TYPE_EDGE_RISING: 129 case IRQ_TYPE_EDGE_RISING:
@@ -70,8 +143,8 @@ static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
70 return -EINVAL; 143 return -EINVAL;
71 } 144 }
72 145
73 irq_reg_writel(gc, rtsr, EXTI_RTSR); 146 irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
74 irq_reg_writel(gc, ftsr, EXTI_FTSR); 147 irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
75 148
76 irq_gc_unlock(gc); 149 irq_gc_unlock(gc);
77 150
@@ -81,17 +154,18 @@ static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
81static int stm32_irq_set_wake(struct irq_data *data, unsigned int on) 154static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
82{ 155{
83 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); 156 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
84 int pin = data->hwirq; 157 const struct stm32_exti_bank *stm32_bank = gc->private;
85 u32 emr; 158 int pin = data->hwirq % IRQS_PER_BANK;
159 u32 imr;
86 160
87 irq_gc_lock(gc); 161 irq_gc_lock(gc);
88 162
89 emr = irq_reg_readl(gc, EXTI_EMR); 163 imr = irq_reg_readl(gc, stm32_bank->imr_ofst);
90 if (on) 164 if (on)
91 emr |= BIT(pin); 165 imr |= BIT(pin);
92 else 166 else
93 emr &= ~BIT(pin); 167 imr &= ~BIT(pin);
94 irq_reg_writel(gc, emr, EXTI_EMR); 168 irq_reg_writel(gc, imr, stm32_bank->imr_ofst);
95 169
96 irq_gc_unlock(gc); 170 irq_gc_unlock(gc);
97 171
@@ -101,11 +175,12 @@ static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
101static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq, 175static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
102 unsigned int nr_irqs, void *data) 176 unsigned int nr_irqs, void *data)
103{ 177{
104 struct irq_chip_generic *gc = d->gc->gc[0]; 178 struct irq_chip_generic *gc;
105 struct irq_fwspec *fwspec = data; 179 struct irq_fwspec *fwspec = data;
106 irq_hw_number_t hwirq; 180 irq_hw_number_t hwirq;
107 181
108 hwirq = fwspec->param[0]; 182 hwirq = fwspec->param[0];
183 gc = irq_get_domain_generic_chip(d, hwirq);
109 184
110 irq_map_generic_chip(d, virq, hwirq); 185 irq_map_generic_chip(d, virq, hwirq);
111 irq_domain_set_info(d, virq, hwirq, &gc->chip_types->chip, gc, 186 irq_domain_set_info(d, virq, hwirq, &gc->chip_types->chip, gc,
@@ -129,8 +204,9 @@ struct irq_domain_ops irq_exti_domain_ops = {
129 .free = stm32_exti_free, 204 .free = stm32_exti_free,
130}; 205};
131 206
132static int __init stm32_exti_init(struct device_node *node, 207static int
133 struct device_node *parent) 208__init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks,
209 int bank_nr, struct device_node *node)
134{ 210{
135 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; 211 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
136 int nr_irqs, nr_exti, ret, i; 212 int nr_irqs, nr_exti, ret, i;
@@ -144,23 +220,16 @@ static int __init stm32_exti_init(struct device_node *node,
144 return -ENOMEM; 220 return -ENOMEM;
145 } 221 }
146 222
147 /* Determine number of irqs supported */ 223 domain = irq_domain_add_linear(node, bank_nr * IRQS_PER_BANK,
148 writel_relaxed(~0UL, base + EXTI_RTSR);
149 nr_exti = fls(readl_relaxed(base + EXTI_RTSR));
150 writel_relaxed(0, base + EXTI_RTSR);
151
152 pr_info("%pOF: %d External IRQs detected\n", node, nr_exti);
153
154 domain = irq_domain_add_linear(node, nr_exti,
155 &irq_exti_domain_ops, NULL); 224 &irq_exti_domain_ops, NULL);
156 if (!domain) { 225 if (!domain) {
157 pr_err("%s: Could not register interrupt domain.\n", 226 pr_err("%s: Could not register interrupt domain.\n",
158 node->name); 227 node->name);
159 ret = -ENOMEM; 228 ret = -ENOMEM;
160 goto out_unmap; 229 goto out_unmap;
161 } 230 }
162 231
163 ret = irq_alloc_domain_generic_chips(domain, nr_exti, 1, "exti", 232 ret = irq_alloc_domain_generic_chips(domain, IRQS_PER_BANK, 1, "exti",
164 handle_edge_irq, clr, 0, 0); 233 handle_edge_irq, clr, 0, 0);
165 if (ret) { 234 if (ret) {
166 pr_err("%pOF: Could not allocate generic interrupt chip.\n", 235 pr_err("%pOF: Could not allocate generic interrupt chip.\n",
@@ -168,18 +237,41 @@ static int __init stm32_exti_init(struct device_node *node,
168 goto out_free_domain; 237 goto out_free_domain;
169 } 238 }
170 239
171 gc = domain->gc->gc[0]; 240 for (i = 0; i < bank_nr; i++) {
172 gc->reg_base = base; 241 const struct stm32_exti_bank *stm32_bank = stm32_exti_banks[i];
173 gc->chip_types->type = IRQ_TYPE_EDGE_BOTH; 242 u32 irqs_mask;
174 gc->chip_types->chip.name = gc->chip_types[0].chip.name; 243
175 gc->chip_types->chip.irq_ack = irq_gc_ack_set_bit; 244 gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
176 gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit; 245
177 gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit; 246 gc->reg_base = base;
178 gc->chip_types->chip.irq_set_type = stm32_irq_set_type; 247 gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
179 gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake; 248 gc->chip_types->chip.irq_ack = irq_gc_ack_set_bit;
180 gc->chip_types->regs.ack = EXTI_PR; 249 gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
181 gc->chip_types->regs.mask = EXTI_IMR; 250 gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
182 gc->chip_types->handler = handle_edge_irq; 251 gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
252 gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake;
253 gc->chip_types->regs.ack = stm32_bank->pr_ofst;
254 gc->chip_types->regs.mask = stm32_bank->imr_ofst;
255 gc->private = (void *)stm32_bank;
256
257 /* Determine number of irqs supported */
258 writel_relaxed(~0UL, base + stm32_bank->rtsr_ofst);
259 irqs_mask = readl_relaxed(base + stm32_bank->rtsr_ofst);
260 nr_exti = fls(readl_relaxed(base + stm32_bank->rtsr_ofst));
261
262 /*
263 * This IP has no reset, so after hot reboot we should
264 * clear registers to avoid residue
265 */
266 writel_relaxed(0, base + stm32_bank->imr_ofst);
267 writel_relaxed(0, base + stm32_bank->emr_ofst);
268 writel_relaxed(0, base + stm32_bank->rtsr_ofst);
269 writel_relaxed(0, base + stm32_bank->ftsr_ofst);
270 writel_relaxed(~0UL, base + stm32_bank->pr_ofst);
271
272 pr_info("%s: bank%d, External IRQs available:%#x\n",
273 node->full_name, i, irqs_mask);
274 }
183 275
184 nr_irqs = of_irq_count(node); 276 nr_irqs = of_irq_count(node);
185 for (i = 0; i < nr_irqs; i++) { 277 for (i = 0; i < nr_irqs; i++) {
@@ -198,4 +290,20 @@ out_unmap:
198 return ret; 290 return ret;
199} 291}
200 292
201IRQCHIP_DECLARE(stm32_exti, "st,stm32-exti", stm32_exti_init); 293static int __init stm32f4_exti_of_init(struct device_node *np,
294 struct device_node *parent)
295{
296 return stm32_exti_init(stm32f4xx_exti_banks,
297 ARRAY_SIZE(stm32f4xx_exti_banks), np);
298}
299
300IRQCHIP_DECLARE(stm32f4_exti, "st,stm32-exti", stm32f4_exti_of_init);
301
302static int __init stm32h7_exti_of_init(struct device_node *np,
303 struct device_node *parent)
304{
305 return stm32_exti_init(stm32h7xx_exti_banks,
306 ARRAY_SIZE(stm32h7xx_exti_banks), np);
307}
308
309IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);