mirror of https://github.com/torvalds/linux.git
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.
-----BEGIN PGP SIGNATURE-----
iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmkswMYTHHRnbHhAbGlu
dXRyb25peC5kZQAKCRCmGPVMDXSYoZvSEACZdCx7vO2XX7oef7DxQ6EKFA/NQvd0
xJGFTBlrxIucp26yUxWKkuDVdhu8WYe13zJG6+LVl9IxH3IIBa2duQ4HhIyqxuz6
z74IDjBlOcKAHu2xLFJmBIS4vGTd6UPOg1KvSrIFd9oiuMXikphbnFgyrFGAFiSQ
J1gP7mKZATUH08mTXK5k1pmBIbMjEHpyyTdBEJKoVgiN/MB/qsq95dy0Oxal+C13
1cOKBaFreTMdX+77U5RucBcGaLHW4SdoaAVaqc/UXw2c2TAezbt/gPYexRpkdVaG
2tuYTWIfCUuHbjUoOOYwI+ILnuiBMzjxlIUx3uSvcvtUVO4YuMDR4JOWVsevtfgI
uUV+4OPq9kBI6PNqAyo16NhDdZ9rmjg3q14F9oyidQfR5gRbsZPPDmtCB/M2jbE1
n3LlsHUJt0UYo8ZqCPrGhiw9hkGXv4wsEl10FKkyoNrQ0Y4SCUrdzGdr6vwhAAub
yxMe1+BrFQT23R9l+qVrUZmDmpV9tlFNr6rPwtucrQX3PMWEfAeCc6a/vjY3eqJl
sZ4pGyFEx0cwfKzHu1/SmNpnjSNdyc7niiN8HAQ7AnxzRW13fDdGQuuVGsKxHyJc
Tke9wJsyUO4MxpSQDI+cmpsF8OeJDHuRDKMBdLFxlLPhABECdLUO0qKq9l0Ry/Ji
uDkc3WvM14zKpw==
=kdyt
-----END PGP SIGNATURE-----
Merge tag 'irq-drivers-2025-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq driver updates from Thomas Gleixner:
"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"
* tag 'irq-drivers-2025-11-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (32 commits)
irqchip/meson-gpio: Add support for Amlogic S6 S7 and S7D SoCs
dt-bindings: interrupt-controller: Add support for Amlogic S6 S7 and S7D SoCs
dt-bindings: interrupt-controller: aspeed,ast2700: Correct #interrupt-cells and interrupts count
irqchip/aclint-sswi: Add Nuclei UX900 support
dt-bindings: interrupt-controller: Add Anlogic DR1V90 ACLINT SSWI
dt-bindings: interrupt-controller: Add Anlogic DR1V90 ACLINT MSWI
dt-bindings: interrupt-controller: Add Anlogic DR1V90 PLIC
irqchip/irq-bcm7038-l1: Remove unused reg_mask_status()
irqchip/sifive-plic: Fix call to __plic_toggle() in M-Mode code path
irqchip/sifive-plic: Add support for UltraRISC DP1000 PLIC
irqchip/sifive-plic: Cache the interrupt enable state
dt-bindings: interrupt-controller: Add UltraRISC DP1000 PLIC
dt-bindings: vendor-prefixes: Add UltraRISC
irqchip/qcom-irq-combiner: Rename driver structure
irqchip/riscv-imsic: Inline imsic_vector_from_local_id()
irqchip/riscv-imsic: Embed the vector array in lpriv
irqchip/riscv-imsic: Remove redundant irq_data lookups
irqchip/ts4800: Drop unused module alias
irqchip/mvebu-pic: Drop unused module alias
irqchip/meson-gpio: Drop unused module alias
...
This commit is contained in:
commit
15b87bec89
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,.*":
|
||||
|
|
|
|||
|
|
@ -150,7 +150,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
|
||||
|
|
@ -158,14 +158,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>");
|
||||
|
|
|
|||
|
|
@ -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,8 +213,7 @@ 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,
|
||||
static int bcm7038_l1_init_one(struct device_node *dn, unsigned int idx,
|
||||
struct bcm7038_l1_chip *intc)
|
||||
{
|
||||
struct resource res;
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 *),
|
||||
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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 +
|
||||
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",
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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, ...) \
|
||||
|
|
|
|||
Loading…
Reference in New Issue