diff options
48 files changed, 1510 insertions, 449 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt index 23b18b92c558..bde63f8f090e 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt @@ -18,6 +18,7 @@ Required properties: "amlogic,meson-g12a-gpio-intc" for G12A SoCs (S905D2, S905X2, S905Y2) "amlogic,meson-sm1-gpio-intc" for SM1 SoCs (S905D3, S905X3, S905Y3) "amlogic,meson-a1-gpio-intc" for A1 SoCs (A113L) + "amlogic,meson-s4-gpio-intc" for S4 SoCs (S802X2, S905Y4, S805X2G, S905W2) - reg : Specifies base physical address and size of the registers. - interrupt-controller : Identifies the node as an interrupt controller. - #interrupt-cells : Specifies the number of cells needed to encode an diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml new file mode 100644 index 000000000000..47a78a167aba --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/apple,aic2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Apple Interrupt Controller 2 + +maintainers: + - Hector Martin <marcan@marcan.st> + +description: | + The Apple Interrupt Controller 2 is a simple interrupt controller present on + Apple ARM SoC platforms starting with t600x (M1 Pro and Max). + + It provides the following features: + + - Level-triggered hardware IRQs wired to SoC blocks + - Single mask bit per IRQ + - Automatic masking on event delivery (auto-ack) + - Software triggering (ORed with hw line) + - Automatic prioritization (single event/ack register per CPU, lower IRQs = + higher priority) + - Automatic masking on ack + - Support for multiple dies + + This device also represents the FIQ interrupt sources on platforms using AIC, + which do not go through a discrete interrupt controller. It also handles + FIQ-based Fast IPIs. + +properties: + compatible: + items: + - const: apple,t6000-aic + - const: apple,aic2 + + interrupt-controller: true + + '#interrupt-cells': + const: 4 + description: | + The 1st cell contains the interrupt type: + - 0: Hardware IRQ + - 1: FIQ + + The 2nd cell contains the die ID. + + The next cell contains the interrupt number. + - HW IRQs: interrupt number + - FIQs: + - 0: physical HV timer + - 1: virtual HV timer + - 2: physical guest timer + - 3: virtual guest timer + + The last cell contains the interrupt flags. This is normally + IRQ_TYPE_LEVEL_HIGH (4). + + reg: + items: + - description: Address and size of the main AIC2 registers. + - description: Address and size of the AIC2 Event register. + + reg-names: + items: + - const: core + - const: event + + power-domains: + maxItems: 1 + +required: + - compatible + - '#interrupt-cells' + - interrupt-controller + - reg + - reg-names + +additionalProperties: false + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +examples: + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + + aic: interrupt-controller@28e100000 { + compatible = "apple,t6000-aic", "apple,aic2"; + #interrupt-cells = <4>; + interrupt-controller; + reg = <0x2 0x8e100000 0x0 0xc000>, + <0x2 0x8e10c000 0x0 0x4>; + reg-names = "core", "event"; + }; + }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml new file mode 100644 index 000000000000..509d20c091af --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,mpm.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/qcom,mpm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcom MPM Interrupt Controller + +maintainers: + - Shawn Guo <shawn.guo@linaro.org> + +description: + Qualcomm Technologies Inc. SoCs based on the RPM architecture have a + MSM Power Manager (MPM) that is in always-on domain. In addition to managing + resources during sleep, the hardware also has an interrupt controller that + monitors the interrupts when the system is asleep, wakes up the APSS when + one of these interrupts occur and replays it to GIC interrupt controller + after GIC becomes operational. + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +properties: + compatible: + items: + - const: qcom,mpm + + reg: + maxItems: 1 + description: + Specifies the base address and size of vMPM registers in RPM MSG RAM. + + interrupts: + maxItems: 1 + description: + Specify the IRQ used by RPM to wakeup APSS. + + mboxes: + maxItems: 1 + description: + Specify the mailbox used to notify RPM for writing vMPM registers. + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + description: + The first cell is the MPM pin number for the interrupt, and the second + is the trigger type. + + qcom,mpm-pin-count: + description: + Specify the total MPM pin count that a SoC supports. + $ref: /schemas/types.yaml#/definitions/uint32 + + qcom,mpm-pin-map: + description: + A set of MPM pin numbers and the corresponding GIC SPIs. + $ref: /schemas/types.yaml#/definitions/uint32-matrix + items: + items: + - description: MPM pin number + - description: GIC SPI number for the MPM pin + +required: + - compatible + - reg + - interrupts + - mboxes + - interrupt-controller + - '#interrupt-cells' + - qcom,mpm-pin-count + - qcom,mpm-pin-map + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + mpm: interrupt-controller@45f01b8 { + compatible = "qcom,mpm"; + interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>; + reg = <0x45f01b8 0x1000>; + mboxes = <&apcs_glb 1>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + qcom,mpm-pin-count = <96>; + qcom,mpm-pin-map = <2 275>, + <5 296>, + <12 422>, + <24 79>, + <86 183>, + <90 260>, + <91 260>; + }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml index d19c881b4abc..e44daa09b137 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml @@ -20,6 +20,7 @@ properties: - items: - enum: - st,stm32mp1-exti + - st,stm32mp13-exti - const: syscon "#interrupt-cells": diff --git a/MAINTAINERS b/MAINTAINERS index f092ad6d5212..0bbdd40cb23f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1769,7 +1769,7 @@ T: git https://github.com/AsahiLinux/linux.git F: Documentation/devicetree/bindings/arm/apple.yaml F: Documentation/devicetree/bindings/arm/apple/* F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml -F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml +F: Documentation/devicetree/bindings/interrupt-controller/apple,* F: Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml F: Documentation/devicetree/bindings/pci/apple,pcie.yaml F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 59798e43cdb0..da568e981604 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -45,6 +45,8 @@ config MICROBLAZE select SET_FS select ZONE_DMA select TRACE_IRQFLAGS_SUPPORT + select GENERIC_IRQ_MULTI_HANDLER + select HANDLE_DOMAIN_IRQ # Endianness selection choice diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h index 0a28e80bbab0..cb6ab55d1d01 100644 --- a/arch/microblaze/include/asm/irq.h +++ b/arch/microblaze/include/asm/irq.h @@ -11,7 +11,4 @@ struct pt_regs; extern void do_IRQ(struct pt_regs *regs); -/* should be defined in each interrupt controller driver */ -extern unsigned int xintc_get_irq(void); - #endif /* _ASM_MICROBLAZE_IRQ_H */ diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index 903dad822fad..1f8cb4c4f74f 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c @@ -20,27 +20,13 @@ #include <linux/irqchip.h> #include <linux/of_irq.h> -static u32 concurrent_irq; - void __irq_entry do_IRQ(struct pt_regs *regs) { - unsigned int irq; struct pt_regs *old_regs = set_irq_regs(regs); trace_hardirqs_off(); irq_enter(); - irq = xintc_get_irq(); -next_irq: - BUG_ON(!irq); - generic_handle_irq(irq); - - irq = xintc_get_irq(); - if (irq != -1U) { - pr_debug("next irq: %d\n", irq); - ++concurrent_irq; - goto next_irq; - } - + handle_arch_irq(regs); irq_exit(); set_irq_regs(old_regs); trace_hardirqs_on(); diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c index ccaad1cb3c2e..d8a26e503ca5 100644 --- a/drivers/gpio/gpio-mt7621.c +++ b/drivers/gpio/gpio-mt7621.c @@ -239,7 +239,6 @@ mediatek_gpio_bank_probe(struct device *dev, int bank) rg->chip.offset = bank * MTK_BANK_WIDTH; rg->irq_chip.name = dev_name(dev); - rg->irq_chip.parent_device = dev; rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask; rg->irq_chip.irq_mask = mediatek_gpio_irq_mask; rg->irq_chip.irq_mask_ack = mediatek_gpio_irq_mask; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index e099c39e0355..80ddc43fd875 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -986,7 +986,8 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) writel_relaxed(0, base + bank->regs->ctrl); } -static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) +static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc, + struct device *pm_dev) { struct gpio_irq_chip *irq; static int gpio; @@ -1052,6 +1053,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) if (ret) return dev_err_probe(bank->chip.parent, ret, "Could not register gpio chip\n"); + irq_domain_set_pm_device(bank->chip.irq.domain, pm_dev); ret = devm_request_irq(bank->chip.parent, bank->irq, omap_gpio_irq_handler, 0, dev_name(bank->chip.parent), bank); @@ -1402,7 +1404,6 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, irqc->name = dev_name(&pdev->dev); irqc->flags = IRQCHIP_MASK_ON_SUSPEND; - irqc->parent_device = dev; bank->irq = platform_get_irq(pdev, 0); if (bank->irq <= 0) { @@ -1466,7 +1467,7 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_gpio_mod_init(bank); - ret = omap_gpio_chip_init(bank, irqc); + ret = omap_gpio_chip_init(bank, irqc, dev); if (ret) { pm_runtime_put_sync(dev); pm_runtime_disable(dev); diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index bd2e16d6e21c..3a76538f27fa 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -530,7 +530,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip = &p->irq_chip; irq_chip->name = "gpio-rcar"; - irq_chip->parent_device = dev; irq_chip->irq_mask = gpio_rcar_irq_disable; irq_chip->irq_unmask = gpio_rcar_irq_enable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; @@ -552,6 +551,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) goto err0; } + irq_domain_set_pm_device(gpio_chip->irq.domain, dev); ret = devm_request_irq(dev, p->irq_parent, gpio_rcar_irq_handler, IRQF_SHARED, name, p); if (ret) { diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c index 5b103221b58d..fa4bc7481f9a 100644 --- a/drivers/gpio/gpio-tqmx86.c +++ b/drivers/gpio/gpio-tqmx86.c @@ -281,7 +281,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) u8 irq_status; irq_chip->name = chip->label; - irq_chip->parent_device = &pdev->dev; irq_chip->irq_mask = tqmx86_gpio_irq_mask; irq_chip->irq_unmask = tqmx86_gpio_irq_unmask; irq_chip->irq_set_type = tqmx86_gpio_irq_set_type; @@ -316,6 +315,8 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) goto out_pm_dis; } + irq_domain_set_pm_device(girq->domain, dev); + dev_info(dev, "GPIO functionality initialized with %d pins\n", chip->ngpio); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 7038957f4a77..680d2fcf2686 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -430,6 +430,14 @@ config QCOM_PDC Power Domain Controller driver to manage and configure wakeup IRQs for Qualcomm Technologies Inc (QTI) mobile chips. +config QCOM_MPM + tristate "QCOM MPM" + depends on ARCH_QCOM + select IRQ_DOMAIN_HIERARCHY + help + MSM Power Manager driver to manage and configure wakeup + IRQs for Qualcomm Technologies Inc (QTI) mobile chips. + config CSKY_MPINTC bool depends on CSKY diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index c1f611cbfbf8..1f8990f812f1 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -94,6 +94,7 @@ obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o obj-$(CONFIG_NDS32) += irq-ativic32.o obj-$(CONFIG_QCOM_PDC) += qcom-pdc.o +obj-$(CONFIG_QCOM_MPM) += irq-qcom-mpm.o obj-$(CONFIG_CSKY_MPINTC) += irq-csky-mpintc.o obj-$(CONFIG_CSKY_APB_INTC) += irq-csky-apb-intc.o obj-$(CONFIG_RISCV_INTC) += irq-riscv-intc.o diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index b40199c6625e..12dd48727a15 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -24,7 +24,7 @@ * - Default "this CPU" register view and explicit per-CPU views * * In addition, this driver also handles FIQs, as these are routed to the same - * IRQ vector. These are used for Fast IPIs (TODO), the ARMv8 timer IRQs, and + * IRQ vector. These are used for Fast IPIs, the ARMv8 timer IRQs, and * performance counters (TODO). * * Implementation notes: @@ -52,10 +52,12 @@ #include <linux/irqchip.h> #include <linux/irqchip/arm-vgic-info.h> #include <linux/irqdomain.h> +#include <linux/jump_label.h> #include <linux/limits.h> #include <linux/of_address.h> #include <linux/slab.h> #include <asm/apple_m1_pmu.h> +#include <asm/cputype.h> #include <asm/exception.h> #include <asm/sysreg.h> #include <asm/virt.h> @@ -63,20 +65,22 @@ #include <dt-bindings/interrupt-controller/apple-aic.h> /* - * AIC registers (MMIO) + * AIC v1 registers (MMIO) */ #define AIC_INFO 0x0004 -#define AIC_INFO_NR_HW GENMASK(15, 0) +#define AIC_INFO_NR_IRQ GENMASK(15, 0) #define AIC_CONFIG 0x0010 #define AIC_WHOAMI 0x2000 #define AIC_EVENT 0x2004 -#define AIC_EVENT_TYPE GENMASK(31, 16) +#define AIC_EVENT_DIE GENMASK(31, 24) +#define AIC_EVENT_TYPE GENMASK(23, 16) #define AIC_EVENT_NUM GENMASK(15, 0) -#define AIC_EVENT_TYPE_HW 1 +#define AIC_EVENT_TYPE_FIQ 0 /* Software use */ +#define AIC_EVENT_TYPE_IRQ 1 #define AIC_EVENT_TYPE_IPI 4 #define AIC_EVENT_IPI_OTHER 1 #define AIC_EVENT_IPI_SELF 2 @@ -92,22 +96,71 @@ #define AIC_IPI_SELF BIT(31) #define AIC_TARGET_CPU 0x3000 -#define AIC_SW_SET 0x4000 -#define AIC_SW_CLR 0x4080 -#define AIC_MASK_SET 0x4100 -#define AIC_MASK_CLR 0x4180 #define AIC_CPU_IPI_SET(cpu) (0x5008 + ((cpu) << 7)) #define AIC_CPU_IPI_CLR(cpu) (0x500c + ((cpu) << 7)) #define AIC_CPU_IPI_MASK_SET(cpu) (0x5024 + ((cpu) << 7)) #define AIC_CPU_IPI_MASK_CLR(cpu) (0x5028 + ((cpu) << 7)) +#define AIC_MAX_IRQ 0x400 + +/* + * AIC v2 registers (MMIO) + */ + +#define AIC2_VERSION 0x0000 +#define AIC2_VERSION_VER GENMASK(7, 0) + +#define AIC2_INFO1 0x0004 +#define AIC2_INFO1_NR_IRQ GENMASK(15, 0) +#define AIC2_INFO1_LAST_DIE GENMASK(27, 24) + +#define AIC2_INFO2 0x0008 + +#define AIC2_INFO3 0x000c +#define AIC2_INFO3_MAX_IRQ GENMASK(15, 0) +#define AIC2_INFO3_MAX_DIE GENMASK(27, 24) + +#define AIC2_RESET 0x0010 +#define AIC2_RESET_RESET BIT(0) + +#define AIC2_CONFIG 0x0014 +#define AIC2_CONFIG_ENABLE BIT(0) +#define AIC2_CONFIG_PREFER_PCPU BIT(28) + +#define AIC2_TIMEOUT 0x0028 +#define AIC2_CLUSTER_PRIO 0x0030 +#define AIC2_DELAY_GROUPS 0x0100 + +#define AIC2_IRQ_CFG 0x2000 + +/* + * AIC2 registers are laid out like this, starting at AIC2_IRQ_CFG: + * + * Repeat for each die: + * IRQ_CFG: u32 * MAX_IRQS + * SW_SET: u32 * (MAX_IRQS / 32) + * SW_CLR: u32 * (MAX_IRQS / 32) + * MASK_SET: u32 * (MAX_IRQS / 32) + * MASK_CLR: u32 * (MAX_IRQS / 32) + * HW_STATE: u32 * (MAX_IRQS / 32) + * + * This is followed by a set of event registers, each 16K page aligned. + * The first one is the AP event register we will use. Unfortunately, + * the actual implemented die count is not specified anywhere in the + * capability registers, so we have to explicitly specify the event + * register as a second reg entry in the device tree to remain + * forward-compatible. + */ + +#define AIC2_IRQ_CFG_TARGET GENMASK(3, 0) +#define AIC2_IRQ_CFG_DELAY_IDX GENMASK(7, 5) + #define MASK_REG(x) (4 * ((x) >> 5)) #define MASK_BIT(x) BIT((x) & GENMASK(4, 0)) /* * IMP-DEF sysregs that control FIQ sources - * Note: sysreg-based IPIs are not supported yet. */ /* IPI request registers */ @@ -146,6 +199,17 @@ #define SYS_IMP_APL_UPMSR_EL1 sys_reg(3, 7, 15, 6, 4) #define UPMSR_IACT BIT(0) +/* MPIDR fields */ +#define MPIDR_CPU(x) MPIDR_AFFINITY_LEVEL(x, 0) +#define MPIDR_CLUSTER(x) MPIDR_AFFINITY_LEVEL(x, 1) + +#define AIC_IRQ_HWIRQ(die, irq) (FIELD_PREP(AIC_EVENT_DIE, die) | \ + FIELD_PREP(AIC_EVENT_TYPE, AIC_EVENT_TYPE_IRQ) | \ + FIELD_PREP(AIC_EVENT_NUM, irq)) +#define AIC_FIQ_HWIRQ(x) (FIELD_PREP(AIC_EVENT_TYPE, AIC_EVENT_TYPE_FIQ) | \ + FIELD_PREP(AIC_EVENT_NUM, x)) +#define AIC_HWIRQ_IRQ(x) FIELD_GET(AIC_EVENT_NUM, x) +#define AIC_HWIRQ_DIE(x) FIELD_GET(AIC_EVENT_DIE, x) #define AIC_NR_FIQ 6 #define AIC_NR_SWIPI 32 @@ -164,14 +228,81 @@ #define AIC_TMR_EL02_PHYS AIC_TMR_GUEST_PHYS #define AIC_TMR_EL02_VIRT AIC_TMR_GUEST_VIRT +DEFINE_STATIC_KEY_TRUE(use_fast_ipi); + +struct aic_info { + int version; + + /* Register offsets */ + u32 event; + u32 target_cpu; + u32 irq_cfg; + u32 sw_set; + u32 sw_clr; + u32 mask_set; + u32 mask_clr; + + u32 die_stride; + + /* Features */ + bool fast_ipi; +}; + +static const struct aic_info aic1_info = { + .version = 1, + + .event = AIC_EVENT, + .target_cpu = AIC_TARGET_CPU, +}; + +static const struct aic_info aic1_fipi_info = { + .version = 1, + + .event = AIC_EVENT, + .target_cpu = AIC_TARGET_CPU, + + .fast_ipi = true, +}; + +static const struct aic_info aic2_info = { + .version = 2, + + .irq_cfg = AIC2_IRQ_CFG, + + .fast_ipi = true, +}; + +static const struct of_device_id aic_info_match[] = { + { + .compatible = "apple,t8103-aic", + .data = &aic1_fipi_info, + }, + { + .compatible = "apple,aic", + .data = &aic1_info, + }, + { + .compatible = "apple,aic2", + .data = &aic2_info, + }, + {} +}; + struct aic_irq_chip { void __iomem *base; + void __iomem *event; struct irq_domain *hw_domain; struct irq_domain *ipi_domain; struct { cpumask_t aff; } *fiq_aff[AIC_NR_FIQ]; - int nr_hw; + + int nr_irq; + int max_irq; + int nr_die; + int max_die; + + struct aic_info info; }; static DEFINE_PER_CPU(uint32_t, aic_fiq_unmasked); @@ -199,18 +330,24 @@ static void aic_ic_write(struct aic_irq_chip *ic, u32 reg, u32 val) static void aic_irq_mask(struct irq_data *d) { + irq_hw_number_t hwirq = irqd_to_hwirq(d); struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); - aic_ic_write(ic, AIC_MASK_SET + MASK_REG(irqd_to_hwirq(d)), - MASK_BIT(irqd_to_hwirq(d))); + u32 off = AIC_HWIRQ_DIE(hwirq) * ic->info.die_stride; + u32 irq = AIC_HWIRQ_IRQ(hwirq); + + aic_ic_write(ic, ic->info.mask_set + off + MASK_REG(irq), MASK_BIT(irq)); } static void aic_irq_unmask(struct irq_data *d) { + irq_hw_number_t hwirq = irqd_to_hwirq(d); struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); - aic_ic_write(ic, AIC_MASK_CLR + MASK_REG(d->hwirq), - MASK_BIT(irqd_to_hwirq(d))); + u32 off = AIC_HWIRQ_DIE(hwirq) * ic->info.die_stride; + u32 irq = AIC_HWIRQ_IRQ(hwirq); + + aic_ic_write(ic, ic->info.mask_clr + off + MASK_REG(irq), MASK_BIT(irq)); } static void aic_irq_eoi(struct irq_data *d) @@ -233,12 +370,12 @@ static void __exception_irq_entry aic_handle_irq(struct pt_regs *regs) * We cannot use a relaxed read here, as reads from DMA buffers * need to be ordered after the IRQ fires. */ - event = readl(ic->base + AIC_EVENT); + event = readl(ic->event + ic->info.event); type = FIELD_GET(AIC_EVENT_TYPE, event); irq = FIELD_GET(AIC_EVENT_NUM, event); - if (type = |
