1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) Maxime Coquelin 2015
4 * Copyright (C) STMicroelectronics 2017-2024
5 * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
8 #include <linux/bitops.h>
9 #include <linux/hwspinlock.h>
10 #include <linux/interrupt.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>
22 #include <dt-bindings/interrupt-controller/arm-gic.h>
24 #define IRQS_PER_BANK 32
26 #define HWSPNLCK_TIMEOUT 1000 /* usec */
28 #define EXTI_EnCIDCFGR(n) (0x180 + (n) * 4)
29 #define EXTI_HWCFGR1 0x3f0
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
36 /* Register: EXTI_HWCFGR1 */
37 #define EXTI_HWCFGR1_CIDWIDTH_MASK GENMASK(27, 24)
41 struct stm32mp_exti_bank
{
52 struct stm32mp_exti_drv_data
{
53 const struct stm32mp_exti_bank
**exti_banks
;
58 struct 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
;
69 struct stm32mp_exti_host_data
{
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
;
79 static const struct stm32mp_exti_bank stm32mp_exti_b1
= {
90 static const struct stm32mp_exti_bank stm32mp_exti_b2
= {
101 static const struct stm32mp_exti_bank stm32mp_exti_b3
= {
109 .seccfgr_ofst
= 0x54,
112 static const struct stm32mp_exti_bank
*stm32mp_exti_banks
[] = {
118 static struct irq_chip stm32mp_exti_chip
;
119 static struct irq_chip stm32mp_exti_chip_direct
;
121 #define EXTI_INVALID_IRQ U8_MAX
122 #define STM32MP_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp_exti_banks) * IRQS_PER_BANK)
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.
131 __diag_ignore_all("-Woverride-init",
132 "logic to initialize all and then override some is OK");
134 static const u8 stm32mp1_desc_irq
[] = {
136 [0 ... (STM32MP_DESC_IRQ_SIZE
- 1)] = EXTI_INVALID_IRQ
,
183 static const u8 stm32mp13_desc_irq
[] = {
185 [0 ... (STM32MP_DESC_IRQ_SIZE
- 1)] = EXTI_INVALID_IRQ
,
230 static 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
,
236 static 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
,
242 static int stm32mp_exti_convert_type(struct irq_data
*d
, unsigned int type
, u32
*rtsr
, u32
*ftsr
)
244 u32 mask
= BIT(d
->hwirq
% IRQS_PER_BANK
);
247 case IRQ_TYPE_EDGE_RISING
:
251 case IRQ_TYPE_EDGE_FALLING
:
255 case IRQ_TYPE_EDGE_BOTH
:
266 static void stm32mp_chip_suspend(struct stm32mp_exti_chip_data
*chip_data
, u32 wake_active
)
268 const struct stm32mp_exti_bank
*bank
= chip_data
->reg_bank
;
269 void __iomem
*base
= chip_data
->host_data
->base
;
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
);
275 writel_relaxed(wake_active
, base
+ bank
->imr_ofst
);
278 static void stm32mp_chip_resume(struct stm32mp_exti_chip_data
*chip_data
, u32 mask_cache
)
280 const struct stm32mp_exti_bank
*bank
= chip_data
->reg_bank
;
281 void __iomem
*base
= chip_data
->host_data
->base
;
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
);
287 writel_relaxed(mask_cache
, base
+ bank
->imr_ofst
);
290 /* directly set the target bit without reading first. */
291 static inline void stm32mp_exti_write_bit(struct irq_data
*d
, u32 reg
)
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
);
297 writel_relaxed(val
, base
+ reg
);
300 static inline u32
stm32mp_exti_set_bit(struct irq_data
*d
, u32 reg
)
302 struct stm32mp_exti_chip_data
*chip_data
= irq_data_get_irq_chip_data(d
);
303 void __iomem
*base
= chip_data
->host_data
->base
;
306 val
= readl_relaxed(base
+ reg
);
307 val
|= BIT(d
->hwirq
% IRQS_PER_BANK
);
308 writel_relaxed(val
, base
+ reg
);
313 static inline u32
stm32mp_exti_clr_bit(struct irq_data
*d
, u32 reg
)
315 struct stm32mp_exti_chip_data
*chip_data
= irq_data_get_irq_chip_data(d
);
316 void __iomem
*base
= chip_data
->host_data
->base
;
319 val
= readl_relaxed(base
+ reg
);
320 val
&= ~BIT(d
->hwirq
% IRQS_PER_BANK
);
321 writel_relaxed(val
, base
+ reg
);
326 static void stm32mp_exti_eoi(struct irq_data
*d
)
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
;
331 raw_spin_lock(&chip_data
->rlock
);
333 stm32mp_exti_write_bit(d
, bank
->rpr_ofst
);
334 stm32mp_exti_write_bit(d
, bank
->fpr_ofst
);
336 raw_spin_unlock(&chip_data
->rlock
);
338 if (d
->parent_data
->chip
)
339 irq_chip_eoi_parent(d
);
342 static void stm32mp_exti_mask(struct irq_data
*d
)
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
;
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
);
351 if (d
->parent_data
->chip
)
352 irq_chip_mask_parent(d
);
355 static void stm32mp_exti_unmask(struct irq_data
*d
)
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
;
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
);
364 if (d
->parent_data
->chip
)
365 irq_chip_unmask_parent(d
);
368 static int stm32mp_exti_set_type(struct irq_data
*d
, unsigned int type
)
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
;
377 raw_spin_lock(&chip_data
->rlock
);
380 err
= hwspin_lock_timeout_in_atomic(hwlock
, HWSPNLCK_TIMEOUT
);
382 pr_err("%s can't get hwspinlock (%d)\n", __func__
, err
);
387 rtsr
= readl_relaxed(base
+ bank
->rtsr_ofst
);
388 ftsr
= readl_relaxed(base
+ bank
->ftsr_ofst
);
390 err
= stm32mp_exti_convert_type(d
, type
, &rtsr
, &ftsr
);
392 writel_relaxed(rtsr
, base
+ bank
->rtsr_ofst
);
393 writel_relaxed(ftsr
, base
+ bank
->ftsr_ofst
);
397 hwspin_unlock_in_atomic(hwlock
);
399 raw_spin_unlock(&chip_data
->rlock
);
403 static int stm32mp_exti_set_wake(struct irq_data
*d
, unsigned int on
)
405 struct stm32mp_exti_chip_data
*chip_data
= irq_data_get_irq_chip_data(d
);
406 u32 mask
= BIT(d
->hwirq
% IRQS_PER_BANK
);
408 raw_spin_lock(&chip_data
->rlock
);
411 chip_data
->wake_active
|= mask
;
413 chip_data
->wake_active
&= ~mask
;
415 raw_spin_unlock(&chip_data
->rlock
);
420 static int stm32mp_exti_set_affinity(struct irq_data
*d
, const struct cpumask
*dest
, bool force
)
422 if (d
->parent_data
->chip
)
423 return irq_chip_set_affinity_parent(d
, dest
, force
);
425 return IRQ_SET_MASK_OK_DONE
;
428 static int stm32mp_exti_suspend(struct device
*dev
)
430 struct stm32mp_exti_host_data
*host_data
= dev_get_drvdata(dev
);
431 struct stm32mp_exti_chip_data
*chip_data
;
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
);
442 static int stm32mp_exti_resume(struct device
*dev
)
444 struct stm32mp_exti_host_data
*host_data
= dev_get_drvdata(dev
);
445 struct stm32mp_exti_chip_data
*chip_data
;
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
);
456 static int stm32mp_exti_retrigger(struct irq_data
*d
)
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
);
463 writel_relaxed(mask
, base
+ bank
->swier_ofst
);
468 static 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
,
480 static 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
,
493 static int stm32mp_exti_domain_alloc(struct irq_domain
*dm
,
495 unsigned int nr_irqs
, void *data
)
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
;
507 hwirq
= fwspec
->param
[0];
508 if (hwirq
>= host_data
->drv_data
->bank_nr
* IRQS_PER_BANK
)
511 bank
= hwirq
/ IRQS_PER_BANK
;
512 chip_data
= &host_data
->chips_data
[bank
];
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
);
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
;
524 irq_domain_set_hwirq_and_chip(dm
, virq
, hwirq
, chip
, chip_data
);
526 if (host_data
->dt_has_irqs_desc
) {
527 struct of_phandle_args out_irq
;
530 ret
= of_irq_parse_one(host_data
->dev
->of_node
, hwirq
, &out_irq
);
533 /* we only support one parent, so far */
534 if (of_node_to_fwnode(out_irq
.np
) != dm
->parent
->fwnode
)
537 of_phandle_args_to_fwspec(out_irq
.np
, out_irq
.args
,
538 out_irq
.args_count
, &p_fwspec
);
540 return irq_domain_alloc_irqs_parent(dm
, virq
, 1, &p_fwspec
);
543 if (!host_data
->drv_data
->desc_irqs
)
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
;
554 return irq_domain_alloc_irqs_parent(dm
, virq
, 1, &p_fwspec
);
560 static struct stm32mp_exti_chip_data
*stm32mp_exti_chip_init(struct stm32mp_exti_host_data
*h_data
,
561 u32 bank_idx
, struct device_node
*node
)
563 struct stm32mp_exti_chip_data
*chip_data
;
564 const struct stm32mp_exti_bank
*bank
;
565 void __iomem
*base
= h_data
->base
;
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
;
572 raw_spin_lock_init(&chip_data
->rlock
);
575 * This IP has no reset, so after hot reboot we should
576 * clear registers to avoid residue
578 writel_relaxed(0, base
+ bank
->imr_ofst
);
580 /* reserve Secure events */
581 chip_data
->event_reserved
= readl_relaxed(base
+ bank
->seccfgr_ofst
);
583 pr_info("%pOF: bank%d\n", node
, bank_idx
);
588 static 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
,
594 static void stm32mp_exti_check_rif(struct stm32mp_exti_host_data
*host_data
)
596 unsigned int bank
, i
, event
;
597 u32 cid
, cidcfgr
, hwcfgr1
;
599 /* quit on CID not supported */
600 hwcfgr1
= readl_relaxed(host_data
->base
+ EXTI_HWCFGR1
);
601 if ((hwcfgr1
& EXTI_HWCFGR1_CIDWIDTH_MASK
) == 0)
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
);
615 static void stm32mp_exti_remove_irq(void *data
)
617 struct irq_domain
*domain
= data
;
619 irq_domain_remove(domain
);
622 static int stm32mp_exti_probe(struct platform_device
*pdev
)
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
;
631 host_data
= devm_kzalloc(dev
, sizeof(*host_data
), GFP_KERNEL
);
635 dev_set_drvdata(dev
, host_data
);
636 host_data
->dev
= dev
;
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 */
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");
650 } else if (ret
!= -ENOENT
) {
651 /* note: ENOENT is a valid case (means 'no hwspinlock') */
652 dev_err(dev
, "Failed to get hwspinlock\n");
656 /* initialize host_data */
657 drv_data
= of_device_get_match_data(dev
);
659 dev_err(dev
, "no of match data\n");
662 host_data
->drv_data
= drv_data
;
664 host_data
->chips_data
= devm_kcalloc(dev
, drv_data
->bank_nr
,
665 sizeof(*host_data
->chips_data
),
667 if (!host_data
->chips_data
)
670 host_data
->base
= devm_platform_ioremap_resource(pdev
, 0);
671 if (IS_ERR(host_data
->base
))
672 return PTR_ERR(host_data
->base
);
674 for (i
= 0; i
< drv_data
->bank_nr
; i
++)
675 stm32mp_exti_chip_init(host_data
, i
, np
);
677 stm32mp_exti_check_rif(host_data
);
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");
685 domain
= irq_domain_add_hierarchy(parent_domain
, 0,
686 drv_data
->bank_nr
* IRQS_PER_BANK
,
687 np
, &stm32mp_exti_domain_ops
,
691 dev_err(dev
, "Could not register exti domain\n");
695 ret
= devm_add_action_or_reset(dev
, stm32mp_exti_remove_irq
, domain
);
699 host_data
->dt_has_irqs_desc
= of_property_present(np
, "interrupts-extended");
704 static 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
},
709 MODULE_DEVICE_TABLE(of
, stm32mp_exti_ids
);
711 static const struct dev_pm_ops stm32mp_exti_dev_pm_ops
= {
712 NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32mp_exti_suspend
, stm32mp_exti_resume
)
715 static struct platform_driver stm32mp_exti_driver
= {
716 .probe
= stm32mp_exti_probe
,
718 .name
= "stm32mp_exti",
719 .of_match_table
= stm32mp_exti_ids
,
720 .pm
= &stm32mp_exti_dev_pm_ops
,
724 module_platform_driver(stm32mp_exti_driver
);
726 MODULE_AUTHOR("Maxime Coquelin <mcoquelin.stm32@gmail.com>");
727 MODULE_DESCRIPTION("STM32MP EXTI driver");
728 MODULE_LICENSE("GPL");