mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'irq-drivers-2026-04-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull interrupt chip driver updates from Thomas Gleixner:
- A large refactoring for the Renesas RZV2H driver to add new interrupt
types cleanly
- A large refactoring for the Renesas RZG2L driver to add support the
new RZ/G3L variant
- Add support for the new NXP S32N79 chip in the IMX irq-steer driver
- Add support for the Apple AICv3 variant
- Enhance the Loongson PCH LPC driver so it can be used on MIPS with
device tree firmware
- Allow the PIC32 EVIC driver to be built independent of MIPS in
compile tests
- The usual small fixes and enhancements all over the place
* tag 'irq-drivers-2026-04-12' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (46 commits)
irqchip/irq-pic32-evic: Add __maybe_unused for board_bind_eic_interrupt in COMPILE_TEST
irqchip/renesas-rzv2h: Kill icu_err string
irqchip/renesas-rzv2h: Kill swint_names[]
irqchip/renesas-rzv2h: Kill swint_idx[]
irqchip/renesas-rzg2l: Add NMI support
irqchip/renesas-rzg2l: Clear the shared interrupt bit in rzg2l_irqc_free()
irqchip/renesas-rzg2l: Replace raw_spin_{lock,unlock} with guard() in rzg2l_irq_set_type()
irqchip/gic-v3: Print a warning for out-of-range interrupt numbers
irqchip/renesas-rzg2l: Add shared interrupt support
irqchip/renesas-rzg2l: Add RZ/G3L support
irqchip/renesas-rzg2l: Drop IRQC_IRQ_COUNT macro
irqchip/renesas-rzg2l: Drop IRQC_TINT_START macro
irqchip/renesas-rzg2l: Drop IRQC_NUM_IRQ macro
irqchip/renesas-rzg2l: Dynamically allocate fwspec array
irqchip/renesas-rzg2l: Split rzfive_irqc_{mask,unmask} into separate IRQ and TINT handlers
irqchip/renesas-rzg2l: Split rzfive_tint_irq_endisable() into separate IRQ and TINT helpers
irqchip/renesas-rzg2l: Replace rzg2l_irqc_irq_{enable,disable} with TINT-specific handlers
irqchip/renesas-rzg2l: Split set_type handler into separate IRQ and TINT functions
irqchip/renesas-rzg2l: Split EOI handler into separate IRQ and TINT functions
irqchip/renesas-rzg2l: Replace single irq_chip with per-region irq_chip instances
...
This commit is contained in:
@@ -4,10 +4,10 @@
|
||||
$id: http://devicetree.org/schemas/interrupt-controller/apple,aic2.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Apple Interrupt Controller 2
|
||||
title: Apple Interrupt Controller 2 and 3
|
||||
|
||||
maintainers:
|
||||
- Hector Martin <marcan@marcan.st>
|
||||
- Janne Grunau <j@jannau.net>
|
||||
|
||||
description: |
|
||||
The Apple Interrupt Controller 2 is a simple interrupt controller present on
|
||||
@@ -28,14 +28,24 @@ description: |
|
||||
which do not go through a discrete interrupt controller. It also handles
|
||||
FIQ-based Fast IPIs.
|
||||
|
||||
The Apple Interrupt Controller 3 is in its base functionality very similar to
|
||||
the Apple Interrupt Controller 2 and uses the same device tree bindings. It is
|
||||
found on Apple ARM SoCs platforms starting with t8122 (M3).
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- apple,t8112-aic
|
||||
- apple,t6000-aic
|
||||
- apple,t6020-aic
|
||||
- const: apple,aic2
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- apple,t6000-aic
|
||||
- apple,t6020-aic
|
||||
- apple,t8112-aic
|
||||
- const: apple,aic2
|
||||
- items:
|
||||
- enum:
|
||||
- apple,t6030-aic3
|
||||
- const: apple,t8122-aic3
|
||||
- const: apple,t8122-aic3
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
@@ -117,7 +127,9 @@ allOf:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: apple,t8112-aic
|
||||
enum:
|
||||
- apple,t8112-aic
|
||||
- apple,t8122-aic3
|
||||
then:
|
||||
properties:
|
||||
'#interrupt-cells':
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/interrupt-controller/loongson,pch-lpc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Loongson PCH LPC Controller
|
||||
|
||||
maintainers:
|
||||
- Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
|
||||
description:
|
||||
This interrupt controller is found in the Loongson LS7A family of PCH for
|
||||
accepting interrupts sent by LPC-connected peripherals and signalling PIC
|
||||
via a single interrupt line when interrupts are available.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: loongson,ls7a-lpc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupt-controller
|
||||
- interrupts
|
||||
- '#interrupt-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
lpc: interrupt-controller@10002000 {
|
||||
compatible = "loongson,ls7a-lpc";
|
||||
reg = <0x10002000 0x400>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&pic>;
|
||||
interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
...
|
||||
@@ -30,7 +30,9 @@ properties:
|
||||
- renesas,r9a08g045-irqc # RZ/G3S
|
||||
- const: renesas,rzg2l-irqc
|
||||
|
||||
- const: renesas,r9a07g043f-irqc # RZ/Five
|
||||
- enum:
|
||||
- renesas,r9a07g043f-irqc # RZ/Five
|
||||
- renesas,r9a08g046-irqc # RZ/G3L
|
||||
|
||||
'#interrupt-cells':
|
||||
description: The first cell should contain a macro RZG2L_{NMI,IRQX} included in the
|
||||
@@ -48,107 +50,35 @@ properties:
|
||||
|
||||
interrupts:
|
||||
minItems: 45
|
||||
items:
|
||||
- description: NMI interrupt
|
||||
- description: IRQ0 interrupt
|
||||
- description: IRQ1 interrupt
|
||||
- description: IRQ2 interrupt
|
||||
- description: IRQ3 interrupt
|
||||
- description: IRQ4 interrupt
|
||||
- description: IRQ5 interrupt
|
||||
- description: IRQ6 interrupt
|
||||
- description: IRQ7 interrupt
|
||||
- description: GPIO interrupt, TINT0
|
||||
- description: GPIO interrupt, TINT1
|
||||
- description: GPIO interrupt, TINT2
|
||||
- description: GPIO interrupt, TINT3
|
||||
- description: GPIO interrupt, TINT4
|
||||
- description: GPIO interrupt, TINT5
|
||||
- description: GPIO interrupt, TINT6
|
||||
- description: GPIO interrupt, TINT7
|
||||
- description: GPIO interrupt, TINT8
|
||||
- description: GPIO interrupt, TINT9
|
||||
- description: GPIO interrupt, TINT10
|
||||
- description: GPIO interrupt, TINT11
|
||||
- description: GPIO interrupt, TINT12
|
||||
- description: GPIO interrupt, TINT13
|
||||
- description: GPIO interrupt, TINT14
|
||||
- description: GPIO interrupt, TINT15
|
||||
- description: GPIO interrupt, TINT16
|
||||
- description: GPIO interrupt, TINT17
|
||||
- description: GPIO interrupt, TINT18
|
||||
- description: GPIO interrupt, TINT19
|
||||
- description: GPIO interrupt, TINT20
|
||||
- description: GPIO interrupt, TINT21
|
||||
- description: GPIO interrupt, TINT22
|
||||
- description: GPIO interrupt, TINT23
|
||||
- description: GPIO interrupt, TINT24
|
||||
- description: GPIO interrupt, TINT25
|
||||
- description: GPIO interrupt, TINT26
|
||||
- description: GPIO interrupt, TINT27
|
||||
- description: GPIO interrupt, TINT28
|
||||
- description: GPIO interrupt, TINT29
|
||||
- description: GPIO interrupt, TINT30
|
||||
- description: GPIO interrupt, TINT31
|
||||
- description: Bus error interrupt
|
||||
- description: ECCRAM0 or combined ECCRAM0/1 1bit error interrupt
|
||||
- description: ECCRAM0 or combined ECCRAM0/1 2bit error interrupt
|
||||
- description: ECCRAM0 or combined ECCRAM0/1 error overflow interrupt
|
||||
- description: ECCRAM1 1bit error interrupt
|
||||
- description: ECCRAM1 2bit error interrupt
|
||||
- description: ECCRAM1 error overflow interrupt
|
||||
maxItems: 61
|
||||
|
||||
interrupt-names:
|
||||
minItems: 45
|
||||
maxItems: 61
|
||||
items:
|
||||
- const: nmi
|
||||
- const: irq0
|
||||
- const: irq1
|
||||
- const: irq2
|
||||
- const: irq3
|
||||
- const: irq4
|
||||
- const: irq5
|
||||
- const: irq6
|
||||
- const: irq7
|
||||
- const: tint0
|
||||
- const: tint1
|
||||
- const: tint2
|
||||
- const: tint3
|
||||
- const: tint4
|
||||
- const: tint5
|
||||
- const: tint6
|
||||
- const: tint7
|
||||
- const: tint8
|
||||
- const: tint9
|
||||
- const: tint10
|
||||
- const: tint11
|
||||
- const: tint12
|
||||
- const: tint13
|
||||
- const: tint14
|
||||
- const: tint15
|
||||
- const: tint16
|
||||
- const: tint17
|
||||
- const: tint18
|
||||
- const: tint19
|
||||
- const: tint20
|
||||
- const: tint21
|
||||
- const: tint22
|
||||
- const: tint23
|
||||
- const: tint24
|
||||
- const: tint25
|
||||
- const: tint26
|
||||
- const: tint27
|
||||
- const: tint28
|
||||
- const: tint29
|
||||
- const: tint30
|
||||
- const: tint31
|
||||
- const: bus-err
|
||||
- const: ec7tie1-0
|
||||
- const: ec7tie2-0
|
||||
- const: ec7tiovf-0
|
||||
- const: ec7tie1-1
|
||||
- const: ec7tie2-1
|
||||
- const: ec7tiovf-1
|
||||
oneOf:
|
||||
- description: NMI interrupt
|
||||
const: nmi
|
||||
- description: External IRQ interrupt
|
||||
pattern: '^irq([0-9]|1[0-5])$'
|
||||
- description: GPIO interrupt
|
||||
pattern: '^tint([0-9]|1[0-9]|2[0-9]|3[0-1])$'
|
||||
- description: Bus error interrupt
|
||||
const: bus-err
|
||||
- description: ECCRAM0 or combined ECCRAM0/1 1bit error interrupt
|
||||
const: ec7tie1-0
|
||||
- description: ECCRAM0 or combined ECCRAM0/1 2bit error interrupt
|
||||
const: ec7tie2-0
|
||||
- description: ECCRAM0 or combined ECCRAM0/1 error overflow interrupt
|
||||
const: ec7tiovf-0
|
||||
- description: ECCRAM1 1bit error interrupt
|
||||
const: ec7tie1-1
|
||||
- description: ECCRAM1 2bit error interrupt
|
||||
const: ec7tie2-1
|
||||
- description: ECCRAM1 error overflow interrupt
|
||||
const: ec7tiovf-1
|
||||
- description: Integrated GPT Error interrupt
|
||||
pattern: '^ovfunf([0-7])$'
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
@@ -180,6 +110,24 @@ required:
|
||||
allOf:
|
||||
- $ref: /schemas/interrupt-controller.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,r9a07g043f-irqc
|
||||
- renesas,r9a07g043u-irqc
|
||||
- renesas,r9a07g044-irqc
|
||||
- renesas,r9a07g054-irqc
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 48
|
||||
maxItems: 48
|
||||
interrupt-names:
|
||||
minItems: 48
|
||||
maxItems: 48
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@@ -192,12 +140,19 @@ allOf:
|
||||
maxItems: 45
|
||||
interrupt-names:
|
||||
maxItems: 45
|
||||
else:
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,r9a08g046-irqc
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 48
|
||||
minItems: 61
|
||||
interrupt-names:
|
||||
minItems: 48
|
||||
minItems: 61
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
@@ -99,6 +100,11 @@ int __init arch_probe_nr_irqs(void)
|
||||
return NR_IRQS_LEGACY;
|
||||
}
|
||||
|
||||
unsigned int arch_dynirq_lower_bound(unsigned int from)
|
||||
{
|
||||
return MAX(from, NR_IRQS_LEGACY);
|
||||
}
|
||||
|
||||
void __init init_IRQ(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/logic_pio.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <asm/bootinfo.h>
|
||||
@@ -227,3 +228,8 @@ void __init arch_init_irq(void)
|
||||
reserve_pio_range();
|
||||
irqchip_init();
|
||||
}
|
||||
|
||||
unsigned int arch_dynirq_lower_bound(unsigned int from)
|
||||
{
|
||||
return MAX(from, NR_IRQS_LEGACY);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ config PIC32MZDA
|
||||
select LIBFDT
|
||||
select USE_OF
|
||||
select PINCTRL
|
||||
select PIC32_EVIC
|
||||
help
|
||||
Support for the Microchip PIC32MZDA microcontroller.
|
||||
|
||||
|
||||
@@ -252,9 +252,12 @@ config ORION_IRQCHIP
|
||||
select IRQ_DOMAIN
|
||||
|
||||
config PIC32_EVIC
|
||||
bool
|
||||
def_bool MACH_PIC32 || COMPILE_TEST
|
||||
select GENERIC_IRQ_CHIP
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Enable support for the interrupt controller on the Microchip PIC32
|
||||
family of platforms.
|
||||
|
||||
config JCORE_AIC
|
||||
bool "J-Core integrated AIC" if COMPILE_TEST
|
||||
@@ -541,11 +544,11 @@ config CSKY_APB_INTC
|
||||
|
||||
config IMX_IRQSTEER
|
||||
bool "i.MX IRQSTEER support"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
default ARCH_MXC
|
||||
depends on ARCH_MXC || ARCH_S32 || COMPILE_TEST
|
||||
default y if ARCH_MXC || ARCH_S32
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Support for the i.MX IRQSTEER interrupt multiplexer/remapper.
|
||||
Support for the i.MX and S32 IRQSTEER interrupt multiplexer/remapper.
|
||||
|
||||
config IMX_INTMUX
|
||||
bool "i.MX INTMUX support" if COMPILE_TEST
|
||||
@@ -761,7 +764,6 @@ config LOONGSON_PCH_MSI
|
||||
|
||||
config LOONGSON_PCH_LPC
|
||||
bool "Loongson PCH LPC Controller"
|
||||
depends on LOONGARCH
|
||||
depends on MACH_LOONGSON64 || LOONGARCH
|
||||
default MACH_LOONGSON64
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
|
||||
@@ -134,8 +134,12 @@
|
||||
|
||||
#define AIC2_IRQ_CFG 0x2000
|
||||
|
||||
/* AIC v3 registers (MMIO) */
|
||||
#define AIC3_IRQ_CFG 0x10000
|
||||
|
||||
/*
|
||||
* AIC2 registers are laid out like this, starting at AIC2_IRQ_CFG:
|
||||
* AIC3 registers use the same layout but start at AIC3_IRQ_CFG:
|
||||
*
|
||||
* Repeat for each die:
|
||||
* IRQ_CFG: u32 * MAX_IRQS
|
||||
@@ -293,6 +297,15 @@ static const struct aic_info aic2_info __initconst = {
|
||||
.local_fast_ipi = true,
|
||||
};
|
||||
|
||||
static const struct aic_info aic3_info __initconst = {
|
||||
.version = 3,
|
||||
|
||||
.irq_cfg = AIC3_IRQ_CFG,
|
||||
|
||||
.fast_ipi = true,
|
||||
.local_fast_ipi = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id aic_info_match[] = {
|
||||
{
|
||||
.compatible = "apple,t8103-aic",
|
||||
@@ -310,6 +323,10 @@ static const struct of_device_id aic_info_match[] = {
|
||||
.compatible = "apple,aic2",
|
||||
.data = &aic2_info,
|
||||
},
|
||||
{
|
||||
.compatible = "apple,t8122-aic3",
|
||||
.data = &aic3_info,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -620,7 +637,7 @@ static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq,
|
||||
u32 type = FIELD_GET(AIC_EVENT_TYPE, hw);
|
||||
struct irq_chip *chip = &aic_chip;
|
||||
|
||||
if (ic->info.version == 2)
|
||||
if (ic->info.version == 2 || ic->info.version == 3)
|
||||
chip = &aic2_chip;
|
||||
|
||||
if (type == AIC_EVENT_TYPE_IRQ) {
|
||||
@@ -991,7 +1008,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
case 2 ... 3: {
|
||||
u32 info1, info3;
|
||||
|
||||
info1 = aic_ic_read(irqc, AIC2_INFO1);
|
||||
@@ -1065,7 +1082,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
|
||||
off += irqc->info.die_stride;
|
||||
}
|
||||
|
||||
if (irqc->info.version == 2) {
|
||||
if (irqc->info.version == 2 || irqc->info.version == 3) {
|
||||
u32 config = aic_ic_read(irqc, AIC2_CONFIG);
|
||||
|
||||
config |= AIC2_CONFIG_ENABLE;
|
||||
@@ -1116,3 +1133,4 @@ err_unmap:
|
||||
|
||||
IRQCHIP_DECLARE(apple_aic, "apple,aic", aic_of_ic_init);
|
||||
IRQCHIP_DECLARE(apple_aic2, "apple,aic2", aic_of_ic_init);
|
||||
IRQCHIP_DECLARE(apple_aic3, "apple,t8122-aic3", aic_of_ic_init);
|
||||
|
||||
@@ -1603,15 +1603,23 @@ static int gic_irq_domain_translate(struct irq_domain *d,
|
||||
|
||||
switch (fwspec->param[0]) {
|
||||
case 0: /* SPI */
|
||||
if (fwspec->param[1] > 987)
|
||||
pr_warn_once("SPI %u out of range (use ESPI?)\n", fwspec->param[1]);
|
||||
*hwirq = fwspec->param[1] + 32;
|
||||
break;
|
||||
case 1: /* PPI */
|
||||
if (fwspec->param[1] > 15)
|
||||
pr_warn_once("PPI %u out of range (use EPPI?)\n", fwspec->param[1]);
|
||||
*hwirq = fwspec->param[1] + 16;
|
||||
break;
|
||||
case 2: /* ESPI */
|
||||
if (fwspec->param[1] > 1023)
|
||||
pr_warn_once("ESPI %u out of range\n", fwspec->param[1]);
|
||||
*hwirq = fwspec->param[1] + ESPI_BASE_INTID;
|
||||
break;
|
||||
case 3: /* EPPI */
|
||||
if (fwspec->param[1] > 63)
|
||||
pr_warn_once("EPPI %u out of range\n", fwspec->param[1]);
|
||||
*hwirq = fwspec->param[1] + EPPI_BASE_INTID;
|
||||
break;
|
||||
case GIC_IRQ_TYPE_LPI: /* LPI */
|
||||
@@ -2252,7 +2260,7 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
|
||||
|
||||
out_unmap_rdist:
|
||||
for (i = 0; i < nr_redist_regions; i++)
|
||||
if (rdist_regs[i].redist_base && !IS_ERR(rdist_regs[i].redist_base))
|
||||
if (!IS_ERR_OR_NULL(rdist_regs[i].redist_base))
|
||||
iounmap(rdist_regs[i].redist_base);
|
||||
kfree(rdist_regs);
|
||||
out_unmap_dist:
|
||||
|
||||
@@ -26,19 +26,38 @@
|
||||
|
||||
#define CHAN_MAX_OUTPUT_INT 0xF
|
||||
|
||||
struct irqsteer_data {
|
||||
void __iomem *regs;
|
||||
struct clk *ipg_clk;
|
||||
int irq[CHAN_MAX_OUTPUT_INT];
|
||||
int irq_count;
|
||||
raw_spinlock_t lock;
|
||||
int reg_num;
|
||||
int channel;
|
||||
struct irq_domain *domain;
|
||||
u32 *saved_reg;
|
||||
struct device *dev;
|
||||
/* SoC does not implement the CHANCTRL register */
|
||||
#define IRQSTEER_QUIRK_NO_CHANCTRL BIT(0)
|
||||
|
||||
struct irqsteer_devtype_data {
|
||||
u32 quirks;
|
||||
};
|
||||
|
||||
struct irqsteer_data {
|
||||
void __iomem *regs;
|
||||
struct clk *ipg_clk;
|
||||
int irq[CHAN_MAX_OUTPUT_INT];
|
||||
int irq_count;
|
||||
raw_spinlock_t lock;
|
||||
int reg_num;
|
||||
int channel;
|
||||
struct irq_domain *domain;
|
||||
u32 *saved_reg;
|
||||
struct device *dev;
|
||||
const struct irqsteer_devtype_data *devtype_data;
|
||||
};
|
||||
|
||||
static const struct irqsteer_devtype_data imx_data = { };
|
||||
|
||||
static const struct irqsteer_devtype_data s32n79_data = {
|
||||
.quirks = IRQSTEER_QUIRK_NO_CHANCTRL,
|
||||
};
|
||||
|
||||
static bool irqsteer_has_chanctrl(const struct irqsteer_devtype_data *data)
|
||||
{
|
||||
return !(data->quirks & IRQSTEER_QUIRK_NO_CHANCTRL);
|
||||
}
|
||||
|
||||
static int imx_irqsteer_get_reg_index(struct irqsteer_data *data,
|
||||
unsigned long irqnum)
|
||||
{
|
||||
@@ -188,6 +207,10 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->devtype_data = device_get_match_data(&pdev->dev);
|
||||
if (!data->devtype_data)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV, "failed to match device data\n");
|
||||
|
||||
/*
|
||||
* There is one output irq for each group of 64 inputs.
|
||||
* One register bit map can represent 32 input interrupts.
|
||||
@@ -210,7 +233,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* steer all IRQs into configured channel */
|
||||
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
|
||||
if (irqsteer_has_chanctrl(data->devtype_data))
|
||||
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
|
||||
|
||||
data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->reg_num * 32,
|
||||
&imx_irqsteer_domain_ops, data);
|
||||
@@ -279,7 +303,9 @@ static void imx_irqsteer_restore_regs(struct irqsteer_data *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
|
||||
if (irqsteer_has_chanctrl(data->devtype_data))
|
||||
writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
|
||||
|
||||
for (i = 0; i < data->reg_num; i++)
|
||||
writel_relaxed(data->saved_reg[i],
|
||||
data->regs + CHANMASK(i, data->reg_num));
|
||||
@@ -319,7 +345,8 @@ static const struct dev_pm_ops imx_irqsteer_pm_ops = {
|
||||
};
|
||||
|
||||
static const struct of_device_id imx_irqsteer_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx-irqsteer", },
|
||||
{ .compatible = "fsl,imx-irqsteer", .data = &imx_data },
|
||||
{ .compatible = "nxp,s32n79-irqsteer", .data = &s32n79_data },
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include "irq-loongson.h"
|
||||
@@ -175,13 +177,10 @@ static struct syscore pch_lpc_syscore = {
|
||||
.ops = &pch_lpc_syscore_ops,
|
||||
};
|
||||
|
||||
int __init pch_lpc_acpi_init(struct irq_domain *parent,
|
||||
struct acpi_madt_lpc_pic *acpi_pchlpc)
|
||||
static int __init pch_lpc_init(phys_addr_t addr, unsigned long size,
|
||||
struct fwnode_handle *irq_handle, int parent_irq)
|
||||
{
|
||||
int parent_irq;
|
||||
struct pch_lpc *priv;
|
||||
struct irq_fwspec fwspec;
|
||||
struct fwnode_handle *irq_handle;
|
||||
|
||||
priv = kzalloc_obj(*priv);
|
||||
if (!priv)
|
||||
@@ -189,7 +188,7 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent,
|
||||
|
||||
raw_spin_lock_init(&priv->lpc_lock);
|
||||
|
||||
priv->base = ioremap(acpi_pchlpc->address, acpi_pchlpc->size);
|
||||
priv->base = ioremap(addr, size);
|
||||
if (!priv->base)
|
||||
goto free_priv;
|
||||
|
||||
@@ -198,12 +197,6 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent,
|
||||
goto iounmap_base;
|
||||
}
|
||||
|
||||
irq_handle = irq_domain_alloc_named_fwnode("lpcintc");
|
||||
if (!irq_handle) {
|
||||
pr_err("Unable to allocate domain handle\n");
|
||||
goto iounmap_base;
|
||||
}
|
||||
|
||||
/*
|
||||
* The LPC interrupt controller is a legacy i8259-compatible device,
|
||||
* which requires a static 1:1 mapping for IRQs 0-15.
|
||||
@@ -213,15 +206,10 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent,
|
||||
&pch_lpc_domain_ops, priv);
|
||||
if (!priv->lpc_domain) {
|
||||
pr_err("Failed to create IRQ domain\n");
|
||||
goto free_irq_handle;
|
||||
goto iounmap_base;
|
||||
}
|
||||
pch_lpc_reset(priv);
|
||||
|
||||
fwspec.fwnode = parent->fwnode;
|
||||
fwspec.param[0] = acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ;
|
||||
fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
|
||||
fwspec.param_count = 2;
|
||||
parent_irq = irq_create_fwspec_mapping(&fwspec);
|
||||
irq_set_chained_handler_and_data(parent_irq, lpc_irq_dispatch, priv);
|
||||
|
||||
pch_lpc_priv = priv;
|
||||
@@ -230,8 +218,6 @@ int __init pch_lpc_acpi_init(struct irq_domain *parent,
|
||||
|
||||
return 0;
|
||||
|
||||
free_irq_handle:
|
||||
irq_domain_free_fwnode(irq_handle);
|
||||
iounmap_base:
|
||||
iounmap(priv->base);
|
||||
free_priv:
|
||||
@@ -239,3 +225,69 @@ free_priv:
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
int __init pch_lpc_acpi_init(struct irq_domain *parent, struct acpi_madt_lpc_pic *acpi_pchlpc)
|
||||
{
|
||||
struct fwnode_handle *irq_handle;
|
||||
struct irq_fwspec fwspec;
|
||||
int parent_irq, ret;
|
||||
|
||||
irq_handle = irq_domain_alloc_named_fwnode("lpcintc");
|
||||
if (!irq_handle) {
|
||||
pr_err("Unable to allocate domain handle\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
fwspec.fwnode = parent->fwnode;
|
||||
fwspec.param[0] = acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ;
|
||||
fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
|
||||
fwspec.param_count = 2;
|
||||
parent_irq = irq_create_fwspec_mapping(&fwspec);
|
||||
if (parent_irq <= 0) {
|
||||
pr_err("Unable to map LPC parent interrupt\n");
|
||||
irq_domain_free_fwnode(irq_handle);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = pch_lpc_init(acpi_pchlpc->address, acpi_pchlpc->size, irq_handle, parent_irq);
|
||||
if (ret) {
|
||||
irq_dispose_mapping(parent_irq);
|
||||
irq_domain_free_fwnode(irq_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int __init pch_lpc_of_init(struct device_node *node, struct device_node *parent)
|
||||
{
|
||||
struct fwnode_handle *irq_handle;
|
||||
struct resource res;
|
||||
int parent_irq, ret;
|
||||
|
||||
if (of_address_to_resource(node, 0, &res))
|
||||
return -EINVAL;
|
||||
|
||||
parent_irq = irq_of_parse_and_map(node, 0);
|
||||
if (!parent_irq) {
|
||||
pr_err("Failed to get the parent IRQ for LPC IRQs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
irq_handle = of_fwnode_handle(node);
|
||||
|
||||
ret = pch_lpc_init(res.start, resource_size(&res), irq_handle,
|
||||
parent_irq);
|
||||
if (ret) {
|
||||
irq_dispose_mapping(parent_irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IRQCHIP_DECLARE(pch_lpc, "loongson,ls7a-lpc", pch_lpc_of_init);
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
@@ -217,7 +217,7 @@ err_unmap:
|
||||
for (i = 0; i < odmis_count; i++) {
|
||||
struct odmi_data *odmi = &odmis[i];
|
||||
|
||||
if (odmi->base && !IS_ERR(odmi->base))
|
||||
if (!IS_ERR_OR_NULL(odmi->base))
|
||||
iounmap(odmis[i].base);
|
||||
}
|
||||
bitmap_free(odmis_bm);
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_data/pic32.h>
|
||||
|
||||
#ifdef CONFIG_MIPS
|
||||
#include <asm/irq.h>
|
||||
#include <asm/traps.h>
|
||||
#endif
|
||||
|
||||
#define REG_INTCON 0x0000
|
||||
#define REG_INTSTAT 0x0020
|
||||
@@ -40,6 +42,7 @@ struct evic_chip_data {
|
||||
static struct irq_domain *evic_irq_domain;
|
||||
static void __iomem *evic_base;
|
||||
|
||||
#ifdef CONFIG_MIPS
|
||||
asmlinkage void __weak plat_irq_dispatch(void)
|
||||
{
|
||||
unsigned int hwirq;
|
||||
@@ -47,6 +50,9 @@ asmlinkage void __weak plat_irq_dispatch(void)
|
||||
hwirq = readl(evic_base + REG_INTSTAT) & 0xFF;
|
||||
do_domain_IRQ(evic_irq_domain, hwirq);
|
||||
}
|
||||
#else
|
||||
static __maybe_unused void (*board_bind_eic_interrupt)(int irq, int regset);
|
||||
#endif
|
||||
|
||||
static struct evic_chip_data *irqd_to_priv(struct irq_data *data)
|
||||
{
|
||||
@@ -196,7 +202,7 @@ static void __init pic32_ext_irq_of_init(struct irq_domain *domain)
|
||||
|
||||
of_property_for_each_u32(node, pname, hwirq) {
|
||||
if (i >= ARRAY_SIZE(priv->ext_irqs)) {
|
||||
pr_warn("More than %d external irq, skip rest\n",
|
||||
pr_warn("More than %zu external irq, skip rest\n",
|
||||
ARRAY_SIZE(priv->ext_irqs));
|
||||
break;
|
||||
}
|
||||
|
||||
+465
-117
File diff suppressed because it is too large
Load Diff
+371
-102
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user