xref: /openbmc/linux/drivers/irqchip/irq-stm32-exti.c (revision 87813e13df5ca4d899e2da0bc37d40f9a95788ee)
18de50dc2SBenjamin Gaignard // SPDX-License-Identifier: GPL-2.0
2e0720416SAlexandre TORGUE /*
3e0720416SAlexandre TORGUE  * Copyright (C) Maxime Coquelin 2015
48de50dc2SBenjamin Gaignard  * Copyright (C) STMicroelectronics 2017
5e0720416SAlexandre TORGUE  * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
6e0720416SAlexandre TORGUE  */
7e0720416SAlexandre TORGUE 
8e0720416SAlexandre TORGUE #include <linux/bitops.h>
9fb94109bSBenjamin Gaignard #include <linux/delay.h>
10fb94109bSBenjamin Gaignard #include <linux/hwspinlock.h>
11e0720416SAlexandre TORGUE #include <linux/interrupt.h>
12e0720416SAlexandre TORGUE #include <linux/io.h>
13e0720416SAlexandre TORGUE #include <linux/irq.h>
14e0720416SAlexandre TORGUE #include <linux/irqchip.h>
15e0720416SAlexandre TORGUE #include <linux/irqchip/chained_irq.h>
16e0720416SAlexandre TORGUE #include <linux/irqdomain.h>
17ee076750SRob Herring #include <linux/mod_devicetable.h>
18cfbf9e49SFabien Dessenne #include <linux/module.h>
19e0720416SAlexandre TORGUE #include <linux/of_address.h>
20e0720416SAlexandre TORGUE #include <linux/of_irq.h>
21ee076750SRob Herring #include <linux/platform_device.h>
2273958b31SLudovic Barre #include <linux/syscore_ops.h>
23e0720416SAlexandre TORGUE 
24927abfc4SLudovic Barre #include <dt-bindings/interrupt-controller/arm-gic.h>
25927abfc4SLudovic Barre 
266dd64ee1SLudovic Barre #define IRQS_PER_BANK 32
276dd64ee1SLudovic Barre 
28fb94109bSBenjamin Gaignard #define HWSPNLCK_TIMEOUT	1000 /* usec */
29fb94109bSBenjamin Gaignard 
306dd64ee1SLudovic Barre struct stm32_exti_bank {
316dd64ee1SLudovic Barre 	u32 imr_ofst;
326dd64ee1SLudovic Barre 	u32 emr_ofst;
336dd64ee1SLudovic Barre 	u32 rtsr_ofst;
346dd64ee1SLudovic Barre 	u32 ftsr_ofst;
356dd64ee1SLudovic Barre 	u32 swier_ofst;
36be6230f0SLudovic Barre 	u32 rpr_ofst;
37be6230f0SLudovic Barre 	u32 fpr_ofst;
38ce4ef8f9SAntonio Borneo 	u32 trg_ofst;
396dd64ee1SLudovic Barre };
406dd64ee1SLudovic Barre 
41be6230f0SLudovic Barre #define UNDEF_REG ~0
42be6230f0SLudovic Barre 
43f9fc1745SLudovic Barre struct stm32_exti_drv_data {
44f9fc1745SLudovic Barre 	const struct stm32_exti_bank **exti_banks;
45c2974933SAntonio Borneo 	const u8 *desc_irqs;
46f9fc1745SLudovic Barre 	u32 bank_nr;
47f9fc1745SLudovic Barre };
48f9fc1745SLudovic Barre 
49d9e2b19bSLudovic Barre struct stm32_exti_chip_data {
50f9fc1745SLudovic Barre 	struct stm32_exti_host_data *host_data;
51d9e2b19bSLudovic Barre 	const struct stm32_exti_bank *reg_bank;
52927abfc4SLudovic Barre 	struct raw_spinlock rlock;
53927abfc4SLudovic Barre 	u32 wake_active;
54927abfc4SLudovic Barre 	u32 mask_cache;
55d9e2b19bSLudovic Barre 	u32 rtsr_cache;
56d9e2b19bSLudovic Barre 	u32 ftsr_cache;
57d9e2b19bSLudovic Barre };
58d9e2b19bSLudovic Barre 
59f9fc1745SLudovic Barre struct stm32_exti_host_data {
60f9fc1745SLudovic Barre 	void __iomem *base;
61f9fc1745SLudovic Barre 	struct stm32_exti_chip_data *chips_data;
62f9fc1745SLudovic Barre 	const struct stm32_exti_drv_data *drv_data;
63fb94109bSBenjamin Gaignard 	struct hwspinlock *hwlock;
64f9fc1745SLudovic Barre };
65d9e2b19bSLudovic Barre 
6673958b31SLudovic Barre static struct stm32_exti_host_data *stm32_host_data;
6773958b31SLudovic Barre 
686dd64ee1SLudovic Barre static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
696dd64ee1SLudovic Barre 	.imr_ofst	= 0x00,
706dd64ee1SLudovic Barre 	.emr_ofst	= 0x04,
716dd64ee1SLudovic Barre 	.rtsr_ofst	= 0x08,
726dd64ee1SLudovic Barre 	.ftsr_ofst	= 0x0C,
736dd64ee1SLudovic Barre 	.swier_ofst	= 0x10,
74be6230f0SLudovic Barre 	.rpr_ofst	= 0x14,
75be6230f0SLudovic Barre 	.fpr_ofst	= UNDEF_REG,
76ce4ef8f9SAntonio Borneo 	.trg_ofst	= UNDEF_REG,
776dd64ee1SLudovic Barre };
786dd64ee1SLudovic Barre 
796dd64ee1SLudovic Barre static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
806dd64ee1SLudovic Barre 	&stm32f4xx_exti_b1,
816dd64ee1SLudovic Barre };
826dd64ee1SLudovic Barre 
83f9fc1745SLudovic Barre static const struct stm32_exti_drv_data stm32f4xx_drv_data = {
84f9fc1745SLudovic Barre 	.exti_banks = stm32f4xx_exti_banks,
85f9fc1745SLudovic Barre 	.bank_nr = ARRAY_SIZE(stm32f4xx_exti_banks),
86f9fc1745SLudovic Barre };
87f9fc1745SLudovic Barre 
88539c603eSLudovic Barre static const struct stm32_exti_bank stm32h7xx_exti_b1 = {
89539c603eSLudovic Barre 	.imr_ofst	= 0x80,
90539c603eSLudovic Barre 	.emr_ofst	= 0x84,
91539c603eSLudovic Barre 	.rtsr_ofst	= 0x00,
92539c603eSLudovic Barre 	.ftsr_ofst	= 0x04,
93539c603eSLudovic Barre 	.swier_ofst	= 0x08,
94be6230f0SLudovic Barre 	.rpr_ofst	= 0x88,
95be6230f0SLudovic Barre 	.fpr_ofst	= UNDEF_REG,
96ce4ef8f9SAntonio Borneo 	.trg_ofst	= UNDEF_REG,
97539c603eSLudovic Barre };
98539c603eSLudovic Barre 
99539c603eSLudovic Barre static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
100539c603eSLudovic Barre 	.imr_ofst	= 0x90,
101539c603eSLudovic Barre 	.emr_ofst	= 0x94,
102539c603eSLudovic Barre 	.rtsr_ofst	= 0x20,
103539c603eSLudovic Barre 	.ftsr_ofst	= 0x24,
104539c603eSLudovic Barre 	.swier_ofst	= 0x28,
105be6230f0SLudovic Barre 	.rpr_ofst	= 0x98,
106be6230f0SLudovic Barre 	.fpr_ofst	= UNDEF_REG,
107ce4ef8f9SAntonio Borneo 	.trg_ofst	= UNDEF_REG,
108539c603eSLudovic Barre };
109539c603eSLudovic Barre 
110539c603eSLudovic Barre static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
111539c603eSLudovic Barre 	.imr_ofst	= 0xA0,
112539c603eSLudovic Barre 	.emr_ofst	= 0xA4,
113539c603eSLudovic Barre 	.rtsr_ofst	= 0x40,
114539c603eSLudovic Barre 	.ftsr_ofst	= 0x44,
115539c603eSLudovic Barre 	.swier_ofst	= 0x48,
116be6230f0SLudovic Barre 	.rpr_ofst	= 0xA8,
117be6230f0SLudovic Barre 	.fpr_ofst	= UNDEF_REG,
118ce4ef8f9SAntonio Borneo 	.trg_ofst	= UNDEF_REG,
119539c603eSLudovic Barre };
120539c603eSLudovic Barre 
121539c603eSLudovic Barre static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
122539c603eSLudovic Barre 	&stm32h7xx_exti_b1,
123539c603eSLudovic Barre 	&stm32h7xx_exti_b2,
124539c603eSLudovic Barre 	&stm32h7xx_exti_b3,
125539c603eSLudovic Barre };
126539c603eSLudovic Barre 
127f9fc1745SLudovic Barre static const struct stm32_exti_drv_data stm32h7xx_drv_data = {
128f9fc1745SLudovic Barre 	.exti_banks = stm32h7xx_exti_banks,
129f9fc1745SLudovic Barre 	.bank_nr = ARRAY_SIZE(stm32h7xx_exti_banks),
130f9fc1745SLudovic Barre };
131f9fc1745SLudovic Barre 
132927abfc4SLudovic Barre static const struct stm32_exti_bank stm32mp1_exti_b1 = {
133927abfc4SLudovic Barre 	.imr_ofst	= 0x80,
134b38040f0SAlexandre Torgue 	.emr_ofst	= UNDEF_REG,
135927abfc4SLudovic Barre 	.rtsr_ofst	= 0x00,
136927abfc4SLudovic Barre 	.ftsr_ofst	= 0x04,
137927abfc4SLudovic Barre 	.swier_ofst	= 0x08,
138927abfc4SLudovic Barre 	.rpr_ofst	= 0x0C,
139927abfc4SLudovic Barre 	.fpr_ofst	= 0x10,
140ce4ef8f9SAntonio Borneo 	.trg_ofst	= 0x3EC,
141927abfc4SLudovic Barre };
142927abfc4SLudovic Barre 
143927abfc4SLudovic Barre static const struct stm32_exti_bank stm32mp1_exti_b2 = {
144927abfc4SLudovic Barre 	.imr_ofst	= 0x90,
145b38040f0SAlexandre Torgue 	.emr_ofst	= UNDEF_REG,
146927abfc4SLudovic Barre 	.rtsr_ofst	= 0x20,
147927abfc4SLudovic Barre 	.ftsr_ofst	= 0x24,
148927abfc4SLudovic Barre 	.swier_ofst	= 0x28,
149927abfc4SLudovic Barre 	.rpr_ofst	= 0x2C,
150927abfc4SLudovic Barre 	.fpr_ofst	= 0x30,
151ce4ef8f9SAntonio Borneo 	.trg_ofst	= 0x3E8,
152927abfc4SLudovic Barre };
153927abfc4SLudovic Barre 
154927abfc4SLudovic Barre static const struct stm32_exti_bank stm32mp1_exti_b3 = {
155927abfc4SLudovic Barre 	.imr_ofst	= 0xA0,
156b38040f0SAlexandre Torgue 	.emr_ofst	= UNDEF_REG,
157927abfc4SLudovic Barre 	.rtsr_ofst	= 0x40,
158927abfc4SLudovic Barre 	.ftsr_ofst	= 0x44,
159927abfc4SLudovic Barre 	.swier_ofst	= 0x48,
160927abfc4SLudovic Barre 	.rpr_ofst	= 0x4C,
161927abfc4SLudovic Barre 	.fpr_ofst	= 0x50,
162ce4ef8f9SAntonio Borneo 	.trg_ofst	= 0x3E4,
163927abfc4SLudovic Barre };
164927abfc4SLudovic Barre 
165927abfc4SLudovic Barre static const struct stm32_exti_bank *stm32mp1_exti_banks[] = {
166927abfc4SLudovic Barre 	&stm32mp1_exti_b1,
167927abfc4SLudovic Barre 	&stm32mp1_exti_b2,
168927abfc4SLudovic Barre 	&stm32mp1_exti_b3,
169927abfc4SLudovic Barre };
170927abfc4SLudovic Barre 
1719d6a5fe1SAlexandre Torgue static struct irq_chip stm32_exti_h_chip;
1729d6a5fe1SAlexandre Torgue static struct irq_chip stm32_exti_h_chip_direct;
1739d6a5fe1SAlexandre Torgue 
174c2974933SAntonio Borneo #define EXTI_INVALID_IRQ       U8_MAX
175c2974933SAntonio Borneo #define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_BANK)
176c2974933SAntonio Borneo 
17748f31e49SAntonio Borneo /*
17848f31e49SAntonio Borneo  * Use some intentionally tricky logic here to initialize the whole array to
17948f31e49SAntonio Borneo  * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indicate
18048f31e49SAntonio Borneo  * that we "know" that there are overrides in this structure, and we'll need to
18148f31e49SAntonio Borneo  * disable that warning from W=1 builds.
18248f31e49SAntonio Borneo  */
18348f31e49SAntonio Borneo __diag_push();
18448f31e49SAntonio Borneo __diag_ignore_all("-Woverride-init",
18548f31e49SAntonio Borneo 		  "logic to initialize all and then override some is OK");
18648f31e49SAntonio Borneo 
187c2974933SAntonio Borneo static const u8 stm32mp1_desc_irq[] = {
188c2974933SAntonio Borneo 	/* default value */
189c2974933SAntonio Borneo 	[0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ,
190c2974933SAntonio Borneo 
191c2974933SAntonio Borneo 	[0] = 6,
192c2974933SAntonio Borneo 	[1] = 7,
193c2974933SAntonio Borneo 	[2] = 8,
194c2974933SAntonio Borneo 	[3] = 9,
195c2974933SAntonio Borneo 	[4] = 10,
196c2974933SAntonio Borneo 	[5] = 23,
197c2974933SAntonio Borneo 	[6] = 64,
198c2974933SAntonio Borneo 	[7] = 65,
199c2974933SAntonio Borneo 	[8] = 66,
200c2974933SAntonio Borneo 	[9] = 67,
201c2974933SAntonio Borneo 	[10] = 40,
202c2974933SAntonio Borneo 	[11] = 42,
203c2974933SAntonio Borneo 	[12] = 76,
204c2974933SAntonio Borneo 	[13] = 77,
205c2974933SAntonio Borneo 	[14] = 121,
206c2974933SAntonio Borneo 	[15] = 127,
207c2974933SAntonio Borneo 	[16] = 1,
208c2974933SAntonio Borneo 	[19] = 3,
209c2974933SAntonio Borneo 	[21] = 31,
210c2974933SAntonio Borneo 	[22] = 33,
211c2974933SAntonio Borneo 	[23] = 72,
212c2974933SAntonio Borneo 	[24] = 95,
213c2974933SAntonio Borneo 	[25] = 107,
214c2974933SAntonio Borneo 	[26] = 37,
215c2974933SAntonio Borneo 	[27] = 38,
216c2974933SAntonio Borneo 	[28] = 39,
217c2974933SAntonio Borneo 	[29] = 71,
218c2974933SAntonio Borneo 	[30] = 52,
219c2974933SAntonio Borneo 	[31] = 53,
220c2974933SAntonio Borneo 	[32] = 82,
221c2974933SAntonio Borneo 	[33] = 83,
2221c518796SMarek Vasut 	[46] = 151,
223c2974933SAntonio Borneo 	[47] = 93,
224c2974933SAntonio Borneo 	[48] = 138,
225c2974933SAntonio Borneo 	[50] = 139,
226c2974933SAntonio Borneo 	[52] = 140,
227c2974933SAntonio Borneo 	[53] = 141,
228c2974933SAntonio Borneo 	[54] = 135,
229c2974933SAntonio Borneo 	[61] = 100,
230c2974933SAntonio Borneo 	[65] = 144,
231c2974933SAntonio Borneo 	[68] = 143,
232c2974933SAntonio Borneo 	[70] = 62,
233c2974933SAntonio Borneo 	[73] = 129,
234927abfc4SLudovic Barre };
235927abfc4SLudovic Barre 
236c2974933SAntonio Borneo static const u8 stm32mp13_desc_irq[] = {
237c2974933SAntonio Borneo 	/* default value */
238c2974933SAntonio Borneo 	[0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ,
239c2974933SAntonio Borneo 
240c2974933SAntonio Borneo 	[0] = 6,
241c2974933SAntonio Borneo 	[1] = 7,
242c2974933SAntonio Borneo 	[2] = 8,
243c2974933SAntonio Borneo 	[3] = 9,
244c2974933SAntonio Borneo 	[4] = 10,
245c2974933SAntonio Borneo 	[5] = 24,
246c2974933SAntonio Borneo 	[6] = 65,
247c2974933SAntonio Borneo 	[7] = 66,
248c2974933SAntonio Borneo 	[8] = 67,
249c2974933SAntonio Borneo 	[9] = 68,
250c2974933SAntonio Borneo 	[10] = 41,
251c2974933SAntonio Borneo 	[11] = 43,
252c2974933SAntonio Borneo 	[12] = 77,
253c2974933SAntonio Borneo 	[13] = 78,
254c2974933SAntonio Borneo 	[14] = 106,
255c2974933SAntonio Borneo 	[15] = 109,
256c2974933SAntonio Borneo 	[16] = 1,
257c2974933SAntonio Borneo 	[19] = 3,
258c2974933SAntonio Borneo 	[21] = 32,
259c2974933SAntonio Borneo 	[22] = 34,
260c2974933SAntonio Borneo 	[23] = 73,
261c2974933SAntonio Borneo 	[24] = 93,
262c2974933SAntonio Borneo 	[25] = 114,
263c2974933SAntonio Borneo 	[26] = 38,
264c2974933SAntonio Borneo 	[27] = 39,
265c2974933SAntonio Borneo 	[28] = 40,
266c2974933SAntonio Borneo 	[29] = 72,
267c2974933SAntonio Borneo 	[30] = 53,
268c2974933SAntonio Borneo 	[31] = 54,
269c2974933SAntonio Borneo 	[32] = 83,
270c2974933SAntonio Borneo 	[33] = 84,
271c2974933SAntonio Borneo 	[44] = 96,
272c2974933SAntonio Borneo 	[47] = 92,
273c2974933SAntonio Borneo 	[48] = 116,
274c2974933SAntonio Borneo 	[50] = 117,
275c2974933SAntonio Borneo 	[52] = 118,
276c2974933SAntonio Borneo 	[53] = 119,
277c2974933SAntonio Borneo 	[68] = 63,
278c2974933SAntonio Borneo 	[70] = 98,
27904133bb1SAlexandre Torgue };
28004133bb1SAlexandre Torgue 
28148f31e49SAntonio Borneo __diag_pop();
28248f31e49SAntonio Borneo 
283927abfc4SLudovic Barre static const struct stm32_exti_drv_data stm32mp1_drv_data = {
284927abfc4SLudovic Barre 	.exti_banks = stm32mp1_exti_banks,
285927abfc4SLudovic Barre 	.bank_nr = ARRAY_SIZE(stm32mp1_exti_banks),
286927abfc4SLudovic Barre 	.desc_irqs = stm32mp1_desc_irq,
287927abfc4SLudovic Barre };
288927abfc4SLudovic Barre 
28904133bb1SAlexandre Torgue static const struct stm32_exti_drv_data stm32mp13_drv_data = {
29004133bb1SAlexandre Torgue 	.exti_banks = stm32mp1_exti_banks,
29104133bb1SAlexandre Torgue 	.bank_nr = ARRAY_SIZE(stm32mp1_exti_banks),
29204133bb1SAlexandre Torgue 	.desc_irqs = stm32mp13_desc_irq,
29304133bb1SAlexandre Torgue };
29404133bb1SAlexandre Torgue 
stm32_exti_pending(struct irq_chip_generic * gc)2956dd64ee1SLudovic Barre static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
2966dd64ee1SLudovic Barre {
297d9e2b19bSLudovic Barre 	struct stm32_exti_chip_data *chip_data = gc->private;
298d9e2b19bSLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
299be6230f0SLudovic Barre 	unsigned long pending;
3006dd64ee1SLudovic Barre 
301be6230f0SLudovic Barre 	pending = irq_reg_readl(gc, stm32_bank->rpr_ofst);
302be6230f0SLudovic Barre 	if (stm32_bank->fpr_ofst != UNDEF_REG)
303be6230f0SLudovic Barre 		pending |= irq_reg_readl(gc, stm32_bank->fpr_ofst);
304be6230f0SLudovic Barre 
305be6230f0SLudovic Barre 	return pending;
3066dd64ee1SLudovic Barre }
3076dd64ee1SLudovic Barre 
stm32_irq_handler(struct irq_desc * desc)308e0720416SAlexandre TORGUE static void stm32_irq_handler(struct irq_desc *desc)
309e0720416SAlexandre TORGUE {
310e0720416SAlexandre TORGUE 	struct irq_domain *domain = irq_desc_get_handler_data(desc);
311e0720416SAlexandre TORGUE 	struct irq_chip *chip = irq_desc_get_chip(desc);
312046a6ee2SMarc Zyngier 	unsigned int nbanks = domain->gc->num_chips;
3136dd64ee1SLudovic Barre 	struct irq_chip_generic *gc;
314e0720416SAlexandre TORGUE 	unsigned long pending;
3156dd64ee1SLudovic Barre 	int n, i, irq_base = 0;
316e0720416SAlexandre TORGUE 
317e0720416SAlexandre TORGUE 	chained_irq_enter(chip, desc);
318e0720416SAlexandre TORGUE 
3196dd64ee1SLudovic Barre 	for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
3206dd64ee1SLudovic Barre 		gc = irq_get_domain_generic_chip(domain, irq_base);
3216dd64ee1SLudovic Barre 
3226dd64ee1SLudovic Barre 		while ((pending = stm32_exti_pending(gc))) {
323046a6ee2SMarc Zyngier 			for_each_set_bit(n, &pending, IRQS_PER_BANK)
324046a6ee2SMarc Zyngier 				generic_handle_domain_irq(domain, irq_base + n);
325e0720416SAlexandre TORGUE  		}
326e0720416SAlexandre TORGUE 	}
327e0720416SAlexandre TORGUE 
328e0720416SAlexandre TORGUE 	chained_irq_exit(chip, desc);
329e0720416SAlexandre TORGUE }
330e0720416SAlexandre TORGUE 
stm32_exti_set_type(struct irq_data * d,unsigned int type,u32 * rtsr,u32 * ftsr)3315a2490e0SLudovic Barre static int stm32_exti_set_type(struct irq_data *d,
3325a2490e0SLudovic Barre 			       unsigned int type, u32 *rtsr, u32 *ftsr)
333e0720416SAlexandre TORGUE {
3345a2490e0SLudovic Barre 	u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
3355a2490e0SLudovic Barre 
3365a2490e0SLudovic Barre 	switch (type) {
3375a2490e0SLudovic Barre 	case IRQ_TYPE_EDGE_RISING:
3385a2490e0SLudovic Barre 		*rtsr |= mask;
3395a2490e0SLudovic Barre 		*ftsr &= ~mask;
3405a2490e0SLudovic Barre 		break;
3415a2490e0SLudovic Barre 	case IRQ_TYPE_EDGE_FALLING:
3425a2490e0SLudovic Barre 		*rtsr &= ~mask;
3435a2490e0SLudovic Barre 		*ftsr |= mask;
3445a2490e0SLudovic Barre 		break;
3455a2490e0SLudovic Barre 	case IRQ_TYPE_EDGE_BOTH:
3465a2490e0SLudovic Barre 		*rtsr |= mask;
3475a2490e0SLudovic Barre 		*ftsr |= mask;
3485a2490e0SLudovic Barre 		break;
3495a2490e0SLudovic Barre 	default:
3505a2490e0SLudovic Barre 		return -EINVAL;
3515a2490e0SLudovic Barre 	}
3525a2490e0SLudovic Barre 
3535a2490e0SLudovic Barre 	return 0;
3545a2490e0SLudovic Barre }
3555a2490e0SLudovic Barre 
stm32_irq_set_type(struct irq_data * d,unsigned int type)3565a2490e0SLudovic Barre static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
3575a2490e0SLudovic Barre {
3585a2490e0SLudovic Barre 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
359d9e2b19bSLudovic Barre 	struct stm32_exti_chip_data *chip_data = gc->private;
360d9e2b19bSLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
3615257169aSFabien Dessenne 	struct hwspinlock *hwlock = chip_data->host_data->hwlock;
362e0720416SAlexandre TORGUE 	u32 rtsr, ftsr;
3635a2490e0SLudovic Barre 	int err;
364e0720416SAlexandre TORGUE 
365e0720416SAlexandre TORGUE 	irq_gc_lock(gc);
366e0720416SAlexandre TORGUE 
3675257169aSFabien Dessenne 	if (hwlock) {
3685257169aSFabien Dessenne 		err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT);
3695257169aSFabien Dessenne 		if (err) {
3705257169aSFabien Dessenne 			pr_err("%s can't get hwspinlock (%d)\n", __func__, err);
371fb94109bSBenjamin Gaignard 			goto unlock;
3725257169aSFabien Dessenne 		}
3735257169aSFabien Dessenne 	}
374fb94109bSBenjamin Gaignard 
3756dd64ee1SLudovic Barre 	rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
3766dd64ee1SLudovic Barre 	ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
377e0720416SAlexandre TORGUE 
3785a2490e0SLudovic Barre 	err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
379fb94109bSBenjamin Gaignard 	if (err)
380fb94109bSBenjamin Gaignard 		goto unspinlock;
381e0720416SAlexandre TORGUE 
3826dd64ee1SLudovic Barre 	irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
3836dd64ee1SLudovic Barre 	irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
384e0720416SAlexandre TORGUE 
385fb94109bSBenjamin Gaignard unspinlock:
3865257169aSFabien Dessenne 	if (hwlock)
3875257169aSFabien Dessenne 		hwspin_unlock_in_atomic(hwlock);
388fb94109bSBenjamin Gaignard unlock:
389e0720416SAlexandre TORGUE 	irq_gc_unlock(gc);
390e0720416SAlexandre TORGUE 
391fb94109bSBenjamin Gaignard 	return err;
392e0720416SAlexandre TORGUE }
393e0720416SAlexandre TORGUE 
stm32_chip_suspend(struct stm32_exti_chip_data * chip_data,u32 wake_active)3945a2490e0SLudovic Barre static void stm32_chip_suspend(struct stm32_exti_chip_data *chip_data,
3955a2490e0SLudovic Barre 			       u32 wake_active)
3965a2490e0SLudovic Barre {
3975a2490e0SLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
3985a2490e0SLudovic Barre 	void __iomem *base = chip_data->host_data->base;
3995a2490e0SLudovic Barre 
4005a2490e0SLudovic Barre 	/* save rtsr, ftsr registers */
4015a2490e0SLudovic Barre 	chip_data->rtsr_cache = readl_relaxed(base + stm32_bank->rtsr_ofst);
4025a2490e0SLudovic Barre 	chip_data->ftsr_cache = readl_relaxed(base + stm32_bank->ftsr_ofst);
4035a2490e0SLudovic Barre 
4045a2490e0SLudovic Barre 	writel_relaxed(wake_active, base + stm32_bank->imr_ofst);
4055a2490e0SLudovic Barre }
4065a2490e0SLudovic Barre 
stm32_chip_resume(struct stm32_exti_chip_data * chip_data,u32 mask_cache)4075a2490e0SLudovic Barre static void stm32_chip_resume(struct stm32_exti_chip_data *chip_data,
4085a2490e0SLudovic Barre 			      u32 mask_cache)
4095a2490e0SLudovic Barre {
4105a2490e0SLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
4115a2490e0SLudovic Barre 	void __iomem *base = chip_data->host_data->base;
4125a2490e0SLudovic Barre 
4135a2490e0SLudovic Barre 	/* restore rtsr, ftsr, registers */
4145a2490e0SLudovic Barre 	writel_relaxed(chip_data->rtsr_cache, base + stm32_bank->rtsr_ofst);
4155a2490e0SLudovic Barre 	writel_relaxed(chip_data->ftsr_cache, base + stm32_bank->ftsr_ofst);
4165a2490e0SLudovic Barre 
4175a2490e0SLudovic Barre 	writel_relaxed(mask_cache, base + stm32_bank->imr_ofst);
4185a2490e0SLudovic Barre }
4195a2490e0SLudovic Barre 
stm32_irq_suspend(struct irq_chip_generic * gc)420d9e2b19bSLudovic Barre static void stm32_irq_suspend(struct irq_chip_generic *gc)
421e0720416SAlexandre TORGUE {
422d9e2b19bSLudovic Barre 	struct stm32_exti_chip_data *chip_data = gc->private;
423e0720416SAlexandre TORGUE 
424e0720416SAlexandre TORGUE 	irq_gc_lock(gc);
4255a2490e0SLudovic Barre 	stm32_chip_suspend(chip_data, gc->wake_active);
426e0720416SAlexandre TORGUE 	irq_gc_unlock(gc);
427d9e2b19bSLudovic Barre }
428e0720416SAlexandre TORGUE 
stm32_irq_resume(struct irq_chip_generic * gc)429d9e2b19bSLudovic Barre static void stm32_irq_resume(struct irq_chip_generic *gc)
430d9e2b19bSLudovic Barre {
431d9e2b19bSLudovic Barre 	struct stm32_exti_chip_data *chip_data = gc->private;
432d9e2b19bSLudovic Barre 
433d9e2b19bSLudovic Barre 	irq_gc_lock(gc);
4345a2490e0SLudovic Barre 	stm32_chip_resume(chip_data, gc->mask_cache);
435d9e2b19bSLudovic Barre 	irq_gc_unlock(gc);
436e0720416SAlexandre TORGUE }
437e0720416SAlexandre TORGUE 
stm32_exti_alloc(struct irq_domain * d,unsigned int virq,unsigned int nr_irqs,void * data)438e0720416SAlexandre TORGUE static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
439e0720416SAlexandre TORGUE 			    unsigned int nr_irqs, void *data)
440e0720416SAlexandre TORGUE {
441e0720416SAlexandre TORGUE 	struct irq_fwspec *fwspec = data;
442e0720416SAlexandre TORGUE 	irq_hw_number_t hwirq;
443e0720416SAlexandre TORGUE 
444e0720416SAlexandre TORGUE 	hwirq = fwspec->param[0];
445e0720416SAlexandre TORGUE 
446e0720416SAlexandre TORGUE 	irq_map_generic_chip(d, virq, hwirq);
447e0720416SAlexandre TORGUE 
448e0720416SAlexandre TORGUE 	return 0;
449e0720416SAlexandre TORGUE }
450e0720416SAlexandre TORGUE 
stm32_exti_free(struct irq_domain * d,unsigned int virq,unsigned int nr_irqs)451e0720416SAlexandre TORGUE static void stm32_exti_free(struct irq_domain *d, unsigned int virq,
452e0720416SAlexandre TORGUE 			    unsigned int nr_irqs)
453e0720416SAlexandre TORGUE {
454e0720416SAlexandre TORGUE 	struct irq_data *data = irq_domain_get_irq_data(d, virq);
455e0720416SAlexandre TORGUE 
456e0720416SAlexandre TORGUE 	irq_domain_reset_irq_data(data);
457e0720416SAlexandre TORGUE }
458e0720416SAlexandre TORGUE 
459ea80aa2aSLudovic Barre static const struct irq_domain_ops irq_exti_domain_ops = {
460e0720416SAlexandre TORGUE 	.map	= irq_map_generic_chip,
461e0720416SAlexandre TORGUE 	.alloc  = stm32_exti_alloc,
462e0720416SAlexandre TORGUE 	.free	= stm32_exti_free,
463*8554cba1SBen Wolsieffer 	.xlate	= irq_domain_xlate_twocell,
464e0720416SAlexandre TORGUE };
465e0720416SAlexandre TORGUE 
stm32_irq_ack(struct irq_data * d)466be6230f0SLudovic Barre static void stm32_irq_ack(struct irq_data *d)
467be6230f0SLudovic Barre {
468be6230f0SLudovic Barre 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
469d9e2b19bSLudovic Barre 	struct stm32_exti_chip_data *chip_data = gc->private;
470d9e2b19bSLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
471be6230f0SLudovic Barre 
472be6230f0SLudovic Barre 	irq_gc_lock(gc);
473be6230f0SLudovic Barre 
474be6230f0SLudovic Barre 	irq_reg_writel(gc, d->mask, stm32_bank->rpr_ofst);
475be6230f0SLudovic Barre 	if (stm32_bank->fpr_ofst != UNDEF_REG)
476be6230f0SLudovic Barre 		irq_reg_writel(gc, d->mask, stm32_bank->fpr_ofst);
477be6230f0SLudovic Barre 
478be6230f0SLudovic Barre 	irq_gc_unlock(gc);
479be6230f0SLudovic Barre }
480927abfc4SLudovic Barre 
481e579076aSqiuguorui1 /* directly set the target bit without reading first. */
stm32_exti_write_bit(struct irq_data * d,u32 reg)482e579076aSqiuguorui1 static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg)
483e579076aSqiuguorui1 {
484e579076aSqiuguorui1 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
485e579076aSqiuguorui1 	void __iomem *base = chip_data->host_data->base;
486e579076aSqiuguorui1 	u32 val = BIT(d->hwirq % IRQS_PER_BANK);
487e579076aSqiuguorui1 
488e579076aSqiuguorui1 	writel_relaxed(val, base + reg);
489e579076aSqiuguorui1 }
490e579076aSqiuguorui1 
stm32_exti_set_bit(struct irq_data * d,u32 reg)491927abfc4SLudovic Barre static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg)
492927abfc4SLudovic Barre {
493927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
494927abfc4SLudovic Barre 	void __iomem *base = chip_data->host_data->base;
495927abfc4SLudovic Barre 	u32 val;
496927abfc4SLudovic Barre 
497927abfc4SLudovic Barre 	val = readl_relaxed(base + reg);
498927abfc4SLudovic Barre 	val |= BIT(d->hwirq % IRQS_PER_BANK);
499927abfc4SLudovic Barre 	writel_relaxed(val, base + reg);
500927abfc4SLudovic Barre 
501927abfc4SLudovic Barre 	return val;
502927abfc4SLudovic Barre }
503927abfc4SLudovic Barre 
stm32_exti_clr_bit(struct irq_data * d,u32 reg)504927abfc4SLudovic Barre static inline u32 stm32_exti_clr_bit(struct irq_data *d, u32 reg)
505927abfc4SLudovic Barre {
506927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
507927abfc4SLudovic Barre 	void __iomem *base = chip_data->host_data->base;
508927abfc4SLudovic Barre 	u32 val;
509927abfc4SLudovic Barre 
510927abfc4SLudovic Barre 	val = readl_relaxed(base + reg);
511927abfc4SLudovic Barre 	val &= ~BIT(d->hwirq % IRQS_PER_BANK);
512927abfc4SLudovic Barre 	writel_relaxed(val, base + reg);
513927abfc4SLudovic Barre 
514927abfc4SLudovic Barre 	return val;
515927abfc4SLudovic Barre }
516927abfc4SLudovic Barre 
stm32_exti_h_eoi(struct irq_data * d)517927abfc4SLudovic Barre static void stm32_exti_h_eoi(struct irq_data *d)
518927abfc4SLudovic Barre {
519927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
520927abfc4SLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
521927abfc4SLudovic Barre 
522927abfc4SLudovic Barre 	raw_spin_lock(&chip_data->rlock);
523927abfc4SLudovic Barre 
524e579076aSqiuguorui1 	stm32_exti_write_bit(d, stm32_bank->rpr_ofst);
525927abfc4SLudovic Barre 	if (stm32_bank->fpr_ofst != UNDEF_REG)
526e579076aSqiuguorui1 		stm32_exti_write_bit(d, stm32_bank->fpr_ofst);
527927abfc4SLudovic Barre 
528927abfc4SLudovic Barre 	raw_spin_unlock(&chip_data->rlock);
529927abfc4SLudovic Barre 
530927abfc4SLudovic Barre 	if (d->parent_data->chip)
531927abfc4SLudovic Barre 		irq_chip_eoi_parent(d);
532927abfc4SLudovic Barre }
533927abfc4SLudovic Barre 
stm32_exti_h_mask(struct irq_data * d)534927abfc4SLudovic Barre static void stm32_exti_h_mask(struct irq_data *d)
535927abfc4SLudovic Barre {
536927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
537927abfc4SLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
538927abfc4SLudovic Barre 
539927abfc4SLudovic Barre 	raw_spin_lock(&chip_data->rlock);
540927abfc4SLudovic Barre 	chip_data->mask_cache = stm32_exti_clr_bit(d, stm32_bank->imr_ofst);
541927abfc4SLudovic Barre 	raw_spin_unlock(&chip_data->rlock);
542927abfc4SLudovic Barre 
543927abfc4SLudovic Barre 	if (d->parent_data->chip)
544927abfc4SLudovic Barre 		irq_chip_mask_parent(d);
545927abfc4SLudovic Barre }
546927abfc4SLudovic Barre 
stm32_exti_h_unmask(struct irq_data * d)547927abfc4SLudovic Barre static void stm32_exti_h_unmask(struct irq_data *d)
548927abfc4SLudovic Barre {
549927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
550927abfc4SLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
551927abfc4SLudovic Barre 
552927abfc4SLudovic Barre 	raw_spin_lock(&chip_data->rlock);
553927abfc4SLudovic Barre 	chip_data->mask_cache = stm32_exti_set_bit(d, stm32_bank->imr_ofst);
554927abfc4SLudovic Barre 	raw_spin_unlock(&chip_data->rlock);
555927abfc4SLudovic Barre 
556927abfc4SLudovic Barre 	if (d->parent_data->chip)
557927abfc4SLudovic Barre 		irq_chip_unmask_parent(d);
558927abfc4SLudovic Barre }
559927abfc4SLudovic Barre 
stm32_exti_h_set_type(struct irq_data * d,unsigned int type)560927abfc4SLudovic Barre static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
561927abfc4SLudovic Barre {
562927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
563927abfc4SLudovic Barre 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
5645257169aSFabien Dessenne 	struct hwspinlock *hwlock = chip_data->host_data->hwlock;
565927abfc4SLudovic Barre 	void __iomem *base = chip_data->host_data->base;
566927abfc4SLudovic Barre 	u32 rtsr, ftsr;
567927abfc4SLudovic Barre 	int err;
568927abfc4SLudovic Barre 
569927abfc4SLudovic Barre 	raw_spin_lock(&chip_data->rlock);
570fb94109bSBenjamin Gaignard 
5715257169aSFabien Dessenne 	if (hwlock) {
5725257169aSFabien Dessenne 		err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT);
5735257169aSFabien Dessenne 		if (err) {
5745257169aSFabien Dessenne 			pr_err("%s can't get hwspinlock (%d)\n", __func__, err);
575fb94109bSBenjamin Gaignard 			goto unlock;
5765257169aSFabien Dessenne 		}
5775257169aSFabien Dessenne 	}
578fb94109bSBenjamin Gaignard 
579927abfc4SLudovic Barre 	rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst);
580927abfc4SLudovic Barre 	ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst);
581927abfc4SLudovic Barre 
582927abfc4SLudovic Barre 	err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
583fb94109bSBenjamin Gaignard 	if (err)
584fb94109bSBenjamin Gaignard 		goto unspinlock;
585927abfc4SLudovic Barre 
586927abfc4SLudovic Barre 	writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst);
587927abfc4SLudovic Barre 	writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst);
588fb94109bSBenjamin Gaignard 
589fb94109bSBenjamin Gaignard unspinlock:
5905257169aSFabien Dessenne 	if (hwlock)
5915257169aSFabien Dessenne 		hwspin_unlock_in_atomic(hwlock);
592fb94109bSBenjamin Gaignard unlock:
593927abfc4SLudovic Barre 	raw_spin_unlock(&chip_data->rlock);
594927abfc4SLudovic Barre 
595fb94109bSBenjamin Gaignard 	return err;
596927abfc4SLudovic Barre }
597927abfc4SLudovic Barre 
stm32_exti_h_set_wake(struct irq_data * d,unsigned int on)598927abfc4SLudovic Barre static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on)
599927abfc4SLudovic Barre {
600927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
601927abfc4SLudovic Barre 	u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
602927abfc4SLudovic Barre 
603927abfc4SLudovic Barre 	raw_spin_lock(&chip_data->rlock);
604927abfc4SLudovic Barre 
605927abfc4SLudovic Barre 	if (on)
606927abfc4SLudovic Barre 		chip_data->wake_active |= mask;
607927abfc4SLudovic Barre 	else
608927abfc4SLudovic Barre 		chip_data->wake_active &= ~mask;
609927abfc4SLudovic Barre 
610927abfc4SLudovic Barre 	raw_spin_unlock(&chip_data->rlock);
611927abfc4SLudovic Barre 
612927abfc4SLudovic Barre 	return 0;
613927abfc4SLudovic Barre }
614927abfc4SLudovic Barre 
stm32_exti_h_set_affinity(struct irq_data * d,const struct cpumask * dest,bool force)615927abfc4SLudovic Barre static int stm32_exti_h_set_affinity(struct irq_data *d,
616927abfc4SLudovic Barre 				     const struct cpumask *dest, bool force)
617927abfc4SLudovic Barre {
618927abfc4SLudovic Barre 	if (d->parent_data->chip)
619927abfc4SLudovic Barre 		return irq_chip_set_affinity_parent(d, dest, force);
620927abfc4SLudovic Barre 
6213e17683fSLudovic Barre 	return IRQ_SET_MASK_OK_DONE;
622927abfc4SLudovic Barre }
623927abfc4SLudovic Barre 
stm32_exti_h_suspend(void)624cfbf9e49SFabien Dessenne static int __maybe_unused stm32_exti_h_suspend(void)
62573958b31SLudovic Barre {
62673958b31SLudovic Barre 	struct stm32_exti_chip_data *chip_data;
62773958b31SLudovic Barre 	int i;
62873958b31SLudovic Barre 
62973958b31SLudovic Barre 	for (i = 0; i < stm32_host_data->drv_data->bank_nr; i++) {
63073958b31SLudovic Barre 		chip_data = &stm32_host_data->chips_data[i];
63173958b31SLudovic Barre 		raw_spin_lock(&chip_data->rlock);
63273958b31SLudovic Barre 		stm32_chip_suspend(chip_data, chip_data->wake_active);
63373958b31SLudovic Barre 		raw_spin_unlock(&chip_data->rlock);
63473958b31SLudovic Barre 	}
63573958b31SLudovic Barre 
63673958b31SLudovic Barre 	return 0;
63773958b31SLudovic Barre }
63873958b31SLudovic Barre 
stm32_exti_h_resume(void)639cfbf9e49SFabien Dessenne static void __maybe_unused stm32_exti_h_resume(void)
64073958b31SLudovic Barre {
64173958b31SLudovic Barre 	struct stm32_exti_chip_data *chip_data;
64273958b31SLudovic Barre 	int i;
64373958b31SLudovic Barre 
64473958b31SLudovic Barre 	for (i = 0; i < stm32_host_data->drv_data->bank_nr; i++) {
64573958b31SLudovic Barre 		chip_data = &stm32_host_data->chips_data[i];
64673958b31SLudovic Barre 		raw_spin_lock(&chip_data->rlock);
64773958b31SLudovic Barre 		stm32_chip_resume(chip_data, chip_data->mask_cache);
64873958b31SLudovic Barre 		raw_spin_unlock(&chip_data->rlock);
64973958b31SLudovic Barre 	}
65073958b31SLudovic Barre }
65173958b31SLudovic Barre 
65273958b31SLudovic Barre static struct syscore_ops stm32_exti_h_syscore_ops = {
653cfbf9e49SFabien Dessenne #ifdef CONFIG_PM_SLEEP
65473958b31SLudovic Barre 	.suspend	= stm32_exti_h_suspend,
65573958b31SLudovic Barre 	.resume		= stm32_exti_h_resume,
656cfbf9e49SFabien Dessenne #endif
65773958b31SLudovic Barre };
65873958b31SLudovic Barre 
stm32_exti_h_syscore_init(struct stm32_exti_host_data * host_data)659cfbf9e49SFabien Dessenne static void stm32_exti_h_syscore_init(struct stm32_exti_host_data *host_data)
66073958b31SLudovic Barre {
661cfbf9e49SFabien Dessenne 	stm32_host_data = host_data;
66273958b31SLudovic Barre 	register_syscore_ops(&stm32_exti_h_syscore_ops);
66373958b31SLudovic Barre }
664cfbf9e49SFabien Dessenne 
stm32_exti_h_syscore_deinit(void)665cfbf9e49SFabien Dessenne static void stm32_exti_h_syscore_deinit(void)
666cfbf9e49SFabien Dessenne {
667cfbf9e49SFabien Dessenne 	unregister_syscore_ops(&stm32_exti_h_syscore_ops);
668cfbf9e49SFabien Dessenne }
66973958b31SLudovic Barre 
stm32_exti_h_retrigger(struct irq_data * d)67025591d4cSAlexandre Torgue static int stm32_exti_h_retrigger(struct irq_data *d)
67125591d4cSAlexandre Torgue {
67225591d4cSAlexandre Torgue 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
67325591d4cSAlexandre Torgue 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
67425591d4cSAlexandre Torgue 	void __iomem *base = chip_data->host_data->base;
67525591d4cSAlexandre Torgue 	u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
67625591d4cSAlexandre Torgue 
67725591d4cSAlexandre Torgue 	writel_relaxed(mask, base + stm32_bank->swier_ofst);
67825591d4cSAlexandre Torgue 
67925591d4cSAlexandre Torgue 	return 0;
68025591d4cSAlexandre Torgue }
68125591d4cSAlexandre Torgue 
682927abfc4SLudovic Barre static struct irq_chip stm32_exti_h_chip = {
683927abfc4SLudovic Barre 	.name			= "stm32-exti-h",
684927abfc4SLudovic Barre 	.irq_eoi		= stm32_exti_h_eoi,
685927abfc4SLudovic Barre 	.irq_mask		= stm32_exti_h_mask,
686927abfc4SLudovic Barre 	.irq_unmask		= stm32_exti_h_unmask,
68725591d4cSAlexandre Torgue 	.irq_retrigger		= stm32_exti_h_retrigger,
688927abfc4SLudovic Barre 	.irq_set_type		= stm32_exti_h_set_type,
689927abfc4SLudovic Barre 	.irq_set_wake		= stm32_exti_h_set_wake,
690927abfc4SLudovic Barre 	.flags			= IRQCHIP_MASK_ON_SUSPEND,
691a84277bfSArnd Bergmann 	.irq_set_affinity	= IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : NULL,
692927abfc4SLudovic Barre };
693927abfc4SLudovic Barre 
6949d6a5fe1SAlexandre Torgue static struct irq_chip stm32_exti_h_chip_direct = {
6959d6a5fe1SAlexandre Torgue 	.name			= "stm32-exti-h-direct",
6969d6a5fe1SAlexandre Torgue 	.irq_eoi		= irq_chip_eoi_parent,
6979d6a5fe1SAlexandre Torgue 	.irq_ack		= irq_chip_ack_parent,
698f8b3eb42SLoic Pallardy 	.irq_mask		= stm32_exti_h_mask,
699f8b3eb42SLoic Pallardy 	.irq_unmask		= stm32_exti_h_unmask,
7009d6a5fe1SAlexandre Torgue 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
7019d6a5fe1SAlexandre Torgue 	.irq_set_type		= irq_chip_set_type_parent,
7029d6a5fe1SAlexandre Torgue 	.irq_set_wake		= stm32_exti_h_set_wake,
7039d6a5fe1SAlexandre Torgue 	.flags			= IRQCHIP_MASK_ON_SUSPEND,
7049d6a5fe1SAlexandre Torgue 	.irq_set_affinity	= IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL,
7059d6a5fe1SAlexandre Torgue };
7069d6a5fe1SAlexandre Torgue 
stm32_exti_h_domain_alloc(struct irq_domain * dm,unsigned int virq,unsigned int nr_irqs,void * data)707927abfc4SLudovic Barre static int stm32_exti_h_domain_alloc(struct irq_domain *dm,
708927abfc4SLudovic Barre 				     unsigned int virq,
709927abfc4SLudovic Barre 				     unsigned int nr_irqs, void *data)
710927abfc4SLudovic Barre {
711927abfc4SLudovic Barre 	struct stm32_exti_host_data *host_data = dm->host_data;
712927abfc4SLudovic Barre 	struct stm32_exti_chip_data *chip_data;
713c2974933SAntonio Borneo 	u8 desc_irq;
714927abfc4SLudovic Barre 	struct irq_fwspec *fwspec = data;
715927abfc4SLudovic Barre 	struct irq_fwspec p_fwspec;
716927abfc4SLudovic Barre 	irq_hw_number_t hwirq;
7179d6a5fe1SAlexandre Torgue 	int bank;
718ce4ef8f9SAntonio Borneo 	u32 event_trg;
719ce4ef8f9SAntonio Borneo 	struct irq_chip *chip;
720927abfc4SLudovic Barre 
721927abfc4SLudovic Barre 	hwirq = fwspec->param[0];
722c16ae609SAntonio Borneo 	if (hwirq >= host_data->drv_data->bank_nr * IRQS_PER_BANK)
723c16ae609SAntonio Borneo 		return -EINVAL;
724c16ae609SAntonio Borneo 
725927abfc4SLudovic Barre 	bank  = hwirq / IRQS_PER_BANK;
726927abfc4SLudovic Barre 	chip_data = &host_data->chips_data[bank];
727927abfc4SLudovic Barre 
728ce4ef8f9SAntonio Borneo 	event_trg = readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst);
729ce4ef8f9SAntonio Borneo 	chip = (event_trg & BIT(hwirq % IRQS_PER_BANK)) ?
730ce4ef8f9SAntonio Borneo 	       &stm32_exti_h_chip : &stm32_exti_h_chip_direct;
731ce4ef8f9SAntonio Borneo 
732ce4ef8f9SAntonio Borneo 	irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data);
733c2974933SAntonio Borneo 
7348fc7a619SAntonio Borneo 	if (!host_data->drv_data->desc_irqs)
735c2974933SAntonio Borneo 		return -EINVAL;
736c2974933SAntonio Borneo 
737c2974933SAntonio Borneo 	desc_irq = host_data->drv_data->desc_irqs[hwirq];
738c2974933SAntonio Borneo 	if (desc_irq != EXTI_INVALID_IRQ) {
739927abfc4SLudovic Barre 		p_fwspec.fwnode = dm->parent->fwnode;
740927abfc4SLudovic Barre 		p_fwspec.param_count = 3;
741927abfc4SLudovic Barre 		p_fwspec.param[0] = GIC_SPI;
742c2974933SAntonio Borneo 		p_fwspec.param[1] = desc_irq;
743927abfc4SLudovic Barre 		p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
744927abfc4SLudovic Barre 
745927abfc4SLudovic Barre 		return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec);
746927abfc4SLudovic Barre 	}
747927abfc4SLudovic Barre 
748927abfc4SLudovic Barre 	return 0;
749927abfc4SLudovic Barre }
750927abfc4SLudovic Barre 
751f9fc1745SLudovic Barre static struct
stm32_exti_host_init(const struct stm32_exti_drv_data * dd,struct device_node * node)752f9fc1745SLudovic Barre stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
753f9fc1745SLudovic Barre 					   struct device_node *node)
754e0720416SAlexandre TORGUE {
755f9fc1745SLudovic Barre 	struct stm32_exti_host_data *host_data;
756e0720416SAlexandre TORGUE 
757f9fc1745SLudovic Barre 	host_data = kzalloc(sizeof(*host_data), GFP_KERNEL);
758f9fc1745SLudovic Barre 	if (!host_data)
759f9fc1745SLudovic Barre 		return NULL;
760f9fc1745SLudovic Barre 
761f9fc1745SLudovic Barre 	host_data->drv_data = dd;
762f9fc1745SLudovic Barre 	host_data->chips_data = kcalloc(dd->bank_nr,
763f9fc1745SLudovic Barre 					sizeof(struct stm32_exti_chip_data),
764f9fc1745SLudovic Barre 					GFP_KERNEL);
765f9fc1745SLudovic Barre 	if (!host_data->chips_data)
7664096165dSDan Carpenter 		goto free_host_data;
767f9fc1745SLudovic Barre 
768f9fc1745SLudovic Barre 	host_data->base = of_iomap(node, 0);
769f9fc1745SLudovic Barre 	if (!host_data->base) {
770e81f54c6SRob Herring 		pr_err("%pOF: Unable to map registers\n", node);
7714096165dSDan Carpenter 		goto free_chips_data;
772e0720416SAlexandre TORGUE 	}
773e0720416SAlexandre TORGUE 
77473958b31SLudovic Barre 	stm32_host_data = host_data;
77573958b31SLudovic Barre 
776f9fc1745SLudovic Barre 	return host_data;
7774096165dSDan Carpenter 
7784096165dSDan Carpenter free_chips_data:
7794096165dSDan Carpenter 	kfree(host_data->chips_data);
7804096165dSDan Carpenter free_host_data:
7814096165dSDan Carpenter 	kfree(host_data);
7824096165dSDan Carpenter 
7834096165dSDan Carpenter 	return NULL;
784f9fc1745SLudovic Barre }
785d9e2b19bSLudovic Barre 
786f9fc1745SLudovic Barre static struct
stm32_exti_chip_init(struct stm32_exti_host_data * h_data,u32 bank_idx,struct device_node * node)787f9fc1745SLudovic Barre stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
788cfbf9e49SFabien Dessenne 					   u32 bank_idx,
789cfbf9e49SFabien Dessenne 					   struct device_node *node)
790f9fc1745SLudovic Barre {
791f9fc1745SLudovic Barre 	const struct stm32_exti_bank *stm32_bank;
792f9fc1745SLudovic Barre 	struct stm32_exti_chip_data *chip_data;
793f9fc1745SLudovic Barre 	void __iomem *base = h_data->base;
794f9fc1745SLudovic Barre 
795f9fc1745SLudovic Barre 	stm32_bank = h_data->drv_data->exti_banks[bank_idx];
796f9fc1745SLudovic Barre 	chip_data = &h_data->chips_data[bank_idx];
797f9fc1745SLudovic Barre 	chip_data->host_data = h_data;
798f9fc1745SLudovic Barre 	chip_data->reg_bank = stm32_bank;
799f9fc1745SLudovic Barre 
800927abfc4SLudovic Barre 	raw_spin_lock_init(&chip_data->rlock);
801927abfc4SLudovic Barre 
802f9fc1745SLudovic Barre 	/*
803f9fc1745SLudovic Barre 	 * This IP has no reset, so after hot reboot we should
804f9fc1745SLudovic Barre 	 * clear registers to avoid residue
805f9fc1745SLudovic Barre 	 */
806f9fc1745SLudovic Barre 	writel_relaxed(0, base + stm32_bank->imr_ofst);
807b38040f0SAlexandre Torgue 	if (stm32_bank->emr_ofst != UNDEF_REG)
808f9fc1745SLudovic Barre 		writel_relaxed(0, base + stm32_bank->emr_ofst);
809f9fc1745SLudovic Barre 
810cfbf9e49SFabien Dessenne 	pr_info("%pOF: bank%d\n", node, bank_idx);
811f9fc1745SLudovic Barre 
812f9fc1745SLudovic Barre 	return chip_data;
813f9fc1745SLudovic Barre }
814f9fc1745SLudovic Barre 
stm32_exti_init(const struct stm32_exti_drv_data * drv_data,struct device_node * node)815f9fc1745SLudovic Barre static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
816f9fc1745SLudovic Barre 				  struct device_node *node)
817f9fc1745SLudovic Barre {
818f9fc1745SLudovic Barre 	struct stm32_exti_host_data *host_data;
819f9fc1745SLudovic Barre 	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
820f9fc1745SLudovic Barre 	int nr_irqs, ret, i;
821f9fc1745SLudovic Barre 	struct irq_chip_generic *gc;
822f9fc1745SLudovic Barre 	struct irq_domain *domain;
823f9fc1745SLudovic Barre 
824f9fc1745SLudovic Barre 	host_data = stm32_exti_host_init(drv_data, node);
8254096165dSDan Carpenter 	if (!host_data)
8264096165dSDan Carpenter 		return -ENOMEM;
827f9fc1745SLudovic Barre 
828f9fc1745SLudovic Barre 	domain = irq_domain_add_linear(node, drv_data->bank_nr * IRQS_PER_BANK,
829e0720416SAlexandre TORGUE 				       &irq_exti_domain_ops, NULL);
830e0720416SAlexandre TORGUE 	if (!domain) {
831f9c75bcaSYangtao Li 		pr_err("%pOFn: Could not register interrupt domain.\n",
832f9c75bcaSYangtao Li 		       node);
833e0720416SAlexandre TORGUE 		ret = -ENOMEM;
834e0720416SAlexandre TORGUE 		goto out_unmap;
835e0720416SAlexandre TORGUE 	}
836e0720416SAlexandre TORGUE 
8376dd64ee1SLudovic Barre 	ret = irq_alloc_domain_generic_chips(domain, IRQS_PER_BANK, 1, "exti",
838e0720416SAlexandre TORGUE 					     handle_edge_irq, clr, 0, 0);
839e0720416SAlexandre TORGUE 	if (ret) {
840e81f54c6SRob Herring 		pr_err("%pOF: Could not allocate generic interrupt chip.\n",
841e81f54c6SRob Herring 		       node);
842e0720416SAlexandre TORGUE 		goto out_free_domain;
843e0720416SAlexandre TORGUE 	}
844e0720416SAlexandre TORGUE 
845f9fc1745SLudovic Barre 	for (i = 0; i < drv_data->bank_nr; i++) {
846f9fc1745SLudovic Barre 		const struct stm32_exti_bank *stm32_bank;
847f9fc1745SLudovic Barre 		struct stm32_exti_chip_data *chip_data;
8486dd64ee1SLudovic Barre 
849f9fc1745SLudovic Barre 		stm32_bank = drv_data->exti_banks[i];
850cfbf9e49SFabien Dessenne 		chip_data = stm32_exti_chip_init(host_data, i, node);
851d9e2b19bSLudovic Barre 
8526dd64ee1SLudovic Barre 		gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
8536dd64ee1SLudovic Barre 
854f9fc1745SLudovic Barre 		gc->reg_base = host_data->base;
855e0720416SAlexandre TORGUE 		gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
856be6230f0SLudovic Barre 		gc->chip_types->chip.irq_ack = stm32_irq_ack;
857e0720416SAlexandre TORGUE 		gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
858e0720416SAlexandre TORGUE 		gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
859e0720416SAlexandre TORGUE 		gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
860d9e2b19bSLudovic Barre 		gc->chip_types->chip.irq_set_wake = irq_gc_set_wake;
861d9e2b19bSLudovic Barre 		gc->suspend = stm32_irq_suspend;
862d9e2b19bSLudovic Barre 		gc->resume = stm32_irq_resume;
863d9e2b19bSLudovic Barre 		gc->wake_enabled = IRQ_MSK(IRQS_PER_BANK);
864d9e2b19bSLudovic Barre 
8656dd64ee1SLudovic Barre 		gc->chip_types->regs.mask = stm32_bank->imr_ofst;
866d9e2b19bSLudovic Barre 		gc->private = (void *)chip_data;
8676dd64ee1SLudovic Barre 	}
868e0720416SAlexandre TORGUE 
869e0720416SAlexandre TORGUE 	nr_irqs = of_irq_count(node);
870e0720416SAlexandre TORGUE 	for (i = 0; i < nr_irqs; i++) {
871e0720416SAlexandre TORGUE 		unsigned int irq = irq_of_parse_and_map(node, i);
872e0720416SAlexandre TORGUE 
873e0720416SAlexandre TORGUE 		irq_set_handler_data(irq, domain);
874e0720416SAlexandre TORGUE 		irq_set_chained_handler(irq, stm32_irq_handler);
875e0720416SAlexandre TORGUE 	}
876e0720416SAlexandre TORGUE 
877e0720416SAlexandre TORGUE 	return 0;
878e0720416SAlexandre TORGUE 
879e0720416SAlexandre TORGUE out_free_domain:
880e0720416SAlexandre TORGUE 	irq_domain_remove(domain);
881e0720416SAlexandre TORGUE out_unmap:
882f9fc1745SLudovic Barre 	iounmap(host_data->base);
883f9fc1745SLudovic Barre 	kfree(host_data->chips_data);
884f9fc1745SLudovic Barre 	kfree(host_data);
885e0720416SAlexandre TORGUE 	return ret;
886e0720416SAlexandre TORGUE }
887e0720416SAlexandre TORGUE 
888927abfc4SLudovic Barre static const struct irq_domain_ops stm32_exti_h_domain_ops = {
889927abfc4SLudovic Barre 	.alloc	= stm32_exti_h_domain_alloc,
890927abfc4SLudovic Barre 	.free	= irq_domain_free_irqs_common,
8911d47f48bSLoic Pallardy 	.xlate = irq_domain_xlate_twocell,
892927abfc4SLudovic Barre };
893927abfc4SLudovic Barre 
stm32_exti_remove_irq(void * data)894cfbf9e49SFabien Dessenne static void stm32_exti_remove_irq(void *data)
895927abfc4SLudovic Barre {
896cfbf9e49SFabien Dessenne 	struct irq_domain *domain = data;
897927abfc4SLudovic Barre 
898cfbf9e49SFabien Dessenne 	irq_domain_remove(domain);
899927abfc4SLudovic Barre }
900927abfc4SLudovic Barre 
stm32_exti_remove(struct platform_device * pdev)901cfbf9e49SFabien Dessenne static int stm32_exti_remove(struct platform_device *pdev)
902cfbf9e49SFabien Dessenne {
903cfbf9e49SFabien Dessenne 	stm32_exti_h_syscore_deinit();
904cfbf9e49SFabien Dessenne 	return 0;
905cfbf9e49SFabien Dessenne }
906cfbf9e49SFabien Dessenne 
stm32_exti_probe(struct platform_device * pdev)907cfbf9e49SFabien Dessenne static int stm32_exti_probe(struct platform_device *pdev)
908cfbf9e49SFabien Dessenne {
909cfbf9e49SFabien Dessenne 	int ret, i;
910cfbf9e49SFabien Dessenne 	struct device *dev = &pdev->dev;
911cfbf9e49SFabien Dessenne 	struct device_node *np = dev->of_node;
912cfbf9e49SFabien Dessenne 	struct irq_domain *parent_domain, *domain;
913cfbf9e49SFabien Dessenne 	struct stm32_exti_host_data *host_data;
914cfbf9e49SFabien Dessenne 	const struct stm32_exti_drv_data *drv_data;
915cfbf9e49SFabien Dessenne 
916cfbf9e49SFabien Dessenne 	host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL);
9174096165dSDan Carpenter 	if (!host_data)
9184096165dSDan Carpenter 		return -ENOMEM;
919927abfc4SLudovic Barre 
920cfbf9e49SFabien Dessenne 	/* check for optional hwspinlock which may be not available yet */
921cfbf9e49SFabien Dessenne 	ret = of_hwspin_lock_get_id(np, 0);
922cfbf9e49SFabien Dessenne 	if (ret == -EPROBE_DEFER)
923cfbf9e49SFabien Dessenne 		/* hwspinlock framework not yet ready */
924cfbf9e49SFabien Dessenne 		return ret;
925927abfc4SLudovic Barre 
926cfbf9e49SFabien Dessenne 	if (ret >= 0) {
927cfbf9e49SFabien Dessenne 		host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret);
928cfbf9e49SFabien Dessenne 		if (!host_data->hwlock) {
929cfbf9e49SFabien Dessenne 			dev_err(dev, "Failed to request hwspinlock\n");
930cfbf9e49SFabien Dessenne 			return -EINVAL;
931927abfc4SLudovic Barre 		}
932cfbf9e49SFabien Dessenne 	} else if (ret != -ENOENT) {
933cfbf9e49SFabien Dessenne 		/* note: ENOENT is a valid case (means 'no hwspinlock') */
934cfbf9e49SFabien Dessenne 		dev_err(dev, "Failed to get hwspinlock\n");
935927abfc4SLudovic Barre 		return ret;
936927abfc4SLudovic Barre 	}
937927abfc4SLudovic Barre 
938cfbf9e49SFabien Dessenne 	/* initialize host_data */
939cfbf9e49SFabien Dessenne 	drv_data = of_device_get_match_data(dev);
940cfbf9e49SFabien Dessenne 	if (!drv_data) {
941cfbf9e49SFabien Dessenne 		dev_err(dev, "no of match data\n");
942cfbf9e49SFabien Dessenne 		return -ENODEV;
943cfbf9e49SFabien Dessenne 	}
944cfbf9e49SFabien Dessenne 	host_data->drv_data = drv_data;
945cfbf9e49SFabien Dessenne 
946cfbf9e49SFabien Dessenne 	host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr,
947cfbf9e49SFabien Dessenne 					     sizeof(*host_data->chips_data),
948cfbf9e49SFabien Dessenne 					     GFP_KERNEL);
949cfbf9e49SFabien Dessenne 	if (!host_data->chips_data)
950cfbf9e49SFabien Dessenne 		return -ENOMEM;
951cfbf9e49SFabien Dessenne 
952fd9ac236SCai Huoqing 	host_data->base = devm_platform_ioremap_resource(pdev, 0);
953fbb80d5aSZhen Lei 	if (IS_ERR(host_data->base))
954cfbf9e49SFabien Dessenne 		return PTR_ERR(host_data->base);
955cfbf9e49SFabien Dessenne 
956cfbf9e49SFabien Dessenne 	for (i = 0; i < drv_data->bank_nr; i++)
957cfbf9e49SFabien Dessenne 		stm32_exti_chip_init(host_data, i, np);
958cfbf9e49SFabien Dessenne 
959cfbf9e49SFabien Dessenne 	parent_domain = irq_find_host(of_irq_find_parent(np));
960cfbf9e49SFabien Dessenne 	if (!parent_domain) {
961cfbf9e49SFabien Dessenne 		dev_err(dev, "GIC interrupt-parent not found\n");
962cfbf9e49SFabien Dessenne 		return -EINVAL;
963cfbf9e49SFabien Dessenne 	}
964cfbf9e49SFabien Dessenne 
965cfbf9e49SFabien Dessenne 	domain = irq_domain_add_hierarchy(parent_domain, 0,
966cfbf9e49SFabien Dessenne 					  drv_data->bank_nr * IRQS_PER_BANK,
967cfbf9e49SFabien Dessenne 					  np, &stm32_exti_h_domain_ops,
968cfbf9e49SFabien Dessenne 					  host_data);
969cfbf9e49SFabien Dessenne 
970cfbf9e49SFabien Dessenne 	if (!domain) {
971cfbf9e49SFabien Dessenne 		dev_err(dev, "Could not register exti domain\n");
972cfbf9e49SFabien Dessenne 		return -ENOMEM;
973cfbf9e49SFabien Dessenne 	}
974cfbf9e49SFabien Dessenne 
975cfbf9e49SFabien Dessenne 	ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain);
976cfbf9e49SFabien Dessenne 	if (ret)
977cfbf9e49SFabien Dessenne 		return ret;
978cfbf9e49SFabien Dessenne 
979cfbf9e49SFabien Dessenne 	stm32_exti_h_syscore_init(host_data);
980cfbf9e49SFabien Dessenne 
981cfbf9e49SFabien Dessenne 	return 0;
982cfbf9e49SFabien Dessenne }
983cfbf9e49SFabien Dessenne 
984cfbf9e49SFabien Dessenne /* platform driver only for MP1 */
985cfbf9e49SFabien Dessenne static const struct of_device_id stm32_exti_ids[] = {
986cfbf9e49SFabien Dessenne 	{ .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data},
98704133bb1SAlexandre Torgue 	{ .compatible = "st,stm32mp13-exti", .data = &stm32mp13_drv_data},
988cfbf9e49SFabien Dessenne 	{},
989cfbf9e49SFabien Dessenne };
990cfbf9e49SFabien Dessenne MODULE_DEVICE_TABLE(of, stm32_exti_ids);
991cfbf9e49SFabien Dessenne 
992cfbf9e49SFabien Dessenne static struct platform_driver stm32_exti_driver = {
993cfbf9e49SFabien Dessenne 	.probe		= stm32_exti_probe,
994cfbf9e49SFabien Dessenne 	.remove		= stm32_exti_remove,
995cfbf9e49SFabien Dessenne 	.driver		= {
996cfbf9e49SFabien Dessenne 		.name	= "stm32_exti",
997cfbf9e49SFabien Dessenne 		.of_match_table = stm32_exti_ids,
998cfbf9e49SFabien Dessenne 	},
999cfbf9e49SFabien Dessenne };
1000cfbf9e49SFabien Dessenne 
stm32_exti_arch_init(void)1001cfbf9e49SFabien Dessenne static int __init stm32_exti_arch_init(void)
1002cfbf9e49SFabien Dessenne {
1003cfbf9e49SFabien Dessenne 	return platform_driver_register(&stm32_exti_driver);
1004cfbf9e49SFabien Dessenne }
1005cfbf9e49SFabien Dessenne 
stm32_exti_arch_exit(void)1006cfbf9e49SFabien Dessenne static void __exit stm32_exti_arch_exit(void)
1007cfbf9e49SFabien Dessenne {
1008cfbf9e49SFabien Dessenne 	return platform_driver_unregister(&stm32_exti_driver);
1009cfbf9e49SFabien Dessenne }
1010cfbf9e49SFabien Dessenne 
1011cfbf9e49SFabien Dessenne arch_initcall(stm32_exti_arch_init);
1012cfbf9e49SFabien Dessenne module_exit(stm32_exti_arch_exit);
1013cfbf9e49SFabien Dessenne 
1014cfbf9e49SFabien Dessenne /* no platform driver for F4 and H7 */
stm32f4_exti_of_init(struct device_node * np,struct device_node * parent)10156dd64ee1SLudovic Barre static int __init stm32f4_exti_of_init(struct device_node *np,
10166dd64ee1SLudovic Barre 				       struct device_node *parent)
10176dd64ee1SLudovic Barre {
1018f9fc1745SLudovic Barre 	return stm32_exti_init(&stm32f4xx_drv_data, np);
10196dd64ee1SLudovic Barre }
10206dd64ee1SLudovic Barre 
10216dd64ee1SLudovic Barre IRQCHIP_DECLARE(stm32f4_exti, "st,stm32-exti", stm32f4_exti_of_init);
1022539c603eSLudovic Barre 
stm32h7_exti_of_init(struct device_node * np,struct device_node * parent)1023539c603eSLudovic Barre static int __init stm32h7_exti_of_init(struct device_node *np,
1024539c603eSLudovic Barre 				       struct device_node *parent)
1025539c603eSLudovic Barre {
1026f9fc1745SLudovic Barre 	return stm32_exti_init(&stm32h7xx_drv_data, np);
1027539c603eSLudovic Barre }
1028539c603eSLudovic Barre 
1029539c603eSLudovic Barre IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
1030