From: Hector Martin <marcan@marcan.st> To: Hector Martin <marcan@marcan.st>, soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, Marc Zyngier <maz@kernel.org>, robh+dt@kernel.org, Arnd Bergmann <arnd@kernel.org>, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Olof Johansson <olof@lixom.net> Subject: [PATCH 15/18] irqchip/apple-aic: Add support for the Apple Interrupt Controller Date: Fri, 5 Feb 2021 05:39:48 +0900 [thread overview] Message-ID: <20210204203951.52105-16-marcan@marcan.st> (raw) In-Reply-To: <20210204203951.52105-1-marcan@marcan.st> This is the root interrupt controller used on Apple ARM SoCs such as the M1. This irqchip driver performs multiple functions: * Discriminates between IRQs and FIQs * Drives the AIC peripheral itself (which handles IRQs) * Dispatches FIQs to downstream hard-wired clients (currently the ARM timer). This patch introduces basic UP irqchip support, without SMP/IPI support. Signed-off-by: Hector Martin <marcan@marcan.st> --- MAINTAINERS | 1 + drivers/irqchip/Kconfig | 10 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-apple-aic.c | 316 ++++++++++++++++++++++++++++++++ 4 files changed, 328 insertions(+) create mode 100644 drivers/irqchip/irq-apple-aic.c diff --git a/MAINTAINERS b/MAINTAINERS index f3d4661731c8..3a54ee5747d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1635,6 +1635,7 @@ C: irc://chat.freenode.net/asahi-dev T: git https://github.com/AsahiLinux/linux.git F: Documentation/devicetree/bindings/arm/AAPL.yaml F: Documentation/devicetree/bindings/interrupt-controller/AAPL,aic.yaml +F: drivers/irqchip/irq-apple-aic.c F: include/dt-bindings/interrupt-controller/apple-aic.h ARM/ARTPEC MACHINE SUPPORT diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b147f22a78f4..288c01a9abd4 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -590,4 +590,14 @@ config MST_IRQ help Support MStar Interrupt Controller. +config APPLE_AIC + bool "Apple Interrupt Controller (AIC)" + depends on ARCH_APPLE || COMPILE_TEST + default ARCH_APPLE + select IRQ_DOMAIN + select IRQ_DOMAIN_HIERARCHY + help + Support for the Apple Interrupt Controller found on Apple Silicon SoCs, + such as the M1. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 0ac93bfaec61..0e2ba7c2dce7 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -113,3 +113,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-loongson-pch-pic.o obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o +obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c new file mode 100644 index 000000000000..533e3ce9f432 --- /dev/null +++ b/drivers/irqchip/irq-apple-aic.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2021 Hector Martin <marcan@marcan.st> + * + * Based on irq-lpc32xx: + * Copyright 2015-2016 Vladimir Zapolskiy <vz@mleia.com> + * Based on irq-bcm2836: + * Copyright 2015 Broadcom + */ + +/* + * AIC is a fairly simple interrupt controller with the following features: + * + * - 896 level-triggered hardware IRQs + * - Single mask bit per IRQ + * - Per-IRQ affinity setting + * - Automatic masking on event delivery (auto-ack) + * - Software triggering (ORed with hw line) + * - 2 per-CPU IPIs (meant as "self" and "other", but they are interchangeable if not symmetric) + * - Automatic prioritization (single event/ack register per CPU, lower IRQs = higher priority) + * - Automatic masking on ack + * - 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) and the ARMv8 timer IRQs. + * + * Implementation notes: + * + * - This driver creates one IRQ domain for HW IRQs and the timer FIQs + * - FIQ hwirq numbers are assigned after true hwirqs, and are per-cpu + * - DT bindings use 3-cell form (like GIC): + * - <0 nr flags> - hwirq #nr + * - <1 nr flags> - FIQ #nr + * - nr=0 physical timer + * - nr=1 virtual timer + * - <2 nr flags> - IPI #nr + * - nr=0 other IPI + * - nr=1 self IPI + * + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include <linux/io.h> +#include <linux/irqchip.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/slab.h> +#include <asm/exception.h> + +#include <dt-bindings/interrupt-controller/apple-aic.h> + +#define AIC_INFO 0x0004 +#define AIC_INFO_NR_HW(i) ((i) & 0x0000ffff) + +#define AIC_CONFIG 0x0010 + +#define AIC_WHOAMI 0x2000 +#define AIC_EVENT 0x2004 + +#define AIC_EVENT_TYPE_HW 1 +#define AIC_EVENT_TYPE_IPI 4 +#define AIC_EVENT_IPI_OTHER 1 +#define AIC_EVENT_IPI_SELF 2 + +#define AIC_IPI_SEND 0x2008 +#define AIC_IPI_ACK 0x200c +#define AIC_IPI_MASK_SET 0x2024 +#define AIC_IPI_MASK_CLR 0x2028 + +#define AIC_IPI_SEND_CPU(cpu) BIT(cpu) + +#define AIC_IPI_OTHER BIT(0) +#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 MASK_REG(x) (4 * ((x) >> 5)) +#define MASK_BIT(x) BIT((x) & 0x1f) + +#define AIC_NR_FIQ 2 +#define AIC_NR_IPI 2 + +/* + * Max 31 bits in IPI SEND register (top bit is self). + * >=32-core chips will need code changes anyway. + */ +#define AIC_MAX_CPUS 31 + +struct aic_irq_chip { + void __iomem *base; + struct irq_domain *hw_domain; + int nr_hw; +}; + +static struct aic_irq_chip *aic_irqc; + +static inline u32 aic_ic_read(struct aic_irq_chip *ic, u32 reg) +{ + return readl(ic->base + reg); +} + +static inline void aic_ic_write(struct aic_irq_chip *ic, u32 reg, u32 val) +{ + writel(val, ic->base + reg); +} + +/* These functions do nothing for FIQs, because they have no masks */ +static void aic_irq_mask(struct irq_data *d) +{ + struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); + + if (d->hwirq < ic->nr_hw) + aic_ic_write(ic, AIC_MASK_SET + MASK_REG(d->hwirq), + MASK_BIT(d->hwirq)); +} + +static void aic_irq_unmask(struct irq_data *d) +{ + struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); + + if (d->hwirq < ic->nr_hw) + aic_ic_write(ic, AIC_MASK_CLR + MASK_REG(d->hwirq), + MASK_BIT(d->hwirq)); +} + +static void aic_irq_eoi(struct irq_data *d) +{ + /* + * Reading the interrupt reason automatically acknowledges and masks + * the IRQ, so we just unmask it here if needed. + */ + if (!irqd_irq_disabled(d) && !irqd_irq_masked(d)) + aic_irq_unmask(d); +} + +static void aic_handle_irq(struct pt_regs *regs) +{ + struct aic_irq_chip *ic = aic_irqc; + u32 event = aic_ic_read(ic, AIC_EVENT); + + while (event) { + u32 type = event >> 16, irq = event & 0xffff; + + /* AIC_EVENT is read-sensitive, ensure it happens before we proceed */ + isb(); + + if (type == AIC_EVENT_TYPE_HW) { + handle_domain_irq(aic_irqc->hw_domain, irq, regs); + } else if (type == AIC_EVENT_TYPE_IPI) { + handle_domain_irq(aic_irqc->hw_domain, + ic->nr_hw + AIC_NR_FIQ + irq - 1, regs); + } else { + pr_err("spurious IRQ event %d, %d\n", type, irq); + } + + event = aic_ic_read(ic, AIC_EVENT); + } +} + +#define TIMER_FIRING(x) \ + (((x) & (ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_MASK | \ + ARCH_TIMER_CTRL_IT_STAT)) == \ + (ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_STAT)) + +static void aic_handle_fiq(struct pt_regs *regs) +{ + /* + * It would be really nice to find a system register that lets us get the FIQ source + * state without having to peek down into clients... + */ + if (TIMER_FIRING(read_sysreg(cntp_ctl_el0))) { + handle_domain_irq(aic_irqc->hw_domain, + aic_irqc->nr_hw + AIC_TMR_PHYS, regs); + } + + if (TIMER_FIRING(read_sysreg(cntv_ctl_el0))) { + handle_domain_irq(aic_irqc->hw_domain, + aic_irqc->nr_hw + AIC_TMR_VIRT, regs); + } +} + +static void __exception_irq_entry aic_handle_irq_or_fiq(struct pt_regs *regs) +{ + u64 isr = read_sysreg(isr_el1); + + if (isr & PSR_F_BIT) + aic_handle_fiq(regs); + + if (isr & PSR_I_BIT) + aic_handle_irq(regs); +} + +static struct irq_chip aic_chip = { + .name = "AIC", + .irq_mask = aic_irq_mask, + .irq_unmask = aic_irq_unmask, + .irq_eoi = aic_irq_eoi, +}; + +static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq, + irq_hw_number_t hw) +{ + struct aic_irq_chip *ic = id->host_data; + + irq_set_chip_data(irq, ic); + if (hw < ic->nr_hw) { + irq_set_chip_and_handler(irq, &aic_chip, handle_fasteoi_irq); + } else { + irq_set_percpu_devid(irq); + irq_set_chip_and_handler(irq, &aic_chip, + handle_percpu_devid_irq); + } + irq_set_status_flags(irq, IRQ_LEVEL); + irq_set_noprobe(irq); + + return 0; +} + +static void aic_irq_domain_unmap(struct irq_domain *id, unsigned int irq) +{ + irq_set_chip_and_handler(irq, NULL, NULL); +} + +static int aic_irq_domain_xlate(struct irq_domain *id, + struct device_node *ctrlr, const u32 *intspec, + unsigned int intsize, + irq_hw_number_t *out_hwirq, + unsigned int *out_type) +{ + struct aic_irq_chip *ic = id->host_data; + + if (intsize != 3) + return -EINVAL; + + if (intspec[0] == AIC_IRQ && intspec[1] < ic->nr_hw) + *out_hwirq = intspec[1]; + else if (intspec[0] == AIC_FIQ && intspec[1] < AIC_NR_FIQ) + *out_hwirq = ic->nr_hw + intspec[1]; + else if (intspec[0] == AIC_IPI && intspec[1] < AIC_NR_IPI) + *out_hwirq = ic->nr_hw + AIC_NR_FIQ + intspec[1]; + else + return -EINVAL; + + *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; + + return 0; +} + +static const struct irq_domain_ops aic_irq_domain_ops = { + .map = aic_irq_domain_map, + .unmap = aic_irq_domain_unmap, + .xlate = aic_irq_domain_xlate, +}; + +static int __init aic_of_ic_init(struct device_node *node, + struct device_node *parent) +{ + int i; + void __iomem *regs; + u32 info; + struct aic_irq_chip *irqc; + + regs = of_iomap(node, 0); + if (WARN_ON(!regs)) + return -EIO; + + irqc = kzalloc(sizeof(*irqc), GFP_KERNEL); + if (!irqc) + return -ENOMEM; + + aic_irqc = irqc; + irqc->base = regs; + + info = aic_ic_read(irqc, AIC_INFO); + irqc->nr_hw = AIC_INFO_NR_HW(info); + + irqc->hw_domain = + irq_domain_add_linear(node, + irqc->nr_hw + AIC_NR_FIQ + AIC_NR_IPI, + &aic_irq_domain_ops, irqc); + if (WARN_ON(!irqc->hw_domain)) { + iounmap(irqc->base); + kfree(irqc); + return -ENODEV; + } + + irq_domain_update_bus_token(irqc->hw_domain, DOMAIN_BUS_WIRED); + + set_handle_irq(aic_handle_irq_or_fiq); + + for (i = 0; i < BITS_TO_LONGS(irqc->nr_hw); i++) + aic_ic_write(irqc, AIC_MASK_SET + i * 4, ~0); + for (i = 0; i < BITS_TO_LONGS(irqc->nr_hw); i++) + aic_ic_write(irqc, AIC_SW_CLR + i * 4, ~0); + for (i = 0; i < irqc->nr_hw; i++) + aic_ic_write(irqc, AIC_TARGET_CPU + i * 4, 1); + + pr_info("AIC: initialized with %d IRQs, %d FIQs, %d IPIs\n", + irqc->nr_hw, AIC_NR_FIQ, AIC_NR_IPI); + + return 0; +} + +IRQCHIP_DECLARE(apple_m1_aic, "AAPL,aic", aic_of_ic_init); -- 2.30.0
WARNING: multiple messages have this Message-ID (diff)
From: Hector Martin <marcan@marcan.st> To: Hector Martin <marcan@marcan.st>, soc@kernel.org Cc: devicetree@vger.kernel.org, Arnd Bergmann <arnd@kernel.org>, Marc Zyngier <maz@kernel.org>, linux-kernel@vger.kernel.org, robh+dt@kernel.org, Olof Johansson <olof@lixom.net>, linux-arm-kernel@lists.infradead.org Subject: [PATCH 15/18] irqchip/apple-aic: Add support for the Apple Interrupt Controller Date: Fri, 5 Feb 2021 05:39:48 +0900 [thread overview] Message-ID: <20210204203951.52105-16-marcan@marcan.st> (raw) In-Reply-To: <20210204203951.52105-1-marcan@marcan.st> This is the root interrupt controller used on Apple ARM SoCs such as the M1. This irqchip driver performs multiple functions: * Discriminates between IRQs and FIQs * Drives the AIC peripheral itself (which handles IRQs) * Dispatches FIQs to downstream hard-wired clients (currently the ARM timer). This patch introduces basic UP irqchip support, without SMP/IPI support. Signed-off-by: Hector Martin <marcan@marcan.st> --- MAINTAINERS | 1 + drivers/irqchip/Kconfig | 10 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-apple-aic.c | 316 ++++++++++++++++++++++++++++++++ 4 files changed, 328 insertions(+) create mode 100644 drivers/irqchip/irq-apple-aic.c diff --git a/MAINTAINERS b/MAINTAINERS index f3d4661731c8..3a54ee5747d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1635,6 +1635,7 @@ C: irc://chat.freenode.net/asahi-dev T: git https://github.com/AsahiLinux/linux.git F: Documentation/devicetree/bindings/arm/AAPL.yaml F: Documentation/devicetree/bindings/interrupt-controller/AAPL,aic.yaml +F: drivers/irqchip/irq-apple-aic.c F: include/dt-bindings/interrupt-controller/apple-aic.h ARM/ARTPEC MACHINE SUPPORT diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b147f22a78f4..288c01a9abd4 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -590,4 +590,14 @@ config MST_IRQ help Support MStar Interrupt Controller. +config APPLE_AIC + bool "Apple Interrupt Controller (AIC)" + depends on ARCH_APPLE || COMPILE_TEST + default ARCH_APPLE + select IRQ_DOMAIN + select IRQ_DOMAIN_HIERARCHY + help + Support for the Apple Interrupt Controller found on Apple Silicon SoCs, + such as the M1. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 0ac93bfaec61..0e2ba7c2dce7 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -113,3 +113,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-loongson-pch-pic.o obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o +obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c new file mode 100644 index 000000000000..533e3ce9f432 --- /dev/null +++ b/drivers/irqchip/irq-apple-aic.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2021 Hector Martin <marcan@marcan.st> + * + * Based on irq-lpc32xx: + * Copyright 2015-2016 Vladimir Zapolskiy <vz@mleia.com> + * Based on irq-bcm2836: + * Copyright 2015 Broadcom + */ + +/* + * AIC is a fairly simple interrupt controller with the following features: + * + * - 896 level-triggered hardware IRQs + * - Single mask bit per IRQ + * - Per-IRQ affinity setting + * - Automatic masking on event delivery (auto-ack) + * - Software triggering (ORed with hw line) + * - 2 per-CPU IPIs (meant as "self" and "other", but they are interchangeable if not symmetric) + * - Automatic prioritization (single event/ack register per CPU, lower IRQs = higher priority) + * - Automatic masking on ack + * - 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) and the ARMv8 timer IRQs. + * + * Implementation notes: + * + * - This driver creates one IRQ domain for HW IRQs and the timer FIQs + * - FIQ hwirq numbers are assigned after true hwirqs, and are per-cpu + * - DT bindings use 3-cell form (like GIC): + * - <0 nr flags> - hwirq #nr + * - <1 nr flags> - FIQ #nr + * - nr=0 physical timer + * - nr=1 virtual timer + * - <2 nr flags> - IPI #nr + * - nr=0 other IPI + * - nr=1 self IPI + * + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include <linux/io.h> +#include <linux/irqchip.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/slab.h> +#include <asm/exception.h> + +#include <dt-bindings/interrupt-controller/apple-aic.h> + +#define AIC_INFO 0x0004 +#define AIC_INFO_NR_HW(i) ((i) & 0x0000ffff) + +#define AIC_CONFIG 0x0010 + +#define AIC_WHOAMI 0x2000 +#define AIC_EVENT 0x2004 + +#define AIC_EVENT_TYPE_HW 1 +#define AIC_EVENT_TYPE_IPI 4 +#define AIC_EVENT_IPI_OTHER 1 +#define AIC_EVENT_IPI_SELF 2 + +#define AIC_IPI_SEND 0x2008 +#define AIC_IPI_ACK 0x200c +#define AIC_IPI_MASK_SET 0x2024 +#define AIC_IPI_MASK_CLR 0x2028 + +#define AIC_IPI_SEND_CPU(cpu) BIT(cpu) + +#define AIC_IPI_OTHER BIT(0) +#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 MASK_REG(x) (4 * ((x) >> 5)) +#define MASK_BIT(x) BIT((x) & 0x1f) + +#define AIC_NR_FIQ 2 +#define AIC_NR_IPI 2 + +/* + * Max 31 bits in IPI SEND register (top bit is self). + * >=32-core chips will need code changes anyway. + */ +#define AIC_MAX_CPUS 31 + +struct aic_irq_chip { + void __iomem *base; + struct irq_domain *hw_domain; + int nr_hw; +}; + +static struct aic_irq_chip *aic_irqc; + +static inline u32 aic_ic_read(struct aic_irq_chip *ic, u32 reg) +{ + return readl(ic->base + reg); +} + +static inline void aic_ic_write(struct aic_irq_chip *ic, u32 reg, u32 val) +{ + writel(val, ic->base + reg); +} + +/* These functions do nothing for FIQs, because they have no masks */ +static void aic_irq_mask(struct irq_data *d) +{ + struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); + + if (d->hwirq < ic->nr_hw) + aic_ic_write(ic, AIC_MASK_SET + MASK_REG(d->hwirq), + MASK_BIT(d->hwirq)); +} + +static void aic_irq_unmask(struct irq_data *d) +{ + struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); + + if (d->hwirq < ic->nr_hw) + aic_ic_write(ic, AIC_MASK_CLR + MASK_REG(d->hwirq), + MASK_BIT(d->hwirq)); +} + +static void aic_irq_eoi(struct irq_data *d) +{ + /* + * Reading the interrupt reason automatically acknowledges and masks + * the IRQ, so we just unmask it here if needed. + */ + if (!irqd_irq_disabled(d) && !irqd_irq_masked(d)) + aic_irq_unmask(d); +} + +static void aic_handle_irq(struct pt_regs *regs) +{ + struct aic_irq_chip *ic = aic_irqc; + u32 event = aic_ic_read(ic, AIC_EVENT); + + while (event) { + u32 type = event >> 16, irq = event & 0xffff; + + /* AIC_EVENT is read-sensitive, ensure it happens before we proceed */ + isb(); + + if (type == AIC_EVENT_TYPE_HW) { + handle_domain_irq(aic_irqc->hw_domain, irq, regs); + } else if (type == AIC_EVENT_TYPE_IPI) { + handle_domain_irq(aic_irqc->hw_domain, + ic->nr_hw + AIC_NR_FIQ + irq - 1, regs); + } else { + pr_err("spurious IRQ event %d, %d\n", type, irq); + } + + event = aic_ic_read(ic, AIC_EVENT); + } +} + +#define TIMER_FIRING(x) \ + (((x) & (ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_MASK | \ + ARCH_TIMER_CTRL_IT_STAT)) == \ + (ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_STAT)) + +static void aic_handle_fiq(struct pt_regs *regs) +{ + /* + * It would be really nice to find a system register that lets us get the FIQ source + * state without having to peek down into clients... + */ + if (TIMER_FIRING(read_sysreg(cntp_ctl_el0))) { + handle_domain_irq(aic_irqc->hw_domain, + aic_irqc->nr_hw + AIC_TMR_PHYS, regs); + } + + if (TIMER_FIRING(read_sysreg(cntv_ctl_el0))) { + handle_domain_irq(aic_irqc->hw_domain, + aic_irqc->nr_hw + AIC_TMR_VIRT, regs); + } +} + +static void __exception_irq_entry aic_handle_irq_or_fiq(struct pt_regs *regs) +{ + u64 isr = read_sysreg(isr_el1); + + if (isr & PSR_F_BIT) + aic_handle_fiq(regs); + + if (isr & PSR_I_BIT) + aic_handle_irq(regs); +} + +static struct irq_chip aic_chip = { + .name = "AIC", + .irq_mask = aic_irq_mask, + .irq_unmask = aic_irq_unmask, + .irq_eoi = aic_irq_eoi, +}; + +static int aic_irq_domain_map(struct irq_domain *id, unsigned int irq, + irq_hw_number_t hw) +{ + struct aic_irq_chip *ic = id->host_data; + + irq_set_chip_data(irq, ic); + if (hw < ic->nr_hw) { + irq_set_chip_and_handler(irq, &aic_chip, handle_fasteoi_irq); + } else { + irq_set_percpu_devid(irq); + irq_set_chip_and_handler(irq, &aic_chip, + handle_percpu_devid_irq); + } + irq_set_status_flags(irq, IRQ_LEVEL); + irq_set_noprobe(irq); + + return 0; +} + +static void aic_irq_domain_unmap(struct irq_domain *id, unsigned int irq) +{ + irq_set_chip_and_handler(irq, NULL, NULL); +} + +static int aic_irq_domain_xlate(struct irq_domain *id, + struct device_node *ctrlr, const u32 *intspec, + unsigned int intsize, + irq_hw_number_t *out_hwirq, + unsigned int *out_type) +{ + struct aic_irq_chip *ic = id->host_data; + + if (intsize != 3) + return -EINVAL; + + if (intspec[0] == AIC_IRQ && intspec[1] < ic->nr_hw) + *out_hwirq = intspec[1]; + else if (intspec[0] == AIC_FIQ && intspec[1] < AIC_NR_FIQ) + *out_hwirq = ic->nr_hw + intspec[1]; + else if (intspec[0] == AIC_IPI && intspec[1] < AIC_NR_IPI) + *out_hwirq = ic->nr_hw + AIC_NR_FIQ + intspec[1]; + else + return -EINVAL; + + *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; + + return 0; +} + +static const struct irq_domain_ops aic_irq_domain_ops = { + .map = aic_irq_domain_map, + .unmap = aic_irq_domain_unmap, + .xlate = aic_irq_domain_xlate, +}; + +static int __init aic_of_ic_init(struct device_node *node, + struct device_node *parent) +{ + int i; + void __iomem *regs; + u32 info; + struct aic_irq_chip *irqc; + + regs = of_iomap(node, 0); + if (WARN_ON(!regs)) + return -EIO; + + irqc = kzalloc(sizeof(*irqc), GFP_KERNEL); + if (!irqc) + return -ENOMEM; + + aic_irqc = irqc; + irqc->base = regs; + + info = aic_ic_read(irqc, AIC_INFO); + irqc->nr_hw = AIC_INFO_NR_HW(info); + + irqc->hw_domain = + irq_domain_add_linear(node, + irqc->nr_hw + AIC_NR_FIQ + AIC_NR_IPI, + &aic_irq_domain_ops, irqc); + if (WARN_ON(!irqc->hw_domain)) { + iounmap(irqc->base); + kfree(irqc); + return -ENODEV; + } + + irq_domain_update_bus_token(irqc->hw_domain, DOMAIN_BUS_WIRED); + + set_handle_irq(aic_handle_irq_or_fiq); + + for (i = 0; i < BITS_TO_LONGS(irqc->nr_hw); i++) + aic_ic_write(irqc, AIC_MASK_SET + i * 4, ~0); + for (i = 0; i < BITS_TO_LONGS(irqc->nr_hw); i++) + aic_ic_write(irqc, AIC_SW_CLR + i * 4, ~0); + for (i = 0; i < irqc->nr_hw; i++) + aic_ic_write(irqc, AIC_TARGET_CPU + i * 4, 1); + + pr_info("AIC: initialized with %d IRQs, %d FIQs, %d IPIs\n", + irqc->nr_hw, AIC_NR_FIQ, AIC_NR_IPI); + + return 0; +} + +IRQCHIP_DECLARE(apple_m1_aic, "AAPL,aic", aic_of_ic_init); -- 2.30.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2021-02-04 20:46 UTC|newest] Thread overview: 240+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-02-04 20:39 [PATCH 00/18] Apple M1 SoC platform bring-up Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 20:39 ` [PATCH 01/18] dt-bindings: vendor-prefixes: add AAPL prefix Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-08 10:27 ` Krzysztof Kozlowski 2021-02-08 10:27 ` Krzysztof Kozlowski 2021-02-08 17:32 ` Rob Herring 2021-02-08 17:32 ` Rob Herring 2021-02-08 18:12 ` Krzysztof Kozlowski 2021-02-08 18:12 ` Krzysztof Kozlowski 2021-02-08 19:59 ` Arnd Bergmann 2021-02-08 19:59 ` Arnd Bergmann 2021-02-08 23:17 ` Hector Martin 2021-02-08 23:17 ` Hector Martin 2021-02-04 20:39 ` [PATCH 02/18] dt-bindings: arm: cpus: Add AAPL,firestorm & icestorm compatibles Hector Martin 2021-02-04 20:39 ` [PATCH 02/18] dt-bindings: arm: cpus: Add AAPL, firestorm " Hector Martin 2021-02-04 20:39 ` [PATCH 03/18] dt-bindings: arm: AAPL: Add bindings for Apple ARM platforms Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 20:39 ` [PATCH 04/18] arm64: Kconfig: Introduce CONFIG_ARCH_APPLE Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-06 13:17 ` Marc Zyngier 2021-02-06 13:17 ` Marc Zyngier 2021-02-07 8:05 ` Hector Martin 'marcan' 2021-02-07 8:05 ` Hector Martin 'marcan' 2021-02-04 20:39 ` [PATCH 05/18] tty: serial: samsung_tty: add support for Apple UARTs Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 23:55 ` kernel test robot 2021-02-04 23:55 ` kernel test robot 2021-02-04 23:55 ` kernel test robot 2021-02-05 9:44 ` Hector Martin 'marcan' 2021-02-05 9:44 ` Hector Martin 'marcan' 2021-02-05 2:19 ` kernel test robot 2021-02-05 2:19 ` kernel test robot 2021-02-05 2:19 ` kernel test robot 2021-02-06 13:15 ` Marc Zyngier 2021-02-06 13:15 ` Marc Zyngier 2021-02-07 9:12 ` Hector Martin 'marcan' 2021-02-07 9:12 ` Hector Martin 'marcan' 2021-02-07 9:26 ` Hector Martin 'marcan' 2021-02-07 9:26 ` Hector Martin 'marcan' 2021-02-08 9:36 ` Krzysztof Kozlowski 2021-02-08 9:36 ` Krzysztof Kozlowski 2021-02-08 16:14 ` Hector Martin 2021-02-08 16:14 ` Hector Martin 2021-02-08 10:34 ` Marc Zyngier 2021-02-08 10:34 ` Marc Zyngier 2021-02-08 16:18 ` Hector Martin 2021-02-08 16:18 ` Hector Martin 2021-02-08 16:46 ` Greg Kroah-Hartman 2021-02-08 16:46 ` Greg Kroah-Hartman 2021-02-08 23:22 ` Hector Martin 2021-02-08 23:22 ` Hector Martin 2021-02-08 10:54 ` Krzysztof Kozlowski 2021-02-08 10:54 ` Krzysztof Kozlowski 2021-02-08 16:10 ` Hector Martin 2021-02-08 16:10 ` Hector Martin 2021-02-08 18:37 ` Krzysztof Kozlowski 2021-02-08 18:37 ` Krzysztof Kozlowski 2021-02-08 23:23 ` Hector Martin 2021-02-08 23:23 ` Hector Martin 2021-02-04 20:39 ` [PATCH 06/18] dt-bindings: serial: samsung: Add AAPL,s5l-uart compatible Hector Martin 2021-02-04 20:39 ` [PATCH 06/18] dt-bindings: serial: samsung: Add AAPL, s5l-uart compatible Hector Martin 2021-02-04 20:39 ` [PATCH 07/18] tty: serial: samsung_tty: enable for ARCH_APPLE Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 21:16 ` Arnd Bergmann 2021-02-04 21:16 ` Arnd Bergmann 2021-02-04 21:27 ` Hector Martin 'marcan' 2021-02-04 21:27 ` Hector Martin 'marcan' 2021-02-04 20:39 ` [PATCH 08/18] arm64: cpufeature: Add a feature for FIQ support Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-06 13:58 ` Marc Zyngier 2021-02-06 13:58 ` Marc Zyngier 2021-02-07 8:28 ` Hector Martin 'marcan' 2021-02-07 8:28 ` Hector Martin 'marcan' 2021-02-08 11:29 ` Marc Zyngier 2021-02-08 11:29 ` Marc Zyngier 2021-02-08 15:51 ` Hector Martin 2021-02-08 15:51 ` Hector Martin 2021-02-04 20:39 ` [PATCH 09/18] arm64: cputype: Add CPU types for the Apple M1 big/little cores Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 20:39 ` [PATCH 10/18] arm64: Introduce FIQ support Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-06 15:37 ` Marc Zyngier 2021-02-06 15:37 ` Marc Zyngier 2021-02-06 16:22 ` Arnd Bergmann 2021-02-06 16:22 ` Arnd Bergmann 2021-02-07 8:36 ` Hector Martin 'marcan' 2021-02-07 8:36 ` Hector Martin 'marcan' 2021-02-07 12:25 ` Arnd Bergmann 2021-02-07 12:25 ` Arnd Bergmann 2021-02-07 15:38 ` Hector Martin 'marcan' 2021-02-07 15:38 ` Hector Martin 'marcan' 2021-02-07 18:49 ` Arnd Bergmann 2021-02-07 18:49 ` Arnd Bergmann 2021-02-08 23:34 ` Hector Martin 2021-02-08 23:34 ` Hector Martin 2021-02-07 8:47 ` Hector Martin 'marcan' 2021-02-07 8:47 ` Hector Martin 'marcan' 2021-02-08 11:30 ` Marc Zyngier 2021-02-08 11:30 ` Marc Zyngier 2021-02-04 20:39 ` [PATCH 11/18] arm64: Kconfig: Require FIQ support for ARCH_APPLE Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-06 15:46 ` Marc Zyngier 2021-02-06 15:46 ` Marc Zyngier 2021-02-07 9:23 ` Hector Martin 'marcan' 2021-02-07 9:23 ` Hector Martin 'marcan' 2021-02-08 12:05 ` Marc Zyngier 2021-02-08 12:05 ` Marc Zyngier 2021-02-08 15:48 ` Hector Martin 2021-02-08 15:48 ` Hector Martin 2021-02-04 20:39 ` [PATCH 12/18] arm64: setup: Use nGnRnE IO mappings for fixmap on Apple platforms Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 22:25 ` Arnd Bergmann 2021-02-04 22:25 ` Arnd Bergmann 2021-02-04 20:39 ` [PATCH 13/18] arm64: ioremap: use nGnRnE mappings on platforms that require it Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 22:21 ` Arnd Bergmann 2021-02-04 22:21 ` Arnd Bergmann 2021-02-08 22:57 ` Arnd Bergmann 2021-02-08 22:57 ` Arnd Bergmann 2021-02-08 23:20 ` Mark Kettenis 2021-02-08 23:20 ` Mark Kettenis 2021-02-09 0:25 ` Hector Martin 2021-02-09 0:25 ` Hector Martin 2021-02-09 9:15 ` Arnd Bergmann 2021-02-09 9:15 ` Arnd Bergmann 2021-02-09 9:58 ` Mark Kettenis 2021-02-09 9:58 ` Mark Kettenis 2021-02-09 11:22 ` Hector Martin 2021-02-09 11:22 ` Hector Martin 2021-02-09 9:35 ` Arnd Bergmann 2021-02-09 9:35 ` Arnd Bergmann 2021-02-10 12:24 ` Hector Martin 2021-02-10 12:24 ` Hector Martin 2021-02-10 13:40 ` Mark Kettenis 2021-02-10 13:40 ` Mark Kettenis 2021-02-04 20:39 ` [PATCH 14/18] dt-bindings: interrupt-controller: Add DT bindings for apple-aic Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-09 23:07 ` Rob Herring 2021-02-09 23:07 ` Rob Herring 2021-02-04 20:39 ` Hector Martin [this message] 2021-02-04 20:39 ` [PATCH 15/18] irqchip/apple-aic: Add support for the Apple Interrupt Controller Hector Martin 2021-02-04 21:37 ` Arnd Bergmann 2021-02-04 21:37 ` Arnd Bergmann 2021-02-04 22:04 ` Hector Martin 'marcan' 2021-02-04 22:04 ` Hector Martin 'marcan' 2021-02-04 23:04 ` Arnd Bergmann 2021-02-04 23:04 ` Arnd Bergmann 2021-02-05 7:41 ` Hector Martin 'marcan' 2021-02-05 7:41 ` Hector Martin 'marcan' 2021-02-05 10:33 ` Arnd Bergmann 2021-02-05 10:33 ` Arnd Bergmann 2021-02-05 2:27 ` kernel test robot 2021-02-05 2:27 ` kernel test robot 2021-02-05 2:27 ` kernel test robot 2021-02-05 9:45 ` Hector Martin 'marcan' 2021-02-05 9:45 ` Hector Martin 'marcan' 2021-02-08 9:25 ` Marc Zyngier 2021-02-08 9:25 ` Marc Zyngier 2021-02-08 10:29 ` Arnd Bergmann 2021-02-08 10:29 ` Arnd Bergmann 2021-02-08 11:13 ` Hector Martin 'marcan' 2021-02-08 11:13 ` Hector Martin 'marcan' 2021-02-08 11:21 ` Arnd Bergmann 2021-02-08 11:21 ` Arnd Bergmann 2021-02-08 11:36 ` Marc Zyngier 2021-02-08 11:36 ` Marc Zyngier 2021-02-08 12:17 ` Arnd Bergmann 2021-02-08 12:17 ` Arnd Bergmann 2021-02-08 15:31 ` Hector Martin 2021-02-08 15:31 ` Hector Martin 2021-02-09 6:20 ` Hector Martin 2021-02-09 6:20 ` Hector Martin 2021-02-04 20:39 ` [PATCH 16/18] irqchip/apple-aic: Add SMP / IPI support Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 20:39 ` [PATCH 17/18] dt-bindings: display: add AAPL,simple-framebuffer Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 20:39 ` [PATCH 18/18] arm64: apple: Add initial Mac Mini 2020 (M1) devicetree Hector Martin 2021-02-04 20:39 ` Hector Martin 2021-02-04 21:29 ` Arnd Bergmann 2021-02-04 21:29 ` Arnd Bergmann 2021-02-04 21:44 ` Hector Martin 'marcan' 2021-02-04 21:44 ` Hector Martin 'marcan' 2021-02-04 23:08 ` Arnd Bergmann 2021-02-04 23:08 ` Arnd Bergmann 2021-02-05 7:11 ` Hector Martin 'marcan' 2021-02-05 7:11 ` Hector Martin 'marcan' 2021-02-05 12:43 ` Arnd Bergmann 2021-02-05 12:43 ` Arnd Bergmann 2021-02-08 11:04 ` Krzysztof Kozlowski 2021-02-08 11:04 ` Krzysztof Kozlowski 2021-02-08 11:56 ` Hector Martin 'marcan' 2021-02-08 11:56 ` Hector Martin 'marcan' 2021-02-08 12:13 ` Krzysztof Kozlowski 2021-02-08 12:13 ` Krzysztof Kozlowski 2021-02-08 12:40 ` Arnd Bergmann 2021-02-08 12:40 ` Arnd Bergmann 2021-02-08 14:12 ` Hector Martin 2021-02-08 14:12 ` Hector Martin 2021-02-08 17:58 ` Rob Herring 2021-02-08 17:58 ` Rob Herring 2021-02-09 0:32 ` Hector Martin 2021-02-09 0:32 ` Hector Martin 2021-02-08 19:14 ` Rob Herring 2021-02-08 19:14 ` Rob Herring 2021-02-09 0:49 ` Hector Martin 2021-02-09 0:49 ` Hector Martin 2021-02-09 2:05 ` Rob Herring 2021-02-09 2:05 ` Rob Herring 2021-02-10 10:19 ` Tony Lindgren 2021-02-10 10:19 ` Tony Lindgren 2021-02-10 11:07 ` Hector Martin 2021-02-10 11:07 ` Hector Martin 2021-02-10 11:34 ` Tony Lindgren 2021-02-10 11:34 ` Tony Lindgren 2021-02-10 11:43 ` Hector Martin 2021-02-10 11:43 ` Hector Martin 2021-02-10 12:24 ` Daniel Palmer 2021-02-10 12:24 ` Daniel Palmer 2021-02-10 12:24 ` Daniel Palmer 2021-02-10 12:54 ` Tony Lindgren 2021-02-10 12:54 ` Tony Lindgren 2021-02-10 12:56 ` Hector Martin 2021-02-10 12:56 ` Hector Martin 2021-02-10 12:55 ` Krzysztof Kozlowski 2021-02-10 12:55 ` Krzysztof Kozlowski 2021-02-10 13:19 ` Tony Lindgren 2021-02-10 13:19 ` Tony Lindgren 2021-02-10 13:25 ` Krzysztof Kozlowski 2021-02-10 13:25 ` Krzysztof Kozlowski 2021-02-08 12:27 ` Marc Zyngier 2021-02-08 12:27 ` Marc Zyngier 2021-02-08 14:53 ` Hector Martin 2021-02-08 14:53 ` Hector Martin 2021-02-08 15:36 ` Marc Zyngier 2021-02-08 15:36 ` Marc Zyngier 2021-02-04 22:43 ` [PATCH 00/18] Apple M1 SoC platform bring-up Arnd Bergmann 2021-02-04 22:43 ` Arnd Bergmann 2021-02-05 11:35 ` Hector Martin 'marcan' 2021-02-05 11:35 ` Hector Martin 'marcan'
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210204203951.52105-16-marcan@marcan.st \ --to=marcan@marcan.st \ --cc=arnd@kernel.org \ --cc=devicetree@vger.kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=maz@kernel.org \ --cc=olof@lixom.net \ --cc=robh+dt@kernel.org \ --cc=soc@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.