diff options
author | Ludovic Barre <ludovic.barre@st.com> | 2018-04-26 12:18:26 -0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2018-05-24 07:38:20 -0400 |
commit | be6230f0c2bd5d2fe7530d04d015d454f235f21d (patch) | |
tree | 0232fd99da6d7694562ab9e655f1f1c890e51b02 /drivers | |
parent | ea80aa2a1a594fb21c8b5aec192e1d6deee686b0 (diff) |
irqchip/stm32: Add falling pending register support
This patch adds support of rising/falling pending registers.
Falling pending register (fpr) is needed for next revision.
Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/irqchip/irq-stm32-exti.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c index b91a8c289836..69a4453c2952 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c | |||
@@ -23,16 +23,20 @@ struct stm32_exti_bank { | |||
23 | u32 rtsr_ofst; | 23 | u32 rtsr_ofst; |
24 | u32 ftsr_ofst; | 24 | u32 ftsr_ofst; |
25 | u32 swier_ofst; | 25 | u32 swier_ofst; |
26 | u32 pr_ofst; | 26 | u32 rpr_ofst; |
27 | u32 fpr_ofst; | ||
27 | }; | 28 | }; |
28 | 29 | ||
30 | #define UNDEF_REG ~0 | ||
31 | |||
29 | static const struct stm32_exti_bank stm32f4xx_exti_b1 = { | 32 | static const struct stm32_exti_bank stm32f4xx_exti_b1 = { |
30 | .imr_ofst = 0x00, | 33 | .imr_ofst = 0x00, |
31 | .emr_ofst = 0x04, | 34 | .emr_ofst = 0x04, |
32 | .rtsr_ofst = 0x08, | 35 | .rtsr_ofst = 0x08, |
33 | .ftsr_ofst = 0x0C, | 36 | .ftsr_ofst = 0x0C, |
34 | .swier_ofst = 0x10, | 37 | .swier_ofst = 0x10, |
35 | .pr_ofst = 0x14, | 38 | .rpr_ofst = 0x14, |
39 | .fpr_ofst = UNDEF_REG, | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = { | 42 | static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = { |
@@ -45,7 +49,8 @@ static const struct stm32_exti_bank stm32h7xx_exti_b1 = { | |||
45 | .rtsr_ofst = 0x00, | 49 | .rtsr_ofst = 0x00, |
46 | .ftsr_ofst = 0x04, | 50 | .ftsr_ofst = 0x04, |
47 | .swier_ofst = 0x08, | 51 | .swier_ofst = 0x08, |
48 | .pr_ofst = 0x88, | 52 | .rpr_ofst = 0x88, |
53 | .fpr_ofst = UNDEF_REG, | ||
49 | }; | 54 | }; |
50 | 55 | ||
51 | static const struct stm32_exti_bank stm32h7xx_exti_b2 = { | 56 | static const struct stm32_exti_bank stm32h7xx_exti_b2 = { |
@@ -54,7 +59,8 @@ static const struct stm32_exti_bank stm32h7xx_exti_b2 = { | |||
54 | .rtsr_ofst = 0x20, | 59 | .rtsr_ofst = 0x20, |
55 | .ftsr_ofst = 0x24, | 60 | .ftsr_ofst = 0x24, |
56 | .swier_ofst = 0x28, | 61 | .swier_ofst = 0x28, |
57 | .pr_ofst = 0x98, | 62 | .rpr_ofst = 0x98, |
63 | .fpr_ofst = UNDEF_REG, | ||
58 | }; | 64 | }; |
59 | 65 | ||
60 | static const struct stm32_exti_bank stm32h7xx_exti_b3 = { | 66 | static const struct stm32_exti_bank stm32h7xx_exti_b3 = { |
@@ -63,7 +69,8 @@ static const struct stm32_exti_bank stm32h7xx_exti_b3 = { | |||
63 | .rtsr_ofst = 0x40, | 69 | .rtsr_ofst = 0x40, |
64 | .ftsr_ofst = 0x44, | 70 | .ftsr_ofst = 0x44, |
65 | .swier_ofst = 0x48, | 71 | .swier_ofst = 0x48, |
66 | .pr_ofst = 0xA8, | 72 | .rpr_ofst = 0xA8, |
73 | .fpr_ofst = UNDEF_REG, | ||
67 | }; | 74 | }; |
68 | 75 | ||
69 | static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = { | 76 | static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = { |
@@ -75,8 +82,13 @@ static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = { | |||
75 | static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) | 82 | static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) |
76 | { | 83 | { |
77 | const struct stm32_exti_bank *stm32_bank = gc->private; | 84 | const struct stm32_exti_bank *stm32_bank = gc->private; |
85 | unsigned long pending; | ||
86 | |||
87 | pending = irq_reg_readl(gc, stm32_bank->rpr_ofst); | ||
88 | if (stm32_bank->fpr_ofst != UNDEF_REG) | ||
89 | pending |= irq_reg_readl(gc, stm32_bank->fpr_ofst); | ||
78 | 90 | ||
79 | return irq_reg_readl(gc, stm32_bank->pr_ofst); | 91 | return pending; |
80 | } | 92 | } |
81 | 93 | ||
82 | static void stm32_irq_handler(struct irq_desc *desc) | 94 | static void stm32_irq_handler(struct irq_desc *desc) |
@@ -85,7 +97,6 @@ static void stm32_irq_handler(struct irq_desc *desc) | |||
85 | struct irq_chip *chip = irq_desc_get_chip(desc); | 97 | struct irq_chip *chip = irq_desc_get_chip(desc); |
86 | unsigned int virq, nbanks = domain->gc->num_chips; | 98 | unsigned int virq, nbanks = domain->gc->num_chips; |
87 | struct irq_chip_generic *gc; | 99 | struct irq_chip_generic *gc; |
88 | const struct stm32_exti_bank *stm32_bank; | ||
89 | unsigned long pending; | 100 | unsigned long pending; |
90 | int n, i, irq_base = 0; | 101 | int n, i, irq_base = 0; |
91 | 102 | ||
@@ -93,7 +104,6 @@ static void stm32_irq_handler(struct irq_desc *desc) | |||
93 | 104 | ||
94 | for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) { | 105 | for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) { |
95 | gc = irq_get_domain_generic_chip(domain, irq_base); | 106 | gc = irq_get_domain_generic_chip(domain, irq_base); |
96 | stm32_bank = gc->private; | ||
97 | 107 | ||
98 | while ((pending = stm32_exti_pending(gc))) { | 108 | while ((pending = stm32_exti_pending(gc))) { |
99 | for_each_set_bit(n, &pending, IRQS_PER_BANK) { | 109 | for_each_set_bit(n, &pending, IRQS_PER_BANK) { |
@@ -192,6 +202,20 @@ static const struct irq_domain_ops irq_exti_domain_ops = { | |||
192 | .free = stm32_exti_free, | 202 | .free = stm32_exti_free, |
193 | }; | 203 | }; |
194 | 204 | ||
205 | static void stm32_irq_ack(struct irq_data *d) | ||
206 | { | ||
207 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
208 | const struct stm32_exti_bank *stm32_bank = gc->private; | ||
209 | |||
210 | irq_gc_lock(gc); | ||
211 | |||
212 | irq_reg_writel(gc, d->mask, stm32_bank->rpr_ofst); | ||
213 | if (stm32_bank->fpr_ofst != UNDEF_REG) | ||
214 | irq_reg_writel(gc, d->mask, stm32_bank->fpr_ofst); | ||
215 | |||
216 | irq_gc_unlock(gc); | ||
217 | } | ||
218 | |||
195 | static int | 219 | static int |
196 | __init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks, | 220 | __init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks, |
197 | int bank_nr, struct device_node *node) | 221 | int bank_nr, struct device_node *node) |
@@ -233,12 +257,11 @@ __init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks, | |||
233 | 257 | ||
234 | gc->reg_base = base; | 258 | gc->reg_base = base; |
235 | gc->chip_types->type = IRQ_TYPE_EDGE_BOTH; | 259 | gc->chip_types->type = IRQ_TYPE_EDGE_BOTH; |
236 | gc->chip_types->chip.irq_ack = irq_gc_ack_set_bit; | 260 | gc->chip_types->chip.irq_ack = stm32_irq_ack; |
237 | gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit; | 261 | gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit; |
238 | gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit; | 262 | gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit; |
239 | gc->chip_types->chip.irq_set_type = stm32_irq_set_type; | 263 | gc->chip_types->chip.irq_set_type = stm32_irq_set_type; |
240 | gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake; | 264 | gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake; |
241 | gc->chip_types->regs.ack = stm32_bank->pr_ofst; | ||
242 | gc->chip_types->regs.mask = stm32_bank->imr_ofst; | 265 | gc->chip_types->regs.mask = stm32_bank->imr_ofst; |
243 | gc->private = (void *)stm32_bank; | 266 | gc->private = (void *)stm32_bank; |
244 | 267 | ||
@@ -255,7 +278,9 @@ __init stm32_exti_init(const struct stm32_exti_bank **stm32_exti_banks, | |||
255 | writel_relaxed(0, base + stm32_bank->emr_ofst); | 278 | writel_relaxed(0, base + stm32_bank->emr_ofst); |
256 | writel_relaxed(0, base + stm32_bank->rtsr_ofst); | 279 | writel_relaxed(0, base + stm32_bank->rtsr_ofst); |
257 | writel_relaxed(0, base + stm32_bank->ftsr_ofst); | 280 | writel_relaxed(0, base + stm32_bank->ftsr_ofst); |
258 | writel_relaxed(~0UL, base + stm32_bank->pr_ofst); | 281 | writel_relaxed(~0UL, base + stm32_bank->rpr_ofst); |
282 | if (stm32_bank->fpr_ofst != UNDEF_REG) | ||
283 | writel_relaxed(~0UL, base + stm32_bank->fpr_ofst); | ||
259 | 284 | ||
260 | pr_info("%s: bank%d, External IRQs available:%#x\n", | 285 | pr_info("%s: bank%d, External IRQs available:%#x\n", |
261 | node->full_name, i, irqs_mask); | 286 | node->full_name, i, irqs_mask); |