Linux Audio

Check our new training course

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