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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'irq-drivers-2026-04-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull interrupt chip driver updates from Thomas Gleixner:

- A large refactoring for the Renesas RZV2H driver to add new interrupt
types cleanly

- A large refactoring for the Renesas RZG2L driver to add support the
new RZ/G3L variant

- Add support for the new NXP S32N79 chip in the IMX irq-steer driver

- Add support for the Apple AICv3 variant

- Enhance the Loongson PCH LPC driver so it can be used on MIPS with
device tree firmware

- Allow the PIC32 EVIC driver to be built independent of MIPS in
compile tests

- The usual small fixes and enhancements all over the place

* tag 'irq-drivers-2026-04-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (46 commits)
irqchip/irq-pic32-evic: Add __maybe_unused for board_bind_eic_interrupt in COMPILE_TEST
irqchip/renesas-rzv2h: Kill icu_err string
irqchip/renesas-rzv2h: Kill swint_names[]
irqchip/renesas-rzv2h: Kill swint_idx[]
irqchip/renesas-rzg2l: Add NMI support
irqchip/renesas-rzg2l: Clear the shared interrupt bit in rzg2l_irqc_free()
irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type()
irqchip/gic-v3: Print a warning for out-of-range interrupt numbers
irqchip/renesas-rzg2l: Add shared interrupt support
irqchip/renesas-rzg2l: Add RZ/G3L support
irqchip/renesas-rzg2l: Drop IRQC_IRQ_COUNT macro
irqchip/renesas-rzg2l: Drop IRQC_TINT_START macro
irqchip/renesas-rzg2l: Drop IRQC_NUM_IRQ macro
irqchip/renesas-rzg2l: Dynamically allocate fwspec array
irqchip/renesas-rzg2l: Split rzfive_irqc_{mask,unmask} into separate IRQ and TINT handlers
irqchip/renesas-rzg2l: Split rzfive_tint_irq_endisable() into separate IRQ and TINT helpers
irqchip/renesas-rzg2l: Replace rzg2l_irqc_irq_{enable,disable} with TINT-specific handlers
irqchip/renesas-rzg2l: Split set_type handler into separate IRQ and TINT functions
irqchip/renesas-rzg2l: Split EOI handler into separate IRQ and TINT functions
irqchip/renesas-rzg2l: Replace single irq_chip with per-region irq_chip instances
...

+1135 -375
+21 -9
Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml
··· 4 4 $id: http://devicetree.org/schemas/interrupt-controller/apple,aic2.yaml# 5 5 $schema: http://devicetree.org/meta-schemas/core.yaml# 6 6 7 - title: Apple Interrupt Controller 2 7 + title: Apple Interrupt Controller 2 and 3 8 8 9 9 maintainers: 10 - - Hector Martin <marcan@marcan.st> 10 + - Janne Grunau <j@jannau.net> 11 11 12 12 description: | 13 13 The Apple Interrupt Controller 2 is a simple interrupt controller present on ··· 28 28 which do not go through a discrete interrupt controller. It also handles 29 29 FIQ-based Fast IPIs. 30 30 31 + The Apple Interrupt Controller 3 is in its base functionality very similar to 32 + the Apple Interrupt Controller 2 and uses the same device tree bindings. It is 33 + found on Apple ARM SoCs platforms starting with t8122 (M3). 34 + 31 35 properties: 32 36 compatible: 33 - items: 34 - - enum: 35 - - apple,t8112-aic 36 - - apple,t6000-aic 37 - - apple,t6020-aic 38 - - const: apple,aic2 37 + oneOf: 38 + - items: 39 + - enum: 40 + - apple,t6000-aic 41 + - apple,t6020-aic 42 + - apple,t8112-aic 43 + - const: apple,aic2 44 + - items: 45 + - enum: 46 + - apple,t6030-aic3 47 + - const: apple,t8122-aic3 48 + - const: apple,t8122-aic3 39 49 40 50 interrupt-controller: true 41 51 ··· 127 117 properties: 128 118 compatible: 129 119 contains: 130 - const: apple,t8112-aic 120 + enum: 121 + - apple,t8112-aic 122 + - apple,t8122-aic3 131 123 then: 132 124 properties: 133 125 '#interrupt-cells':
+52
Documentation/devicetree/bindings/interrupt-controller/loongson,pch-lpc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interrupt-controller/loongson,pch-lpc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Loongson PCH LPC Controller 8 + 9 + maintainers: 10 + - Jiaxun Yang <jiaxun.yang@flygoat.com> 11 + 12 + description: 13 + This interrupt controller is found in the Loongson LS7A family of PCH for 14 + accepting interrupts sent by LPC-connected peripherals and signalling PIC 15 + via a single interrupt line when interrupts are available. 16 + 17 + properties: 18 + compatible: 19 + const: loongson,ls7a-lpc 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + interrupt-controller: true 25 + 26 + interrupts: 27 + maxItems: 1 28 + 29 + '#interrupt-cells': 30 + const: 2 31 + 32 + required: 33 + - compatible 34 + - reg 35 + - interrupt-controller 36 + - interrupts 37 + - '#interrupt-cells' 38 + 39 + additionalProperties: false 40 + 41 + examples: 42 + - | 43 + #include <dt-bindings/interrupt-controller/irq.h> 44 + lpc: interrupt-controller@10002000 { 45 + compatible = "loongson,ls7a-lpc"; 46 + reg = <0x10002000 0x400>; 47 + interrupt-controller; 48 + #interrupt-cells = <2>; 49 + interrupt-parent = <&pic>; 50 + interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; 51 + }; 52 + ...
+56 -101
Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
··· 30 30 - renesas,r9a08g045-irqc # RZ/G3S 31 31 - const: renesas,rzg2l-irqc 32 32 33 - - const: renesas,r9a07g043f-irqc # RZ/Five 33 + - enum: 34 + - renesas,r9a07g043f-irqc # RZ/Five 35 + - renesas,r9a08g046-irqc # RZ/G3L 34 36 35 37 '#interrupt-cells': 36 38 description: The first cell should contain a macro RZG2L_{NMI,IRQX} included in the ··· 50 48 51 49 interrupts: 52 50 minItems: 45 53 - items: 54 - - description: NMI interrupt 55 - - description: IRQ0 interrupt 56 - - description: IRQ1 interrupt 57 - - description: IRQ2 interrupt 58 - - description: IRQ3 interrupt 59 - - description: IRQ4 interrupt 60 - - description: IRQ5 interrupt 61 - - description: IRQ6 interrupt 62 - - description: IRQ7 interrupt 63 - - description: GPIO interrupt, TINT0 64 - - description: GPIO interrupt, TINT1 65 - - description: GPIO interrupt, TINT2 66 - - description: GPIO interrupt, TINT3 67 - - description: GPIO interrupt, TINT4 68 - - description: GPIO interrupt, TINT5 69 - - description: GPIO interrupt, TINT6 70 - - description: GPIO interrupt, TINT7 71 - - description: GPIO interrupt, TINT8 72 - - description: GPIO interrupt, TINT9 73 - - description: GPIO interrupt, TINT10 74 - - description: GPIO interrupt, TINT11 75 - - description: GPIO interrupt, TINT12 76 - - description: GPIO interrupt, TINT13 77 - - description: GPIO interrupt, TINT14 78 - - description: GPIO interrupt, TINT15 79 - - description: GPIO interrupt, TINT16 80 - - description: GPIO interrupt, TINT17 81 - - description: GPIO interrupt, TINT18 82 - - description: GPIO interrupt, TINT19 83 - - description: GPIO interrupt, TINT20 84 - - description: GPIO interrupt, TINT21 85 - - description: GPIO interrupt, TINT22 86 - - description: GPIO interrupt, TINT23 87 - - description: GPIO interrupt, TINT24 88 - - description: GPIO interrupt, TINT25 89 - - description: GPIO interrupt, TINT26 90 - - description: GPIO interrupt, TINT27 91 - - description: GPIO interrupt, TINT28 92 - - description: GPIO interrupt, TINT29 93 - - description: GPIO interrupt, TINT30 94 - - description: GPIO interrupt, TINT31 95 - - description: Bus error interrupt 96 - - description: ECCRAM0 or combined ECCRAM0/1 1bit error interrupt 97 - - description: ECCRAM0 or combined ECCRAM0/1 2bit error interrupt 98 - - description: ECCRAM0 or combined ECCRAM0/1 error overflow interrupt 99 - - description: ECCRAM1 1bit error interrupt 100 - - description: ECCRAM1 2bit error interrupt 101 - - description: ECCRAM1 error overflow interrupt 51 + maxItems: 61 102 52 103 53 interrupt-names: 104 54 minItems: 45 55 + maxItems: 61 105 56 items: 106 - - const: nmi 107 - - const: irq0 108 - - const: irq1 109 - - const: irq2 110 - - const: irq3 111 - - const: irq4 112 - - const: irq5 113 - - const: irq6 114 - - const: irq7 115 - - const: tint0 116 - - const: tint1 117 - - const: tint2 118 - - const: tint3 119 - - const: tint4 120 - - const: tint5 121 - - const: tint6 122 - - const: tint7 123 - - const: tint8 124 - - const: tint9 125 - - const: tint10 126 - - const: tint11 127 - - const: tint12 128 - - const: tint13 129 - - const: tint14 130 - - const: tint15 131 - - const: tint16 132 - - const: tint17 133 - - const: tint18 134 - - const: tint19 135 - - const: tint20 136 - - const: tint21 137 - - const: tint22 138 - - const: tint23 139 - - const: tint24 140 - - const: tint25 141 - - const: tint26 142 - - const: tint27 143 - - const: tint28 144 - - const: tint29 145 - - const: tint30 146 - - const: tint31 147 - - const: bus-err 148 - - const: ec7tie1-0 149 - - const: ec7tie2-0 150 - - const: ec7tiovf-0 151 - - const: ec7tie1-1 152 - - const: ec7tie2-1 153 - - const: ec7tiovf-1 57 + oneOf: 58 + - description: NMI interrupt 59 + const: nmi 60 + - description: External IRQ interrupt 61 + pattern: '^irq([0-9]|1[0-5])$' 62 + - description: GPIO interrupt 63 + pattern: '^tint([0-9]|1[0-9]|2[0-9]|3[0-1])$' 64 + - description: Bus error interrupt 65 + const: bus-err 66 + - description: ECCRAM0 or combined ECCRAM0/1 1bit error interrupt 67 + const: ec7tie1-0 68 + - description: ECCRAM0 or combined ECCRAM0/1 2bit error interrupt 69 + const: ec7tie2-0 70 + - description: ECCRAM0 or combined ECCRAM0/1 error overflow interrupt 71 + const: ec7tiovf-0 72 + - description: ECCRAM1 1bit error interrupt 73 + const: ec7tie1-1 74 + - description: ECCRAM1 2bit error interrupt 75 + const: ec7tie2-1 76 + - description: ECCRAM1 error overflow interrupt 77 + const: ec7tiovf-1 78 + - description: Integrated GPT Error interrupt 79 + pattern: '^ovfunf([0-7])$' 154 80 155 81 clocks: 156 82 maxItems: 2 ··· 115 185 compatible: 116 186 contains: 117 187 enum: 188 + - renesas,r9a07g043f-irqc 189 + - renesas,r9a07g043u-irqc 190 + - renesas,r9a07g044-irqc 191 + - renesas,r9a07g054-irqc 192 + then: 193 + properties: 194 + interrupts: 195 + minItems: 48 196 + maxItems: 48 197 + interrupt-names: 198 + minItems: 48 199 + maxItems: 48 200 + 201 + - if: 202 + properties: 203 + compatible: 204 + contains: 205 + enum: 118 206 - renesas,r9a08g045-irqc 119 207 then: 120 208 properties: ··· 140 192 maxItems: 45 141 193 interrupt-names: 142 194 maxItems: 45 143 - else: 195 + 196 + - if: 197 + properties: 198 + compatible: 199 + contains: 200 + enum: 201 + - renesas,r9a08g046-irqc 202 + then: 144 203 properties: 145 204 interrupts: 146 - minItems: 48 205 + minItems: 61 147 206 interrupt-names: 148 - minItems: 48 207 + minItems: 61 149 208 150 209 unevaluatedProperties: false 151 210
+6
arch/loongarch/kernel/irq.c
··· 11 11 #include <linux/irqchip.h> 12 12 #include <linux/kernel_stat.h> 13 13 #include <linux/proc_fs.h> 14 + #include <linux/minmax.h> 14 15 #include <linux/mm.h> 15 16 #include <linux/sched.h> 16 17 #include <linux/seq_file.h> ··· 98 97 irq_set_nr_irqs(64 + NR_VECTORS * (nr_cpu_ids + nr_io_pics)); 99 98 100 99 return NR_IRQS_LEGACY; 100 + } 101 + 102 + unsigned int arch_dynirq_lower_bound(unsigned int from) 103 + { 104 + return MAX(from, NR_IRQS_LEGACY); 101 105 } 102 106 103 107 void __init init_IRQ(void)
+6
arch/mips/loongson64/init.c
··· 7 7 #include <linux/irqchip.h> 8 8 #include <linux/logic_pio.h> 9 9 #include <linux/memblock.h> 10 + #include <linux/minmax.h> 10 11 #include <linux/of.h> 11 12 #include <linux/of_address.h> 12 13 #include <asm/bootinfo.h> ··· 227 226 { 228 227 reserve_pio_range(); 229 228 irqchip_init(); 229 + } 230 + 231 + unsigned int arch_dynirq_lower_bound(unsigned int from) 232 + { 233 + return MAX(from, NR_IRQS_LEGACY); 230 234 }
-1
arch/mips/pic32/Kconfig
··· 20 20 select LIBFDT 21 21 select USE_OF 22 22 select PINCTRL 23 - select PIC32_EVIC 24 23 help 25 24 Support for the Microchip PIC32MZDA microcontroller. 26 25
+7 -5
drivers/irqchip/Kconfig
··· 252 252 select IRQ_DOMAIN 253 253 254 254 config PIC32_EVIC 255 - bool 255 + def_bool MACH_PIC32 || COMPILE_TEST 256 256 select GENERIC_IRQ_CHIP 257 257 select IRQ_DOMAIN 258 + help 259 + Enable support for the interrupt controller on the Microchip PIC32 260 + family of platforms. 258 261 259 262 config JCORE_AIC 260 263 bool "J-Core integrated AIC" if COMPILE_TEST ··· 544 541 545 542 config IMX_IRQSTEER 546 543 bool "i.MX IRQSTEER support" 547 - depends on ARCH_MXC || COMPILE_TEST 548 - default ARCH_MXC 544 + depends on ARCH_MXC || ARCH_S32 || COMPILE_TEST 545 + default y if ARCH_MXC || ARCH_S32 549 546 select IRQ_DOMAIN 550 547 help 551 - Support for the i.MX IRQSTEER interrupt multiplexer/remapper. 548 + Support for the i.MX and S32 IRQSTEER interrupt multiplexer/remapper. 552 549 553 550 config IMX_INTMUX 554 551 bool "i.MX INTMUX support" if COMPILE_TEST ··· 764 761 765 762 config LOONGSON_PCH_LPC 766 763 bool "Loongson PCH LPC Controller" 767 - depends on LOONGARCH 768 764 depends on MACH_LOONGSON64 || LOONGARCH 769 765 default MACH_LOONGSON64 770 766 select IRQ_DOMAIN_HIERARCHY
+21 -3
drivers/irqchip/irq-apple-aic.c
··· 134 134 135 135 #define AIC2_IRQ_CFG 0x2000 136 136 137 + /* AIC v3 registers (MMIO) */ 138 + #define AIC3_IRQ_CFG 0x10000 139 + 137 140 /* 138 141 * AIC2 registers are laid out like this, starting at AIC2_IRQ_CFG: 142 + * AIC3 registers use the same layout but start at AIC3_IRQ_CFG: 139 143 * 140 144 * Repeat for each die: 141 145 * IRQ_CFG: u32 * MAX_IRQS ··· 297 293 .local_fast_ipi = true, 298 294 }; 299 295 296 + static const struct aic_info aic3_info __initconst = { 297 + .version = 3, 298 + 299 + .irq_cfg = AIC3_IRQ_CFG, 300 + 301 + .fast_ipi = true, 302 + .local_fast_ipi = true, 303 + }; 304 + 300 305 static const struct of_device_id aic_info_match[] = { 301 306 { 302 307 .compatible = "apple,t8103-aic", ··· 322 309 { 323 310 .compatible = "apple,aic2", 324 311 .data = &aic2_info, 312 + }, 313 + { 314 + .compatible = "apple,t8122-aic3", 315 + .data = &aic3_info, 325 316 }, 326 317 {} 327 318 }; ··· 637 620 u32 type = FIELD_GET(AIC_EVENT_TYPE, hw); 638 621 struct irq_chip *chip = &aic_chip; 639 622 640 - if (ic->info.version == 2) 623 + if (ic->info.version == 2 || ic->info.version == 3) 641 624 chip = &aic2_chip; 642 625 643 626 if (type == AIC_EVENT_TYPE_IRQ) { ··· 1008 991 1009 992 break; 1010 993 } 1011 - case 2: { 994 + case 2 ... 3: { 1012 995 u32 info1, info3; 1013 996 1014 997 info1 = aic_ic_read(irqc, AIC2_INFO1); ··· 1082 1065 off += irqc->info.die_stride; 1083 1066 } 1084 1067 1085 - if (irqc->info.version == 2) { 1068 + if (irqc->info.version == 2 || irqc->info.version == 3) { 1086 1069 u32 config = aic_ic_read(irqc, AIC2_CONFIG); 1087 1070 1088 1071 config |= AIC2_CONFIG_ENABLE; ··· 1133 1116 1134 1117 IRQCHIP_DECLARE(apple_aic, "apple,aic", aic_of_ic_init); 1135 1118 IRQCHIP_DECLARE(apple_aic2, "apple,aic2", aic_of_ic_init); 1119 + IRQCHIP_DECLARE(apple_aic3, "apple,t8122-aic3", aic_of_ic_init);
+9 -1
drivers/irqchip/irq-gic-v3.c
··· 1603 1603 1604 1604 switch (fwspec->param[0]) { 1605 1605 case 0: /* SPI */ 1606 + if (fwspec->param[1] > 987) 1607 + pr_warn_once("SPI %u out of range (use ESPI?)\n", fwspec->param[1]); 1606 1608 *hwirq = fwspec->param[1] + 32; 1607 1609 break; 1608 1610 case 1: /* PPI */ 1611 + if (fwspec->param[1] > 15) 1612 + pr_warn_once("PPI %u out of range (use EPPI?)\n", fwspec->param[1]); 1609 1613 *hwirq = fwspec->param[1] + 16; 1610 1614 break; 1611 1615 case 2: /* ESPI */ 1616 + if (fwspec->param[1] > 1023) 1617 + pr_warn_once("ESPI %u out of range\n", fwspec->param[1]); 1612 1618 *hwirq = fwspec->param[1] + ESPI_BASE_INTID; 1613 1619 break; 1614 1620 case 3: /* EPPI */ 1621 + if (fwspec->param[1] > 63) 1622 + pr_warn_once("EPPI %u out of range\n", fwspec->param[1]); 1615 1623 *hwirq = fwspec->param[1] + EPPI_BASE_INTID; 1616 1624 break; 1617 1625 case GIC_IRQ_TYPE_LPI: /* LPI */ ··· 2260 2252 2261 2253 out_unmap_rdist: 2262 2254 for (i = 0; i < nr_redist_regions; i++) 2263 - if (rdist_regs[i].redist_base && !IS_ERR(rdist_regs[i].redist_base)) 2255 + if (!IS_ERR_OR_NULL(rdist_regs[i].redist_base)) 2264 2256 iounmap(rdist_regs[i].redist_base); 2265 2257 kfree(rdist_regs); 2266 2258 out_unmap_dist:
+41 -14
drivers/irqchip/irq-imx-irqsteer.c
··· 26 26 27 27 #define CHAN_MAX_OUTPUT_INT 0xF 28 28 29 - struct irqsteer_data { 30 - void __iomem *regs; 31 - struct clk *ipg_clk; 32 - int irq[CHAN_MAX_OUTPUT_INT]; 33 - int irq_count; 34 - raw_spinlock_t lock; 35 - int reg_num; 36 - int channel; 37 - struct irq_domain *domain; 38 - u32 *saved_reg; 39 - struct device *dev; 29 + /* SoC does not implement the CHANCTRL register */ 30 + #define IRQSTEER_QUIRK_NO_CHANCTRL BIT(0) 31 + 32 + struct irqsteer_devtype_data { 33 + u32 quirks; 40 34 }; 35 + 36 + struct irqsteer_data { 37 + void __iomem *regs; 38 + struct clk *ipg_clk; 39 + int irq[CHAN_MAX_OUTPUT_INT]; 40 + int irq_count; 41 + raw_spinlock_t lock; 42 + int reg_num; 43 + int channel; 44 + struct irq_domain *domain; 45 + u32 *saved_reg; 46 + struct device *dev; 47 + const struct irqsteer_devtype_data *devtype_data; 48 + }; 49 + 50 + static const struct irqsteer_devtype_data imx_data = { }; 51 + 52 + static const struct irqsteer_devtype_data s32n79_data = { 53 + .quirks = IRQSTEER_QUIRK_NO_CHANCTRL, 54 + }; 55 + 56 + static bool irqsteer_has_chanctrl(const struct irqsteer_devtype_data *data) 57 + { 58 + return !(data->quirks & IRQSTEER_QUIRK_NO_CHANCTRL); 59 + } 41 60 42 61 static int imx_irqsteer_get_reg_index(struct irqsteer_data *data, 43 62 unsigned long irqnum) ··· 207 188 if (ret) 208 189 return ret; 209 190 191 + data->devtype_data = device_get_match_data(&pdev->dev); 192 + if (!data->devtype_data) 193 + return dev_err_probe(&pdev->dev, -ENODEV, "failed to match device data\n"); 194 + 210 195 /* 211 196 * There is one output irq for each group of 64 inputs. 212 197 * One register bit map can represent 32 input interrupts. ··· 233 210 } 234 211 235 212 /* steer all IRQs into configured channel */ 236 - writel_relaxed(BIT(data->channel), data->regs + CHANCTRL); 213 + if (irqsteer_has_chanctrl(data->devtype_data)) 214 + writel_relaxed(BIT(data->channel), data->regs + CHANCTRL); 237 215 238 216 data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->reg_num * 32, 239 217 &imx_irqsteer_domain_ops, data); ··· 303 279 { 304 280 int i; 305 281 306 - writel_relaxed(BIT(data->channel), data->regs + CHANCTRL); 282 + if (irqsteer_has_chanctrl(data->devtype_data)) 283 + writel_relaxed(BIT(data->channel), data->regs + CHANCTRL); 284 + 307 285 for (i = 0; i < data->reg_num; i++) 308 286 writel_relaxed(data->saved_reg[i], 309 287 data->regs + CHANMASK(i, data->reg_num)); ··· 345 319 }; 346 320 347 321 static const struct of_device_id imx_irqsteer_dt_ids[] = { 348 - { .compatible = "fsl,imx-irqsteer", }, 322 + { .compatible = "fsl,imx-irqsteer", .data = &imx_data }, 323 + { .compatible = "nxp,s32n79-irqsteer", .data = &s32n79_data }, 349 324 {}, 350 325 }; 351 326
+72 -20
drivers/irqchip/irq-loongson-pch-lpc.c
··· 13 13 #include <linux/irqchip/chained_irq.h> 14 14 #include <linux/irqdomain.h> 15 15 #include <linux/kernel.h> 16 + #include <linux/of_address.h> 17 + #include <linux/of_irq.h> 16 18 #include <linux/syscore_ops.h> 17 19 18 20 #include "irq-loongson.h" ··· 177 175 .ops = &pch_lpc_syscore_ops, 178 176 }; 179 177 180 - int __init pch_lpc_acpi_init(struct irq_domain *parent, 181 - struct acpi_madt_lpc_pic *acpi_pchlpc) 178 + static int __init pch_lpc_init(phys_addr_t addr, unsigned long size, 179 + struct fwnode_handle *irq_handle, int parent_irq) 182 180 { 183 - int parent_irq; 184 181 struct pch_lpc *priv; 185 - struct irq_fwspec fwspec; 186 - struct fwnode_handle *irq_handle; 187 182 188 183 priv = kzalloc_obj(*priv); 189 184 if (!priv) ··· 188 189 189 190 raw_spin_lock_init(&priv->lpc_lock); 190 191 191 - priv->base = ioremap(acpi_pchlpc->address, acpi_pchlpc->size); 192 + priv->base = ioremap(addr, size); 192 193 if (!priv->base) 193 194 goto free_priv; 194 195 195 196 if (pch_lpc_disabled(priv)) { 196 197 pr_err("Failed to get LPC status\n"); 197 - goto iounmap_base; 198 - } 199 - 200 - irq_handle = irq_domain_alloc_named_fwnode("lpcintc"); 201 - if (!irq_handle) { 202 - pr_err("Unable to allocate domain handle\n"); 203 198 goto iounmap_base; 204 199 } 205 200 ··· 206 213 &pch_lpc_domain_ops, priv); 207 214 if (!priv->lpc_domain) { 208 215 pr_err("Failed to create IRQ domain\n"); 209 - goto free_irq_handle; 216 + goto iounmap_base; 210 217 } 211 218 pch_lpc_reset(priv); 212 219 213 - fwspec.fwnode = parent->fwnode; 214 - fwspec.param[0] = acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ; 215 - fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; 216 - fwspec.param_count = 2; 217 - parent_irq = irq_create_fwspec_mapping(&fwspec); 218 220 irq_set_chained_handler_and_data(parent_irq, lpc_irq_dispatch, priv); 219 221 220 222 pch_lpc_priv = priv; ··· 218 230 219 231 return 0; 220 232 221 - free_irq_handle: 222 - irq_domain_free_fwnode(irq_handle); 223 233 iounmap_base: 224 234 iounmap(priv->base); 225 235 free_priv: ··· 225 239 226 240 return -ENOMEM; 227 241 } 242 + 243 + #ifdef CONFIG_ACPI 244 + int __init pch_lpc_acpi_init(struct irq_domain *parent, struct acpi_madt_lpc_pic *acpi_pchlpc) 245 + { 246 + struct fwnode_handle *irq_handle; 247 + struct irq_fwspec fwspec; 248 + int parent_irq, ret; 249 + 250 + irq_handle = irq_domain_alloc_named_fwnode("lpcintc"); 251 + if (!irq_handle) { 252 + pr_err("Unable to allocate domain handle\n"); 253 + return -ENOMEM; 254 + } 255 + 256 + fwspec.fwnode = parent->fwnode; 257 + fwspec.param[0] = acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ; 258 + fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; 259 + fwspec.param_count = 2; 260 + parent_irq = irq_create_fwspec_mapping(&fwspec); 261 + if (parent_irq <= 0) { 262 + pr_err("Unable to map LPC parent interrupt\n"); 263 + irq_domain_free_fwnode(irq_handle); 264 + return -ENOMEM; 265 + } 266 + 267 + ret = pch_lpc_init(acpi_pchlpc->address, acpi_pchlpc->size, irq_handle, parent_irq); 268 + if (ret) { 269 + irq_dispose_mapping(parent_irq); 270 + irq_domain_free_fwnode(irq_handle); 271 + return ret; 272 + } 273 + 274 + return 0; 275 + } 276 + #endif /* CONFIG_ACPI */ 277 + 278 + #ifdef CONFIG_OF 279 + static int __init pch_lpc_of_init(struct device_node *node, struct device_node *parent) 280 + { 281 + struct fwnode_handle *irq_handle; 282 + struct resource res; 283 + int parent_irq, ret; 284 + 285 + if (of_address_to_resource(node, 0, &res)) 286 + return -EINVAL; 287 + 288 + parent_irq = irq_of_parse_and_map(node, 0); 289 + if (!parent_irq) { 290 + pr_err("Failed to get the parent IRQ for LPC IRQs\n"); 291 + return -EINVAL; 292 + } 293 + 294 + irq_handle = of_fwnode_handle(node); 295 + 296 + ret = pch_lpc_init(res.start, resource_size(&res), irq_handle, 297 + parent_irq); 298 + if (ret) { 299 + irq_dispose_mapping(parent_irq); 300 + return ret; 301 + } 302 + 303 + return 0; 304 + } 305 + 306 + IRQCHIP_DECLARE(pch_lpc, "loongson,ls7a-lpc", pch_lpc_of_init); 307 + #endif /* CONFIG_OF */
+1 -1
drivers/irqchip/irq-mvebu-odmi.c
··· 217 217 for (i = 0; i < odmis_count; i++) { 218 218 struct odmi_data *odmi = &odmis[i]; 219 219 220 - if (odmi->base && !IS_ERR(odmi->base)) 220 + if (!IS_ERR_OR_NULL(odmi->base)) 221 221 iounmap(odmis[i].base); 222 222 } 223 223 bitmap_free(odmis_bm);
+7 -1
drivers/irqchip/irq-pic32-evic.c
··· 15 15 #include <linux/irq.h> 16 16 #include <linux/platform_data/pic32.h> 17 17 18 + #ifdef CONFIG_MIPS 18 19 #include <asm/irq.h> 19 20 #include <asm/traps.h> 21 + #endif 20 22 21 23 #define REG_INTCON 0x0000 22 24 #define REG_INTSTAT 0x0020 ··· 42 40 static struct irq_domain *evic_irq_domain; 43 41 static void __iomem *evic_base; 44 42 43 + #ifdef CONFIG_MIPS 45 44 asmlinkage void __weak plat_irq_dispatch(void) 46 45 { 47 46 unsigned int hwirq; ··· 50 47 hwirq = readl(evic_base + REG_INTSTAT) & 0xFF; 51 48 do_domain_IRQ(evic_irq_domain, hwirq); 52 49 } 50 + #else 51 + static __maybe_unused void (*board_bind_eic_interrupt)(int irq, int regset); 52 + #endif 53 53 54 54 static struct evic_chip_data *irqd_to_priv(struct irq_data *data) 55 55 { ··· 202 196 203 197 of_property_for_each_u32(node, pname, hwirq) { 204 198 if (i >= ARRAY_SIZE(priv->ext_irqs)) { 205 - pr_warn("More than %d external irq, skip rest\n", 199 + pr_warn("More than %zu external irq, skip rest\n", 206 200 ARRAY_SIZE(priv->ext_irqs)); 207 201 break; 208 202 }
+465 -117
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 - #define IRQC_IRQ_COUNT 8 25 - #define IRQC_TINT_START (IRQC_IRQ_START + IRQC_IRQ_COUNT) 26 25 #define IRQC_TINT_COUNT 32 27 - #define IRQC_NUM_IRQ (IRQC_TINT_START + IRQC_TINT_COUNT) 26 + #define IRQC_SHARED_IRQ_COUNT 8 27 + #define IRQC_IRQ_SHARED_START (IRQC_IRQ_START + IRQC_SHARED_IRQ_COUNT) 28 28 29 + #define NSCR 0x0 30 + #define NITSR 0x4 29 31 #define ISCR 0x10 30 32 #define IITSR 0x14 31 33 #define TSCR 0x20 32 34 #define TITSR(n) (0x24 + (n) * 4) 33 35 #define TITSR0_MAX_INT 16 34 36 #define TITSEL_WIDTH 0x2 37 + #define INTTSEL 0x2c 35 38 #define TSSR(n) (0x30 + ((n) * 4)) 36 39 #define TIEN BIT(7) 37 40 #define TSSEL_SHIFT(n) (8 * (n)) ··· 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 ··· 62 55 #define IITSR_IITSEL_EDGE_BOTH 3 63 56 #define IITSR_IITSEL_MASK(n) IITSR_IITSEL((n), 3) 64 57 58 + #define INTTSEL_TINTSEL(n) BIT(n) 59 + #define INTTSEL_TINTSEL_START 24 60 + 65 61 #define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x)) 66 62 #define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x)) 67 63 68 64 /** 69 65 * struct rzg2l_irqc_reg_cache - registers cache (necessary for suspend/resume) 70 - * @iitsr: IITSR register 71 - * @titsr: TITSR registers 66 + * @nitsr: NITSR register 67 + * @iitsr: IITSR register 68 + * @inttsel: INTTSEL register 69 + * @titsr: TITSR registers 72 70 */ 73 71 struct rzg2l_irqc_reg_cache { 72 + u32 nitsr; 74 73 u32 iitsr; 74 + u32 inttsel; 75 75 u32 titsr[2]; 76 + }; 77 + 78 + /** 79 + * struct rzg2l_hw_info - Interrupt Control Unit controller hardware info structure. 80 + * @tssel_lut: TINT lookup table 81 + * @irq_count: Number of IRQC interrupts 82 + * @tint_start: Start of TINT interrupts 83 + * @num_irq: Total Number of interrupts 84 + * @shared_irq_cnt: Number of shared interrupts 85 + */ 86 + struct rzg2l_hw_info { 87 + const u8 *tssel_lut; 88 + unsigned int irq_count; 89 + unsigned int tint_start; 90 + unsigned int num_irq; 91 + unsigned int shared_irq_cnt; 76 92 }; 77 93 78 94 /** 79 95 * struct rzg2l_irqc_priv - IRQ controller private data structure 80 96 * @base: Controller's base address 81 - * @irqchip: Pointer to struct irq_chip 97 + * @irq_chip: Pointer to struct irq_chip for irq 98 + * @tint_chip: Pointer to struct irq_chip for tint 82 99 * @fwspec: IRQ firmware specific data 83 100 * @lock: Lock to serialize access to hardware registers 101 + * @info: Hardware specific data 84 102 * @cache: Registers cache for suspend/resume 103 + * @used_irqs: Bitmap to manage the shared interrupts 85 104 */ 86 105 static struct rzg2l_irqc_priv { 87 106 void __iomem *base; 88 - const struct irq_chip *irqchip; 89 - struct irq_fwspec fwspec[IRQC_NUM_IRQ]; 107 + const struct irq_chip *irq_chip; 108 + const struct irq_chip *tint_chip; 109 + struct irq_fwspec *fwspec; 90 110 raw_spinlock_t lock; 111 + struct rzg2l_hw_info info; 91 112 struct rzg2l_irqc_reg_cache cache; 113 + DECLARE_BITMAP(used_irqs, IRQC_SHARED_IRQ_COUNT); 92 114 } *rzg2l_irqc_data; 93 115 94 116 static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data) 95 117 { 96 118 return data->domain->host_data; 119 + } 120 + 121 + static void rzg2l_clear_nmi_int(struct rzg2l_irqc_priv *priv) 122 + { 123 + u32 bit = BIT(NSCR_NSTAT); 124 + u32 reg; 125 + 126 + /* 127 + * No locking required as the register is not shared 128 + * with other interrupts. 129 + * 130 + * Writing is allowed only when NSTAT is 1 131 + */ 132 + reg = readl_relaxed(priv->base + NSCR); 133 + if (reg & bit) { 134 + writel_relaxed(reg & ~bit, priv->base + NSCR); 135 + /* 136 + * Enforce that the posted write is flushed to prevent that the 137 + * just handled interrupt is raised again. 138 + */ 139 + readl_relaxed(priv->base + NSCR); 140 + } 97 141 } 98 142 99 143 static void rzg2l_clear_irq_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq) ··· 172 114 173 115 static void rzg2l_clear_tint_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq) 174 116 { 175 - u32 bit = BIT(hwirq - IRQC_TINT_START); 117 + u32 bit = BIT(hwirq - priv->info.tint_start); 176 118 u32 reg; 177 119 178 120 reg = readl_relaxed(priv->base + TSCR); ··· 186 128 } 187 129 } 188 130 189 - static void rzg2l_irqc_eoi(struct irq_data *d) 131 + static void rzg2l_irqc_nmi_eoi(struct irq_data *d) 132 + { 133 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 134 + 135 + rzg2l_clear_nmi_int(priv); 136 + irq_chip_eoi_parent(d); 137 + } 138 + 139 + static void rzg2l_irqc_irq_eoi(struct irq_data *d) 190 140 { 191 141 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 192 142 unsigned int hw_irq = irqd_to_hwirq(d); 193 143 194 - raw_spin_lock(&priv->lock); 195 - if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT) 144 + scoped_guard(raw_spinlock, &priv->lock) 196 145 rzg2l_clear_irq_int(priv, hw_irq); 197 - else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) 146 + 147 + irq_chip_eoi_parent(d); 148 + } 149 + 150 + static void rzg2l_irqc_tint_eoi(struct irq_data *d) 151 + { 152 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 153 + unsigned int hw_irq = irqd_to_hwirq(d); 154 + 155 + scoped_guard(raw_spinlock, &priv->lock) 198 156 rzg2l_clear_tint_int(priv, hw_irq); 199 - raw_spin_unlock(&priv->lock); 157 + 200 158 irq_chip_eoi_parent(d); 201 159 } 202 160 ··· 235 161 static void rzfive_irqc_mask_tint_interrupt(struct rzg2l_irqc_priv *priv, 236 162 unsigned int hwirq) 237 163 { 238 - u32 bit = BIT(hwirq - IRQC_TINT_START); 164 + u32 bit = BIT(hwirq - priv->info.tint_start); 239 165 240 166 writel_relaxed(readl_relaxed(priv->base + TMSK) | bit, priv->base + TMSK); 241 167 } ··· 243 169 static void rzfive_irqc_unmask_tint_interrupt(struct rzg2l_irqc_priv *priv, 244 170 unsigned int hwirq) 245 171 { 246 - u32 bit = BIT(hwirq - IRQC_TINT_START); 172 + u32 bit = BIT(hwirq - priv->info.tint_start); 247 173 248 174 writel_relaxed(readl_relaxed(priv->base + TMSK) & ~bit, priv->base + TMSK); 249 175 } 250 176 251 - static void rzfive_irqc_mask(struct irq_data *d) 177 + static void rzfive_irqc_irq_mask(struct irq_data *d) 252 178 { 253 179 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 254 180 unsigned int hwirq = irqd_to_hwirq(d); 255 181 256 - raw_spin_lock(&priv->lock); 257 - if (hwirq >= IRQC_IRQ_START && hwirq <= IRQC_IRQ_COUNT) 182 + scoped_guard(raw_spinlock, &priv->lock) 258 183 rzfive_irqc_mask_irq_interrupt(priv, hwirq); 259 - else if (hwirq >= IRQC_TINT_START && hwirq < IRQC_NUM_IRQ) 260 - rzfive_irqc_mask_tint_interrupt(priv, hwirq); 261 - raw_spin_unlock(&priv->lock); 184 + 262 185 irq_chip_mask_parent(d); 263 186 } 264 187 265 - static void rzfive_irqc_unmask(struct irq_data *d) 188 + static void rzfive_irqc_tint_mask(struct irq_data *d) 266 189 { 267 190 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 268 191 unsigned int hwirq = irqd_to_hwirq(d); 269 192 270 - raw_spin_lock(&priv->lock); 271 - if (hwirq >= IRQC_IRQ_START && hwirq <= IRQC_IRQ_COUNT) 193 + scoped_guard(raw_spinlock, &priv->lock) 194 + rzfive_irqc_mask_tint_interrupt(priv, hwirq); 195 + 196 + irq_chip_mask_parent(d); 197 + } 198 + 199 + static void rzfive_irqc_irq_unmask(struct irq_data *d) 200 + { 201 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 202 + unsigned int hwirq = irqd_to_hwirq(d); 203 + 204 + scoped_guard(raw_spinlock, &priv->lock) 272 205 rzfive_irqc_unmask_irq_interrupt(priv, hwirq); 273 - else if (hwirq >= IRQC_TINT_START && hwirq < IRQC_NUM_IRQ) 274 - rzfive_irqc_unmask_tint_interrupt(priv, hwirq); 275 - raw_spin_unlock(&priv->lock); 206 + 276 207 irq_chip_unmask_parent(d); 277 208 } 278 209 279 - static void rzfive_tint_irq_endisable(struct irq_data *d, bool enable) 210 + static void rzfive_irqc_tint_unmask(struct irq_data *d) 280 211 { 281 212 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 282 213 unsigned int hwirq = irqd_to_hwirq(d); 283 214 284 - if (hwirq >= IRQC_TINT_START && hwirq < IRQC_NUM_IRQ) { 285 - u32 offset = hwirq - IRQC_TINT_START; 286 - u32 tssr_offset = TSSR_OFFSET(offset); 287 - u8 tssr_index = TSSR_INDEX(offset); 288 - u32 reg; 215 + scoped_guard(raw_spinlock, &priv->lock) 216 + rzfive_irqc_unmask_tint_interrupt(priv, hwirq); 289 217 290 - raw_spin_lock(&priv->lock); 291 - if (enable) 292 - rzfive_irqc_unmask_tint_interrupt(priv, hwirq); 293 - else 294 - rzfive_irqc_mask_tint_interrupt(priv, hwirq); 295 - reg = readl_relaxed(priv->base + TSSR(tssr_index)); 296 - if (enable) 297 - reg |= TIEN << TSSEL_SHIFT(tssr_offset); 298 - else 299 - reg &= ~(TIEN << TSSEL_SHIFT(tssr_offset)); 300 - writel_relaxed(reg, priv->base + TSSR(tssr_index)); 301 - raw_spin_unlock(&priv->lock); 302 - } else { 303 - raw_spin_lock(&priv->lock); 304 - if (enable) 305 - rzfive_irqc_unmask_irq_interrupt(priv, hwirq); 306 - else 307 - rzfive_irqc_mask_irq_interrupt(priv, hwirq); 308 - raw_spin_unlock(&priv->lock); 309 - } 218 + irq_chip_unmask_parent(d); 219 + } 220 + 221 + static void rzfive_irq_endisable(struct irq_data *d, bool enable) 222 + { 223 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 224 + unsigned int hwirq = irqd_to_hwirq(d); 225 + 226 + guard(raw_spinlock)(&priv->lock); 227 + if (enable) 228 + rzfive_irqc_unmask_irq_interrupt(priv, hwirq); 229 + else 230 + rzfive_irqc_mask_irq_interrupt(priv, hwirq); 231 + } 232 + 233 + static void rzfive_tint_endisable(struct irq_data *d, bool enable) 234 + { 235 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 236 + unsigned int hwirq = irqd_to_hwirq(d); 237 + unsigned int offset = hwirq - priv->info.tint_start; 238 + unsigned int tssr_offset = TSSR_OFFSET(offset); 239 + unsigned int tssr_index = TSSR_INDEX(offset); 240 + u32 reg; 241 + 242 + guard(raw_spinlock)(&priv->lock); 243 + if (enable) 244 + rzfive_irqc_unmask_tint_interrupt(priv, hwirq); 245 + else 246 + rzfive_irqc_mask_tint_interrupt(priv, hwirq); 247 + reg = readl_relaxed(priv->base + TSSR(tssr_index)); 248 + if (enable) 249 + reg |= TIEN << TSSEL_SHIFT(tssr_offset); 250 + else 251 + reg &= ~(TIEN << TSSEL_SHIFT(tssr_offset)); 252 + writel_relaxed(reg, priv->base + TSSR(tssr_index)); 310 253 } 311 254 312 255 static void rzfive_irqc_irq_disable(struct irq_data *d) 313 256 { 314 257 irq_chip_disable_parent(d); 315 - rzfive_tint_irq_endisable(d, false); 258 + rzfive_irq_endisable(d, false); 316 259 } 317 260 318 261 static void rzfive_irqc_irq_enable(struct irq_data *d) 319 262 { 320 - rzfive_tint_irq_endisable(d, true); 263 + rzfive_irq_endisable(d, true); 264 + irq_chip_enable_parent(d); 265 + } 266 + 267 + static void rzfive_irqc_tint_disable(struct irq_data *d) 268 + { 269 + irq_chip_disable_parent(d); 270 + rzfive_tint_endisable(d, false); 271 + } 272 + 273 + static void rzfive_irqc_tint_enable(struct irq_data *d) 274 + { 275 + rzfive_tint_endisable(d, true); 321 276 irq_chip_enable_parent(d); 322 277 } 323 278 324 279 static void rzg2l_tint_irq_endisable(struct irq_data *d, bool enable) 325 280 { 281 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 326 282 unsigned int hw_irq = irqd_to_hwirq(d); 283 + unsigned int offset = hw_irq - priv->info.tint_start; 284 + unsigned int tssr_offset = TSSR_OFFSET(offset); 285 + unsigned int tssr_index = TSSR_INDEX(offset); 286 + u32 reg; 327 287 328 - if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) { 329 - struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 330 - u32 offset = hw_irq - IRQC_TINT_START; 331 - u32 tssr_offset = TSSR_OFFSET(offset); 332 - u8 tssr_index = TSSR_INDEX(offset); 333 - u32 reg; 334 - 335 - raw_spin_lock(&priv->lock); 336 - reg = readl_relaxed(priv->base + TSSR(tssr_index)); 337 - if (enable) 338 - reg |= TIEN << TSSEL_SHIFT(tssr_offset); 339 - else 340 - reg &= ~(TIEN << TSSEL_SHIFT(tssr_offset)); 341 - writel_relaxed(reg, priv->base + TSSR(tssr_index)); 342 - raw_spin_unlock(&priv->lock); 343 - } 288 + guard(raw_spinlock)(&priv->lock); 289 + reg = readl_relaxed(priv->base + TSSR(tssr_index)); 290 + if (enable) 291 + reg |= TIEN << TSSEL_SHIFT(tssr_offset); 292 + else 293 + reg &= ~(TIEN << TSSEL_SHIFT(tssr_offset)); 294 + writel_relaxed(reg, priv->base + TSSR(tssr_index)); 344 295 } 345 296 346 - static void rzg2l_irqc_irq_disable(struct irq_data *d) 297 + static void rzg2l_irqc_tint_disable(struct irq_data *d) 347 298 { 348 299 irq_chip_disable_parent(d); 349 300 rzg2l_tint_irq_endisable(d, false); 350 301 } 351 302 352 - static void rzg2l_irqc_irq_enable(struct irq_data *d) 303 + static void rzg2l_irqc_tint_enable(struct irq_data *d) 353 304 { 354 305 rzg2l_tint_irq_endisable(d, true); 355 306 irq_chip_enable_parent(d); 307 + } 308 + 309 + static int rzg2l_nmi_set_type(struct irq_data *d, unsigned int type) 310 + { 311 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 312 + u32 sense; 313 + 314 + switch (type & IRQ_TYPE_SENSE_MASK) { 315 + case IRQ_TYPE_EDGE_FALLING: 316 + sense = NITSR_NTSEL_EDGE_FALLING; 317 + break; 318 + case IRQ_TYPE_EDGE_RISING: 319 + sense = NITSR_NTSEL_EDGE_RISING; 320 + break; 321 + default: 322 + return -EINVAL; 323 + } 324 + 325 + writel_relaxed(sense, priv->base + NITSR); 326 + return 0; 356 327 } 357 328 358 329 static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type) 359 330 { 360 331 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 361 332 unsigned int hwirq = irqd_to_hwirq(d); 362 - u32 iitseln = hwirq - IRQC_IRQ_START; 333 + unsigned int iitseln = hwirq - IRQC_IRQ_START; 363 334 bool clear_irq_int = false; 364 - u16 sense, tmp; 335 + unsigned int sense, tmp; 365 336 366 337 switch (type & IRQ_TYPE_SENSE_MASK) { 367 338 case IRQ_TYPE_LEVEL_LOW: ··· 432 313 return -EINVAL; 433 314 } 434 315 435 - raw_spin_lock(&priv->lock); 316 + guard(raw_spinlock)(&priv->lock); 436 317 tmp = readl_relaxed(priv->base + IITSR); 437 318 tmp &= ~IITSR_IITSEL_MASK(iitseln); 438 319 tmp |= IITSR_IITSEL(iitseln, sense); 439 320 if (clear_irq_int) 440 321 rzg2l_clear_irq_int(priv, hwirq); 441 322 writel_relaxed(tmp, priv->base + IITSR); 442 - raw_spin_unlock(&priv->lock); 443 323 444 324 return 0; 445 325 } ··· 448 330 { 449 331 u32 tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d); 450 332 u32 tien = reg & (TIEN << TSSEL_SHIFT(tssr_offset)); 333 + 334 + if (priv->info.tssel_lut) 335 + tint = priv->info.tssel_lut[tint]; 336 + else 337 + tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d); 451 338 452 339 /* Clear the relevant byte in reg */ 453 340 reg &= ~(TSSEL_MASK << TSSEL_SHIFT(tssr_offset)); ··· 467 344 { 468 345 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 469 346 unsigned int hwirq = irqd_to_hwirq(d); 470 - u32 titseln = hwirq - IRQC_TINT_START; 471 - u32 tssr_offset = TSSR_OFFSET(titseln); 472 - u8 tssr_index = TSSR_INDEX(titseln); 473 - u8 index, sense; 347 + unsigned int titseln = hwirq - priv->info.tint_start; 348 + unsigned int tssr_offset = TSSR_OFFSET(titseln); 349 + unsigned int tssr_index = TSSR_INDEX(titseln); 350 + unsigned int index, sense; 474 351 u32 reg, tssr; 475 352 476 353 switch (type & IRQ_TYPE_SENSE_MASK) { ··· 506 383 return 0; 507 384 } 508 385 509 - static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type) 386 + static int rzg2l_irqc_irq_set_type(struct irq_data *d, unsigned int type) 510 387 { 511 - unsigned int hw_irq = irqd_to_hwirq(d); 512 - int ret = -EINVAL; 388 + int ret = rzg2l_irq_set_type(d, type); 513 389 514 - if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT) 515 - ret = rzg2l_irq_set_type(d, type); 516 - else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) 517 - ret = rzg2l_tint_set_edge(d, type); 390 + if (ret) 391 + return ret; 392 + 393 + return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 394 + } 395 + 396 + static int rzg2l_irqc_tint_set_type(struct irq_data *d, unsigned int type) 397 + { 398 + int ret = rzg2l_tint_set_edge(d, type); 399 + 400 + if (ret) 401 + return ret; 402 + 403 + return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 404 + } 405 + 406 + static int rzg2l_irqc_nmi_set_type(struct irq_data *d, unsigned int type) 407 + { 408 + int ret; 409 + 410 + ret = rzg2l_nmi_set_type(d, type); 518 411 if (ret) 519 412 return ret; 520 413 ··· 542 403 struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache; 543 404 void __iomem *base = rzg2l_irqc_data->base; 544 405 406 + cache->nitsr = readl_relaxed(base + NITSR); 545 407 cache->iitsr = readl_relaxed(base + IITSR); 408 + if (rzg2l_irqc_data->info.shared_irq_cnt) 409 + cache->inttsel = readl_relaxed(base + INTTSEL); 546 410 for (u8 i = 0; i < 2; i++) 547 411 cache->titsr[i] = readl_relaxed(base + TITSR(i)); 548 412 ··· 564 422 */ 565 423 for (u8 i = 0; i < 2; i++) 566 424 writel_relaxed(cache->titsr[i], base + TITSR(i)); 425 + if (rzg2l_irqc_data->info.shared_irq_cnt) 426 + writel_relaxed(cache->inttsel, base + INTTSEL); 567 427 writel_relaxed(cache->iitsr, base + IITSR); 428 + writel_relaxed(cache->nitsr, base + NITSR); 568 429 } 569 430 570 431 static const struct syscore_ops rzg2l_irqc_syscore_ops = { ··· 579 434 .ops = &rzg2l_irqc_syscore_ops, 580 435 }; 581 436 582 - static const struct irq_chip rzg2l_irqc_chip = { 437 + static const struct irq_chip rzg2l_irqc_nmi_chip = { 583 438 .name = "rzg2l-irqc", 584 - .irq_eoi = rzg2l_irqc_eoi, 439 + .irq_eoi = rzg2l_irqc_nmi_eoi, 585 440 .irq_mask = irq_chip_mask_parent, 586 441 .irq_unmask = irq_chip_unmask_parent, 587 - .irq_disable = rzg2l_irqc_irq_disable, 588 - .irq_enable = rzg2l_irqc_irq_enable, 442 + .irq_disable = irq_chip_disable_parent, 443 + .irq_enable = irq_chip_enable_parent, 589 444 .irq_get_irqchip_state = irq_chip_get_parent_state, 590 445 .irq_set_irqchip_state = irq_chip_set_parent_state, 591 446 .irq_retrigger = irq_chip_retrigger_hierarchy, 592 - .irq_set_type = rzg2l_irqc_set_type, 447 + .irq_set_type = rzg2l_irqc_nmi_set_type, 593 448 .irq_set_affinity = irq_chip_set_affinity_parent, 594 449 .flags = IRQCHIP_MASK_ON_SUSPEND | 595 450 IRQCHIP_SET_TYPE_MASKED | 596 451 IRQCHIP_SKIP_SET_WAKE, 597 452 }; 598 453 599 - static const struct irq_chip rzfive_irqc_chip = { 454 + static const struct irq_chip rzg2l_irqc_irq_chip = { 455 + .name = "rzg2l-irqc", 456 + .irq_eoi = rzg2l_irqc_irq_eoi, 457 + .irq_mask = irq_chip_mask_parent, 458 + .irq_unmask = irq_chip_unmask_parent, 459 + .irq_disable = irq_chip_disable_parent, 460 + .irq_enable = irq_chip_enable_parent, 461 + .irq_get_irqchip_state = irq_chip_get_parent_state, 462 + .irq_set_irqchip_state = irq_chip_set_parent_state, 463 + .irq_retrigger = irq_chip_retrigger_hierarchy, 464 + .irq_set_type = rzg2l_irqc_irq_set_type, 465 + .irq_set_affinity = irq_chip_set_affinity_parent, 466 + .flags = IRQCHIP_MASK_ON_SUSPEND | 467 + IRQCHIP_SET_TYPE_MASKED | 468 + IRQCHIP_SKIP_SET_WAKE, 469 + }; 470 + 471 + static const struct irq_chip rzg2l_irqc_tint_chip = { 472 + .name = "rzg2l-irqc", 473 + .irq_eoi = rzg2l_irqc_tint_eoi, 474 + .irq_mask = irq_chip_mask_parent, 475 + .irq_unmask = irq_chip_unmask_parent, 476 + .irq_disable = rzg2l_irqc_tint_disable, 477 + .irq_enable = rzg2l_irqc_tint_enable, 478 + .irq_get_irqchip_state = irq_chip_get_parent_state, 479 + .irq_set_irqchip_state = irq_chip_set_parent_state, 480 + .irq_retrigger = irq_chip_retrigger_hierarchy, 481 + .irq_set_type = rzg2l_irqc_tint_set_type, 482 + .irq_set_affinity = irq_chip_set_affinity_parent, 483 + .flags = IRQCHIP_MASK_ON_SUSPEND | 484 + IRQCHIP_SET_TYPE_MASKED | 485 + IRQCHIP_SKIP_SET_WAKE, 486 + }; 487 + 488 + static const struct irq_chip rzfive_irqc_irq_chip = { 600 489 .name = "rzfive-irqc", 601 - .irq_eoi = rzg2l_irqc_eoi, 602 - .irq_mask = rzfive_irqc_mask, 603 - .irq_unmask = rzfive_irqc_unmask, 490 + .irq_eoi = rzg2l_irqc_irq_eoi, 491 + .irq_mask = rzfive_irqc_irq_mask, 492 + .irq_unmask = rzfive_irqc_irq_unmask, 604 493 .irq_disable = rzfive_irqc_irq_disable, 605 494 .irq_enable = rzfive_irqc_irq_enable, 606 495 .irq_get_irqchip_state = irq_chip_get_parent_state, 607 496 .irq_set_irqchip_state = irq_chip_set_parent_state, 608 497 .irq_retrigger = irq_chip_retrigger_hierarchy, 609 - .irq_set_type = rzg2l_irqc_set_type, 498 + .irq_set_type = rzg2l_irqc_irq_set_type, 610 499 .irq_set_affinity = irq_chip_set_affinity_parent, 611 500 .flags = IRQCHIP_MASK_ON_SUSPEND | 612 501 IRQCHIP_SET_TYPE_MASKED | 613 502 IRQCHIP_SKIP_SET_WAKE, 614 503 }; 615 504 505 + static const struct irq_chip rzfive_irqc_tint_chip = { 506 + .name = "rzfive-irqc", 507 + .irq_eoi = rzg2l_irqc_tint_eoi, 508 + .irq_mask = rzfive_irqc_tint_mask, 509 + .irq_unmask = rzfive_irqc_tint_unmask, 510 + .irq_disable = rzfive_irqc_tint_disable, 511 + .irq_enable = rzfive_irqc_tint_enable, 512 + .irq_get_irqchip_state = irq_chip_get_parent_state, 513 + .irq_set_irqchip_state = irq_chip_set_parent_state, 514 + .irq_retrigger = irq_chip_retrigger_hierarchy, 515 + .irq_set_type = rzg2l_irqc_tint_set_type, 516 + .irq_set_affinity = irq_chip_set_affinity_parent, 517 + .flags = IRQCHIP_MASK_ON_SUSPEND | 518 + IRQCHIP_SET_TYPE_MASKED | 519 + IRQCHIP_SKIP_SET_WAKE, 520 + }; 521 + 522 + static bool rzg2l_irqc_is_shared_irqc(const struct rzg2l_hw_info info, unsigned int hw_irq) 523 + { 524 + return ((hw_irq >= (info.tint_start - info.shared_irq_cnt)) && hw_irq < info.tint_start); 525 + } 526 + 527 + static bool rzg2l_irqc_is_shared_tint(const struct rzg2l_hw_info info, unsigned int hw_irq) 528 + { 529 + return ((hw_irq >= (info.num_irq - info.shared_irq_cnt)) && hw_irq < info.num_irq); 530 + } 531 + 532 + static bool rzg2l_irqc_is_shared_and_get_irq_num(struct rzg2l_irqc_priv *priv, 533 + irq_hw_number_t hwirq, unsigned int *irq_num) 534 + { 535 + bool is_shared = false; 536 + 537 + if (rzg2l_irqc_is_shared_irqc(priv->info, hwirq)) { 538 + *irq_num = hwirq - IRQC_IRQ_SHARED_START; 539 + is_shared = true; 540 + } else if (rzg2l_irqc_is_shared_tint(priv->info, hwirq)) { 541 + *irq_num = hwirq - IRQC_TINT_COUNT - IRQC_IRQ_SHARED_START; 542 + is_shared = true; 543 + } 544 + 545 + return is_shared; 546 + } 547 + 548 + static void rzg2l_irqc_set_inttsel(struct rzg2l_irqc_priv *priv, unsigned int offset, 549 + unsigned int select_irq) 550 + { 551 + u32 reg; 552 + 553 + guard(raw_spinlock_irqsave)(&priv->lock); 554 + reg = readl_relaxed(priv->base + INTTSEL); 555 + if (select_irq) 556 + reg |= INTTSEL_TINTSEL(offset); 557 + else 558 + reg &= ~INTTSEL_TINTSEL(offset); 559 + writel_relaxed(reg, priv->base + INTTSEL); 560 + } 561 + 562 + static int rzg2l_irqc_shared_irq_alloc(struct rzg2l_irqc_priv *priv, irq_hw_number_t hwirq) 563 + { 564 + unsigned int irq_num; 565 + 566 + if (rzg2l_irqc_is_shared_and_get_irq_num(priv, hwirq, &irq_num)) { 567 + if (test_and_set_bit(irq_num, priv->used_irqs)) 568 + return -EBUSY; 569 + 570 + if (hwirq < priv->info.tint_start) 571 + rzg2l_irqc_set_inttsel(priv, INTTSEL_TINTSEL_START + irq_num, 1); 572 + else 573 + rzg2l_irqc_set_inttsel(priv, INTTSEL_TINTSEL_START + irq_num, 0); 574 + } 575 + 576 + return 0; 577 + } 578 + 579 + static void rzg2l_irqc_shared_irq_free(struct rzg2l_irqc_priv *priv, irq_hw_number_t hwirq) 580 + { 581 + unsigned int irq_num; 582 + 583 + if (rzg2l_irqc_is_shared_and_get_irq_num(priv, hwirq, &irq_num) && 584 + test_and_clear_bit(irq_num, priv->used_irqs)) 585 + rzg2l_irqc_set_inttsel(priv, INTTSEL_TINTSEL_START + irq_num, 0); 586 + } 587 + 616 588 static int rzg2l_irqc_alloc(struct irq_domain *domain, unsigned int virq, 617 589 unsigned int nr_irqs, void *arg) 618 590 { 619 591 struct rzg2l_irqc_priv *priv = domain->host_data; 592 + const struct irq_chip *chip; 620 593 unsigned long tint = 0; 621 594 irq_hw_number_t hwirq; 622 595 unsigned int type; ··· 751 488 * from 16-31 bits. TINT from the pinctrl driver needs to be programmed 752 489 * in IRQC registers to enable a given gpio pin as interrupt. 753 490 */ 754 - if (hwirq > IRQC_IRQ_COUNT) { 491 + if (hwirq == IRQC_NMI) { 492 + chip = &rzg2l_irqc_nmi_chip; 493 + } else if (hwirq > priv->info.irq_count) { 755 494 tint = TINT_EXTRACT_GPIOINT(hwirq); 756 495 hwirq = TINT_EXTRACT_HWIRQ(hwirq); 757 - 758 - if (hwirq < IRQC_TINT_START) 759 - return -EINVAL; 496 + chip = priv->tint_chip; 497 + } else { 498 + chip = priv->irq_chip; 760 499 } 761 500 762 - if (hwirq > (IRQC_NUM_IRQ - 1)) 501 + if (hwirq >= priv->info.num_irq) 763 502 return -EINVAL; 764 503 765 - ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, priv->irqchip, 766 - (void *)(uintptr_t)tint); 767 - if (ret) 768 - return ret; 504 + if (priv->info.shared_irq_cnt) { 505 + ret = rzg2l_irqc_shared_irq_alloc(priv, hwirq); 506 + if (ret) 507 + return ret; 508 + } 769 509 770 - return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]); 510 + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, chip, (void *)(uintptr_t)tint); 511 + if (ret) 512 + goto shared_irq_free; 513 + 514 + ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]); 515 + if (ret) 516 + goto shared_irq_free; 517 + 518 + return 0; 519 + 520 + shared_irq_free: 521 + if (priv->info.shared_irq_cnt) 522 + rzg2l_irqc_shared_irq_free(priv, hwirq); 523 + 524 + return ret; 525 + } 526 + 527 + static void rzg2l_irqc_free(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs) 528 + { 529 + struct irq_data *d = irq_domain_get_irq_data(domain, virq); 530 + struct rzg2l_irqc_priv *priv = domain->host_data; 531 + irq_hw_number_t hwirq = irqd_to_hwirq(d); 532 + 533 + irq_domain_free_irqs_common(domain, virq, nr_irqs); 534 + 535 + if (priv->info.shared_irq_cnt) 536 + rzg2l_irqc_shared_irq_free(priv, hwirq); 771 537 } 772 538 773 539 static const struct irq_domain_ops rzg2l_irqc_domain_ops = { 774 540 .alloc = rzg2l_irqc_alloc, 775 - .free = irq_domain_free_irqs_common, 541 + .free = rzg2l_irqc_free, 776 542 .translate = irq_domain_translate_twocell, 777 543 }; 778 544 ··· 812 520 unsigned int i; 813 521 int ret; 814 522 815 - for (i = 0; i < IRQC_NUM_IRQ; i++) { 523 + for (i = 0; i < priv->info.num_irq; i++) { 816 524 ret = of_irq_parse_one(np, i, &map); 817 525 if (ret) 818 526 return ret; ··· 824 532 } 825 533 826 534 static int rzg2l_irqc_common_probe(struct platform_device *pdev, struct device_node *parent, 827 - const struct irq_chip *irq_chip) 535 + const struct irq_chip *irq_chip, 536 + const struct irq_chip *tint_chip, 537 + const struct rzg2l_hw_info info) 828 538 { 829 539 struct irq_domain *irq_domain, *parent_domain; 830 540 struct device_node *node = pdev->dev.of_node; ··· 842 548 if (!rzg2l_irqc_data) 843 549 return -ENOMEM; 844 550 845 - rzg2l_irqc_data->irqchip = irq_chip; 551 + rzg2l_irqc_data->irq_chip = irq_chip; 552 + rzg2l_irqc_data->tint_chip = tint_chip; 846 553 847 554 rzg2l_irqc_data->base = devm_of_iomap(dev, dev->of_node, 0, NULL); 848 555 if (IS_ERR(rzg2l_irqc_data->base)) 849 556 return PTR_ERR(rzg2l_irqc_data->base); 557 + 558 + rzg2l_irqc_data->info = info; 559 + 560 + rzg2l_irqc_data->fwspec = devm_kcalloc(&pdev->dev, info.num_irq, 561 + sizeof(*rzg2l_irqc_data->fwspec), GFP_KERNEL); 562 + if (!rzg2l_irqc_data->fwspec) 563 + return -ENOMEM; 850 564 851 565 ret = rzg2l_irqc_parse_interrupts(rzg2l_irqc_data, node); 852 566 if (ret) ··· 876 574 877 575 raw_spin_lock_init(&rzg2l_irqc_data->lock); 878 576 879 - irq_domain = irq_domain_create_hierarchy(parent_domain, 0, IRQC_NUM_IRQ, dev_fwnode(dev), 577 + irq_domain = irq_domain_create_hierarchy(parent_domain, 0, info.num_irq, dev_fwnode(dev), 880 578 &rzg2l_irqc_domain_ops, rzg2l_irqc_data); 881 579 if (!irq_domain) { 882 - pm_runtime_put(dev); 580 + pm_runtime_put_sync(dev); 883 581 return -ENOMEM; 884 582 } 885 583 ··· 888 586 return 0; 889 587 } 890 588 589 + /* Mapping based on port index on Table 4.2-1 and GPIOINT on Table 4.6-7 */ 590 + static const u8 rzg3l_tssel_lut[] = { 591 + 83, 84, /* P20-P21 */ 592 + 7, 8, 9, 10, 11, 12, 13, /* P30-P36 */ 593 + 85, 86, 87, 88, 89, 90, 91, /* P50-P56 */ 594 + 92, 93, 94, 95, 96, 97, 98, /* P60-P66 */ 595 + 99, 100, 101, 102, 103, 104, 105, 106, /* P70-P77 */ 596 + 107, 108, 109, 110, 111, 112, /* P80-P85 */ 597 + 45, 46, 47, 48, 49, 50, 51, 52, /* PA0-PA7 */ 598 + 53, 54, 55, 56, 57, 58, 59, 60, /* PB0-PB7 */ 599 + 61, 62, 63, /* PC0-PC2 */ 600 + 64, 65, 66, 67, 68, 69, 70, 71, /* PD0-PD7 */ 601 + 72, 73, 74, 75, 76, 77, 78, 79, /* PE0-PE7 */ 602 + 80, 81, 82, /* PF0-PF2 */ 603 + 27, 28, 29, 30, 31, 32, 33, 34, /* PG0-PG7 */ 604 + 35, 36, 37, 38, 39, 40, /* PH0-PH5 */ 605 + 2, 3, 4, 5, 6, /* PJ0-PJ4 */ 606 + 41, 42, 43, 44, /* PK0-PK3 */ 607 + 14, 15, 16, 17, 26, /* PL0-PL4 */ 608 + 18, 19, 20, 21, 22, 23, 24, 25, /* PM0-PM7 */ 609 + 0, 1 /* PS0-PS1 */ 610 + }; 611 + 612 + static const struct rzg2l_hw_info rzg3l_hw_params = { 613 + .tssel_lut = rzg3l_tssel_lut, 614 + .irq_count = 16, 615 + .tint_start = IRQC_IRQ_START + 16, 616 + .num_irq = IRQC_IRQ_START + 16 + IRQC_TINT_COUNT, 617 + .shared_irq_cnt = IRQC_SHARED_IRQ_COUNT, 618 + }; 619 + 620 + static const struct rzg2l_hw_info rzg2l_hw_params = { 621 + .irq_count = 8, 622 + .tint_start = IRQC_IRQ_START + 8, 623 + .num_irq = IRQC_IRQ_START + 8 + IRQC_TINT_COUNT, 624 + }; 625 + 891 626 static int rzg2l_irqc_probe(struct platform_device *pdev, struct device_node *parent) 892 627 { 893 - return rzg2l_irqc_common_probe(pdev, parent, &rzg2l_irqc_chip); 628 + return rzg2l_irqc_common_probe(pdev, parent, &rzg2l_irqc_irq_chip, &rzg2l_irqc_tint_chip, 629 + rzg2l_hw_params); 630 + } 631 + 632 + static int rzg3l_irqc_probe(struct platform_device *pdev, struct device_node *parent) 633 + { 634 + return rzg2l_irqc_common_probe(pdev, parent, &rzg2l_irqc_irq_chip, &rzg2l_irqc_tint_chip, 635 + rzg3l_hw_params); 894 636 } 895 637 896 638 static int rzfive_irqc_probe(struct platform_device *pdev, struct device_node *parent) 897 639 { 898 - return rzg2l_irqc_common_probe(pdev, parent, &rzfive_irqc_chip); 640 + return rzg2l_irqc_common_probe(pdev, parent, &rzfive_irqc_irq_chip, &rzfive_irqc_tint_chip, 641 + rzg2l_hw_params); 899 642 } 900 643 901 644 IRQCHIP_PLATFORM_DRIVER_BEGIN(rzg2l_irqc) 902 645 IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_probe) 646 + IRQCHIP_MATCH("renesas,r9a08g046-irqc", rzg3l_irqc_probe) 903 647 IRQCHIP_MATCH("renesas,r9a07g043f-irqc", rzfive_irqc_probe) 904 648 IRQCHIP_PLATFORM_DRIVER_END(rzg2l_irqc) 905 649 MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
+371 -102
drivers/irqchip/irq-renesas-rzv2h.c
··· 12 12 #include <linux/bitfield.h> 13 13 #include <linux/cleanup.h> 14 14 #include <linux/err.h> 15 + #include <linux/interrupt.h> 15 16 #include <linux/io.h> 16 17 #include <linux/irqchip.h> 17 18 #include <linux/irqchip/irq-renesas-rzv2h.h> ··· 26 25 /* DT "interrupts" indexes */ 27 26 #define ICU_IRQ_START 1 28 27 #define ICU_IRQ_COUNT 16 29 - #define ICU_TINT_START (ICU_IRQ_START + ICU_IRQ_COUNT) 28 + #define ICU_IRQ_LAST (ICU_IRQ_START + ICU_IRQ_COUNT - 1) 29 + #define ICU_TINT_START (ICU_IRQ_LAST + 1) 30 30 #define ICU_TINT_COUNT 32 31 - #define ICU_NUM_IRQ (ICU_TINT_START + ICU_TINT_COUNT) 31 + #define ICU_TINT_LAST (ICU_TINT_START + ICU_TINT_COUNT - 1) 32 + #define ICU_CA55_INT_START (ICU_TINT_LAST + 1) 33 + #define ICU_CA55_INT_COUNT 4 34 + #define ICU_CA55_INT_LAST (ICU_CA55_INT_START + ICU_CA55_INT_COUNT - 1) 35 + #define ICU_ERR_INT_START (ICU_CA55_INT_LAST + 1) 36 + #define ICU_ERR_INT_COUNT 1 37 + #define ICU_ERR_INT_LAST (ICU_ERR_INT_START + ICU_ERR_INT_COUNT - 1) 38 + #define ICU_NUM_IRQ (ICU_ERR_INT_LAST + 1) 32 39 33 40 /* Registers */ 34 41 #define ICU_NSCNT 0x00 ··· 49 40 #define ICU_TSCLR 0x24 50 41 #define ICU_TITSR(k) (0x28 + (k) * 4) 51 42 #define ICU_TSSR(k) (0x30 + (k) * 4) 43 + #define ICU_BEISR(k) (0x70 + (k) * 4) 44 + #define ICU_BECLR(k) (0x80 + (k) * 4) 45 + #define ICU_EREISR(k) (0x90 + (k) * 4) 46 + #define ICU_ERCLR(k) (0xE0 + (k) * 4) 47 + #define ICU_SWINT 0x130 48 + #define ICU_ERINTA55CTL(k) (0x338 + (k) * 4) 49 + #define ICU_ERINTA55CRL(k) (0x348 + (k) * 4) 50 + #define ICU_ERINTA55MSK(k) (0x358 + (k) * 4) 51 + #define ICU_SWPE 0x370 52 52 #define ICU_DMkSELy(k, y) (0x420 + (k) * 0x20 + (y) * 4) 53 53 #define ICU_DMACKSELk(k) (0x500 + (k) * 4) 54 54 ··· 108 90 #define ICU_RZG3E_TSSEL_MAX_VAL 0x8c 109 91 #define ICU_RZV2H_TSSEL_MAX_VAL 0x55 110 92 93 + #define ICU_SWPE_NUM 16 94 + #define ICU_NUM_BE 4 95 + #define ICU_NUM_A55ERR 4 96 + 111 97 /** 112 98 * struct rzv2h_irqc_reg_cache - registers cache (necessary for suspend/resume) 113 99 * @nitsr: ICU_NITSR register ··· 130 108 * @t_offs: TINT offset 131 109 * @max_tssel: TSSEL max value 132 110 * @field_width: TSSR field width 111 + * @ecc_start: Start index of ECC RAM interrupts 112 + * @ecc_end: End index of ECC RAM interrupts 133 113 */ 134 114 struct rzv2h_hw_info { 135 115 const u8 *tssel_lut; 136 116 u16 t_offs; 137 117 u8 max_tssel; 138 118 u8 field_width; 119 + u8 ecc_start; 120 + u8 ecc_end; 139 121 }; 140 122 141 123 /* DMAC */ ··· 193 167 return data->domain->host_data; 194 168 } 195 169 196 - static void rzv2h_icu_eoi(struct irq_data *d) 170 + static void rzv2h_icu_tint_eoi(struct irq_data *d) 197 171 { 198 172 struct rzv2h_icu_priv *priv = irq_data_to_priv(d); 199 173 unsigned int hw_irq = irqd_to_hwirq(d); 200 174 unsigned int tintirq_nr; 201 175 u32 bit; 202 176 203 - scoped_guard(raw_spinlock, &priv->lock) { 204 - if (hw_irq >= ICU_TINT_START) { 205 - tintirq_nr = hw_irq - ICU_TINT_START; 206 - bit = BIT(tintirq_nr); 207 - if (!irqd_is_level_type(d)) 208 - writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR); 209 - } else if (hw_irq >= ICU_IRQ_START) { 210 - tintirq_nr = hw_irq - ICU_IRQ_START; 211 - bit = BIT(tintirq_nr); 212 - if (!irqd_is_level_type(d)) 213 - writel_relaxed(bit, priv->base + ICU_ISCLR); 214 - } else { 215 - writel_relaxed(ICU_NSCLR_NCLR, priv->base + ICU_NSCLR); 216 - } 177 + if (!irqd_is_level_type(d)) { 178 + tintirq_nr = hw_irq - ICU_TINT_START; 179 + bit = BIT(tintirq_nr); 180 + writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR); 217 181 } 182 + 183 + irq_chip_eoi_parent(d); 184 + } 185 + 186 + static void rzv2h_icu_irq_eoi(struct irq_data *d) 187 + { 188 + struct rzv2h_icu_priv *priv = irq_data_to_priv(d); 189 + unsigned int hw_irq = irqd_to_hwirq(d); 190 + unsigned int tintirq_nr; 191 + u32 bit; 192 + 193 + if (!irqd_is_level_type(d)) { 194 + tintirq_nr = hw_irq - ICU_IRQ_START; 195 + bit = BIT(tintirq_nr); 196 + writel_relaxed(bit, priv->base + ICU_ISCLR); 197 + } 198 + 199 + irq_chip_eoi_parent(d); 200 + } 201 + 202 + static void rzv2h_icu_nmi_eoi(struct irq_data *d) 203 + { 204 + struct rzv2h_icu_priv *priv = irq_data_to_priv(d); 205 + 206 + writel_relaxed(ICU_NSCLR_NCLR, priv->base + ICU_NSCLR); 218 207 219 208 irq_chip_eoi_parent(d); 220 209 } ··· 240 199 unsigned int hw_irq = irqd_to_hwirq(d); 241 200 u32 tint_nr, tssel_n, k, tssr; 242 201 u8 nr_tint; 243 - 244 - if (hw_irq < ICU_TINT_START) 245 - return; 246 202 247 203 tint_nr = hw_irq - ICU_TINT_START; 248 204 nr_tint = 32 / priv->info->field_width; ··· 263 225 writel_relaxed(BIT(tint_nr), priv->base + priv->info->t_offs + ICU_TSCLR); 264 226 } 265 227 266 - static void rzv2h_icu_irq_disable(struct irq_data *d) 228 + static void rzv2h_icu_tint_disable(struct irq_data *d) 267 229 { 268 230 irq_chip_disable_parent(d); 269 231 rzv2h_tint_irq_endisable(d, false); 270 232 } 271 233 272 - static void rzv2h_icu_irq_enable(struct irq_data *d) 234 + static void rzv2h_icu_tint_enable(struct irq_data *d) 273 235 { 274 236 rzv2h_tint_irq_endisable(d, true); 275 237 irq_chip_enable_parent(d); ··· 295 257 296 258 writel_relaxed(sense, priv->base + ICU_NITSR); 297 259 298 - return 0; 260 + return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 299 261 } 300 262 301 263 static void rzv2h_clear_irq_int(struct rzv2h_icu_priv *priv, unsigned int hwirq) ··· 345 307 return -EINVAL; 346 308 } 347 309 348 - guard(raw_spinlock)(&priv->lock); 349 - iitsr = readl_relaxed(priv->base + ICU_IITSR); 350 - iitsr &= ~ICU_IITSR_IITSEL_MASK(irq_nr); 351 - iitsr |= ICU_IITSR_IITSEL_PREP(sense, irq_nr); 352 - rzv2h_clear_irq_int(priv, hwirq); 353 - writel_relaxed(iitsr, priv->base + ICU_IITSR); 310 + scoped_guard(raw_spinlock, &priv->lock) { 311 + iitsr = readl_relaxed(priv->base + ICU_IITSR); 312 + iitsr &= ~ICU_IITSR_IITSEL_MASK(irq_nr); 313 + iitsr |= ICU_IITSR_IITSEL_PREP(sense, irq_nr); 314 + rzv2h_clear_irq_int(priv, hwirq); 315 + writel_relaxed(iitsr, priv->base + ICU_IITSR); 316 + } 354 317 355 - return 0; 318 + return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 356 319 } 357 320 358 321 static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq) ··· 428 389 titsr_k = ICU_TITSR_K(tint_nr); 429 390 titsel_n = ICU_TITSR_TITSEL_N(tint_nr); 430 391 431 - guard(raw_spinlock)(&priv->lock); 392 + scoped_guard(raw_spinlock, &priv->lock) { 393 + tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(tssr_k)); 394 + titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(titsr_k)); 432 395 433 - tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(tssr_k)); 434 - titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(titsr_k)); 396 + tssr_cur = field_get(ICU_TSSR_TSSEL_MASK(tssel_n, priv->info->field_width), tssr); 397 + titsr_cur = field_get(ICU_TITSR_TITSEL_MASK(titsel_n), titsr); 398 + if (tssr_cur == tint && titsr_cur == sense) 399 + goto set_parent_type; 435 400 436 - tssr_cur = field_get(ICU_TSSR_TSSEL_MASK(tssel_n, priv->info->field_width), tssr); 437 - titsr_cur = field_get(ICU_TITSR_TITSEL_MASK(titsel_n), titsr); 438 - if (tssr_cur == tint && titsr_cur == sense) 401 + tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n, priv->info->field_width) | tien); 402 + tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n, priv->info->field_width); 403 + 404 + writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k)); 405 + 406 + titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n); 407 + titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n); 408 + 409 + writel_relaxed(titsr, priv->base + priv->info->t_offs + ICU_TITSR(titsr_k)); 410 + 411 + rzv2h_clear_tint_int(priv, hwirq); 412 + 413 + writel_relaxed(tssr | tien, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k)); 414 + } 415 + set_parent_type: 416 + return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 417 + } 418 + 419 + static int rzv2h_icu_swint_set_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, 420 + bool state) 421 + { 422 + unsigned int hwirq = irqd_to_hwirq(d); 423 + struct rzv2h_icu_priv *priv; 424 + unsigned int bit; 425 + 426 + if (which != IRQCHIP_STATE_PENDING) 427 + return irq_chip_set_parent_state(d, which, state); 428 + 429 + if (!state) 439 430 return 0; 440 431 441 - tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n, priv->info->field_width) | tien); 442 - tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n, priv->info->field_width); 432 + priv = irq_data_to_priv(d); 433 + bit = BIT(hwirq - ICU_CA55_INT_START); 443 434 444 - writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k)); 445 - 446 - titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n); 447 - titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n); 448 - 449 - writel_relaxed(titsr, priv->base + priv->info->t_offs + ICU_TITSR(titsr_k)); 450 - 451 - rzv2h_clear_tint_int(priv, hwirq); 452 - 453 - writel_relaxed(tssr | tien, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k)); 435 + /* Trigger the software interrupt */ 436 + writel_relaxed(bit, priv->base + ICU_SWINT); 454 437 455 438 return 0; 456 439 } 457 440 458 - static int rzv2h_icu_set_type(struct irq_data *d, unsigned int type) 441 + static int rzv2h_icu_swpe_set_irqchip_state(struct irq_data *d, enum irqchip_irq_state which, 442 + bool state) 459 443 { 460 - unsigned int hw_irq = irqd_to_hwirq(d); 461 - int ret; 444 + struct rzv2h_icu_priv *priv; 445 + unsigned int bit; 446 + static u8 swpe; 462 447 463 - if (hw_irq >= ICU_TINT_START) 464 - ret = rzv2h_tint_set_type(d, type); 465 - else if (hw_irq >= ICU_IRQ_START) 466 - ret = rzv2h_irq_set_type(d, type); 467 - else 468 - ret = rzv2h_nmi_set_type(d, type); 448 + if (which != IRQCHIP_STATE_PENDING) 449 + return irq_chip_set_parent_state(d, which, state); 469 450 470 - if (ret) 471 - return ret; 451 + if (!state) 452 + return 0; 472 453 473 - return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 454 + priv = irq_data_to_priv(d); 455 + 456 + bit = BIT(swpe); 457 + /* 458 + * SWPE has 16 bits; the bit position is rotated on each trigger 459 + * and wraps around once all bits have been used. 460 + */ 461 + if (++swpe >= ICU_SWPE_NUM) 462 + swpe = 0; 463 + 464 + /* Trigger the pseudo error interrupt */ 465 + writel_relaxed(bit, priv->base + ICU_SWPE); 466 + 467 + return 0; 474 468 } 475 469 476 470 static int rzv2h_irqc_irq_suspend(void *data) ··· 544 472 .ops = &rzv2h_irqc_syscore_ops, 545 473 }; 546 474 547 - static const struct irq_chip rzv2h_icu_chip = { 475 + static const struct irq_chip rzv2h_icu_tint_chip = { 548 476 .name = "rzv2h-icu", 549 - .irq_eoi = rzv2h_icu_eoi, 477 + .irq_eoi = rzv2h_icu_tint_eoi, 550 478 .irq_mask = irq_chip_mask_parent, 551 479 .irq_unmask = irq_chip_unmask_parent, 552 - .irq_disable = rzv2h_icu_irq_disable, 553 - .irq_enable = rzv2h_icu_irq_enable, 480 + .irq_disable = rzv2h_icu_tint_disable, 481 + .irq_enable = rzv2h_icu_tint_enable, 554 482 .irq_get_irqchip_state = irq_chip_get_parent_state, 555 483 .irq_set_irqchip_state = irq_chip_set_parent_state, 556 484 .irq_retrigger = irq_chip_retrigger_hierarchy, 557 - .irq_set_type = rzv2h_icu_set_type, 485 + .irq_set_type = rzv2h_tint_set_type, 558 486 .irq_set_affinity = irq_chip_set_affinity_parent, 559 487 .flags = IRQCHIP_MASK_ON_SUSPEND | 560 488 IRQCHIP_SET_TYPE_MASKED | 561 489 IRQCHIP_SKIP_SET_WAKE, 562 490 }; 563 491 492 + static const struct irq_chip rzv2h_icu_irq_chip = { 493 + .name = "rzv2h-icu", 494 + .irq_eoi = rzv2h_icu_irq_eoi, 495 + .irq_mask = irq_chip_mask_parent, 496 + .irq_unmask = irq_chip_unmask_parent, 497 + .irq_disable = irq_chip_disable_parent, 498 + .irq_enable = irq_chip_enable_parent, 499 + .irq_get_irqchip_state = irq_chip_get_parent_state, 500 + .irq_set_irqchip_state = irq_chip_set_parent_state, 501 + .irq_retrigger = irq_chip_retrigger_hierarchy, 502 + .irq_set_type = rzv2h_irq_set_type, 503 + .irq_set_affinity = irq_chip_set_affinity_parent, 504 + .flags = IRQCHIP_MASK_ON_SUSPEND | 505 + IRQCHIP_SET_TYPE_MASKED | 506 + IRQCHIP_SKIP_SET_WAKE, 507 + }; 508 + 509 + static const struct irq_chip rzv2h_icu_nmi_chip = { 510 + .name = "rzv2h-icu", 511 + .irq_eoi = rzv2h_icu_nmi_eoi, 512 + .irq_mask = irq_chip_mask_parent, 513 + .irq_unmask = irq_chip_unmask_parent, 514 + .irq_disable = irq_chip_disable_parent, 515 + .irq_enable = irq_chip_enable_parent, 516 + .irq_get_irqchip_state = irq_chip_get_parent_state, 517 + .irq_set_irqchip_state = irq_chip_set_parent_state, 518 + .irq_retrigger = irq_chip_retrigger_hierarchy, 519 + .irq_set_type = rzv2h_nmi_set_type, 520 + .irq_set_affinity = irq_chip_set_affinity_parent, 521 + .flags = IRQCHIP_MASK_ON_SUSPEND | 522 + IRQCHIP_SET_TYPE_MASKED | 523 + IRQCHIP_SKIP_SET_WAKE, 524 + }; 525 + 526 + static const struct irq_chip rzv2h_icu_swint_chip = { 527 + .name = "rzv2h-icu", 528 + .irq_eoi = irq_chip_eoi_parent, 529 + .irq_mask = irq_chip_mask_parent, 530 + .irq_unmask = irq_chip_unmask_parent, 531 + .irq_disable = irq_chip_disable_parent, 532 + .irq_enable = irq_chip_enable_parent, 533 + .irq_get_irqchip_state = irq_chip_get_parent_state, 534 + .irq_set_irqchip_state = rzv2h_icu_swint_set_irqchip_state, 535 + .irq_retrigger = irq_chip_retrigger_hierarchy, 536 + .irq_set_type = irq_chip_set_type_parent, 537 + .irq_set_affinity = irq_chip_set_affinity_parent, 538 + .flags = IRQCHIP_MASK_ON_SUSPEND | 539 + IRQCHIP_SET_TYPE_MASKED | 540 + IRQCHIP_SKIP_SET_WAKE, 541 + }; 542 + 543 + static const struct irq_chip rzv2h_icu_swpe_err_chip = { 544 + .name = "rzv2h-icu", 545 + .irq_eoi = irq_chip_eoi_parent, 546 + .irq_mask = irq_chip_mask_parent, 547 + .irq_unmask = irq_chip_unmask_parent, 548 + .irq_disable = irq_chip_disable_parent, 549 + .irq_enable = irq_chip_enable_parent, 550 + .irq_get_irqchip_state = irq_chip_get_parent_state, 551 + .irq_set_irqchip_state = rzv2h_icu_swpe_set_irqchip_state, 552 + .irq_retrigger = irq_chip_retrigger_hierarchy, 553 + .irq_set_type = irq_chip_set_type_parent, 554 + .irq_set_affinity = irq_chip_set_affinity_parent, 555 + .flags = IRQCHIP_MASK_ON_SUSPEND | 556 + IRQCHIP_SET_TYPE_MASKED | 557 + IRQCHIP_SKIP_SET_WAKE, 558 + }; 559 + 560 + #define hwirq_within(hwirq, which) ((hwirq) >= which##_START && (hwirq) <= which##_LAST) 561 + 564 562 static int rzv2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, 565 563 void *arg) 566 564 { 567 565 struct rzv2h_icu_priv *priv = domain->host_data; 566 + const struct irq_chip *chip; 568 567 unsigned long tint = 0; 569 568 irq_hw_number_t hwirq; 570 569 unsigned int type; ··· 651 508 * hwirq is embedded in bits 0-15. 652 509 * TINT is embedded in bits 16-31. 653 510 */ 654 - if (hwirq >= ICU_TINT_START) { 655 - tint = ICU_TINT_EXTRACT_GPIOINT(hwirq); 511 + tint = ICU_TINT_EXTRACT_GPIOINT(hwirq); 512 + if (tint || hwirq_within(hwirq, ICU_TINT)) { 656 513 hwirq = ICU_TINT_EXTRACT_HWIRQ(hwirq); 657 514 658 - if (hwirq < ICU_TINT_START) 515 + if (!hwirq_within(hwirq, ICU_TINT)) 659 516 return -EINVAL; 517 + chip = &rzv2h_icu_tint_chip; 518 + } else if (hwirq_within(hwirq, ICU_IRQ)) { 519 + chip = &rzv2h_icu_irq_chip; 520 + } else if (hwirq_within(hwirq, ICU_CA55_INT)) { 521 + chip = &rzv2h_icu_swint_chip; 522 + } else if (hwirq_within(hwirq, ICU_ERR_INT)) { 523 + chip = &rzv2h_icu_swpe_err_chip; 524 + } else { 525 + chip = &rzv2h_icu_nmi_chip; 660 526 } 661 527 662 528 if (hwirq > (ICU_NUM_IRQ - 1)) 663 529 return -EINVAL; 664 530 665 - ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &rzv2h_icu_chip, 666 - (void *)(uintptr_t)tint); 531 + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, chip, (void *)(uintptr_t)tint); 667 532 if (ret) 668 533 return ret; 669 534 ··· 701 550 return 0; 702 551 } 703 552 553 + static irqreturn_t rzv2h_icu_error_irq(int irq, void *data) 554 + { 555 + struct rzv2h_icu_priv *priv = data; 556 + const struct rzv2h_hw_info *hw_info = priv->info; 557 + void __iomem *base = priv->base; 558 + unsigned int k; 559 + u32 st; 560 + 561 + /* 1) Bus errors (BEISR0..3) */ 562 + for (k = 0; k < ICU_NUM_BE; k++) { 563 + st = readl(base + ICU_BEISR(k)); 564 + if (!st) 565 + continue; 566 + 567 + writel_relaxed(st, base + ICU_BECLR(k)); 568 + pr_warn("rzv2h-icu: BUS error k=%u status=0x%08x\n", k, st); 569 + } 570 + 571 + /* 2) ECC RAM errors (EREISR0..X) */ 572 + for (k = hw_info->ecc_start; k <= hw_info->ecc_end; k++) { 573 + st = readl(base + ICU_EREISR(k)); 574 + if (!st) 575 + continue; 576 + 577 + writel_relaxed(st, base + ICU_ERCLR(k)); 578 + pr_warn("rzv2h-icu: ECC error k=%u status=0x%08x\n", k, st); 579 + } 580 + 581 + /* 3) IP/CA55 error interrupt status (ERINTA55CTL0..3) */ 582 + for (k = 0; k < ICU_NUM_A55ERR; k++) { 583 + st = readl(base + ICU_ERINTA55CTL(k)); 584 + if (!st) 585 + continue; 586 + 587 + /* there is no relation with status bits so clear all the interrupts */ 588 + writel_relaxed(0xffffffff, base + ICU_ERINTA55CRL(k)); 589 + pr_warn("rzv2h-icu: IP/CA55 error k=%u status=0x%08x\n", k, st); 590 + } 591 + 592 + return IRQ_HANDLED; 593 + } 594 + 595 + static irqreturn_t rzv2h_icu_swint_irq(int irq, void *data) 596 + { 597 + unsigned int cpu = (uintptr_t)data; 598 + 599 + pr_info("SWINT interrupt for CA55 core %u\n", cpu); 600 + return IRQ_HANDLED; 601 + } 602 + 603 + static int rzv2h_icu_setup_irqs(struct platform_device *pdev, struct irq_domain *irq_domain) 604 + { 605 + const struct rzv2h_hw_info *hw_info = rzv2h_icu_data->info; 606 + bool irq_inject = IS_ENABLED(CONFIG_GENERIC_IRQ_INJECTION); 607 + void __iomem *base = rzv2h_icu_data->base; 608 + struct device *dev = &pdev->dev; 609 + struct irq_fwspec fwspec; 610 + unsigned int i, virq; 611 + int ret; 612 + 613 + for (i = 0; i < ICU_CA55_INT_COUNT && irq_inject; i++) { 614 + fwspec.fwnode = irq_domain->fwnode; 615 + fwspec.param_count = 2; 616 + fwspec.param[0] = ICU_CA55_INT_START + i; 617 + fwspec.param[1] = IRQ_TYPE_EDGE_RISING; 618 + 619 + virq = irq_create_fwspec_mapping(&fwspec); 620 + if (!virq) { 621 + return dev_err_probe(dev, -EINVAL, 622 + "failed to create int-ca55-%u IRQ mapping\n", i); 623 + } 624 + 625 + ret = devm_request_irq(dev, virq, rzv2h_icu_swint_irq, 0, dev_name(dev), 626 + (void *)(uintptr_t)i); 627 + if (ret) 628 + return dev_err_probe(dev, ret, "Failed to request int-ca55-%u IRQ\n", i); 629 + } 630 + 631 + /* Unmask and clear all IP/CA55 error interrupts */ 632 + for (i = 0; i < ICU_NUM_A55ERR; i++) { 633 + writel_relaxed(0xffffff, base + ICU_ERINTA55CRL(i)); 634 + writel_relaxed(0x0, base + ICU_ERINTA55MSK(i)); 635 + } 636 + 637 + /* Clear all Bus errors */ 638 + for (i = 0; i < ICU_NUM_BE; i++) 639 + writel_relaxed(0xffffffff, base + ICU_BECLR(i)); 640 + 641 + /* Clear all ECCRAM errors */ 642 + for (i = hw_info->ecc_start; i <= hw_info->ecc_end; i++) 643 + writel_relaxed(0xffffffff, base + ICU_ERCLR(i)); 644 + 645 + fwspec.fwnode = irq_domain->fwnode; 646 + fwspec.param_count = 2; 647 + fwspec.param[0] = ICU_ERR_INT_START; 648 + fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; 649 + 650 + virq = irq_create_fwspec_mapping(&fwspec); 651 + if (!virq) 652 + return dev_err_probe(dev, -EINVAL, "failed to create icu-error-ca55 IRQ mapping\n"); 653 + 654 + ret = devm_request_irq(dev, virq, rzv2h_icu_error_irq, 0, dev_name(dev), rzv2h_icu_data); 655 + if (ret) 656 + return dev_err_probe(dev, ret, "Failed to request icu-error-ca55 IRQ\n"); 657 + 658 + return 0; 659 + } 660 + 704 661 static int rzv2h_icu_probe_common(struct platform_device *pdev, struct device_node *parent, 705 662 const struct rzv2h_hw_info *hw_info) 706 663 { 707 664 struct irq_domain *irq_domain, *parent_domain; 708 665 struct device_node *node = pdev->dev.of_node; 666 + struct device *dev = &pdev->dev; 709 667 struct reset_control *resetn; 710 668 int ret; 711 669 712 670 parent_domain = irq_find_host(parent); 713 - if (!parent_domain) { 714 - dev_err(&pdev->dev, "cannot find parent domain\n"); 715 - return -ENODEV; 716 - } 671 + if (!parent_domain) 672 + return dev_err_probe(dev, -ENODEV, "cannot find parent domain\n"); 717 673 718 - rzv2h_icu_data = devm_kzalloc(&pdev->dev, sizeof(*rzv2h_icu_data), GFP_KERNEL); 674 + rzv2h_icu_data = devm_kzalloc(dev, sizeof(*rzv2h_icu_data), GFP_KERNEL); 719 675 if (!rzv2h_icu_data) 720 676 return -ENOMEM; 721 677 722 678 platform_set_drvdata(pdev, rzv2h_icu_data); 723 679 724 - rzv2h_icu_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); 680 + rzv2h_icu_data->base = devm_of_iomap(dev, node, 0, NULL); 725 681 if (IS_ERR(rzv2h_icu_data->base)) 726 682 return PTR_ERR(rzv2h_icu_data->base); 727 683 728 684 ret = rzv2h_icu_parse_interrupts(rzv2h_icu_data, node); 729 - if (ret) { 730 - dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret); 731 - return ret; 732 - } 685 + if (ret) 686 + return dev_err_probe(dev, ret, "cannot parse interrupts\n"); 733 687 734 - resetn = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL); 735 - if (IS_ERR(resetn)) { 736 - ret = PTR_ERR(resetn); 737 - dev_err(&pdev->dev, "failed to acquire deasserted reset: %d\n", ret); 738 - return ret; 739 - } 688 + resetn = devm_reset_control_get_exclusive_deasserted(dev, NULL); 689 + if (IS_ERR(resetn)) 690 + return dev_err_probe(dev, PTR_ERR(resetn), "failed to acquire deasserted reset\n"); 740 691 741 - ret = devm_pm_runtime_enable(&pdev->dev); 742 - if (ret < 0) { 743 - dev_err(&pdev->dev, "devm_pm_runtime_enable failed, %d\n", ret); 744 - return ret; 745 - } 692 + ret = devm_pm_runtime_enable(dev); 693 + if (ret < 0) 694 + return dev_err_probe(dev, ret, "devm_pm_runtime_enable failed\n"); 746 695 747 - ret = pm_runtime_resume_and_get(&pdev->dev); 748 - if (ret < 0) { 749 - dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret); 750 - return ret; 751 - } 696 + ret = pm_runtime_resume_and_get(dev); 697 + if (ret < 0) 698 + return dev_err_probe(dev, ret, "pm_runtime_resume_and_get failed\n"); 752 699 753 700 raw_spin_lock_init(&rzv2h_icu_data->lock); 754 701 755 702 irq_domain = irq_domain_create_hierarchy(parent_domain, 0, ICU_NUM_IRQ, 756 - dev_fwnode(&pdev->dev), &rzv2h_icu_domain_ops, 703 + dev_fwnode(dev), &rzv2h_icu_domain_ops, 757 704 rzv2h_icu_data); 758 705 if (!irq_domain) { 759 - dev_err(&pdev->dev, "failed to add irq domain\n"); 706 + dev_err(dev, "failed to add irq domain\n"); 760 707 ret = -ENOMEM; 761 708 goto pm_put; 762 709 } ··· 863 614 864 615 register_syscore(&rzv2h_irqc_syscore); 865 616 617 + ret = rzv2h_icu_setup_irqs(pdev, irq_domain); 618 + if (ret) 619 + goto pm_put; 620 + 866 621 /* 867 622 * coccicheck complains about a missing put_device call before returning, but it's a false 868 - * positive. We still need &pdev->dev after successfully returning from this function. 623 + * positive. We still need dev after successfully returning from this function. 869 624 */ 870 625 return 0; 871 626 872 627 pm_put: 873 - pm_runtime_put_sync(&pdev->dev); 874 - 628 + pm_runtime_put_sync(dev); 875 629 return ret; 876 630 } 877 631 ··· 909 657 .t_offs = ICU_RZG3E_TINT_OFFSET, 910 658 .max_tssel = ICU_RZG3E_TSSEL_MAX_VAL, 911 659 .field_width = 16, 660 + .ecc_start = 1, 661 + .ecc_end = 4, 662 + }; 663 + 664 + static const struct rzv2h_hw_info rzv2n_hw_params = { 665 + .t_offs = 0, 666 + .max_tssel = ICU_RZV2H_TSSEL_MAX_VAL, 667 + .field_width = 8, 668 + .ecc_start = 0, 669 + .ecc_end = 2, 912 670 }; 913 671 914 672 static const struct rzv2h_hw_info rzv2h_hw_params = { 915 673 .t_offs = 0, 916 674 .max_tssel = ICU_RZV2H_TSSEL_MAX_VAL, 917 675 .field_width = 8, 676 + .ecc_start = 0, 677 + .ecc_end = 11, 918 678 }; 919 679 920 680 static int rzg3e_icu_probe(struct platform_device *pdev, struct device_node *parent) 921 681 { 922 682 return rzv2h_icu_probe_common(pdev, parent, &rzg3e_hw_params); 683 + } 684 + 685 + static int rzv2n_icu_probe(struct platform_device *pdev, struct device_node *parent) 686 + { 687 + return rzv2h_icu_probe_common(pdev, parent, &rzv2n_hw_params); 923 688 } 924 689 925 690 static int rzv2h_icu_probe(struct platform_device *pdev, struct device_node *parent) ··· 946 677 947 678 IRQCHIP_PLATFORM_DRIVER_BEGIN(rzv2h_icu) 948 679 IRQCHIP_MATCH("renesas,r9a09g047-icu", rzg3e_icu_probe) 949 - IRQCHIP_MATCH("renesas,r9a09g056-icu", rzv2h_icu_probe) 680 + IRQCHIP_MATCH("renesas,r9a09g056-icu", rzv2n_icu_probe) 950 681 IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_probe) 951 682 IRQCHIP_PLATFORM_DRIVER_END(rzv2h_icu) 952 683 MODULE_AUTHOR("Fabrizio Castro <fabrizio.castro.jz@renesas.com>");