xref: /OK3568_Linux_fs/kernel/drivers/irqchip/irq-stm32-exti.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) Maxime Coquelin 2015
4*4882a593Smuzhiyun  * Copyright (C) STMicroelectronics 2017
5*4882a593Smuzhiyun  * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/bitops.h>
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/hwspinlock.h>
11*4882a593Smuzhiyun #include <linux/interrupt.h>
12*4882a593Smuzhiyun #include <linux/io.h>
13*4882a593Smuzhiyun #include <linux/irq.h>
14*4882a593Smuzhiyun #include <linux/irqchip.h>
15*4882a593Smuzhiyun #include <linux/irqchip/chained_irq.h>
16*4882a593Smuzhiyun #include <linux/irqdomain.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/of_address.h>
19*4882a593Smuzhiyun #include <linux/of_irq.h>
20*4882a593Smuzhiyun #include <linux/of_platform.h>
21*4882a593Smuzhiyun #include <linux/syscore_ops.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include <dt-bindings/interrupt-controller/arm-gic.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define IRQS_PER_BANK 32
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define HWSPNLCK_TIMEOUT	1000 /* usec */
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct stm32_exti_bank {
30*4882a593Smuzhiyun 	u32 imr_ofst;
31*4882a593Smuzhiyun 	u32 emr_ofst;
32*4882a593Smuzhiyun 	u32 rtsr_ofst;
33*4882a593Smuzhiyun 	u32 ftsr_ofst;
34*4882a593Smuzhiyun 	u32 swier_ofst;
35*4882a593Smuzhiyun 	u32 rpr_ofst;
36*4882a593Smuzhiyun 	u32 fpr_ofst;
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define UNDEF_REG ~0
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun struct stm32_desc_irq {
42*4882a593Smuzhiyun 	u32 exti;
43*4882a593Smuzhiyun 	u32 irq_parent;
44*4882a593Smuzhiyun 	struct irq_chip *chip;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun struct stm32_exti_drv_data {
48*4882a593Smuzhiyun 	const struct stm32_exti_bank **exti_banks;
49*4882a593Smuzhiyun 	const struct stm32_desc_irq *desc_irqs;
50*4882a593Smuzhiyun 	u32 bank_nr;
51*4882a593Smuzhiyun 	u32 irq_nr;
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun struct stm32_exti_chip_data {
55*4882a593Smuzhiyun 	struct stm32_exti_host_data *host_data;
56*4882a593Smuzhiyun 	const struct stm32_exti_bank *reg_bank;
57*4882a593Smuzhiyun 	struct raw_spinlock rlock;
58*4882a593Smuzhiyun 	u32 wake_active;
59*4882a593Smuzhiyun 	u32 mask_cache;
60*4882a593Smuzhiyun 	u32 rtsr_cache;
61*4882a593Smuzhiyun 	u32 ftsr_cache;
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun struct stm32_exti_host_data {
65*4882a593Smuzhiyun 	void __iomem *base;
66*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chips_data;
67*4882a593Smuzhiyun 	const struct stm32_exti_drv_data *drv_data;
68*4882a593Smuzhiyun 	struct hwspinlock *hwlock;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static struct stm32_exti_host_data *stm32_host_data;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
74*4882a593Smuzhiyun 	.imr_ofst	= 0x00,
75*4882a593Smuzhiyun 	.emr_ofst	= 0x04,
76*4882a593Smuzhiyun 	.rtsr_ofst	= 0x08,
77*4882a593Smuzhiyun 	.ftsr_ofst	= 0x0C,
78*4882a593Smuzhiyun 	.swier_ofst	= 0x10,
79*4882a593Smuzhiyun 	.rpr_ofst	= 0x14,
80*4882a593Smuzhiyun 	.fpr_ofst	= UNDEF_REG,
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
84*4882a593Smuzhiyun 	&stm32f4xx_exti_b1,
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static const struct stm32_exti_drv_data stm32f4xx_drv_data = {
88*4882a593Smuzhiyun 	.exti_banks = stm32f4xx_exti_banks,
89*4882a593Smuzhiyun 	.bank_nr = ARRAY_SIZE(stm32f4xx_exti_banks),
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static const struct stm32_exti_bank stm32h7xx_exti_b1 = {
93*4882a593Smuzhiyun 	.imr_ofst	= 0x80,
94*4882a593Smuzhiyun 	.emr_ofst	= 0x84,
95*4882a593Smuzhiyun 	.rtsr_ofst	= 0x00,
96*4882a593Smuzhiyun 	.ftsr_ofst	= 0x04,
97*4882a593Smuzhiyun 	.swier_ofst	= 0x08,
98*4882a593Smuzhiyun 	.rpr_ofst	= 0x88,
99*4882a593Smuzhiyun 	.fpr_ofst	= UNDEF_REG,
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
103*4882a593Smuzhiyun 	.imr_ofst	= 0x90,
104*4882a593Smuzhiyun 	.emr_ofst	= 0x94,
105*4882a593Smuzhiyun 	.rtsr_ofst	= 0x20,
106*4882a593Smuzhiyun 	.ftsr_ofst	= 0x24,
107*4882a593Smuzhiyun 	.swier_ofst	= 0x28,
108*4882a593Smuzhiyun 	.rpr_ofst	= 0x98,
109*4882a593Smuzhiyun 	.fpr_ofst	= UNDEF_REG,
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
113*4882a593Smuzhiyun 	.imr_ofst	= 0xA0,
114*4882a593Smuzhiyun 	.emr_ofst	= 0xA4,
115*4882a593Smuzhiyun 	.rtsr_ofst	= 0x40,
116*4882a593Smuzhiyun 	.ftsr_ofst	= 0x44,
117*4882a593Smuzhiyun 	.swier_ofst	= 0x48,
118*4882a593Smuzhiyun 	.rpr_ofst	= 0xA8,
119*4882a593Smuzhiyun 	.fpr_ofst	= UNDEF_REG,
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
123*4882a593Smuzhiyun 	&stm32h7xx_exti_b1,
124*4882a593Smuzhiyun 	&stm32h7xx_exti_b2,
125*4882a593Smuzhiyun 	&stm32h7xx_exti_b3,
126*4882a593Smuzhiyun };
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun static const struct stm32_exti_drv_data stm32h7xx_drv_data = {
129*4882a593Smuzhiyun 	.exti_banks = stm32h7xx_exti_banks,
130*4882a593Smuzhiyun 	.bank_nr = ARRAY_SIZE(stm32h7xx_exti_banks),
131*4882a593Smuzhiyun };
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun static const struct stm32_exti_bank stm32mp1_exti_b1 = {
134*4882a593Smuzhiyun 	.imr_ofst	= 0x80,
135*4882a593Smuzhiyun 	.emr_ofst	= 0x84,
136*4882a593Smuzhiyun 	.rtsr_ofst	= 0x00,
137*4882a593Smuzhiyun 	.ftsr_ofst	= 0x04,
138*4882a593Smuzhiyun 	.swier_ofst	= 0x08,
139*4882a593Smuzhiyun 	.rpr_ofst	= 0x0C,
140*4882a593Smuzhiyun 	.fpr_ofst	= 0x10,
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun static const struct stm32_exti_bank stm32mp1_exti_b2 = {
144*4882a593Smuzhiyun 	.imr_ofst	= 0x90,
145*4882a593Smuzhiyun 	.emr_ofst	= 0x94,
146*4882a593Smuzhiyun 	.rtsr_ofst	= 0x20,
147*4882a593Smuzhiyun 	.ftsr_ofst	= 0x24,
148*4882a593Smuzhiyun 	.swier_ofst	= 0x28,
149*4882a593Smuzhiyun 	.rpr_ofst	= 0x2C,
150*4882a593Smuzhiyun 	.fpr_ofst	= 0x30,
151*4882a593Smuzhiyun };
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun static const struct stm32_exti_bank stm32mp1_exti_b3 = {
154*4882a593Smuzhiyun 	.imr_ofst	= 0xA0,
155*4882a593Smuzhiyun 	.emr_ofst	= 0xA4,
156*4882a593Smuzhiyun 	.rtsr_ofst	= 0x40,
157*4882a593Smuzhiyun 	.ftsr_ofst	= 0x44,
158*4882a593Smuzhiyun 	.swier_ofst	= 0x48,
159*4882a593Smuzhiyun 	.rpr_ofst	= 0x4C,
160*4882a593Smuzhiyun 	.fpr_ofst	= 0x50,
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun static const struct stm32_exti_bank *stm32mp1_exti_banks[] = {
164*4882a593Smuzhiyun 	&stm32mp1_exti_b1,
165*4882a593Smuzhiyun 	&stm32mp1_exti_b2,
166*4882a593Smuzhiyun 	&stm32mp1_exti_b3,
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun static struct irq_chip stm32_exti_h_chip;
170*4882a593Smuzhiyun static struct irq_chip stm32_exti_h_chip_direct;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun static const struct stm32_desc_irq stm32mp1_desc_irq[] = {
173*4882a593Smuzhiyun 	{ .exti = 0, .irq_parent = 6, .chip = &stm32_exti_h_chip },
174*4882a593Smuzhiyun 	{ .exti = 1, .irq_parent = 7, .chip = &stm32_exti_h_chip },
175*4882a593Smuzhiyun 	{ .exti = 2, .irq_parent = 8, .chip = &stm32_exti_h_chip },
176*4882a593Smuzhiyun 	{ .exti = 3, .irq_parent = 9, .chip = &stm32_exti_h_chip },
177*4882a593Smuzhiyun 	{ .exti = 4, .irq_parent = 10, .chip = &stm32_exti_h_chip },
178*4882a593Smuzhiyun 	{ .exti = 5, .irq_parent = 23, .chip = &stm32_exti_h_chip },
179*4882a593Smuzhiyun 	{ .exti = 6, .irq_parent = 64, .chip = &stm32_exti_h_chip },
180*4882a593Smuzhiyun 	{ .exti = 7, .irq_parent = 65, .chip = &stm32_exti_h_chip },
181*4882a593Smuzhiyun 	{ .exti = 8, .irq_parent = 66, .chip = &stm32_exti_h_chip },
182*4882a593Smuzhiyun 	{ .exti = 9, .irq_parent = 67, .chip = &stm32_exti_h_chip },
183*4882a593Smuzhiyun 	{ .exti = 10, .irq_parent = 40, .chip = &stm32_exti_h_chip },
184*4882a593Smuzhiyun 	{ .exti = 11, .irq_parent = 42, .chip = &stm32_exti_h_chip },
185*4882a593Smuzhiyun 	{ .exti = 12, .irq_parent = 76, .chip = &stm32_exti_h_chip },
186*4882a593Smuzhiyun 	{ .exti = 13, .irq_parent = 77, .chip = &stm32_exti_h_chip },
187*4882a593Smuzhiyun 	{ .exti = 14, .irq_parent = 121, .chip = &stm32_exti_h_chip },
188*4882a593Smuzhiyun 	{ .exti = 15, .irq_parent = 127, .chip = &stm32_exti_h_chip },
189*4882a593Smuzhiyun 	{ .exti = 16, .irq_parent = 1, .chip = &stm32_exti_h_chip },
190*4882a593Smuzhiyun 	{ .exti = 19, .irq_parent = 3, .chip = &stm32_exti_h_chip_direct },
191*4882a593Smuzhiyun 	{ .exti = 21, .irq_parent = 31, .chip = &stm32_exti_h_chip_direct },
192*4882a593Smuzhiyun 	{ .exti = 22, .irq_parent = 33, .chip = &stm32_exti_h_chip_direct },
193*4882a593Smuzhiyun 	{ .exti = 23, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct },
194*4882a593Smuzhiyun 	{ .exti = 24, .irq_parent = 95, .chip = &stm32_exti_h_chip_direct },
195*4882a593Smuzhiyun 	{ .exti = 25, .irq_parent = 107, .chip = &stm32_exti_h_chip_direct },
196*4882a593Smuzhiyun 	{ .exti = 30, .irq_parent = 52, .chip = &stm32_exti_h_chip_direct },
197*4882a593Smuzhiyun 	{ .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct },
198*4882a593Smuzhiyun 	{ .exti = 48, .irq_parent = 138, .chip = &stm32_exti_h_chip_direct },
199*4882a593Smuzhiyun 	{ .exti = 50, .irq_parent = 139, .chip = &stm32_exti_h_chip_direct },
200*4882a593Smuzhiyun 	{ .exti = 52, .irq_parent = 140, .chip = &stm32_exti_h_chip_direct },
201*4882a593Smuzhiyun 	{ .exti = 53, .irq_parent = 141, .chip = &stm32_exti_h_chip_direct },
202*4882a593Smuzhiyun 	{ .exti = 54, .irq_parent = 135, .chip = &stm32_exti_h_chip_direct },
203*4882a593Smuzhiyun 	{ .exti = 61, .irq_parent = 100, .chip = &stm32_exti_h_chip_direct },
204*4882a593Smuzhiyun 	{ .exti = 65, .irq_parent = 144, .chip = &stm32_exti_h_chip },
205*4882a593Smuzhiyun 	{ .exti = 68, .irq_parent = 143, .chip = &stm32_exti_h_chip },
206*4882a593Smuzhiyun 	{ .exti = 70, .irq_parent = 62, .chip = &stm32_exti_h_chip_direct },
207*4882a593Smuzhiyun 	{ .exti = 73, .irq_parent = 129, .chip = &stm32_exti_h_chip },
208*4882a593Smuzhiyun };
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static const struct stm32_exti_drv_data stm32mp1_drv_data = {
211*4882a593Smuzhiyun 	.exti_banks = stm32mp1_exti_banks,
212*4882a593Smuzhiyun 	.bank_nr = ARRAY_SIZE(stm32mp1_exti_banks),
213*4882a593Smuzhiyun 	.desc_irqs = stm32mp1_desc_irq,
214*4882a593Smuzhiyun 	.irq_nr = ARRAY_SIZE(stm32mp1_desc_irq),
215*4882a593Smuzhiyun };
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun static const struct
stm32_exti_get_desc(const struct stm32_exti_drv_data * drv_data,irq_hw_number_t hwirq)218*4882a593Smuzhiyun stm32_desc_irq *stm32_exti_get_desc(const struct stm32_exti_drv_data *drv_data,
219*4882a593Smuzhiyun 				    irq_hw_number_t hwirq)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun 	const struct stm32_desc_irq *desc = NULL;
222*4882a593Smuzhiyun 	int i;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	if (!drv_data->desc_irqs)
225*4882a593Smuzhiyun 		return NULL;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	for (i = 0; i < drv_data->irq_nr; i++) {
228*4882a593Smuzhiyun 		desc = &drv_data->desc_irqs[i];
229*4882a593Smuzhiyun 		if (desc->exti == hwirq)
230*4882a593Smuzhiyun 			break;
231*4882a593Smuzhiyun 	}
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	return desc;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
stm32_exti_pending(struct irq_chip_generic * gc)236*4882a593Smuzhiyun static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = gc->private;
239*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
240*4882a593Smuzhiyun 	unsigned long pending;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	pending = irq_reg_readl(gc, stm32_bank->rpr_ofst);
243*4882a593Smuzhiyun 	if (stm32_bank->fpr_ofst != UNDEF_REG)
244*4882a593Smuzhiyun 		pending |= irq_reg_readl(gc, stm32_bank->fpr_ofst);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return pending;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
stm32_irq_handler(struct irq_desc * desc)249*4882a593Smuzhiyun static void stm32_irq_handler(struct irq_desc *desc)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	struct irq_domain *domain = irq_desc_get_handler_data(desc);
252*4882a593Smuzhiyun 	struct irq_chip *chip = irq_desc_get_chip(desc);
253*4882a593Smuzhiyun 	unsigned int virq, nbanks = domain->gc->num_chips;
254*4882a593Smuzhiyun 	struct irq_chip_generic *gc;
255*4882a593Smuzhiyun 	unsigned long pending;
256*4882a593Smuzhiyun 	int n, i, irq_base = 0;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	chained_irq_enter(chip, desc);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
261*4882a593Smuzhiyun 		gc = irq_get_domain_generic_chip(domain, irq_base);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 		while ((pending = stm32_exti_pending(gc))) {
264*4882a593Smuzhiyun 			for_each_set_bit(n, &pending, IRQS_PER_BANK) {
265*4882a593Smuzhiyun 				virq = irq_find_mapping(domain, irq_base + n);
266*4882a593Smuzhiyun 				generic_handle_irq(virq);
267*4882a593Smuzhiyun 			}
268*4882a593Smuzhiyun 		}
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	chained_irq_exit(chip, desc);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
stm32_exti_set_type(struct irq_data * d,unsigned int type,u32 * rtsr,u32 * ftsr)274*4882a593Smuzhiyun static int stm32_exti_set_type(struct irq_data *d,
275*4882a593Smuzhiyun 			       unsigned int type, u32 *rtsr, u32 *ftsr)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun 	u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	switch (type) {
280*4882a593Smuzhiyun 	case IRQ_TYPE_EDGE_RISING:
281*4882a593Smuzhiyun 		*rtsr |= mask;
282*4882a593Smuzhiyun 		*ftsr &= ~mask;
283*4882a593Smuzhiyun 		break;
284*4882a593Smuzhiyun 	case IRQ_TYPE_EDGE_FALLING:
285*4882a593Smuzhiyun 		*rtsr &= ~mask;
286*4882a593Smuzhiyun 		*ftsr |= mask;
287*4882a593Smuzhiyun 		break;
288*4882a593Smuzhiyun 	case IRQ_TYPE_EDGE_BOTH:
289*4882a593Smuzhiyun 		*rtsr |= mask;
290*4882a593Smuzhiyun 		*ftsr |= mask;
291*4882a593Smuzhiyun 		break;
292*4882a593Smuzhiyun 	default:
293*4882a593Smuzhiyun 		return -EINVAL;
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	return 0;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun 
stm32_irq_set_type(struct irq_data * d,unsigned int type)299*4882a593Smuzhiyun static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
302*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = gc->private;
303*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
304*4882a593Smuzhiyun 	struct hwspinlock *hwlock = chip_data->host_data->hwlock;
305*4882a593Smuzhiyun 	u32 rtsr, ftsr;
306*4882a593Smuzhiyun 	int err;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	irq_gc_lock(gc);
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	if (hwlock) {
311*4882a593Smuzhiyun 		err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT);
312*4882a593Smuzhiyun 		if (err) {
313*4882a593Smuzhiyun 			pr_err("%s can't get hwspinlock (%d)\n", __func__, err);
314*4882a593Smuzhiyun 			goto unlock;
315*4882a593Smuzhiyun 		}
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
319*4882a593Smuzhiyun 	ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
322*4882a593Smuzhiyun 	if (err)
323*4882a593Smuzhiyun 		goto unspinlock;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
326*4882a593Smuzhiyun 	irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun unspinlock:
329*4882a593Smuzhiyun 	if (hwlock)
330*4882a593Smuzhiyun 		hwspin_unlock_in_atomic(hwlock);
331*4882a593Smuzhiyun unlock:
332*4882a593Smuzhiyun 	irq_gc_unlock(gc);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	return err;
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
stm32_chip_suspend(struct stm32_exti_chip_data * chip_data,u32 wake_active)337*4882a593Smuzhiyun static void stm32_chip_suspend(struct stm32_exti_chip_data *chip_data,
338*4882a593Smuzhiyun 			       u32 wake_active)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
341*4882a593Smuzhiyun 	void __iomem *base = chip_data->host_data->base;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	/* save rtsr, ftsr registers */
344*4882a593Smuzhiyun 	chip_data->rtsr_cache = readl_relaxed(base + stm32_bank->rtsr_ofst);
345*4882a593Smuzhiyun 	chip_data->ftsr_cache = readl_relaxed(base + stm32_bank->ftsr_ofst);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	writel_relaxed(wake_active, base + stm32_bank->imr_ofst);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
stm32_chip_resume(struct stm32_exti_chip_data * chip_data,u32 mask_cache)350*4882a593Smuzhiyun static void stm32_chip_resume(struct stm32_exti_chip_data *chip_data,
351*4882a593Smuzhiyun 			      u32 mask_cache)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
354*4882a593Smuzhiyun 	void __iomem *base = chip_data->host_data->base;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	/* restore rtsr, ftsr, registers */
357*4882a593Smuzhiyun 	writel_relaxed(chip_data->rtsr_cache, base + stm32_bank->rtsr_ofst);
358*4882a593Smuzhiyun 	writel_relaxed(chip_data->ftsr_cache, base + stm32_bank->ftsr_ofst);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	writel_relaxed(mask_cache, base + stm32_bank->imr_ofst);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun 
stm32_irq_suspend(struct irq_chip_generic * gc)363*4882a593Smuzhiyun static void stm32_irq_suspend(struct irq_chip_generic *gc)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = gc->private;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	irq_gc_lock(gc);
368*4882a593Smuzhiyun 	stm32_chip_suspend(chip_data, gc->wake_active);
369*4882a593Smuzhiyun 	irq_gc_unlock(gc);
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
stm32_irq_resume(struct irq_chip_generic * gc)372*4882a593Smuzhiyun static void stm32_irq_resume(struct irq_chip_generic *gc)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = gc->private;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	irq_gc_lock(gc);
377*4882a593Smuzhiyun 	stm32_chip_resume(chip_data, gc->mask_cache);
378*4882a593Smuzhiyun 	irq_gc_unlock(gc);
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun 
stm32_exti_alloc(struct irq_domain * d,unsigned int virq,unsigned int nr_irqs,void * data)381*4882a593Smuzhiyun static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
382*4882a593Smuzhiyun 			    unsigned int nr_irqs, void *data)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun 	struct irq_fwspec *fwspec = data;
385*4882a593Smuzhiyun 	irq_hw_number_t hwirq;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	hwirq = fwspec->param[0];
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	irq_map_generic_chip(d, virq, hwirq);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	return 0;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
stm32_exti_free(struct irq_domain * d,unsigned int virq,unsigned int nr_irqs)394*4882a593Smuzhiyun static void stm32_exti_free(struct irq_domain *d, unsigned int virq,
395*4882a593Smuzhiyun 			    unsigned int nr_irqs)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	struct irq_data *data = irq_domain_get_irq_data(d, virq);
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	irq_domain_reset_irq_data(data);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun static const struct irq_domain_ops irq_exti_domain_ops = {
403*4882a593Smuzhiyun 	.map	= irq_map_generic_chip,
404*4882a593Smuzhiyun 	.alloc  = stm32_exti_alloc,
405*4882a593Smuzhiyun 	.free	= stm32_exti_free,
406*4882a593Smuzhiyun };
407*4882a593Smuzhiyun 
stm32_irq_ack(struct irq_data * d)408*4882a593Smuzhiyun static void stm32_irq_ack(struct irq_data *d)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
411*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = gc->private;
412*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	irq_gc_lock(gc);
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	irq_reg_writel(gc, d->mask, stm32_bank->rpr_ofst);
417*4882a593Smuzhiyun 	if (stm32_bank->fpr_ofst != UNDEF_REG)
418*4882a593Smuzhiyun 		irq_reg_writel(gc, d->mask, stm32_bank->fpr_ofst);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	irq_gc_unlock(gc);
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun /* directly set the target bit without reading first. */
stm32_exti_write_bit(struct irq_data * d,u32 reg)424*4882a593Smuzhiyun static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
427*4882a593Smuzhiyun 	void __iomem *base = chip_data->host_data->base;
428*4882a593Smuzhiyun 	u32 val = BIT(d->hwirq % IRQS_PER_BANK);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	writel_relaxed(val, base + reg);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
stm32_exti_set_bit(struct irq_data * d,u32 reg)433*4882a593Smuzhiyun static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
436*4882a593Smuzhiyun 	void __iomem *base = chip_data->host_data->base;
437*4882a593Smuzhiyun 	u32 val;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	val = readl_relaxed(base + reg);
440*4882a593Smuzhiyun 	val |= BIT(d->hwirq % IRQS_PER_BANK);
441*4882a593Smuzhiyun 	writel_relaxed(val, base + reg);
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return val;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
stm32_exti_clr_bit(struct irq_data * d,u32 reg)446*4882a593Smuzhiyun static inline u32 stm32_exti_clr_bit(struct irq_data *d, u32 reg)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
449*4882a593Smuzhiyun 	void __iomem *base = chip_data->host_data->base;
450*4882a593Smuzhiyun 	u32 val;
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	val = readl_relaxed(base + reg);
453*4882a593Smuzhiyun 	val &= ~BIT(d->hwirq % IRQS_PER_BANK);
454*4882a593Smuzhiyun 	writel_relaxed(val, base + reg);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	return val;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
stm32_exti_h_eoi(struct irq_data * d)459*4882a593Smuzhiyun static void stm32_exti_h_eoi(struct irq_data *d)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
462*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	raw_spin_lock(&chip_data->rlock);
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	stm32_exti_write_bit(d, stm32_bank->rpr_ofst);
467*4882a593Smuzhiyun 	if (stm32_bank->fpr_ofst != UNDEF_REG)
468*4882a593Smuzhiyun 		stm32_exti_write_bit(d, stm32_bank->fpr_ofst);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	raw_spin_unlock(&chip_data->rlock);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	if (d->parent_data->chip)
473*4882a593Smuzhiyun 		irq_chip_eoi_parent(d);
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun 
stm32_exti_h_mask(struct irq_data * d)476*4882a593Smuzhiyun static void stm32_exti_h_mask(struct irq_data *d)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
479*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	raw_spin_lock(&chip_data->rlock);
482*4882a593Smuzhiyun 	chip_data->mask_cache = stm32_exti_clr_bit(d, stm32_bank->imr_ofst);
483*4882a593Smuzhiyun 	raw_spin_unlock(&chip_data->rlock);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	if (d->parent_data->chip)
486*4882a593Smuzhiyun 		irq_chip_mask_parent(d);
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun 
stm32_exti_h_unmask(struct irq_data * d)489*4882a593Smuzhiyun static void stm32_exti_h_unmask(struct irq_data *d)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
492*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	raw_spin_lock(&chip_data->rlock);
495*4882a593Smuzhiyun 	chip_data->mask_cache = stm32_exti_set_bit(d, stm32_bank->imr_ofst);
496*4882a593Smuzhiyun 	raw_spin_unlock(&chip_data->rlock);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	if (d->parent_data->chip)
499*4882a593Smuzhiyun 		irq_chip_unmask_parent(d);
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
stm32_exti_h_set_type(struct irq_data * d,unsigned int type)502*4882a593Smuzhiyun static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
505*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
506*4882a593Smuzhiyun 	struct hwspinlock *hwlock = chip_data->host_data->hwlock;
507*4882a593Smuzhiyun 	void __iomem *base = chip_data->host_data->base;
508*4882a593Smuzhiyun 	u32 rtsr, ftsr;
509*4882a593Smuzhiyun 	int err;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	raw_spin_lock(&chip_data->rlock);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	if (hwlock) {
514*4882a593Smuzhiyun 		err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT);
515*4882a593Smuzhiyun 		if (err) {
516*4882a593Smuzhiyun 			pr_err("%s can't get hwspinlock (%d)\n", __func__, err);
517*4882a593Smuzhiyun 			goto unlock;
518*4882a593Smuzhiyun 		}
519*4882a593Smuzhiyun 	}
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst);
522*4882a593Smuzhiyun 	ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst);
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
525*4882a593Smuzhiyun 	if (err)
526*4882a593Smuzhiyun 		goto unspinlock;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	writel_relaxed(rtsr, base + stm32_bank->rtsr_ofst);
529*4882a593Smuzhiyun 	writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst);
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun unspinlock:
532*4882a593Smuzhiyun 	if (hwlock)
533*4882a593Smuzhiyun 		hwspin_unlock_in_atomic(hwlock);
534*4882a593Smuzhiyun unlock:
535*4882a593Smuzhiyun 	raw_spin_unlock(&chip_data->rlock);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	return err;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun 
stm32_exti_h_set_wake(struct irq_data * d,unsigned int on)540*4882a593Smuzhiyun static int stm32_exti_h_set_wake(struct irq_data *d, unsigned int on)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
543*4882a593Smuzhiyun 	u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	raw_spin_lock(&chip_data->rlock);
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	if (on)
548*4882a593Smuzhiyun 		chip_data->wake_active |= mask;
549*4882a593Smuzhiyun 	else
550*4882a593Smuzhiyun 		chip_data->wake_active &= ~mask;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	raw_spin_unlock(&chip_data->rlock);
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	return 0;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun 
stm32_exti_h_set_affinity(struct irq_data * d,const struct cpumask * dest,bool force)557*4882a593Smuzhiyun static int stm32_exti_h_set_affinity(struct irq_data *d,
558*4882a593Smuzhiyun 				     const struct cpumask *dest, bool force)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	if (d->parent_data->chip)
561*4882a593Smuzhiyun 		return irq_chip_set_affinity_parent(d, dest, force);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	return -EINVAL;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun 
stm32_exti_h_suspend(void)566*4882a593Smuzhiyun static int __maybe_unused stm32_exti_h_suspend(void)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data;
569*4882a593Smuzhiyun 	int i;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	for (i = 0; i < stm32_host_data->drv_data->bank_nr; i++) {
572*4882a593Smuzhiyun 		chip_data = &stm32_host_data->chips_data[i];
573*4882a593Smuzhiyun 		raw_spin_lock(&chip_data->rlock);
574*4882a593Smuzhiyun 		stm32_chip_suspend(chip_data, chip_data->wake_active);
575*4882a593Smuzhiyun 		raw_spin_unlock(&chip_data->rlock);
576*4882a593Smuzhiyun 	}
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	return 0;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun 
stm32_exti_h_resume(void)581*4882a593Smuzhiyun static void __maybe_unused stm32_exti_h_resume(void)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data;
584*4882a593Smuzhiyun 	int i;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	for (i = 0; i < stm32_host_data->drv_data->bank_nr; i++) {
587*4882a593Smuzhiyun 		chip_data = &stm32_host_data->chips_data[i];
588*4882a593Smuzhiyun 		raw_spin_lock(&chip_data->rlock);
589*4882a593Smuzhiyun 		stm32_chip_resume(chip_data, chip_data->mask_cache);
590*4882a593Smuzhiyun 		raw_spin_unlock(&chip_data->rlock);
591*4882a593Smuzhiyun 	}
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun static struct syscore_ops stm32_exti_h_syscore_ops = {
595*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
596*4882a593Smuzhiyun 	.suspend	= stm32_exti_h_suspend,
597*4882a593Smuzhiyun 	.resume		= stm32_exti_h_resume,
598*4882a593Smuzhiyun #endif
599*4882a593Smuzhiyun };
600*4882a593Smuzhiyun 
stm32_exti_h_syscore_init(struct stm32_exti_host_data * host_data)601*4882a593Smuzhiyun static void stm32_exti_h_syscore_init(struct stm32_exti_host_data *host_data)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun 	stm32_host_data = host_data;
604*4882a593Smuzhiyun 	register_syscore_ops(&stm32_exti_h_syscore_ops);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun 
stm32_exti_h_syscore_deinit(void)607*4882a593Smuzhiyun static void stm32_exti_h_syscore_deinit(void)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	unregister_syscore_ops(&stm32_exti_h_syscore_ops);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun 
stm32_exti_h_retrigger(struct irq_data * d)612*4882a593Smuzhiyun static int stm32_exti_h_retrigger(struct irq_data *d)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
615*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
616*4882a593Smuzhiyun 	void __iomem *base = chip_data->host_data->base;
617*4882a593Smuzhiyun 	u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	writel_relaxed(mask, base + stm32_bank->swier_ofst);
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	return 0;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun static struct irq_chip stm32_exti_h_chip = {
625*4882a593Smuzhiyun 	.name			= "stm32-exti-h",
626*4882a593Smuzhiyun 	.irq_eoi		= stm32_exti_h_eoi,
627*4882a593Smuzhiyun 	.irq_mask		= stm32_exti_h_mask,
628*4882a593Smuzhiyun 	.irq_unmask		= stm32_exti_h_unmask,
629*4882a593Smuzhiyun 	.irq_retrigger		= stm32_exti_h_retrigger,
630*4882a593Smuzhiyun 	.irq_set_type		= stm32_exti_h_set_type,
631*4882a593Smuzhiyun 	.irq_set_wake		= stm32_exti_h_set_wake,
632*4882a593Smuzhiyun 	.flags			= IRQCHIP_MASK_ON_SUSPEND,
633*4882a593Smuzhiyun 	.irq_set_affinity	= IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : NULL,
634*4882a593Smuzhiyun };
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun static struct irq_chip stm32_exti_h_chip_direct = {
637*4882a593Smuzhiyun 	.name			= "stm32-exti-h-direct",
638*4882a593Smuzhiyun 	.irq_eoi		= irq_chip_eoi_parent,
639*4882a593Smuzhiyun 	.irq_ack		= irq_chip_ack_parent,
640*4882a593Smuzhiyun 	.irq_mask		= irq_chip_mask_parent,
641*4882a593Smuzhiyun 	.irq_unmask		= irq_chip_unmask_parent,
642*4882a593Smuzhiyun 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
643*4882a593Smuzhiyun 	.irq_set_type		= irq_chip_set_type_parent,
644*4882a593Smuzhiyun 	.irq_set_wake		= stm32_exti_h_set_wake,
645*4882a593Smuzhiyun 	.flags			= IRQCHIP_MASK_ON_SUSPEND,
646*4882a593Smuzhiyun 	.irq_set_affinity	= IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL,
647*4882a593Smuzhiyun };
648*4882a593Smuzhiyun 
stm32_exti_h_domain_alloc(struct irq_domain * dm,unsigned int virq,unsigned int nr_irqs,void * data)649*4882a593Smuzhiyun static int stm32_exti_h_domain_alloc(struct irq_domain *dm,
650*4882a593Smuzhiyun 				     unsigned int virq,
651*4882a593Smuzhiyun 				     unsigned int nr_irqs, void *data)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun 	struct stm32_exti_host_data *host_data = dm->host_data;
654*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data;
655*4882a593Smuzhiyun 	const struct stm32_desc_irq *desc;
656*4882a593Smuzhiyun 	struct irq_fwspec *fwspec = data;
657*4882a593Smuzhiyun 	struct irq_fwspec p_fwspec;
658*4882a593Smuzhiyun 	irq_hw_number_t hwirq;
659*4882a593Smuzhiyun 	int bank;
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	hwirq = fwspec->param[0];
662*4882a593Smuzhiyun 	bank  = hwirq / IRQS_PER_BANK;
663*4882a593Smuzhiyun 	chip_data = &host_data->chips_data[bank];
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	desc = stm32_exti_get_desc(host_data->drv_data, hwirq);
667*4882a593Smuzhiyun 	if (!desc)
668*4882a593Smuzhiyun 		return -EINVAL;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	irq_domain_set_hwirq_and_chip(dm, virq, hwirq, desc->chip,
671*4882a593Smuzhiyun 				      chip_data);
672*4882a593Smuzhiyun 	if (desc->irq_parent) {
673*4882a593Smuzhiyun 		p_fwspec.fwnode = dm->parent->fwnode;
674*4882a593Smuzhiyun 		p_fwspec.param_count = 3;
675*4882a593Smuzhiyun 		p_fwspec.param[0] = GIC_SPI;
676*4882a593Smuzhiyun 		p_fwspec.param[1] = desc->irq_parent;
677*4882a593Smuzhiyun 		p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 		return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec);
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	return 0;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun static struct
stm32_exti_host_init(const struct stm32_exti_drv_data * dd,struct device_node * node)686*4882a593Smuzhiyun stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
687*4882a593Smuzhiyun 					   struct device_node *node)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	struct stm32_exti_host_data *host_data;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	host_data = kzalloc(sizeof(*host_data), GFP_KERNEL);
692*4882a593Smuzhiyun 	if (!host_data)
693*4882a593Smuzhiyun 		return NULL;
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	host_data->drv_data = dd;
696*4882a593Smuzhiyun 	host_data->chips_data = kcalloc(dd->bank_nr,
697*4882a593Smuzhiyun 					sizeof(struct stm32_exti_chip_data),
698*4882a593Smuzhiyun 					GFP_KERNEL);
699*4882a593Smuzhiyun 	if (!host_data->chips_data)
700*4882a593Smuzhiyun 		goto free_host_data;
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	host_data->base = of_iomap(node, 0);
703*4882a593Smuzhiyun 	if (!host_data->base) {
704*4882a593Smuzhiyun 		pr_err("%pOF: Unable to map registers\n", node);
705*4882a593Smuzhiyun 		goto free_chips_data;
706*4882a593Smuzhiyun 	}
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	stm32_host_data = host_data;
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	return host_data;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun free_chips_data:
713*4882a593Smuzhiyun 	kfree(host_data->chips_data);
714*4882a593Smuzhiyun free_host_data:
715*4882a593Smuzhiyun 	kfree(host_data);
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	return NULL;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun static struct
stm32_exti_chip_init(struct stm32_exti_host_data * h_data,u32 bank_idx,struct device_node * node)721*4882a593Smuzhiyun stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
722*4882a593Smuzhiyun 					   u32 bank_idx,
723*4882a593Smuzhiyun 					   struct device_node *node)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun 	const struct stm32_exti_bank *stm32_bank;
726*4882a593Smuzhiyun 	struct stm32_exti_chip_data *chip_data;
727*4882a593Smuzhiyun 	void __iomem *base = h_data->base;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	stm32_bank = h_data->drv_data->exti_banks[bank_idx];
730*4882a593Smuzhiyun 	chip_data = &h_data->chips_data[bank_idx];
731*4882a593Smuzhiyun 	chip_data->host_data = h_data;
732*4882a593Smuzhiyun 	chip_data->reg_bank = stm32_bank;
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	raw_spin_lock_init(&chip_data->rlock);
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	/*
737*4882a593Smuzhiyun 	 * This IP has no reset, so after hot reboot we should
738*4882a593Smuzhiyun 	 * clear registers to avoid residue
739*4882a593Smuzhiyun 	 */
740*4882a593Smuzhiyun 	writel_relaxed(0, base + stm32_bank->imr_ofst);
741*4882a593Smuzhiyun 	writel_relaxed(0, base + stm32_bank->emr_ofst);
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	pr_info("%pOF: bank%d\n", node, bank_idx);
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	return chip_data;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun 
stm32_exti_init(const struct stm32_exti_drv_data * drv_data,struct device_node * node)748*4882a593Smuzhiyun static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
749*4882a593Smuzhiyun 				  struct device_node *node)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun 	struct stm32_exti_host_data *host_data;
752*4882a593Smuzhiyun 	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
753*4882a593Smuzhiyun 	int nr_irqs, ret, i;
754*4882a593Smuzhiyun 	struct irq_chip_generic *gc;
755*4882a593Smuzhiyun 	struct irq_domain *domain;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	host_data = stm32_exti_host_init(drv_data, node);
758*4882a593Smuzhiyun 	if (!host_data)
759*4882a593Smuzhiyun 		return -ENOMEM;
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	domain = irq_domain_add_linear(node, drv_data->bank_nr * IRQS_PER_BANK,
762*4882a593Smuzhiyun 				       &irq_exti_domain_ops, NULL);
763*4882a593Smuzhiyun 	if (!domain) {
764*4882a593Smuzhiyun 		pr_err("%pOFn: Could not register interrupt domain.\n",
765*4882a593Smuzhiyun 		       node);
766*4882a593Smuzhiyun 		ret = -ENOMEM;
767*4882a593Smuzhiyun 		goto out_unmap;
768*4882a593Smuzhiyun 	}
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	ret = irq_alloc_domain_generic_chips(domain, IRQS_PER_BANK, 1, "exti",
771*4882a593Smuzhiyun 					     handle_edge_irq, clr, 0, 0);
772*4882a593Smuzhiyun 	if (ret) {
773*4882a593Smuzhiyun 		pr_err("%pOF: Could not allocate generic interrupt chip.\n",
774*4882a593Smuzhiyun 		       node);
775*4882a593Smuzhiyun 		goto out_free_domain;
776*4882a593Smuzhiyun 	}
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 	for (i = 0; i < drv_data->bank_nr; i++) {
779*4882a593Smuzhiyun 		const struct stm32_exti_bank *stm32_bank;
780*4882a593Smuzhiyun 		struct stm32_exti_chip_data *chip_data;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 		stm32_bank = drv_data->exti_banks[i];
783*4882a593Smuzhiyun 		chip_data = stm32_exti_chip_init(host_data, i, node);
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 		gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 		gc->reg_base = host_data->base;
788*4882a593Smuzhiyun 		gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
789*4882a593Smuzhiyun 		gc->chip_types->chip.irq_ack = stm32_irq_ack;
790*4882a593Smuzhiyun 		gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
791*4882a593Smuzhiyun 		gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
792*4882a593Smuzhiyun 		gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
793*4882a593Smuzhiyun 		gc->chip_types->chip.irq_set_wake = irq_gc_set_wake;
794*4882a593Smuzhiyun 		gc->suspend = stm32_irq_suspend;
795*4882a593Smuzhiyun 		gc->resume = stm32_irq_resume;
796*4882a593Smuzhiyun 		gc->wake_enabled = IRQ_MSK(IRQS_PER_BANK);
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 		gc->chip_types->regs.mask = stm32_bank->imr_ofst;
799*4882a593Smuzhiyun 		gc->private = (void *)chip_data;
800*4882a593Smuzhiyun 	}
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 	nr_irqs = of_irq_count(node);
803*4882a593Smuzhiyun 	for (i = 0; i < nr_irqs; i++) {
804*4882a593Smuzhiyun 		unsigned int irq = irq_of_parse_and_map(node, i);
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 		irq_set_handler_data(irq, domain);
807*4882a593Smuzhiyun 		irq_set_chained_handler(irq, stm32_irq_handler);
808*4882a593Smuzhiyun 	}
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	return 0;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun out_free_domain:
813*4882a593Smuzhiyun 	irq_domain_remove(domain);
814*4882a593Smuzhiyun out_unmap:
815*4882a593Smuzhiyun 	iounmap(host_data->base);
816*4882a593Smuzhiyun 	kfree(host_data->chips_data);
817*4882a593Smuzhiyun 	kfree(host_data);
818*4882a593Smuzhiyun 	return ret;
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun static const struct irq_domain_ops stm32_exti_h_domain_ops = {
822*4882a593Smuzhiyun 	.alloc	= stm32_exti_h_domain_alloc,
823*4882a593Smuzhiyun 	.free	= irq_domain_free_irqs_common,
824*4882a593Smuzhiyun 	.xlate = irq_domain_xlate_twocell,
825*4882a593Smuzhiyun };
826*4882a593Smuzhiyun 
stm32_exti_remove_irq(void * data)827*4882a593Smuzhiyun static void stm32_exti_remove_irq(void *data)
828*4882a593Smuzhiyun {
829*4882a593Smuzhiyun 	struct irq_domain *domain = data;
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 	irq_domain_remove(domain);
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun 
stm32_exti_remove(struct platform_device * pdev)834*4882a593Smuzhiyun static int stm32_exti_remove(struct platform_device *pdev)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun 	stm32_exti_h_syscore_deinit();
837*4882a593Smuzhiyun 	return 0;
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun 
stm32_exti_probe(struct platform_device * pdev)840*4882a593Smuzhiyun static int stm32_exti_probe(struct platform_device *pdev)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun 	int ret, i;
843*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
844*4882a593Smuzhiyun 	struct device_node *np = dev->of_node;
845*4882a593Smuzhiyun 	struct irq_domain *parent_domain, *domain;
846*4882a593Smuzhiyun 	struct stm32_exti_host_data *host_data;
847*4882a593Smuzhiyun 	const struct stm32_exti_drv_data *drv_data;
848*4882a593Smuzhiyun 	struct resource *res;
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL);
851*4882a593Smuzhiyun 	if (!host_data)
852*4882a593Smuzhiyun 		return -ENOMEM;
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	/* check for optional hwspinlock which may be not available yet */
855*4882a593Smuzhiyun 	ret = of_hwspin_lock_get_id(np, 0);
856*4882a593Smuzhiyun 	if (ret == -EPROBE_DEFER)
857*4882a593Smuzhiyun 		/* hwspinlock framework not yet ready */
858*4882a593Smuzhiyun 		return ret;
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	if (ret >= 0) {
861*4882a593Smuzhiyun 		host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret);
862*4882a593Smuzhiyun 		if (!host_data->hwlock) {
863*4882a593Smuzhiyun 			dev_err(dev, "Failed to request hwspinlock\n");
864*4882a593Smuzhiyun 			return -EINVAL;
865*4882a593Smuzhiyun 		}
866*4882a593Smuzhiyun 	} else if (ret != -ENOENT) {
867*4882a593Smuzhiyun 		/* note: ENOENT is a valid case (means 'no hwspinlock') */
868*4882a593Smuzhiyun 		dev_err(dev, "Failed to get hwspinlock\n");
869*4882a593Smuzhiyun 		return ret;
870*4882a593Smuzhiyun 	}
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	/* initialize host_data */
873*4882a593Smuzhiyun 	drv_data = of_device_get_match_data(dev);
874*4882a593Smuzhiyun 	if (!drv_data) {
875*4882a593Smuzhiyun 		dev_err(dev, "no of match data\n");
876*4882a593Smuzhiyun 		return -ENODEV;
877*4882a593Smuzhiyun 	}
878*4882a593Smuzhiyun 	host_data->drv_data = drv_data;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr,
881*4882a593Smuzhiyun 					     sizeof(*host_data->chips_data),
882*4882a593Smuzhiyun 					     GFP_KERNEL);
883*4882a593Smuzhiyun 	if (!host_data->chips_data)
884*4882a593Smuzhiyun 		return -ENOMEM;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
887*4882a593Smuzhiyun 	host_data->base = devm_ioremap_resource(dev, res);
888*4882a593Smuzhiyun 	if (IS_ERR(host_data->base)) {
889*4882a593Smuzhiyun 		dev_err(dev, "Unable to map registers\n");
890*4882a593Smuzhiyun 		return PTR_ERR(host_data->base);
891*4882a593Smuzhiyun 	}
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun 	for (i = 0; i < drv_data->bank_nr; i++)
894*4882a593Smuzhiyun 		stm32_exti_chip_init(host_data, i, np);
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	parent_domain = irq_find_host(of_irq_find_parent(np));
897*4882a593Smuzhiyun 	if (!parent_domain) {
898*4882a593Smuzhiyun 		dev_err(dev, "GIC interrupt-parent not found\n");
899*4882a593Smuzhiyun 		return -EINVAL;
900*4882a593Smuzhiyun 	}
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	domain = irq_domain_add_hierarchy(parent_domain, 0,
903*4882a593Smuzhiyun 					  drv_data->bank_nr * IRQS_PER_BANK,
904*4882a593Smuzhiyun 					  np, &stm32_exti_h_domain_ops,
905*4882a593Smuzhiyun 					  host_data);
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	if (!domain) {
908*4882a593Smuzhiyun 		dev_err(dev, "Could not register exti domain\n");
909*4882a593Smuzhiyun 		return -ENOMEM;
910*4882a593Smuzhiyun 	}
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 	ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain);
913*4882a593Smuzhiyun 	if (ret)
914*4882a593Smuzhiyun 		return ret;
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	stm32_exti_h_syscore_init(host_data);
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	return 0;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun /* platform driver only for MP1 */
922*4882a593Smuzhiyun static const struct of_device_id stm32_exti_ids[] = {
923*4882a593Smuzhiyun 	{ .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data},
924*4882a593Smuzhiyun 	{},
925*4882a593Smuzhiyun };
926*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, stm32_exti_ids);
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun static struct platform_driver stm32_exti_driver = {
929*4882a593Smuzhiyun 	.probe		= stm32_exti_probe,
930*4882a593Smuzhiyun 	.remove		= stm32_exti_remove,
931*4882a593Smuzhiyun 	.driver		= {
932*4882a593Smuzhiyun 		.name	= "stm32_exti",
933*4882a593Smuzhiyun 		.of_match_table = stm32_exti_ids,
934*4882a593Smuzhiyun 	},
935*4882a593Smuzhiyun };
936*4882a593Smuzhiyun 
stm32_exti_arch_init(void)937*4882a593Smuzhiyun static int __init stm32_exti_arch_init(void)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun 	return platform_driver_register(&stm32_exti_driver);
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun 
stm32_exti_arch_exit(void)942*4882a593Smuzhiyun static void __exit stm32_exti_arch_exit(void)
943*4882a593Smuzhiyun {
944*4882a593Smuzhiyun 	return platform_driver_unregister(&stm32_exti_driver);
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun arch_initcall(stm32_exti_arch_init);
948*4882a593Smuzhiyun module_exit(stm32_exti_arch_exit);
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun /* no platform driver for F4 and H7 */
stm32f4_exti_of_init(struct device_node * np,struct device_node * parent)951*4882a593Smuzhiyun static int __init stm32f4_exti_of_init(struct device_node *np,
952*4882a593Smuzhiyun 				       struct device_node *parent)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun 	return stm32_exti_init(&stm32f4xx_drv_data, np);
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun IRQCHIP_DECLARE(stm32f4_exti, "st,stm32-exti", stm32f4_exti_of_init);
958*4882a593Smuzhiyun 
stm32h7_exti_of_init(struct device_node * np,struct device_node * parent)959*4882a593Smuzhiyun static int __init stm32h7_exti_of_init(struct device_node *np,
960*4882a593Smuzhiyun 				       struct device_node *parent)
961*4882a593Smuzhiyun {
962*4882a593Smuzhiyun 	return stm32_exti_init(&stm32h7xx_drv_data, np);
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
966