Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip/renesas-rzg2l: Add NMI support

The RZ/G2L SoC has an NMI interrupt. Add support for the NMI interrupt.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260401114504.332825-1-biju.das.jz@bp.renesas.com

authored by

Biju Das and committed by
Thomas Gleixner
0e598854 d3689cd0

+95 -4
+95 -4
drivers/irqchip/irq-renesas-rzg2l.c
··· 20 20 #include <linux/spinlock.h> 21 21 #include <linux/syscore_ops.h> 22 22 23 + #define IRQC_NMI 0 23 24 #define IRQC_IRQ_START 1 24 25 #define IRQC_TINT_COUNT 32 25 26 #define IRQC_SHARED_IRQ_COUNT 8 26 27 #define IRQC_IRQ_SHARED_START (IRQC_IRQ_START + IRQC_SHARED_IRQ_COUNT) 27 28 29 + #define NSCR 0x0 30 + #define NITSR 0x4 28 31 #define ISCR 0x10 29 32 #define IITSR 0x14 30 33 #define TSCR 0x20 ··· 45 42 46 43 #define TSSR_OFFSET(n) ((n) % 4) 47 44 #define TSSR_INDEX(n) ((n) / 4) 45 + 46 + #define NSCR_NSTAT 0 47 + #define NITSR_NTSEL_EDGE_FALLING 0 48 + #define NITSR_NTSEL_EDGE_RISING 1 48 49 49 50 #define TITSR_TITSEL_EDGE_RISING 0 50 51 #define TITSR_TITSEL_EDGE_FALLING 1 ··· 70 63 71 64 /** 72 65 * struct rzg2l_irqc_reg_cache - registers cache (necessary for suspend/resume) 73 - * @iitsr: IITSR register 74 - * @inttsel: INTTSEL register 75 - * @titsr: TITSR registers 66 + * @nitsr: NITSR register 67 + * @iitsr: IITSR register 68 + * @inttsel: INTTSEL register 69 + * @titsr: TITSR registers 76 70 */ 77 71 struct rzg2l_irqc_reg_cache { 72 + u32 nitsr; 78 73 u32 iitsr; 79 74 u32 inttsel; 80 75 u32 titsr[2]; ··· 125 116 return data->domain->host_data; 126 117 } 127 118 119 + static void rzg2l_clear_nmi_int(struct rzg2l_irqc_priv *priv) 120 + { 121 + u32 bit = BIT(NSCR_NSTAT); 122 + u32 reg; 123 + 124 + /* 125 + * No locking required as the register is not shared 126 + * with other interrupts. 127 + * 128 + * Writing is allowed only when NSTAT is 1 129 + */ 130 + reg = readl_relaxed(priv->base + NSCR); 131 + if (reg & bit) { 132 + writel_relaxed(reg & ~bit, priv->base + NSCR); 133 + /* 134 + * Enforce that the posted write is flushed to prevent that the 135 + * just handled interrupt is raised again. 136 + */ 137 + readl_relaxed(priv->base + NSCR); 138 + } 139 + } 140 + 128 141 static void rzg2l_clear_irq_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq) 129 142 { 130 143 unsigned int hw_irq = hwirq - IRQC_IRQ_START; ··· 184 153 */ 185 154 readl_relaxed(priv->base + TSCR); 186 155 } 156 + } 157 + 158 + static void rzg2l_irqc_nmi_eoi(struct irq_data *d) 159 + { 160 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 161 + 162 + rzg2l_clear_nmi_int(priv); 163 + irq_chip_eoi_parent(d); 187 164 } 188 165 189 166 static void rzg2l_irqc_irq_eoi(struct irq_data *d) ··· 380 341 irq_chip_enable_parent(d); 381 342 } 382 343 344 + static int rzg2l_nmi_set_type(struct irq_data *d, unsigned int type) 345 + { 346 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 347 + u32 sense; 348 + 349 + switch (type & IRQ_TYPE_SENSE_MASK) { 350 + case IRQ_TYPE_EDGE_FALLING: 351 + sense = NITSR_NTSEL_EDGE_FALLING; 352 + break; 353 + case IRQ_TYPE_EDGE_RISING: 354 + sense = NITSR_NTSEL_EDGE_RISING; 355 + break; 356 + default: 357 + return -EINVAL; 358 + } 359 + 360 + writel_relaxed(sense, priv->base + NITSR); 361 + return 0; 362 + } 363 + 383 364 static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type) 384 365 { 385 366 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); ··· 526 467 return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 527 468 } 528 469 470 + static int rzg2l_irqc_nmi_set_type(struct irq_data *d, unsigned int type) 471 + { 472 + int ret; 473 + 474 + ret = rzg2l_nmi_set_type(d, type); 475 + if (ret) 476 + return ret; 477 + 478 + return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 479 + } 480 + 529 481 static int rzg2l_irqc_irq_suspend(void *data) 530 482 { 531 483 struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache; 532 484 void __iomem *base = rzg2l_irqc_data->base; 533 485 486 + cache->nitsr = readl_relaxed(base + NITSR); 534 487 cache->iitsr = readl_relaxed(base + IITSR); 535 488 if (rzg2l_irqc_data->info.shared_irq_cnt) 536 489 cache->inttsel = readl_relaxed(base + INTTSEL); ··· 567 496 if (rzg2l_irqc_data->info.shared_irq_cnt) 568 497 writel_relaxed(cache->inttsel, base + INTTSEL); 569 498 writel_relaxed(cache->iitsr, base + IITSR); 499 + writel_relaxed(cache->nitsr, base + NITSR); 570 500 } 571 501 572 502 static const struct syscore_ops rzg2l_irqc_syscore_ops = { ··· 577 505 578 506 static struct syscore rzg2l_irqc_syscore = { 579 507 .ops = &rzg2l_irqc_syscore_ops, 508 + }; 509 + 510 + static const struct irq_chip rzg2l_irqc_nmi_chip = { 511 + .name = "rzg2l-irqc", 512 + .irq_eoi = rzg2l_irqc_nmi_eoi, 513 + .irq_mask = irq_chip_mask_parent, 514 + .irq_unmask = irq_chip_unmask_parent, 515 + .irq_disable = irq_chip_disable_parent, 516 + .irq_enable = irq_chip_enable_parent, 517 + .irq_get_irqchip_state = irq_chip_get_parent_state, 518 + .irq_set_irqchip_state = irq_chip_set_parent_state, 519 + .irq_retrigger = irq_chip_retrigger_hierarchy, 520 + .irq_set_type = rzg2l_irqc_nmi_set_type, 521 + .irq_set_affinity = irq_chip_set_affinity_parent, 522 + .flags = IRQCHIP_MASK_ON_SUSPEND | 523 + IRQCHIP_SET_TYPE_MASKED | 524 + IRQCHIP_SKIP_SET_WAKE, 580 525 }; 581 526 582 527 static const struct irq_chip rzg2l_irqc_irq_chip = { ··· 751 662 * from 16-31 bits. TINT from the pinctrl driver needs to be programmed 752 663 * in IRQC registers to enable a given gpio pin as interrupt. 753 664 */ 754 - if (hwirq > priv->info.irq_count) { 665 + if (hwirq == IRQC_NMI) { 666 + chip = &rzg2l_irqc_nmi_chip; 667 + } else if (hwirq > priv->info.irq_count) { 755 668 tint = TINT_EXTRACT_GPIOINT(hwirq); 756 669 hwirq = TINT_EXTRACT_HWIRQ(hwirq); 757 670 chip = priv->tint_chip;