1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) Maxime Coquelin 2015
4 * Copyright (C) STMicroelectronics 2017-2024
5 * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
6 */
7
8 #include <linux/bitops.h>
9 #include <linux/hwspinlock.h>
10 #include <linux/interrupt.h>
11 #include <linux/io.h>
12 #include <linux/irq.h>
13 #include <linux/irqchip.h>
14 #include <linux/irqdomain.h>
15 #include <linux/module.h>
16 #include <linux/of_address.h>
17 #include <linux/of_irq.h>
18 #include <linux/platform_device.h>
19 #include <linux/pm.h>
20
21 #include <dt-bindings/interrupt-controller/arm-gic.h>
22
23 #define IRQS_PER_BANK 32
24
25 #define HWSPNLCK_TIMEOUT_MS 1
26
27 #define EXTI_EnCIDCFGR(n) (0x180 + (n) * 4)
28 #define EXTI_HWCFGR1 0x3f0
29
30 /* Register: EXTI_EnCIDCFGR(n) */
31 #define EXTI_CIDCFGR_CFEN_MASK BIT(0)
32 #define EXTI_CIDCFGR_CID_MASK GENMASK(6, 4)
33 #define EXTI_CIDCFGR_CID_SHIFT 4
34
35 /* Register: EXTI_HWCFGR1 */
36 #define EXTI_HWCFGR1_CIDWIDTH_MASK GENMASK(27, 24)
37
38 #define EXTI_CID1 1
39
40 struct stm32mp_exti_bank {
41 u32 imr_ofst;
42 u32 rtsr_ofst;
43 u32 ftsr_ofst;
44 u32 swier_ofst;
45 u32 rpr_ofst;
46 u32 fpr_ofst;
47 u32 trg_ofst;
48 u32 seccfgr_ofst;
49 };
50
51 struct stm32mp_exti_drv_data {
52 const struct stm32mp_exti_bank **exti_banks;
53 const u8 *desc_irqs;
54 u32 bank_nr;
55 };
56
57 struct stm32mp_exti_chip_data {
58 struct stm32mp_exti_host_data *host_data;
59 const struct stm32mp_exti_bank *reg_bank;
60 struct raw_spinlock rlock;
61 u32 wake_active;
62 u32 mask_cache;
63 u32 rtsr_cache;
64 u32 ftsr_cache;
65 u32 event_reserved;
66 };
67
68 struct stm32mp_exti_host_data {
69 void __iomem *base;
70 struct device *dev;
71 struct stm32mp_exti_chip_data *chips_data;
72 const struct stm32mp_exti_drv_data *drv_data;
73 struct hwspinlock *hwlock;
74 /* skip internal desc_irqs array and get it from DT */
75 bool dt_has_irqs_desc;
76 };
77
78 static const struct stm32mp_exti_bank stm32mp_exti_b1 = {
79 .imr_ofst = 0x80,
80 .rtsr_ofst = 0x00,
81 .ftsr_ofst = 0x04,
82 .swier_ofst = 0x08,
83 .rpr_ofst = 0x0C,
84 .fpr_ofst = 0x10,
85 .trg_ofst = 0x3EC,
86 .seccfgr_ofst = 0x14,
87 };
88
89 static const struct stm32mp_exti_bank stm32mp_exti_b2 = {
90 .imr_ofst = 0x90,
91 .rtsr_ofst = 0x20,
92 .ftsr_ofst = 0x24,
93 .swier_ofst = 0x28,
94 .rpr_ofst = 0x2C,
95 .fpr_ofst = 0x30,
96 .trg_ofst = 0x3E8,
97 .seccfgr_ofst = 0x34,
98 };
99
100 static const struct stm32mp_exti_bank stm32mp_exti_b3 = {
101 .imr_ofst = 0xA0,
102 .rtsr_ofst = 0x40,
103 .ftsr_ofst = 0x44,
104 .swier_ofst = 0x48,
105 .rpr_ofst = 0x4C,
106 .fpr_ofst = 0x50,
107 .trg_ofst = 0x3E4,
108 .seccfgr_ofst = 0x54,
109 };
110
111 static const struct stm32mp_exti_bank *stm32mp_exti_banks[] = {
112 &stm32mp_exti_b1,
113 &stm32mp_exti_b2,
114 &stm32mp_exti_b3,
115 };
116
117 static struct irq_chip stm32mp_exti_chip;
118 static struct irq_chip stm32mp_exti_chip_direct;
119
120 #define EXTI_INVALID_IRQ U8_MAX
121 #define STM32MP_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp_exti_banks) * IRQS_PER_BANK)
122
123 /*
124 * Use some intentionally tricky logic here to initialize the whole array to
125 * EXTI_INVALID_IRQ, but then override certain fields, requiring us to indicate
126 * that we "know" that there are overrides in this structure, and we'll need to
127 * disable that warning from W=1 builds.
128 */
129 __diag_push();
130 __diag_ignore_all("-Woverride-init",
131 "logic to initialize all and then override some is OK");
132
133 static const u8 stm32mp1_desc_irq[] = {
134 /* default value */
135 [0 ... (STM32MP_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ,
136
137 [0] = 6,
138 [1] = 7,
139 [2] = 8,
140 [3] = 9,
141 [4] = 10,
142 [5] = 23,
143 [6] = 64,
144 [7] = 65,
145 [8] = 66,
146 [9] = 67,
147 [10] = 40,
148 [11] = 42,
149 [12] = 76,
150 [13] = 77,
151 [14] = 121,
152 [15] = 127,
153 [16] = 1,
154 [19] = 3,
155 [21] = 31,
156 [22] = 33,
157 [23] = 72,
158 [24] = 95,
159 [25] = 107,
160 [26] = 37,
161 [27] = 38,
162 [28] = 39,
163 [29] = 71,
164 [30] = 52,
165 [31] = 53,
166 [32] = 82,
167 [33] = 83,
168 [46] = 151,
169 [47] = 93,
170 [48] = 138,
171 [50] = 139,
172 [52] = 140,
173 [53] = 141,
174 [54] = 135,
175 [61] = 100,
176 [65] = 144,
177 [68] = 143,
178 [70] = 62,
179 [73] = 129,
180 };
181
182 static const u8 stm32mp13_desc_irq[] = {
183 /* default value */
184 [0 ... (STM32MP_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ,
185
186 [0] = 6,
187 [1] = 7,
188 [2] = 8,
189 [3] = 9,
190 [4] = 10,
191 [5] = 24,
192 [6] = 65,
193 [7] = 66,
194 [8] = 67,
195 [9] = 68,
196 [10] = 41,
197 [11] = 43,
198 [12] = 77,
199 [13] = 78,
200 [14] = 106,
201 [15] = 109,
202 [16] = 1,
203 [19] = 3,
204 [21] = 32,
205 [22] = 34,
206 [23] = 73,
207 [24] = 93,
208 [25] = 114,
209 [26] = 38,
210 [27] = 39,
211 [28] = 40,
212 [29] = 72,
213 [30] = 53,
214 [31] = 54,
215 [32] = 83,
216 [33] = 84,
217 [44] = 96,
218 [47] = 92,
219 [48] = 116,
220 [50] = 117,
221 [52] = 118,
222 [53] = 119,
223 [68] = 63,
224 [70] = 98,
225 };
226
227 __diag_pop();
228
229 static const struct stm32mp_exti_drv_data stm32mp1_drv_data = {
230 .exti_banks = stm32mp_exti_banks,
231 .bank_nr = ARRAY_SIZE(stm32mp_exti_banks),
232 .desc_irqs = stm32mp1_desc_irq,
233 };
234
235 static const struct stm32mp_exti_drv_data stm32mp13_drv_data = {
236 .exti_banks = stm32mp_exti_banks,
237 .bank_nr = ARRAY_SIZE(stm32mp_exti_banks),
238 .desc_irqs = stm32mp13_desc_irq,
239 };
240
stm32mp_exti_convert_type(struct irq_data * d,unsigned int type,u32 * rtsr,u32 * ftsr)241 static int stm32mp_exti_convert_type(struct irq_data *d, unsigned int type, u32 *rtsr, u32 *ftsr)
242 {
243 u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
244
245 switch (type) {
246 case IRQ_TYPE_EDGE_RISING:
247 *rtsr |= mask;
248 *ftsr &= ~mask;
249 break;
250 case IRQ_TYPE_EDGE_FALLING:
251 *rtsr &= ~mask;
252 *ftsr |= mask;
253 break;
254 case IRQ_TYPE_EDGE_BOTH:
255 *rtsr |= mask;
256 *ftsr |= mask;
257 break;
258 default:
259 return -EINVAL;
260 }
261
262 return 0;
263 }
264
stm32mp_chip_suspend(struct stm32mp_exti_chip_data * chip_data,u32 wake_active)265 static void stm32mp_chip_suspend(struct stm32mp_exti_chip_data *chip_data, u32 wake_active)
266 {
267 const struct stm32mp_exti_bank *bank = chip_data->reg_bank;
268 void __iomem *base = chip_data->host_data->base;
269
270 /* save rtsr, ftsr registers */
271 chip_data->rtsr_cache = readl_relaxed(base + bank->rtsr_ofst);
272 chip_data->ftsr_cache = readl_relaxed(base + bank->ftsr_ofst);
273
274 writel_relaxed(wake_active, base + bank->imr_ofst);
275 }
276
stm32mp_chip_resume(struct stm32mp_exti_chip_data * chip_data,u32 mask_cache)277 static void stm32mp_chip_resume(struct stm32mp_exti_chip_data *chip_data, u32 mask_cache)
278 {
279 const struct stm32mp_exti_bank *bank = chip_data->reg_bank;
280 void __iomem *base = chip_data->host_data->base;
281
282 /* restore rtsr, ftsr, registers */
283 writel_relaxed(chip_data->rtsr_cache, base + bank->rtsr_ofst);
284 writel_relaxed(chip_data->ftsr_cache, base + bank->ftsr_ofst);
285
286 writel_relaxed(mask_cache, base + bank->imr_ofst);
287 }
288
289 /* directly set the target bit without reading first. */
stm32mp_exti_write_bit(struct irq_data * d,u32 reg)290 static inline void stm32mp_exti_write_bit(struct irq_data *d, u32 reg)
291 {
292 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
293 void __iomem *base = chip_data->host_data->base;
294 u32 val = BIT(d->hwirq % IRQS_PER_BANK);
295
296 writel_relaxed(val, base + reg);
297 }
298
stm32mp_exti_set_bit(struct irq_data * d,u32 reg)299 static inline u32 stm32mp_exti_set_bit(struct irq_data *d, u32 reg)
300 {
301 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
302 void __iomem *base = chip_data->host_data->base;
303 u32 val;
304
305 val = readl_relaxed(base + reg);
306 val |= BIT(d->hwirq % IRQS_PER_BANK);
307 writel_relaxed(val, base + reg);
308
309 return val;
310 }
311
stm32mp_exti_clr_bit(struct irq_data * d,u32 reg)312 static inline u32 stm32mp_exti_clr_bit(struct irq_data *d, u32 reg)
313 {
314 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
315 void __iomem *base = chip_data->host_data->base;
316 u32 val;
317
318 val = readl_relaxed(base + reg);
319 val &= ~BIT(d->hwirq % IRQS_PER_BANK);
320 writel_relaxed(val, base + reg);
321
322 return val;
323 }
324
stm32mp_exti_eoi(struct irq_data * d)325 static void stm32mp_exti_eoi(struct irq_data *d)
326 {
327 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
328 const struct stm32mp_exti_bank *bank = chip_data->reg_bank;
329
330 raw_spin_lock(&chip_data->rlock);
331
332 stm32mp_exti_write_bit(d, bank->rpr_ofst);
333 stm32mp_exti_write_bit(d, bank->fpr_ofst);
334
335 raw_spin_unlock(&chip_data->rlock);
336
337 if (d->parent_data->chip)
338 irq_chip_eoi_parent(d);
339 }
340
stm32mp_exti_mask(struct irq_data * d)341 static void stm32mp_exti_mask(struct irq_data *d)
342 {
343 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
344 const struct stm32mp_exti_bank *bank = chip_data->reg_bank;
345
346 raw_spin_lock(&chip_data->rlock);
347 chip_data->mask_cache = stm32mp_exti_clr_bit(d, bank->imr_ofst);
348 raw_spin_unlock(&chip_data->rlock);
349
350 if (d->parent_data->chip)
351 irq_chip_mask_parent(d);
352 }
353
stm32mp_exti_unmask(struct irq_data * d)354 static void stm32mp_exti_unmask(struct irq_data *d)
355 {
356 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
357 const struct stm32mp_exti_bank *bank = chip_data->reg_bank;
358
359 raw_spin_lock(&chip_data->rlock);
360 chip_data->mask_cache = stm32mp_exti_set_bit(d, bank->imr_ofst);
361 raw_spin_unlock(&chip_data->rlock);
362
363 if (d->parent_data->chip)
364 irq_chip_unmask_parent(d);
365 }
366
stm32mp_exti_set_type(struct irq_data * d,unsigned int type)367 static int stm32mp_exti_set_type(struct irq_data *d, unsigned int type)
368 {
369 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
370 const struct stm32mp_exti_bank *bank = chip_data->reg_bank;
371 struct hwspinlock *hwlock = chip_data->host_data->hwlock;
372 void __iomem *base = chip_data->host_data->base;
373 u32 rtsr, ftsr;
374 int err;
375
376 raw_spin_lock(&chip_data->rlock);
377
378 if (hwlock) {
379 err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT_MS);
380 if (err) {
381 pr_err("%s can't get hwspinlock (%d)\n", __func__, err);
382 goto unlock;
383 }
384 }
385
386 rtsr = readl_relaxed(base + bank->rtsr_ofst);
387 ftsr = readl_relaxed(base + bank->ftsr_ofst);
388
389 err = stm32mp_exti_convert_type(d, type, &rtsr, &ftsr);
390 if (!err) {
391 writel_relaxed(rtsr, base + bank->rtsr_ofst);
392 writel_relaxed(ftsr, base + bank->ftsr_ofst);
393 }
394
395 if (hwlock)
396 hwspin_unlock_in_atomic(hwlock);
397 unlock:
398 raw_spin_unlock(&chip_data->rlock);
399 return err;
400 }
401
stm32mp_exti_set_wake(struct irq_data * d,unsigned int on)402 static int stm32mp_exti_set_wake(struct irq_data *d, unsigned int on)
403 {
404 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
405 u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
406
407 raw_spin_lock(&chip_data->rlock);
408
409 if (on)
410 chip_data->wake_active |= mask;
411 else
412 chip_data->wake_active &= ~mask;
413
414 raw_spin_unlock(&chip_data->rlock);
415
416 return 0;
417 }
418
stm32mp_exti_set_affinity(struct irq_data * d,const struct cpumask * dest,bool force)419 static int stm32mp_exti_set_affinity(struct irq_data *d, const struct cpumask *dest, bool force)
420 {
421 if (d->parent_data->chip)
422 return irq_chip_set_affinity_parent(d, dest, force);
423
424 return IRQ_SET_MASK_OK_DONE;
425 }
426
stm32mp_exti_suspend(struct device * dev)427 static int stm32mp_exti_suspend(struct device *dev)
428 {
429 struct stm32mp_exti_host_data *host_data = dev_get_drvdata(dev);
430 struct stm32mp_exti_chip_data *chip_data;
431 int i;
432
433 for (i = 0; i < host_data->drv_data->bank_nr; i++) {
434 chip_data = &host_data->chips_data[i];
435 stm32mp_chip_suspend(chip_data, chip_data->wake_active);
436 }
437
438 return 0;
439 }
440
stm32mp_exti_resume(struct device * dev)441 static int stm32mp_exti_resume(struct device *dev)
442 {
443 struct stm32mp_exti_host_data *host_data = dev_get_drvdata(dev);
444 struct stm32mp_exti_chip_data *chip_data;
445 int i;
446
447 for (i = 0; i < host_data->drv_data->bank_nr; i++) {
448 chip_data = &host_data->chips_data[i];
449 stm32mp_chip_resume(chip_data, chip_data->mask_cache);
450 }
451
452 return 0;
453 }
454
stm32mp_exti_retrigger(struct irq_data * d)455 static int stm32mp_exti_retrigger(struct irq_data *d)
456 {
457 struct stm32mp_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
458 const struct stm32mp_exti_bank *bank = chip_data->reg_bank;
459 void __iomem *base = chip_data->host_data->base;
460 u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
461
462 writel_relaxed(mask, base + bank->swier_ofst);
463
464 return 0;
465 }
466
467 static struct irq_chip stm32mp_exti_chip = {
468 .name = "stm32mp-exti",
469 .irq_eoi = stm32mp_exti_eoi,
470 .irq_mask = stm32mp_exti_mask,
471 .irq_unmask = stm32mp_exti_unmask,
472 .irq_retrigger = stm32mp_exti_retrigger,
473 .irq_set_type = stm32mp_exti_set_type,
474 .irq_set_wake = stm32mp_exti_set_wake,
475 .flags = IRQCHIP_MASK_ON_SUSPEND,
476 .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? stm32mp_exti_set_affinity : NULL,
477 };
478
479 static struct irq_chip stm32mp_exti_chip_direct = {
480 .name = "stm32mp-exti-direct",
481 .irq_eoi = irq_chip_eoi_parent,
482 .irq_ack = irq_chip_ack_parent,
483 .irq_mask = stm32mp_exti_mask,
484 .irq_unmask = stm32mp_exti_unmask,
485 .irq_retrigger = irq_chip_retrigger_hierarchy,
486 .irq_set_type = irq_chip_set_type_parent,
487 .irq_set_wake = stm32mp_exti_set_wake,
488 .flags = IRQCHIP_MASK_ON_SUSPEND,
489 .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL,
490 };
491
stm32mp_exti_domain_alloc(struct irq_domain * dm,unsigned int virq,unsigned int nr_irqs,void * data)492 static int stm32mp_exti_domain_alloc(struct irq_domain *dm,
493 unsigned int virq,
494 unsigned int nr_irqs, void *data)
495 {
496 struct stm32mp_exti_host_data *host_data = dm->host_data;
497 struct stm32mp_exti_chip_data *chip_data;
498 struct irq_fwspec *fwspec = data;
499 struct irq_fwspec p_fwspec;
500 irq_hw_number_t hwirq;
501 struct irq_chip *chip;
502 u32 event_trg;
503 u8 desc_irq;
504 int bank;
505
506 hwirq = fwspec->param[0];
507 if (hwirq >= host_data->drv_data->bank_nr * IRQS_PER_BANK)
508 return -EINVAL;
509
510 bank = hwirq / IRQS_PER_BANK;
511 chip_data = &host_data->chips_data[bank];
512
513 /* Check if event is reserved (Secure) */
514 if (chip_data->event_reserved & BIT(hwirq % IRQS_PER_BANK)) {
515 dev_err(host_data->dev, "event %lu is reserved, secure\n", hwirq);
516 return -EPERM;
517 }
518
519 event_trg = readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst);
520 chip = (event_trg & BIT(hwirq % IRQS_PER_BANK)) ?
521 &stm32mp_exti_chip : &stm32mp_exti_chip_direct;
522
523 irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data);
524
525 if (host_data->dt_has_irqs_desc) {
526 struct of_phandle_args out_irq;
527 int ret;
528
529 ret = of_irq_parse_one(host_data->dev->of_node, hwirq, &out_irq);
530 if (ret)
531 return ret;
532 /* we only support one parent, so far */
533 if (of_fwnode_handle(out_irq.np) != dm->parent->fwnode)
534 return -EINVAL;
535
536 of_phandle_args_to_fwspec(out_irq.np, out_irq.args,
537 out_irq.args_count, &p_fwspec);
538
539 return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec);
540 }
541
542 if (!host_data->drv_data->desc_irqs)
543 return -EINVAL;
544
545 desc_irq = host_data->drv_data->desc_irqs[hwirq];
546 if (desc_irq != EXTI_INVALID_IRQ) {
547 p_fwspec.fwnode = dm->parent->fwnode;
548 p_fwspec.param_count = 3;
549 p_fwspec.param[0] = GIC_SPI;
550 p_fwspec.param[1] = desc_irq;
551 p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
552
553 return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec);
554 }
555
556 return 0;
557 }
558
stm32mp_exti_chip_init(struct stm32mp_exti_host_data * h_data,u32 bank_idx,struct device_node * node)559 static struct stm32mp_exti_chip_data *stm32mp_exti_chip_init(struct stm32mp_exti_host_data *h_data,
560 u32 bank_idx, struct device_node *node)
561 {
562 struct stm32mp_exti_chip_data *chip_data;
563 const struct stm32mp_exti_bank *bank;
564 void __iomem *base = h_data->base;
565
566 bank = h_data->drv_data->exti_banks[bank_idx];
567 chip_data = &h_data->chips_data[bank_idx];
568 chip_data->host_data = h_data;
569 chip_data->reg_bank = bank;
570
571 raw_spin_lock_init(&chip_data->rlock);
572
573 /*
574 * This IP has no reset, so after hot reboot we should
575 * clear registers to avoid residue
576 */
577 writel_relaxed(0, base + bank->imr_ofst);
578
579 /* reserve Secure events */
580 chip_data->event_reserved = readl_relaxed(base + bank->seccfgr_ofst);
581
582 pr_info("%pOF: bank%d\n", node, bank_idx);
583
584 return chip_data;
585 }
586
587 static const struct irq_domain_ops stm32mp_exti_domain_ops = {
588 .alloc = stm32mp_exti_domain_alloc,
589 .free = irq_domain_free_irqs_common,
590 .xlate = irq_domain_xlate_twocell,
591 };
592
stm32mp_exti_check_rif(struct stm32mp_exti_host_data * host_data)593 static void stm32mp_exti_check_rif(struct stm32mp_exti_host_data *host_data)
594 {
595 unsigned int bank, i, event;
596 u32 cid, cidcfgr, hwcfgr1;
597
598 /* quit on CID not supported */
599 hwcfgr1 = readl_relaxed(host_data->base + EXTI_HWCFGR1);
600 if ((hwcfgr1 & EXTI_HWCFGR1_CIDWIDTH_MASK) == 0)
601 return;
602
603 for (bank = 0; bank < host_data->drv_data->bank_nr; bank++) {
604 for (i = 0; i < IRQS_PER_BANK; i++) {
605 event = bank * IRQS_PER_BANK + i;
606 cidcfgr = readl_relaxed(host_data->base + EXTI_EnCIDCFGR(event));
607 cid = (cidcfgr & EXTI_CIDCFGR_CID_MASK) >> EXTI_CIDCFGR_CID_SHIFT;
608 if ((cidcfgr & EXTI_CIDCFGR_CFEN_MASK) && cid != EXTI_CID1)
609 host_data->chips_data[bank].event_reserved |= BIT(i);
610 }
611 }
612 }
613
stm32mp_exti_remove_irq(void * data)614 static void stm32mp_exti_remove_irq(void *data)
615 {
616 struct irq_domain *domain = data;
617
618 irq_domain_remove(domain);
619 }
620
stm32mp_exti_probe(struct platform_device * pdev)621 static int stm32mp_exti_probe(struct platform_device *pdev)
622 {
623 const struct stm32mp_exti_drv_data *drv_data;
624 struct irq_domain *parent_domain, *domain;
625 struct stm32mp_exti_host_data *host_data;
626 struct device *dev = &pdev->dev;
627 struct device_node *np = dev->of_node;
628 int ret, i;
629
630 host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL);
631 if (!host_data)
632 return -ENOMEM;
633
634 dev_set_drvdata(dev, host_data);
635 host_data->dev = dev;
636
637 /* check for optional hwspinlock which may be not available yet */
638 ret = of_hwspin_lock_get_id(np, 0);
639 if (ret == -EPROBE_DEFER)
640 /* hwspinlock framework not yet ready */
641 return ret;
642
643 if (ret >= 0) {
644 host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret);
645 if (!host_data->hwlock) {
646 dev_err(dev, "Failed to request hwspinlock\n");
647 return -EINVAL;
648 }
649 } else if (ret != -ENOENT) {
650 /* note: ENOENT is a valid case (means 'no hwspinlock') */
651 dev_err(dev, "Failed to get hwspinlock\n");
652 return ret;
653 }
654
655 /* initialize host_data */
656 drv_data = of_device_get_match_data(dev);
657 if (!drv_data) {
658 dev_err(dev, "no of match data\n");
659 return -ENODEV;
660 }
661 host_data->drv_data = drv_data;
662
663 host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr,
664 sizeof(*host_data->chips_data),
665 GFP_KERNEL);
666 if (!host_data->chips_data)
667 return -ENOMEM;
668
669 host_data->base = devm_platform_ioremap_resource(pdev, 0);
670 if (IS_ERR(host_data->base))
671 return PTR_ERR(host_data->base);
672
673 for (i = 0; i < drv_data->bank_nr; i++)
674 stm32mp_exti_chip_init(host_data, i, np);
675
676 stm32mp_exti_check_rif(host_data);
677
678 parent_domain = irq_find_host(of_irq_find_parent(np));
679 if (!parent_domain) {
680 dev_err(dev, "GIC interrupt-parent not found\n");
681 return -EINVAL;
682 }
683
684 domain = irq_domain_create_hierarchy(parent_domain, 0, drv_data->bank_nr * IRQS_PER_BANK,
685 dev_fwnode(dev), &stm32mp_exti_domain_ops, host_data);
686 if (!domain) {
687 dev_err(dev, "Could not register exti domain\n");
688 return -ENOMEM;
689 }
690
691 ret = devm_add_action_or_reset(dev, stm32mp_exti_remove_irq, domain);
692 if (ret)
693 return ret;
694
695 host_data->dt_has_irqs_desc = of_property_present(np, "interrupts-extended");
696
697 return 0;
698 }
699
700 static const struct of_device_id stm32mp_exti_ids[] = {
701 { .compatible = "st,stm32mp1-exti", .data = &stm32mp1_drv_data},
702 { .compatible = "st,stm32mp13-exti", .data = &stm32mp13_drv_data},
703 {},
704 };
705 MODULE_DEVICE_TABLE(of, stm32mp_exti_ids);
706
707 static const struct dev_pm_ops stm32mp_exti_dev_pm_ops = {
708 NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32mp_exti_suspend, stm32mp_exti_resume)
709 };
710
711 static struct platform_driver stm32mp_exti_driver = {
712 .probe = stm32mp_exti_probe,
713 .driver = {
714 .name = "stm32mp_exti",
715 .of_match_table = stm32mp_exti_ids,
716 .pm = &stm32mp_exti_dev_pm_ops,
717 },
718 };
719
720 module_platform_driver(stm32mp_exti_driver);
721
722 MODULE_AUTHOR("Maxime Coquelin <mcoquelin.stm32@gmail.com>");
723 MODULE_DESCRIPTION("STM32MP EXTI driver");
724 MODULE_LICENSE("GPL");
725