.../amlogic,meson-gpio-intc.yaml | 3 + .../interrupt-controller/aspeed,ast2700-intc.yaml | 13 +- .../interrupt-controller/sifive,plic-1.0.0.yaml | 4 + .../thead,c900-aclint-mswi.yaml | 17 ++- .../thead,c900-aclint-sswi.yaml | 4 + .../devicetree/bindings/vendor-prefixes.yaml | 2 + drivers/irqchip/Kconfig | 6 +- drivers/irqchip/irq-aclint-sswi.c | 3 +- drivers/irqchip/irq-bcm2712-mip.c | 11 +- drivers/irqchip/irq-bcm7038-l1.c | 17 +-- drivers/irqchip/irq-bcm7120-l2.c | 31 ++--- drivers/irqchip/irq-brcmstb-l2.c | 25 ++-- drivers/irqchip/irq-imx-mu-msi.c | 28 ++-- drivers/irqchip/irq-mchp-eic.c | 5 +- drivers/irqchip/irq-meson-gpio.c | 17 ++- drivers/irqchip/irq-mvebu-pic.c | 2 - drivers/irqchip/irq-qcom-mpm.c | 6 +- drivers/irqchip/irq-renesas-rzg2l.c | 37 ++--- drivers/irqchip/irq-renesas-rzv2h.c | 32 ++--- drivers/irqchip/irq-riscv-imsic-early.c | 11 +- drivers/irqchip/irq-riscv-imsic-platform.c | 4 +- drivers/irqchip/irq-riscv-imsic-state.c | 20 +-- drivers/irqchip/irq-riscv-imsic-state.h | 4 +- drivers/irqchip/irq-sifive-plic.c | 149 +++++++++++++++++---- drivers/irqchip/irq-starfive-jh8100-intc.c | 6 +- drivers/irqchip/irq-ts4800.c | 1 - drivers/irqchip/irqchip.c | 10 +- drivers/irqchip/qcom-irq-combiner.c | 6 +- drivers/irqchip/qcom-pdc.c | 5 +- include/linux/irqchip.h | 8 +- 30 files changed, 264 insertions(+), 223 deletions(-)
Linus,
please pull the latest irq/drivers branch from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-drivers-2025-11-30
up to: fc584d871c16: irqchip/meson-gpio: Add support for Amlogic S6 S7 and S7D SoCs
Boring updates for interrupt drivers:
- Support for a couple of new ARM64 and RISCV SoC variants and their
magic interrupt controllers which either can reuse existing code or
require quirks due to a botched hardware implementation.
- More section mismatch fixes.
- The usual cleanups and fixes all over the place.
Thanks,
tglx
------------------>
Charles Mirabile (4):
dt-bindings: interrupt-controller: Add UltraRISC DP1000 PLIC
irqchip/sifive-plic: Cache the interrupt enable state
irqchip/sifive-plic: Add support for UltraRISC DP1000 PLIC
irqchip/sifive-plic: Fix call to __plic_toggle() in M-Mode code path
Johan Hovold (16):
irqchip/bcm2712-mip: Fix OF node reference imbalance
irqchip/bcm2712-mip: Fix section mismatch
irqchip/irq-bcm7038-l1: Fix section mismatch
irqchip/irq-bcm7120-l2: Fix section mismatch
irqchip/irq-brcmstb-l2: Fix section mismatch
irqchip/imx-mu-msi: Fix section mismatch
irqchip/renesas-rzg2l: Fix section mismatch
irqchip/starfive-jh8100: Fix section mismatch
irqchip/qcom-irq-combiner: Fix section mismatch
irqchip: Drop leftover brackets
irqchip: Pass platform device to platform drivers
irqchip: Enable compile testing of Broadcom drivers
irqchip/meson-gpio: Drop unused module alias
irqchip/mvebu-pic: Drop unused module alias
irqchip/ts4800: Drop unused module alias
irqchip/qcom-irq-combiner: Rename driver structure
Junhui Liu (4):
dt-bindings: interrupt-controller: Add Anlogic DR1V90 PLIC
dt-bindings: interrupt-controller: Add Anlogic DR1V90 ACLINT MSWI
dt-bindings: interrupt-controller: Add Anlogic DR1V90 ACLINT SSWI
irqchip/aclint-sswi: Add Nuclei UX900 support
Krzysztof Kozlowski (1):
irqchip/irq-bcm7038-l1: Remove unused reg_mask_status()
Lucas Zampieri (1):
dt-bindings: vendor-prefixes: Add UltraRISC
Ryan Chen (1):
dt-bindings: interrupt-controller: aspeed,ast2700: Correct #interrupt-cells and interrupts count
Samuel Holland (3):
irqchip/riscv-imsic: Remove redundant irq_data lookups
irqchip/riscv-imsic: Embed the vector array in lpriv
irqchip/riscv-imsic: Inline imsic_vector_from_local_id()
Xianwei Zhao (2):
dt-bindings: interrupt-controller: Add support for Amlogic S6 S7 and S7D SoCs
irqchip/meson-gpio: Add support for Amlogic S6 S7 and S7D SoCs
.../amlogic,meson-gpio-intc.yaml | 3 +
.../interrupt-controller/aspeed,ast2700-intc.yaml | 13 +-
.../interrupt-controller/sifive,plic-1.0.0.yaml | 4 +
.../thead,c900-aclint-mswi.yaml | 17 ++-
.../thead,c900-aclint-sswi.yaml | 4 +
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
drivers/irqchip/Kconfig | 6 +-
drivers/irqchip/irq-aclint-sswi.c | 3 +-
drivers/irqchip/irq-bcm2712-mip.c | 11 +-
drivers/irqchip/irq-bcm7038-l1.c | 17 +--
drivers/irqchip/irq-bcm7120-l2.c | 31 ++---
drivers/irqchip/irq-brcmstb-l2.c | 25 ++--
drivers/irqchip/irq-imx-mu-msi.c | 28 ++--
drivers/irqchip/irq-mchp-eic.c | 5 +-
drivers/irqchip/irq-meson-gpio.c | 17 ++-
drivers/irqchip/irq-mvebu-pic.c | 2 -
drivers/irqchip/irq-qcom-mpm.c | 6 +-
drivers/irqchip/irq-renesas-rzg2l.c | 37 ++---
drivers/irqchip/irq-renesas-rzv2h.c | 32 ++---
drivers/irqchip/irq-riscv-imsic-early.c | 11 +-
drivers/irqchip/irq-riscv-imsic-platform.c | 4 +-
drivers/irqchip/irq-riscv-imsic-state.c | 20 +--
drivers/irqchip/irq-riscv-imsic-state.h | 4 +-
drivers/irqchip/irq-sifive-plic.c | 149 +++++++++++++++++----
drivers/irqchip/irq-starfive-jh8100-intc.c | 6 +-
drivers/irqchip/irq-ts4800.c | 1 -
drivers/irqchip/irqchip.c | 10 +-
drivers/irqchip/qcom-irq-combiner.c | 6 +-
drivers/irqchip/qcom-pdc.c | 5 +-
include/linux/irqchip.h | 8 +-
30 files changed, 264 insertions(+), 223 deletions(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
index 3d60d9e9e208..d0fad930de9d 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.yaml
@@ -39,6 +39,9 @@ properties:
- amlogic,a4-gpio-ao-intc
- amlogic,a5-gpio-intc
- amlogic,c3-gpio-intc
+ - amlogic,s6-gpio-intc
+ - amlogic,s7-gpio-intc
+ - amlogic,s7d-gpio-intc
- amlogic,t7-gpio-intc
- const: amlogic,meson-gpio-intc
diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml
index 55636d06a674..999df5b905c5 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2700-intc.yaml
@@ -25,13 +25,14 @@ properties:
interrupt-controller: true
'#interrupt-cells':
- const: 2
+ const: 1
description:
The first cell is the IRQ number, the second cell is the trigger
type as defined in interrupt.txt in this directory.
interrupts:
- maxItems: 6
+ minItems: 1
+ maxItems: 10
description: |
Depend to which INTC0 or INTC1 used.
INTC0 and INTC1 are two kinds of interrupt controller with enable and raw
@@ -74,13 +75,17 @@ examples:
interrupt-controller@12101b00 {
compatible = "aspeed,ast2700-intc-ic";
reg = <0 0x12101b00 0 0x10>;
- #interrupt-cells = <2>;
+ #interrupt-cells = <1>;
interrupt-controller;
interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
};
};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
index f683d696909b..6fdb7ae9e85a 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
@@ -58,6 +58,7 @@ properties:
- const: andestech,nceplic100
- items:
- enum:
+ - anlogic,dr1v90-plic
- canaan,k210-plic
- eswin,eic7700-plic
- sifive,fu540-c000-plic
@@ -75,6 +76,9 @@ properties:
- sophgo,sg2044-plic
- thead,th1520-plic
- const: thead,c900-plic
+ - items:
+ - const: ultrarisc,dp1000-plic
+ - const: ultrarisc,cp100-plic
- items:
- const: sifive,plic-1.0.0
- const: riscv,plic0
diff --git a/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml
index d6fb08a54167..62fd220e126e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-mswi.yaml
@@ -4,18 +4,23 @@
$id: http://devicetree.org/schemas/interrupt-controller/thead,c900-aclint-mswi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Sophgo sg2042 CLINT Machine-level Software Interrupt Device
+title: ACLINT Machine-level Software Interrupt Device
maintainers:
- Inochi Amaoto <inochiama@outlook.com>
properties:
compatible:
- items:
- - enum:
- - sophgo,sg2042-aclint-mswi
- - sophgo,sg2044-aclint-mswi
- - const: thead,c900-aclint-mswi
+ oneOf:
+ - items:
+ - enum:
+ - sophgo,sg2042-aclint-mswi
+ - sophgo,sg2044-aclint-mswi
+ - const: thead,c900-aclint-mswi
+ - items:
+ - enum:
+ - anlogic,dr1v90-aclint-mswi
+ - const: nuclei,ux900-aclint-mswi
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml
index c1ab865fcd64..d02c6886283a 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/thead,c900-aclint-sswi.yaml
@@ -30,6 +30,10 @@ properties:
- const: thead,c900-aclint-sswi
- items:
- const: mips,p8700-aclint-sswi
+ - items:
+ - enum:
+ - anlogic,dr1v90-aclint-sswi
+ - const: nuclei,ux900-aclint-sswi
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index f1d1882009ba..647746e6f75f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1705,6 +1705,8 @@ patternProperties:
description: Universal Scientific Industrial Co., Ltd.
"^usr,.*":
description: U.S. Robotics Corporation
+ "^ultrarisc,.*":
+ description: UltraRISC Technology Co., Ltd.
"^ultratronik,.*":
description: Ultratronik GmbH
"^utoo,.*":
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a61c6dc63c29..9b7153777688 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -151,7 +151,7 @@ config BCM6345_L1_IRQ
config BCM7038_L1_IRQ
tristate "Broadcom STB 7038-style L1/L2 interrupt controller driver"
- depends on ARCH_BRCMSTB || BMIPS_GENERIC
+ depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
default ARCH_BRCMSTB || BMIPS_GENERIC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
@@ -159,14 +159,14 @@ config BCM7038_L1_IRQ
config BCM7120_L2_IRQ
tristate "Broadcom STB 7120-style L2 interrupt controller driver"
- depends on ARCH_BRCMSTB || BMIPS_GENERIC
+ depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
default ARCH_BRCMSTB || BMIPS_GENERIC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
config BRCMSTB_L2_IRQ
tristate "Broadcom STB generic L2 interrupt controller driver"
- depends on ARCH_BCM2835 || ARCH_BRCMSTB || BMIPS_GENERIC
+ depends on ARCH_BCM2835 || ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
default ARCH_BCM2835 || ARCH_BRCMSTB || BMIPS_GENERIC
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
diff --git a/drivers/irqchip/irq-aclint-sswi.c b/drivers/irqchip/irq-aclint-sswi.c
index 93e28e9f281f..fee30f3bc5ac 100644
--- a/drivers/irqchip/irq-aclint-sswi.c
+++ b/drivers/irqchip/irq-aclint-sswi.c
@@ -175,7 +175,8 @@ static int __init generic_aclint_sswi_early_probe(struct device_node *node,
{
return generic_aclint_sswi_probe(&node->fwnode);
}
-IRQCHIP_DECLARE(generic_aclint_sswi, "mips,p8700-aclint-sswi", generic_aclint_sswi_early_probe);
+IRQCHIP_DECLARE(mips_p8700_sswi, "mips,p8700-aclint-sswi", generic_aclint_sswi_early_probe);
+IRQCHIP_DECLARE(nuclei_ux900_sswi, "nuclei,ux900-aclint-sswi", generic_aclint_sswi_early_probe);
/* THEAD variant */
#define THEAD_C9XX_CSR_SXSTATUS 0x5c0
diff --git a/drivers/irqchip/irq-bcm2712-mip.c b/drivers/irqchip/irq-bcm2712-mip.c
index 9bd7bc0bf6d5..4761974ad650 100644
--- a/drivers/irqchip/irq-bcm2712-mip.c
+++ b/drivers/irqchip/irq-bcm2712-mip.c
@@ -232,17 +232,12 @@ static int mip_parse_dt(struct mip_priv *mip, struct device_node *np)
return ret;
}
-static int __init mip_of_msi_init(struct device_node *node, struct device_node *parent)
+static int mip_msi_probe(struct platform_device *pdev, struct device_node *parent)
{
- struct platform_device *pdev;
+ struct device_node *node = pdev->dev.of_node;
struct mip_priv *mip;
int ret;
- pdev = of_find_device_by_node(node);
- of_node_put(node);
- if (!pdev)
- return -EPROBE_DEFER;
-
mip = kzalloc(sizeof(*mip), GFP_KERNEL);
if (!mip)
return -ENOMEM;
@@ -285,7 +280,7 @@ static int __init mip_of_msi_init(struct device_node *node, struct device_node *
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(mip_msi)
-IRQCHIP_MATCH("brcm,bcm2712-mip", mip_of_msi_init)
+IRQCHIP_MATCH("brcm,bcm2712-mip", mip_msi_probe)
IRQCHIP_PLATFORM_DRIVER_END(mip_msi)
MODULE_DESCRIPTION("Broadcom BCM2712 MSI-X interrupt controller");
MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
index 04fac0cc857f..ea1446c0a09c 100644
--- a/drivers/irqchip/irq-bcm7038-l1.c
+++ b/drivers/irqchip/irq-bcm7038-l1.c
@@ -82,12 +82,6 @@ static inline unsigned int reg_status(struct bcm7038_l1_chip *intc,
return (0 * intc->n_words + word) * sizeof(u32);
}
-static inline unsigned int reg_mask_status(struct bcm7038_l1_chip *intc,
- unsigned int word)
-{
- return (1 * intc->n_words + word) * sizeof(u32);
-}
-
static inline unsigned int reg_mask_set(struct bcm7038_l1_chip *intc,
unsigned int word)
{
@@ -219,9 +213,8 @@ static int bcm7038_l1_set_affinity(struct irq_data *d,
}
#endif
-static int __init bcm7038_l1_init_one(struct device_node *dn,
- unsigned int idx,
- struct bcm7038_l1_chip *intc)
+static int bcm7038_l1_init_one(struct device_node *dn, unsigned int idx,
+ struct bcm7038_l1_chip *intc)
{
struct resource res;
resource_size_t sz;
@@ -395,9 +388,9 @@ static const struct irq_domain_ops bcm7038_l1_domain_ops = {
.map = bcm7038_l1_map,
};
-static int __init bcm7038_l1_of_init(struct device_node *dn,
- struct device_node *parent)
+static int bcm7038_l1_probe(struct platform_device *pdev, struct device_node *parent)
{
+ struct device_node *dn = pdev->dev.of_node;
struct bcm7038_l1_chip *intc;
int idx, ret;
@@ -455,7 +448,7 @@ static int __init bcm7038_l1_of_init(struct device_node *dn,
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(bcm7038_l1)
-IRQCHIP_MATCH("brcm,bcm7038-l1-intc", bcm7038_l1_of_init)
+IRQCHIP_MATCH("brcm,bcm7038-l1-intc", bcm7038_l1_probe)
IRQCHIP_PLATFORM_DRIVER_END(bcm7038_l1)
MODULE_DESCRIPTION("Broadcom STB 7038-style L1/L2 interrupt controller");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c
index ff22c3104401..518c9d4366a5 100644
--- a/drivers/irqchip/irq-bcm7120-l2.c
+++ b/drivers/irqchip/irq-bcm7120-l2.c
@@ -143,8 +143,7 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn,
return 0;
}
-static int __init bcm7120_l2_intc_iomap_7120(struct device_node *dn,
- struct bcm7120_l2_intc_data *data)
+static int bcm7120_l2_intc_iomap_7120(struct device_node *dn, struct bcm7120_l2_intc_data *data)
{
int ret;
@@ -177,8 +176,7 @@ static int __init bcm7120_l2_intc_iomap_7120(struct device_node *dn,
return 0;
}
-static int __init bcm7120_l2_intc_iomap_3380(struct device_node *dn,
- struct bcm7120_l2_intc_data *data)
+static int bcm7120_l2_intc_iomap_3380(struct device_node *dn, struct bcm7120_l2_intc_data *data)
{
unsigned int gc_idx;
@@ -208,15 +206,14 @@ static int __init bcm7120_l2_intc_iomap_3380(struct device_node *dn,
return 0;
}
-static int __init bcm7120_l2_intc_probe(struct device_node *dn,
- struct device_node *parent,
+static int bcm7120_l2_intc_probe(struct platform_device *pdev, struct device_node *parent,
int (*iomap_regs_fn)(struct device_node *,
- struct bcm7120_l2_intc_data *),
+ struct bcm7120_l2_intc_data *),
const char *intc_name)
{
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+ struct device_node *dn = pdev->dev.of_node;
struct bcm7120_l2_intc_data *data;
- struct platform_device *pdev;
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
int ret = 0;
@@ -227,14 +224,7 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn,
if (!data)
return -ENOMEM;
- pdev = of_find_device_by_node(dn);
- if (!pdev) {
- ret = -ENODEV;
- goto out_free_data;
- }
-
data->num_parent_irqs = platform_irq_count(pdev);
- put_device(&pdev->dev);
if (data->num_parent_irqs <= 0) {
pr_err("invalid number of parent interrupts\n");
ret = -ENOMEM;
@@ -334,22 +324,19 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn,
if (data->map_base[idx])
iounmap(data->map_base[idx]);
}
-out_free_data:
kfree(data);
return ret;
}
-static int __init bcm7120_l2_intc_probe_7120(struct device_node *dn,
- struct device_node *parent)
+static int bcm7120_l2_intc_probe_7120(struct platform_device *pdev, struct device_node *parent)
{
- return bcm7120_l2_intc_probe(dn, parent, bcm7120_l2_intc_iomap_7120,
+ return bcm7120_l2_intc_probe(pdev, parent, bcm7120_l2_intc_iomap_7120,
"BCM7120 L2");
}
-static int __init bcm7120_l2_intc_probe_3380(struct device_node *dn,
- struct device_node *parent)
+static int bcm7120_l2_intc_probe_3380(struct platform_device *pdev, struct device_node *parent)
{
- return bcm7120_l2_intc_probe(dn, parent, bcm7120_l2_intc_iomap_3380,
+ return bcm7120_l2_intc_probe(pdev, parent, bcm7120_l2_intc_iomap_3380,
"BCM3380 L2");
}
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c
index 1bec5b2cd3f0..bb7078d6524f 100644
--- a/drivers/irqchip/irq-brcmstb-l2.c
+++ b/drivers/irqchip/irq-brcmstb-l2.c
@@ -138,13 +138,12 @@ static void brcmstb_l2_intc_resume(struct irq_data *d)
irq_reg_writel(gc, ~b->saved_mask, ct->regs.enable);
}
-static int __init brcmstb_l2_intc_of_init(struct device_node *np,
- struct device_node *parent,
- const struct brcmstb_intc_init_params
- *init_params)
+static int brcmstb_l2_intc_probe(struct platform_device *pdev, struct device_node *parent,
+ const struct brcmstb_intc_init_params *init_params)
{
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
unsigned int set = 0;
+ struct device_node *np = pdev->dev.of_node;
struct brcmstb_l2_intc_data *data;
struct irq_chip_type *ct;
int ret;
@@ -257,23 +256,21 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np,
return ret;
}
-static int __init brcmstb_l2_edge_intc_of_init(struct device_node *np,
- struct device_node *parent)
+static int brcmstb_l2_edge_intc_probe(struct platform_device *pdev, struct device_node *parent)
{
- return brcmstb_l2_intc_of_init(np, parent, &l2_edge_intc_init);
+ return brcmstb_l2_intc_probe(pdev, parent, &l2_edge_intc_init);
}
-static int __init brcmstb_l2_lvl_intc_of_init(struct device_node *np,
- struct device_node *parent)
+static int brcmstb_l2_lvl_intc_probe(struct platform_device *pdev, struct device_node *parent)
{
- return brcmstb_l2_intc_of_init(np, parent, &l2_lvl_intc_init);
+ return brcmstb_l2_intc_probe(pdev, parent, &l2_lvl_intc_init);
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(brcmstb_l2)
-IRQCHIP_MATCH("brcm,l2-intc", brcmstb_l2_edge_intc_of_init)
-IRQCHIP_MATCH("brcm,hif-spi-l2-intc", brcmstb_l2_edge_intc_of_init)
-IRQCHIP_MATCH("brcm,upg-aux-aon-l2-intc", brcmstb_l2_edge_intc_of_init)
-IRQCHIP_MATCH("brcm,bcm7271-l2-intc", brcmstb_l2_lvl_intc_of_init)
+IRQCHIP_MATCH("brcm,l2-intc", brcmstb_l2_edge_intc_probe)
+IRQCHIP_MATCH("brcm,hif-spi-l2-intc", brcmstb_l2_edge_intc_probe)
+IRQCHIP_MATCH("brcm,upg-aux-aon-l2-intc", brcmstb_l2_edge_intc_probe)
+IRQCHIP_MATCH("brcm,bcm7271-l2-intc", brcmstb_l2_lvl_intc_probe)
IRQCHIP_PLATFORM_DRIVER_END(brcmstb_l2)
MODULE_DESCRIPTION("Broadcom STB generic L2 interrupt controller");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-imx-mu-msi.c b/drivers/irqchip/irq-imx-mu-msi.c
index d2a4e8a61a42..c598f2f52fc6 100644
--- a/drivers/irqchip/irq-imx-mu-msi.c
+++ b/drivers/irqchip/irq-imx-mu-msi.c
@@ -296,11 +296,9 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = {
},
};
-static int __init imx_mu_of_init(struct device_node *dn,
- struct device_node *parent,
- const struct imx_mu_dcfg *cfg)
+static int imx_mu_probe(struct platform_device *pdev, struct device_node *parent,
+ const struct imx_mu_dcfg *cfg)
{
- struct platform_device *pdev = of_find_device_by_node(dn);
struct device_link *pd_link_a;
struct device_link *pd_link_b;
struct imx_mu_msi *msi_data;
@@ -416,31 +414,27 @@ static const struct dev_pm_ops imx_mu_pm_ops = {
imx_mu_runtime_resume, NULL)
};
-static int __init imx_mu_imx7ulp_of_init(struct device_node *dn,
- struct device_node *parent)
+static int imx_mu_imx7ulp_probe(struct platform_device *pdev, struct device_node *parent)
{
- return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx7ulp);
+ return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx7ulp);
}
-static int __init imx_mu_imx6sx_of_init(struct device_node *dn,
- struct device_node *parent)
+static int imx_mu_imx6sx_probe(struct platform_device *pdev, struct device_node *parent)
{
- return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx6sx);
+ return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx6sx);
}
-static int __init imx_mu_imx8ulp_of_init(struct device_node *dn,
- struct device_node *parent)
+static int imx_mu_imx8ulp_probe(struct platform_device *pdev, struct device_node *parent)
{
- return imx_mu_of_init(dn, parent, &imx_mu_cfg_imx8ulp);
+ return imx_mu_probe(pdev, parent, &imx_mu_cfg_imx8ulp);
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(imx_mu_msi)
-IRQCHIP_MATCH("fsl,imx7ulp-mu-msi", imx_mu_imx7ulp_of_init)
-IRQCHIP_MATCH("fsl,imx6sx-mu-msi", imx_mu_imx6sx_of_init)
-IRQCHIP_MATCH("fsl,imx8ulp-mu-msi", imx_mu_imx8ulp_of_init)
+IRQCHIP_MATCH("fsl,imx7ulp-mu-msi", imx_mu_imx7ulp_probe)
+IRQCHIP_MATCH("fsl,imx6sx-mu-msi", imx_mu_imx6sx_probe)
+IRQCHIP_MATCH("fsl,imx8ulp-mu-msi", imx_mu_imx8ulp_probe)
IRQCHIP_PLATFORM_DRIVER_END(imx_mu_msi, .pm = &imx_mu_pm_ops)
-
MODULE_AUTHOR("Frank Li <Frank.Li@nxp.com>");
MODULE_DESCRIPTION("Freescale MU MSI controller driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/irqchip/irq-mchp-eic.c b/drivers/irqchip/irq-mchp-eic.c
index 516a3a0e359c..b513a899c085 100644
--- a/drivers/irqchip/irq-mchp-eic.c
+++ b/drivers/irqchip/irq-mchp-eic.c
@@ -199,8 +199,9 @@ static const struct irq_domain_ops mchp_eic_domain_ops = {
.free = irq_domain_free_irqs_common,
};
-static int mchp_eic_init(struct device_node *node, struct device_node *parent)
+static int mchp_eic_probe(struct platform_device *pdev, struct device_node *parent)
{
+ struct device_node *node = pdev->dev.of_node;
struct irq_domain *parent_domain = NULL;
int ret, i;
@@ -273,7 +274,7 @@ static int mchp_eic_init(struct device_node *node, struct device_node *parent)
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(mchp_eic)
-IRQCHIP_MATCH("microchip,sama7g5-eic", mchp_eic_init)
+IRQCHIP_MATCH("microchip,sama7g5-eic", mchp_eic_probe)
IRQCHIP_PLATFORM_DRIVER_END(mchp_eic)
MODULE_DESCRIPTION("Microchip External Interrupt Controller");
diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
index 7d177626d64b..3fcbb044ae60 100644
--- a/drivers/irqchip/irq-meson-gpio.c
+++ b/drivers/irqchip/irq-meson-gpio.c
@@ -174,6 +174,14 @@ static const struct meson_gpio_irq_params s4_params = {
INIT_MESON_S4_COMMON_DATA(82)
};
+static const struct meson_gpio_irq_params s6_params = {
+ INIT_MESON_S4_COMMON_DATA(100)
+};
+
+static const struct meson_gpio_irq_params s7_params = {
+ INIT_MESON_S4_COMMON_DATA(84)
+};
+
static const struct meson_gpio_irq_params c3_params = {
INIT_MESON_S4_COMMON_DATA(55)
};
@@ -195,6 +203,9 @@ static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
{ .compatible = "amlogic,a4-gpio-ao-intc", .data = &a4_ao_params },
{ .compatible = "amlogic,a4-gpio-intc", .data = &a4_params },
{ .compatible = "amlogic,a5-gpio-intc", .data = &a5_params },
+ { .compatible = "amlogic,s6-gpio-intc", .data = &s6_params },
+ { .compatible = "amlogic,s7-gpio-intc", .data = &s7_params },
+ { .compatible = "amlogic,s7d-gpio-intc", .data = &s7_params },
{ .compatible = "amlogic,c3-gpio-intc", .data = &c3_params },
{ .compatible = "amlogic,t7-gpio-intc", .data = &t7_params },
{ }
@@ -572,8 +583,9 @@ static int meson_gpio_irq_parse_dt(struct device_node *node, struct meson_gpio_i
return 0;
}
-static int meson_gpio_irq_of_init(struct device_node *node, struct device_node *parent)
+static int meson_gpio_irq_probe(struct platform_device *pdev, struct device_node *parent)
{
+ struct device_node *node = pdev->dev.of_node;
struct irq_domain *domain, *parent_domain;
struct meson_gpio_irq_controller *ctl;
int ret;
@@ -630,10 +642,9 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node *
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(meson_gpio_intc)
-IRQCHIP_MATCH("amlogic,meson-gpio-intc", meson_gpio_irq_of_init)
+IRQCHIP_MATCH("amlogic,meson-gpio-intc", meson_gpio_irq_probe)
IRQCHIP_PLATFORM_DRIVER_END(meson_gpio_intc)
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_DESCRIPTION("Meson GPIO Interrupt Multiplexer driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:meson-gpio-intc");
diff --git a/drivers/irqchip/irq-mvebu-pic.c b/drivers/irqchip/irq-mvebu-pic.c
index cd8b73482b9f..10b85128183a 100644
--- a/drivers/irqchip/irq-mvebu-pic.c
+++ b/drivers/irqchip/irq-mvebu-pic.c
@@ -195,5 +195,3 @@ MODULE_AUTHOR("Yehuda Yitschak <yehuday@marvell.com>");
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell Armada 7K/8K PIC driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:mvebu_pic");
-
diff --git a/drivers/irqchip/irq-qcom-mpm.c b/drivers/irqchip/irq-qcom-mpm.c
index 8d569f7c5a7a..83f31ea657b7 100644
--- a/drivers/irqchip/irq-qcom-mpm.c
+++ b/drivers/irqchip/irq-qcom-mpm.c
@@ -320,9 +320,9 @@ static bool gic_hwirq_is_mapped(struct mpm_gic_map *maps, int cnt, u32 hwirq)
return false;
}
-static int qcom_mpm_init(struct device_node *np, struct device_node *parent)
+static int qcom_mpm_probe(struct platform_device *pdev, struct device_node *parent)
{
- struct platform_device *pdev = of_find_device_by_node(np);
+ struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct irq_domain *parent_domain;
struct generic_pm_domain *genpd;
@@ -478,7 +478,7 @@ static int qcom_mpm_init(struct device_node *np, struct device_node *parent)
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(qcom_mpm)
-IRQCHIP_MATCH("qcom,mpm", qcom_mpm_init)
+IRQCHIP_MATCH("qcom,mpm", qcom_mpm_probe)
IRQCHIP_PLATFORM_DRIVER_END(qcom_mpm)
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. MSM Power Manager");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
index 2a54adeb4cc7..1bf19deb02c4 100644
--- a/drivers/irqchip/irq-renesas-rzg2l.c
+++ b/drivers/irqchip/irq-renesas-rzg2l.c
@@ -8,7 +8,6 @@
*/
#include <linux/bitfield.h>
-#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
@@ -528,18 +527,15 @@ static int rzg2l_irqc_parse_interrupts(struct rzg2l_irqc_priv *priv,
return 0;
}
-static int rzg2l_irqc_common_init(struct device_node *node, struct device_node *parent,
- const struct irq_chip *irq_chip)
+static int rzg2l_irqc_common_probe(struct platform_device *pdev, struct device_node *parent,
+ const struct irq_chip *irq_chip)
{
- struct platform_device *pdev = of_find_device_by_node(node);
- struct device *dev __free(put_device) = pdev ? &pdev->dev : NULL;
struct irq_domain *irq_domain, *parent_domain;
+ struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
struct reset_control *resetn;
int ret;
- if (!pdev)
- return -ENODEV;
-
parent_domain = irq_find_host(parent);
if (!parent_domain)
return dev_err_probe(dev, -ENODEV, "cannot find parent domain\n");
@@ -583,35 +579,22 @@ static int rzg2l_irqc_common_init(struct device_node *node, struct device_node *
register_syscore_ops(&rzg2l_irqc_syscore_ops);
- /*
- * Prevent the cleanup function from invoking put_device by assigning
- * NULL to dev.
- *
- * make coccicheck will complain about missing put_device calls, but
- * those are false positives, as dev will be automatically "put" via
- * __free_put_device on the failing path.
- * On the successful path we don't actually want to "put" dev.
- */
- dev = NULL;
-
return 0;
}
-static int __init rzg2l_irqc_init(struct device_node *node,
- struct device_node *parent)
+static int rzg2l_irqc_probe(struct platform_device *pdev, struct device_node *parent)
{
- return rzg2l_irqc_common_init(node, parent, &rzg2l_irqc_chip);
+ return rzg2l_irqc_common_probe(pdev, parent, &rzg2l_irqc_chip);
}
-static int __init rzfive_irqc_init(struct device_node *node,
- struct device_node *parent)
+static int rzfive_irqc_probe(struct platform_device *pdev, struct device_node *parent)
{
- return rzg2l_irqc_common_init(node, parent, &rzfive_irqc_chip);
+ return rzg2l_irqc_common_probe(pdev, parent, &rzfive_irqc_chip);
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(rzg2l_irqc)
-IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_init)
-IRQCHIP_MATCH("renesas,r9a07g043f-irqc", rzfive_irqc_init)
+IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_probe)
+IRQCHIP_MATCH("renesas,r9a07g043f-irqc", rzfive_irqc_probe)
IRQCHIP_PLATFORM_DRIVER_END(rzg2l_irqc)
MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
MODULE_DESCRIPTION("Renesas RZ/G2L IRQC Driver");
diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c
index 9018d9c3911e..899a423b5da8 100644
--- a/drivers/irqchip/irq-renesas-rzv2h.c
+++ b/drivers/irqchip/irq-renesas-rzv2h.c
@@ -490,29 +490,15 @@ static int rzv2h_icu_parse_interrupts(struct rzv2h_icu_priv *priv, struct device
return 0;
}
-static void rzv2h_icu_put_device(void *data)
-{
- put_device(data);
-}
-
-static int rzv2h_icu_init_common(struct device_node *node, struct device_node *parent,
- const struct rzv2h_hw_info *hw_info)
+static int rzv2h_icu_probe_common(struct platform_device *pdev, struct device_node *parent,
+ const struct rzv2h_hw_info *hw_info)
{
struct irq_domain *irq_domain, *parent_domain;
+ struct device_node *node = pdev->dev.of_node;
struct rzv2h_icu_priv *rzv2h_icu_data;
- struct platform_device *pdev;
struct reset_control *resetn;
int ret;
- pdev = of_find_device_by_node(node);
- if (!pdev)
- return -ENODEV;
-
- ret = devm_add_action_or_reset(&pdev->dev, rzv2h_icu_put_device,
- &pdev->dev);
- if (ret < 0)
- return ret;
-
parent_domain = irq_find_host(parent);
if (!parent_domain) {
dev_err(&pdev->dev, "cannot find parent domain\n");
@@ -618,19 +604,19 @@ static const struct rzv2h_hw_info rzv2h_hw_params = {
.field_width = 8,
};
-static int rzg3e_icu_init(struct device_node *node, struct device_node *parent)
+static int rzg3e_icu_probe(struct platform_device *pdev, struct device_node *parent)
{
- return rzv2h_icu_init_common(node, parent, &rzg3e_hw_params);
+ return rzv2h_icu_probe_common(pdev, parent, &rzg3e_hw_params);
}
-static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
+static int rzv2h_icu_probe(struct platform_device *pdev, struct device_node *parent)
{
- return rzv2h_icu_init_common(node, parent, &rzv2h_hw_params);
+ return rzv2h_icu_probe_common(pdev, parent, &rzv2h_hw_params);
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(rzv2h_icu)
-IRQCHIP_MATCH("renesas,r9a09g047-icu", rzg3e_icu_init)
-IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_init)
+IRQCHIP_MATCH("renesas,r9a09g047-icu", rzg3e_icu_probe)
+IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_probe)
IRQCHIP_PLATFORM_DRIVER_END(rzv2h_icu)
MODULE_AUTHOR("Fabrizio Castro <fabrizio.castro.jz@renesas.com>");
MODULE_DESCRIPTION("Renesas RZ/V2H(P) ICU Driver");
diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
index 2c4c682627b8..6bac67cc0b6d 100644
--- a/drivers/irqchip/irq-riscv-imsic-early.c
+++ b/drivers/irqchip/irq-riscv-imsic-early.c
@@ -91,9 +91,8 @@ static int __init imsic_ipi_domain_init(void) { return 0; }
*/
static void imsic_handle_irq(struct irq_desc *desc)
{
+ struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv);
struct irq_chip *chip = irq_desc_get_chip(desc);
- int cpu = smp_processor_id();
- struct imsic_vector *vec;
unsigned long local_id;
/*
@@ -113,16 +112,12 @@ static void imsic_handle_irq(struct irq_desc *desc)
continue;
}
- if (unlikely(!imsic->base_domain))
- continue;
-
- vec = imsic_vector_from_local_id(cpu, local_id);
- if (!vec) {
+ if (unlikely(local_id > imsic->global.nr_ids)) {
pr_warn_ratelimited("vector not found for local ID 0x%lx\n", local_id);
continue;
}
- generic_handle_irq(vec->irq);
+ generic_handle_irq(lpriv->vectors[local_id].irq);
}
chained_irq_exit(chip, desc);
diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
index 643c8e459611..7228a33f6c37 100644
--- a/drivers/irqchip/irq-riscv-imsic-platform.c
+++ b/drivers/irqchip/irq-riscv-imsic-platform.c
@@ -158,11 +158,11 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
tmp_vec.local_id = new_vec->local_id;
/* Point device to the temporary vector */
- imsic_msi_update_msg(irq_get_irq_data(d->irq), &tmp_vec);
+ imsic_msi_update_msg(d, &tmp_vec);
}
/* Point device to the new vector */
- imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec);
+ imsic_msi_update_msg(d, new_vec);
/* Update irq descriptors with the new vector */
d->chip_data = new_vec;
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index dc95ad856d80..385368052d5c 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -434,16 +434,6 @@ void imsic_vector_debug_show_summary(struct seq_file *m, int ind)
}
#endif
-struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id)
-{
- struct imsic_local_priv *lpriv = per_cpu_ptr(imsic->lpriv, cpu);
-
- if (!lpriv || imsic->global.nr_ids < local_id)
- return NULL;
-
- return &lpriv->vectors[local_id];
-}
-
struct imsic_vector *imsic_vector_alloc(unsigned int irq, const struct cpumask *mask)
{
struct imsic_vector *vec = NULL;
@@ -487,7 +477,6 @@ static void __init imsic_local_cleanup(void)
lpriv = per_cpu_ptr(imsic->lpriv, cpu);
bitmap_free(lpriv->dirty_bitmap);
- kfree(lpriv->vectors);
}
free_percpu(imsic->lpriv);
@@ -501,7 +490,8 @@ static int __init imsic_local_init(void)
int cpu, i;
/* Allocate per-CPU private state */
- imsic->lpriv = alloc_percpu(typeof(*imsic->lpriv));
+ imsic->lpriv = __alloc_percpu(struct_size(imsic->lpriv, vectors, global->nr_ids + 1),
+ __alignof__(*imsic->lpriv));
if (!imsic->lpriv)
return -ENOMEM;
@@ -521,12 +511,6 @@ static int __init imsic_local_init(void)
timer_setup(&lpriv->timer, imsic_local_timer_callback, TIMER_PINNED);
#endif
- /* Allocate vector array */
- lpriv->vectors = kcalloc(global->nr_ids + 1, sizeof(*lpriv->vectors),
- GFP_KERNEL);
- if (!lpriv->vectors)
- goto fail_local_cleanup;
-
/* Setup vector array */
for (i = 0; i <= global->nr_ids; i++) {
vec = &lpriv->vectors[i];
diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
index 57f951952b0c..6332501dcbd8 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -40,7 +40,7 @@ struct imsic_local_priv {
#endif
/* Local vector table */
- struct imsic_vector *vectors;
+ struct imsic_vector vectors[];
};
struct imsic_priv {
@@ -95,8 +95,6 @@ static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *ve
void imsic_vector_force_move_cleanup(struct imsic_vector *vec);
void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec);
-struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id);
-
struct imsic_vector *imsic_vector_alloc(unsigned int irq, const struct cpumask *mask);
void imsic_vector_free(struct imsic_vector *vector);
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index cbd7697bc148..c5db7d6e3f7c 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -49,6 +49,8 @@
#define CONTEXT_ENABLE_BASE 0x2000
#define CONTEXT_ENABLE_SIZE 0x80
+#define PENDING_BASE 0x1000
+
/*
* Each hart context has a set of control registers associated with it. Right
* now there's only two: a source priority threshold over which the hart will
@@ -63,6 +65,7 @@
#define PLIC_ENABLE_THRESHOLD 0
#define PLIC_QUIRK_EDGE_INTERRUPT 0
+#define PLIC_QUIRK_CP100_CLAIM_REGISTER_ERRATUM 1
struct plic_priv {
struct fwnode_handle *fwnode;
@@ -94,15 +97,22 @@ static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
static int plic_irq_set_type(struct irq_data *d, unsigned int type);
-static void __plic_toggle(void __iomem *enable_base, int hwirq, int enable)
+static void __plic_toggle(struct plic_handler *handler, int hwirq, int enable)
{
- u32 __iomem *reg = enable_base + (hwirq / 32) * sizeof(u32);
+ u32 __iomem *base = handler->enable_base;
u32 hwirq_mask = 1 << (hwirq % 32);
+ int group = hwirq / 32;
+ u32 value;
+
+ value = readl(base + group);
if (enable)
- writel(readl(reg) | hwirq_mask, reg);
+ value |= hwirq_mask;
else
- writel(readl(reg) & ~hwirq_mask, reg);
+ value &= ~hwirq_mask;
+
+ handler->enable_save[group] = value;
+ writel(value, base + group);
}
static void plic_toggle(struct plic_handler *handler, int hwirq, int enable)
@@ -110,7 +120,7 @@ static void plic_toggle(struct plic_handler *handler, int hwirq, int enable)
unsigned long flags;
raw_spin_lock_irqsave(&handler->enable_lock, flags);
- __plic_toggle(handler->enable_base, hwirq, enable);
+ __plic_toggle(handler, hwirq, enable);
raw_spin_unlock_irqrestore(&handler->enable_lock, flags);
}
@@ -247,33 +257,16 @@ static int plic_irq_set_type(struct irq_data *d, unsigned int type)
static int plic_irq_suspend(void)
{
- unsigned int i, cpu;
- unsigned long flags;
- u32 __iomem *reg;
struct plic_priv *priv;
priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv;
/* irq ID 0 is reserved */
- for (i = 1; i < priv->nr_irqs; i++) {
+ for (unsigned int i = 1; i < priv->nr_irqs; i++) {
__assign_bit(i, priv->prio_save,
readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID));
}
- for_each_present_cpu(cpu) {
- struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
-
- if (!handler->present)
- continue;
-
- raw_spin_lock_irqsave(&handler->enable_lock, flags);
- for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) {
- reg = handler->enable_base + i * sizeof(u32);
- handler->enable_save[i] = readl(reg);
- }
- raw_spin_unlock_irqrestore(&handler->enable_lock, flags);
- }
-
return 0;
}
@@ -398,6 +391,98 @@ static void plic_handle_irq(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
+static u32 cp100_isolate_pending_irq(int nr_irq_groups, struct plic_handler *handler)
+{
+ u32 __iomem *pending = handler->priv->regs + PENDING_BASE;
+ u32 __iomem *enable = handler->enable_base;
+ u32 pending_irqs = 0;
+ int i, j;
+
+ /* Look for first pending interrupt */
+ for (i = 0; i < nr_irq_groups; i++) {
+ /* Any pending interrupts would be annihilated, so skip checking them */
+ if (!handler->enable_save[i])
+ continue;
+
+ pending_irqs = handler->enable_save[i] & readl_relaxed(pending + i);
+ if (pending_irqs)
+ break;
+ }
+
+ if (!pending_irqs)
+ return 0;
+
+ /* Isolate lowest set bit */
+ pending_irqs &= -pending_irqs;
+
+ /* Disable all interrupts but the first pending one */
+ for (j = 0; j < nr_irq_groups; j++) {
+ u32 new_mask = j == i ? pending_irqs : 0;
+
+ if (new_mask != handler->enable_save[j])
+ writel_relaxed(new_mask, enable + j);
+ }
+ return pending_irqs;
+}
+
+static irq_hw_number_t cp100_get_hwirq(struct plic_handler *handler, void __iomem *claim)
+{
+ int nr_irq_groups = DIV_ROUND_UP(handler->priv->nr_irqs, 32);
+ u32 __iomem *enable = handler->enable_base;
+ irq_hw_number_t hwirq = 0;
+ u32 iso_mask;
+ int i;
+
+ guard(raw_spinlock)(&handler->enable_lock);
+
+ /* Existing enable state is already cached in enable_save */
+ iso_mask = cp100_isolate_pending_irq(nr_irq_groups, handler);
+ if (!iso_mask)
+ return 0;
+
+ /*
+ * Interrupts delievered to hardware still become pending, but only
+ * interrupts that are both pending and enabled can be claimed.
+ * Clearing the enable bit for all interrupts but the first pending
+ * one avoids a hardware bug that occurs during read from the claim
+ * register with more than one eligible interrupt.
+ */
+ hwirq = readl(claim);
+
+ /* Restore previous state */
+ for (i = 0; i < nr_irq_groups; i++) {
+ u32 written = i == hwirq / 32 ? iso_mask : 0;
+ u32 stored = handler->enable_save[i];
+
+ if (stored != written)
+ writel_relaxed(stored, enable + i);
+ }
+ return hwirq;
+}
+
+static void plic_handle_irq_cp100(struct irq_desc *desc)
+{
+ struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ void __iomem *claim = handler->hart_base + CONTEXT_CLAIM;
+ irq_hw_number_t hwirq;
+
+ WARN_ON_ONCE(!handler->present);
+
+ chained_irq_enter(chip, desc);
+
+ while ((hwirq = cp100_get_hwirq(handler, claim))) {
+ int err = generic_handle_domain_irq(handler->priv->irqdomain, hwirq);
+
+ if (unlikely(err)) {
+ pr_warn_ratelimited("%pfwP: can't find mapping for hwirq %lu\n",
+ handler->priv->fwnode, hwirq);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
static void plic_set_threshold(struct plic_handler *handler, u32 threshold)
{
/* priority must be > threshold to trigger an interrupt */
@@ -434,6 +519,8 @@ static const struct of_device_id plic_match[] = {
.data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) },
{ .compatible = "thead,c900-plic",
.data = (const void *)BIT(PLIC_QUIRK_EDGE_INTERRUPT) },
+ { .compatible = "ultrarisc,cp100-plic",
+ .data = (const void *)BIT(PLIC_QUIRK_CP100_CLAIM_REGISTER_ERRATUM) },
{}
};
@@ -592,12 +679,11 @@ static int plic_probe(struct fwnode_handle *fwnode)
if (parent_hwirq != RV_IRQ_EXT) {
/* Disable S-mode enable bits if running in M-mode. */
if (IS_ENABLED(CONFIG_RISCV_M_MODE)) {
- void __iomem *enable_base = priv->regs +
- CONTEXT_ENABLE_BASE +
- i * CONTEXT_ENABLE_SIZE;
+ u32 __iomem *enable_base = priv->regs + CONTEXT_ENABLE_BASE +
+ i * CONTEXT_ENABLE_SIZE;
- for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
- __plic_toggle(enable_base, hwirq, 0);
+ for (int j = 0; j <= nr_irqs / 32; j++)
+ writel(0, enable_base + j);
}
continue;
}
@@ -668,12 +754,17 @@ static int plic_probe(struct fwnode_handle *fwnode)
}
if (global_setup) {
+ void (*handler_fn)(struct irq_desc *) = plic_handle_irq;
+
+ if (test_bit(PLIC_QUIRK_CP100_CLAIM_REGISTER_ERRATUM, &handler->priv->plic_quirks))
+ handler_fn = plic_handle_irq_cp100;
+
/* Find parent domain and register chained handler */
domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(), DOMAIN_BUS_ANY);
if (domain)
plic_parent_irq = irq_create_mapping(domain, RV_IRQ_EXT);
if (plic_parent_irq)
- irq_set_chained_handler(plic_parent_irq, plic_handle_irq);
+ irq_set_chained_handler(plic_parent_irq, handler_fn);
cpuhp_setup_state(CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING,
"irqchip/sifive/plic:starting",
diff --git a/drivers/irqchip/irq-starfive-jh8100-intc.c b/drivers/irqchip/irq-starfive-jh8100-intc.c
index 2460798ec158..705361b4ebe0 100644
--- a/drivers/irqchip/irq-starfive-jh8100-intc.c
+++ b/drivers/irqchip/irq-starfive-jh8100-intc.c
@@ -114,9 +114,9 @@ static void starfive_intc_irq_handler(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
-static int __init starfive_intc_init(struct device_node *intc,
- struct device_node *parent)
+static int starfive_intc_probe(struct platform_device *pdev, struct device_node *parent)
{
+ struct device_node *intc = pdev->dev.of_node;
struct starfive_irq_chip *irqc;
struct reset_control *rst;
struct clk *clk;
@@ -199,7 +199,7 @@ static int __init starfive_intc_init(struct device_node *intc,
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(starfive_intc)
-IRQCHIP_MATCH("starfive,jh8100-intc", starfive_intc_init)
+IRQCHIP_MATCH("starfive,jh8100-intc", starfive_intc_probe)
IRQCHIP_PLATFORM_DRIVER_END(starfive_intc)
MODULE_DESCRIPTION("StarFive JH8100 External Interrupt Controller");
diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c
index 1e236d5b7516..2e4013c6834d 100644
--- a/drivers/irqchip/irq-ts4800.c
+++ b/drivers/irqchip/irq-ts4800.c
@@ -165,4 +165,3 @@ module_platform_driver(ts4800_ic_driver);
MODULE_AUTHOR("Damien Riegel <damien.riegel@savoirfairelinux.com>");
MODULE_DESCRIPTION("Multiplexed-IRQs driver for TS-4800's FPGA");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:ts4800_irqc");
diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
index 0ee7b6b71f5f..689c8e448901 100644
--- a/drivers/irqchip/irqchip.c
+++ b/drivers/irqchip/irqchip.c
@@ -36,11 +36,10 @@ int platform_irqchip_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *par_np __free(device_node) = of_irq_find_parent(np);
- of_irq_init_cb_t irq_init_cb = of_device_get_match_data(&pdev->dev);
+ platform_irq_probe_t irq_probe = of_device_get_match_data(&pdev->dev);
- if (!irq_init_cb) {
+ if (!irq_probe)
return -EINVAL;
- }
if (par_np == np)
par_np = NULL;
@@ -53,10 +52,9 @@ int platform_irqchip_probe(struct platform_device *pdev)
* interrupt controller. The actual initialization callback of this
* interrupt controller can check for specific domains as necessary.
*/
- if (par_np && !irq_find_matching_host(par_np, DOMAIN_BUS_ANY)) {
+ if (par_np && !irq_find_matching_host(par_np, DOMAIN_BUS_ANY))
return -EPROBE_DEFER;
- }
- return irq_init_cb(np, par_np);
+ return irq_probe(pdev, par_np);
}
EXPORT_SYMBOL_GPL(platform_irqchip_probe);
diff --git a/drivers/irqchip/qcom-irq-combiner.c b/drivers/irqchip/qcom-irq-combiner.c
index 18e696dc7f4d..09819007d08e 100644
--- a/drivers/irqchip/qcom-irq-combiner.c
+++ b/drivers/irqchip/qcom-irq-combiner.c
@@ -222,7 +222,7 @@ static int get_registers(struct platform_device *pdev, struct combiner *comb)
return 0;
}
-static int __init combiner_probe(struct platform_device *pdev)
+static int combiner_probe(struct platform_device *pdev)
{
struct combiner *combiner;
int nregs;
@@ -266,11 +266,11 @@ static const struct acpi_device_id qcom_irq_combiner_ids[] = {
{ }
};
-static struct platform_driver qcom_irq_combiner_probe = {
+static struct platform_driver qcom_irq_combiner_driver = {
.driver = {
.name = "qcom-irq-combiner",
.acpi_match_table = ACPI_PTR(qcom_irq_combiner_ids),
},
.probe = combiner_probe,
};
-builtin_platform_driver(qcom_irq_combiner_probe);
+builtin_platform_driver(qcom_irq_combiner_driver);
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index 52d77546aacb..518f7f0f3dab 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -350,9 +350,10 @@ static int pdc_setup_pin_mapping(struct device_node *np)
#define QCOM_PDC_SIZE 0x30000
-static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
+static int qcom_pdc_probe(struct platform_device *pdev, struct device_node *parent)
{
struct irq_domain *parent_domain, *pdc_domain;
+ struct device_node *node = pdev->dev.of_node;
resource_size_t res_size;
struct resource res;
int ret;
@@ -428,7 +429,7 @@ static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
}
IRQCHIP_PLATFORM_DRIVER_BEGIN(qcom_pdc)
-IRQCHIP_MATCH("qcom,pdc", qcom_pdc_init)
+IRQCHIP_MATCH("qcom,pdc", qcom_pdc_probe)
IRQCHIP_PLATFORM_DRIVER_END(qcom_pdc)
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Power Domain Controller");
MODULE_LICENSE("GPL v2");
diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h
index d5e6024cb2a8..bc4ddacd6ddc 100644
--- a/include/linux/irqchip.h
+++ b/include/linux/irqchip.h
@@ -17,12 +17,18 @@
#include <linux/of_irq.h>
#include <linux/platform_device.h>
+typedef int (*platform_irq_probe_t)(struct platform_device *, struct device_node *);
+
/* Undefined on purpose */
extern of_irq_init_cb_t typecheck_irq_init_cb;
+extern platform_irq_probe_t typecheck_irq_probe;
#define typecheck_irq_init_cb(fn) \
(__typecheck(typecheck_irq_init_cb, &fn) ? fn : fn)
+#define typecheck_irq_probe(fn) \
+ (__typecheck(typecheck_irq_probe, &fn) ? fn : fn)
+
/*
* This macro must be used by the different irqchip drivers to declare
* the association between their DT compatible string and their
@@ -42,7 +48,7 @@ extern int platform_irqchip_probe(struct platform_device *pdev);
static const struct of_device_id drv_name##_irqchip_match_table[] = {
#define IRQCHIP_MATCH(compat, fn) { .compatible = compat, \
- .data = typecheck_irq_init_cb(fn), },
+ .data = typecheck_irq_probe(fn), },
#define IRQCHIP_PLATFORM_DRIVER_END(drv_name, ...) \
© 2016 - 2025 Red Hat, Inc.