From patchwork Thu Dec 9 04:32:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hector Martin X-Patchwork-Id: 12695436 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F245FC433EF for ; Thu, 9 Dec 2021 04:35:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=pGqRj6dq/Qaf+IYv6bl57/aAUoQP5UbQ+JBMPyAx6do=; b=nddYdlEIPlblbR /m11qHOhS2Hy+/aCcaq2XaavJQzj3ZtAZmK3jVeL/SS0DMKQJoRcCjE4o5P/ZWJkzRSJ3T66ETNKB iaS2muXIBK2VGcQiOECoG7OKgQMz2iWLINIxMV8THZyC5+VKp9rLGyhwEdBN4tvn7a6cHqmKTLMnb dRDJXbwXyyW1jBbZm/ca7KrYA3lp61HcW8014fQU3HaUG3nRpo6cwyjWMzPwgsAoPfV5dPcI/5fch j5u/lLS0Y7aE3nvesQ3CiFgWPK20dIgEw1qYnmMbAxS/jKK6iebV/5+WXUgCTD0hUPVTrKJlQFlvq 6uqechEBOonKACfSXxrw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7h-00EsUp-PK; Thu, 09 Dec 2021 04:33:37 +0000 Received: from marcansoft.com ([212.63.210.85] helo=mail.marcansoft.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7T-00EsQU-LE for linux-arm-kernel@lists.infradead.org; Thu, 09 Dec 2021 04:33:25 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: hector@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id BB7A541EA2; Thu, 9 Dec 2021 04:33:17 +0000 (UTC) From: Hector Martin To: Thomas Gleixner , Marc Zyngier , Rob Herring Cc: Hector Martin , Sven Peter , Alyssa Rosenzweig , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 1/6] dt-bindings: interrupt-controller: apple, aic: Add apple, aic2 support Date: Thu, 9 Dec 2021 13:32:44 +0900 Message-Id: <20211209043249.65474-2-marcan@marcan.st> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211209043249.65474-1-marcan@marcan.st> References: <20211209043249.65474-1-marcan@marcan.st> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211208_203323_889793_3EA6AF00 X-CRM114-Status: GOOD ( 13.67 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This new incompatible revision of the AIC peripheral introduces multi-die support. To handle that, we introduce an optional 4-argument interrupt-cells form. Also add an apple,event-reg property to specify the offset of the event register. Inexplicably, the capability registers allow us to compute other register offsets, but not this one. This allows us to keep forward-compatibility with future SoCs that will likely implement different die counts, thus shifting the event register. Apple do the same thing in their device tree... Signed-off-by: Hector Martin --- .../interrupt-controller/apple,aic.yaml | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml index 97359024709a..6a8dd213e59a 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml @@ -18,38 +18,44 @@ description: | - Level-triggered hardware IRQs wired to SoC blocks - Single mask bit per IRQ - - Per-IRQ affinity setting + - Per-IRQ affinity setting (AICv1 only) - 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) + if not symmetric) (AICv1 only) - 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 + - Default "this CPU" register view and explicit per-CPU views (AICv1 only) This device also represents the FIQ interrupt sources on platforms using AIC, - which do not go through a discrete interrupt controller. - -allOf: - - $ref: /schemas/interrupt-controller.yaml# + which do not go through a discrete interrupt controller. It also handles + FIQ-based Fast IPIs on supported chips. properties: compatible: - items: - - const: apple,t8103-aic - - const: apple,aic + oneOf: + - items: + - const: apple,t8103-aic + - const: apple,aic + - items: + - const: apple,t6000-aic + - const: apple,aic2 interrupt-controller: true '#interrupt-cells': - const: 3 + minimum: 3 + maximum: 4 description: | The 1st cell contains the interrupt type: - 0: Hardware IRQ - 1: FIQ - The 2nd cell contains the interrupt number. + The optional 2nd cell contains the die ID (apple,aic2 only). + If not present, it defaults to 0. + + The next cell contains the interrupt number. - HW IRQs: interrupt number - FIQs: - 0: physical HV timer @@ -57,7 +63,7 @@ properties: - 2: physical guest timer - 3: virtual guest timer - The 3rd cell contains the interrupt flags. This is normally + The last cell contains the interrupt flags. This is normally IRQ_TYPE_LEVEL_HIGH (4). reg: @@ -68,6 +74,13 @@ properties: power-domains: maxItems: 1 + apple,event-reg: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Specifies the offset of the event register, which lies after all the + implemented die register sets, page aligned. This is not computable from + capability register values, so we have to specify it explicitly. + required: - compatible - '#interrupt-cells' @@ -76,6 +89,29 @@ required: additionalProperties: false +allOf: + - $ref: /schemas/interrupt-controller.yaml# + - if: + properties: + compatible: + contains: + enum: + - apple,aic + then: + properties: + '#interrupt-cells': + const: 3 + + - if: + properties: + compatible: + contains: + enum: + - apple,aic2 + then: + required: + - apple,event-reg + examples: - | soc { From patchwork Thu Dec 9 04:32:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hector Martin X-Patchwork-Id: 12695437 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 26244C433FE for ; Thu, 9 Dec 2021 04:35:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=U2dUJoIDH6W+qhrFp7L7qnXRErbOsnRQ1jE6CPRP6fc=; b=gNl/NM0oCoJQG8 XNPXdzexkylrNVjn5fTewPtQ/Lu8PKwBlg1OPaVYIPoqDHsoPSxDfAdUs4D0OoWmvtATqM029pHa2 rka57Bvr+V9qy3wlzql/dn3tNHrZstDELrkZkjuD14YJcheGprGTbmrGNrajRpRnWAPFPzfXFcRXo ZkPAplDpEhEr07hVYSR2UwL0JaKOQVi3imeTaucyasvvC6hxtHqvnngYZp7BTNwWdT02/MEbOxKRp Jwk/HR4okoQ20zZgzSYo8iLgs3LLj99B2pKPHaoDXUYZH8NIuj4DDx15ubUtJatMLpfHtbH6g8PS/ VkjeAfFgQYbZIqtHRTpQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7r-00EsYj-Sc; Thu, 09 Dec 2021 04:33:48 +0000 Received: from marcansoft.com ([212.63.210.85] helo=mail.marcansoft.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7V-00EsRZ-7q for linux-arm-kernel@lists.infradead.org; Thu, 09 Dec 2021 04:33:27 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: hector@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id DBDBE41EA7; Thu, 9 Dec 2021 04:33:20 +0000 (UTC) From: Hector Martin To: Thomas Gleixner , Marc Zyngier , Rob Herring Cc: Hector Martin , Sven Peter , Alyssa Rosenzweig , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 2/6] irqchip/apple-aic: Add Fast IPI support Date: Thu, 9 Dec 2021 13:32:45 +0900 Message-Id: <20211209043249.65474-3-marcan@marcan.st> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211209043249.65474-1-marcan@marcan.st> References: <20211209043249.65474-1-marcan@marcan.st> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211208_203325_466098_B2B33B32 X-CRM114-Status: GOOD ( 27.36 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The newer AICv2 present in t600x SoCs does not have legacy IPI support at all. Since t8103 also supports Fast IPIs, implement support for this first. The legacy IPI code is left as a fallback, so it can be potentially used by older SoCs in the future. The vIPI code is shared; only the IPI firing/acking bits change for Fast IPIs. Signed-off-by: Hector Martin --- drivers/irqchip/irq-apple-aic.c | 112 ++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 14 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 3759dc36cc8f..1aa63580cae4 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: @@ -106,7 +106,6 @@ /* * IMP-DEF sysregs that control FIQ sources - * Note: sysreg-based IPIs are not supported yet. */ /* Core PMC control register */ @@ -155,6 +154,10 @@ #define SYS_IMP_APL_UPMSR_EL1 sys_reg(3, 7, 15, 6, 4) #define UPMSR_IACT BIT(0) +/* MPIDR fields */ +#define MPIDR_CPU GENMASK(7, 0) +#define MPIDR_CLUSTER GENMASK(15, 8) + #define AIC_NR_FIQ 4 #define AIC_NR_SWIPI 32 @@ -173,12 +176,42 @@ #define AIC_TMR_EL02_PHYS AIC_TMR_GUEST_PHYS #define AIC_TMR_EL02_VIRT AIC_TMR_GUEST_VIRT +struct aic_info { + int version; + + /* Features */ + bool fast_ipi; +}; + +static const struct aic_info aic1_info = { + .version = 1, +}; + +static const struct aic_info aic1_fipi_info = { + .version = 1, + + .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, + }, + {} +}; + struct aic_irq_chip { void __iomem *base; struct irq_domain *hw_domain; struct irq_domain *ipi_domain; int nr_hw; - int ipi_hwirq; + + struct aic_info info; }; static DEFINE_PER_CPU(uint32_t, aic_fiq_unmasked); @@ -387,8 +420,12 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) */ if (read_sysreg_s(SYS_IMP_APL_IPI_SR_EL1) & IPI_SR_PENDING) { - pr_err_ratelimited("Fast IPI fired. Acking.\n"); - write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); + if (aic_irqc->info.fast_ipi) { + aic_handle_ipi(regs); + } else { + pr_err_ratelimited("Fast IPI fired. Acking.\n"); + write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); + } } if (TIMER_FIRING(read_sysreg(cntp_ctl_el0))) @@ -564,6 +601,21 @@ static const struct irq_domain_ops aic_irq_domain_ops = { * IPI irqchip */ +static void aic_ipi_send_fast(int cpu) +{ + u64 mpidr = cpu_logical_map(cpu); + u64 my_mpidr = cpu_logical_map(smp_processor_id()); + u64 cluster = FIELD_GET(MPIDR_CLUSTER, mpidr); + u64 idx = FIELD_GET(MPIDR_CPU, mpidr); + + if (FIELD_GET(MPIDR_CLUSTER, my_mpidr) == cluster) + write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx), + SYS_IMP_APL_IPI_RR_LOCAL_EL1); + else + write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx) | FIELD_PREP(IPI_RR_CLUSTER, cluster), + SYS_IMP_APL_IPI_RR_GLOBAL_EL1); +} + static void aic_ipi_mask(struct irq_data *d) { u32 irq_bit = BIT(irqd_to_hwirq(d)); @@ -589,8 +641,12 @@ static void aic_ipi_unmask(struct irq_data *d) * If a pending vIPI was unmasked, raise a HW IPI to ourselves. * No barriers needed here since this is a self-IPI. */ - if (atomic_read(this_cpu_ptr(&aic_vipi_flag)) & irq_bit) - aic_ic_write(ic, AIC_IPI_SEND, AIC_IPI_SEND_CPU(smp_processor_id())); + if (atomic_read(this_cpu_ptr(&aic_vipi_flag)) & irq_bit) { + if (ic->info.fast_ipi) + aic_ipi_send_fast(smp_processor_id()); + else + aic_ic_write(ic, AIC_IPI_SEND, AIC_IPI_SEND_CPU(smp_processor_id())); + } } static void aic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask) @@ -618,8 +674,12 @@ static void aic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask) smp_mb__after_atomic(); if (!(pending & irq_bit) && - (atomic_read(per_cpu_ptr(&aic_vipi_enable, cpu)) & irq_bit)) - send |= AIC_IPI_SEND_CPU(cpu); + (atomic_read(per_cpu_ptr(&aic_vipi_enable, cpu)) & irq_bit)) { + if (ic->info.fast_ipi) + aic_ipi_send_fast(cpu); + else + send |= AIC_IPI_SEND_CPU(cpu); + } } /* @@ -651,8 +711,16 @@ static void aic_handle_ipi(struct pt_regs *regs) /* * Ack the IPI. We need to order this after the AIC event read, but * that is enforced by normal MMIO ordering guarantees. + * + * For the Fast IPI case, this needs to be ordered before the vIPI + * handling below, so we need to isb(); */ - aic_ic_write(aic_irqc, AIC_IPI_ACK, AIC_IPI_OTHER); + if (aic_irqc->info.fast_ipi) { + write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); + isb(); + } else { + aic_ic_write(aic_irqc, AIC_IPI_ACK, AIC_IPI_OTHER); + } /* * The mask read does not need to be ordered. Only we can change @@ -680,7 +748,8 @@ static void aic_handle_ipi(struct pt_regs *regs) * No ordering needed here; at worst this just changes the timing of * when the next IPI will be delivered. */ - aic_ic_write(aic_irqc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER); + if (!aic_irqc->info.fast_ipi) + aic_ic_write(aic_irqc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER); } static int aic_ipi_alloc(struct irq_domain *d, unsigned int virq, @@ -779,8 +848,12 @@ static int aic_init_cpu(unsigned int cpu) * by AIC during processing). We manage masks at the vIPI level. */ aic_ic_write(aic_irqc, AIC_IPI_ACK, AIC_IPI_SELF | AIC_IPI_OTHER); - aic_ic_write(aic_irqc, AIC_IPI_MASK_SET, AIC_IPI_SELF); - aic_ic_write(aic_irqc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER); + if (!aic_irqc->info.fast_ipi) { + aic_ic_write(aic_irqc, AIC_IPI_MASK_SET, AIC_IPI_SELF); + aic_ic_write(aic_irqc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER); + } else { + aic_ic_write(aic_irqc, AIC_IPI_MASK_SET, AIC_IPI_SELF | AIC_IPI_OTHER); + } /* Initialize the local mask state */ __this_cpu_write(aic_fiq_unmasked, 0); @@ -800,6 +873,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p void __iomem *regs; u32 info; struct aic_irq_chip *irqc; + const struct of_device_id *match; regs = of_iomap(node, 0); if (WARN_ON(!regs)) @@ -809,9 +883,16 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p if (!irqc) return -ENOMEM; - aic_irqc = irqc; irqc->base = regs; + match = of_match_node(aic_info_match, node); + if (!match) + return -ENODEV; + + irqc->info = *(struct aic_info *)match->data; + + aic_irqc = irqc; + info = aic_ic_read(irqc, AIC_INFO); irqc->nr_hw = FIELD_GET(AIC_INFO_NR_HW, info); @@ -846,6 +927,9 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p if (!is_kernel_in_hyp_mode()) pr_info("Kernel running in EL1, mapping interrupts"); + if (irqc->info.fast_ipi) + pr_info("Using Fast IPIs"); + cpuhp_setup_state(CPUHP_AP_IRQ_APPLE_AIC_STARTING, "irqchip/apple-aic/ipi:starting", aic_init_cpu, NULL); From patchwork Thu Dec 9 04:32:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hector Martin X-Patchwork-Id: 12695438 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CB757C4332F for ; Thu, 9 Dec 2021 04:35:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Xwv6TEpKIA257Di7CDtDTwDMy8SMXzzz6qnvlb2YK6w=; b=RT2y8P+/cp8+R9 /ynGFR8UypU/laIgRfDNdbh6v4cFxbGBJS/KIi7sIreclUwO9B4+MEHnKUc4xuatqFbNhYFg5oc0a K9Czf/V2lRONZc9UXawc2NK/i1zDYtPIRUlLcUd6fO8wztMY1NPW+Uxcqh10soZI0iijw4PzRj8fp c9tDpI8u1M7Xo5aNnXkWH23CnV+X/+bXe9N1RL/yvEd9KWE3PjhpN13PK47WDdNEmoGY9cUbSDBH4 WGWhAeRzOSspjteka+4HahCLt7ZbznE2bqQUg3pyU/o5xeXDLQF5eMLz47iVBHAkhR8VYBsB5lzHA VaLhqGuIFsDHgbuxtGmg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB81-00Esa7-IO; Thu, 09 Dec 2021 04:33:57 +0000 Received: from marcansoft.com ([2a01:298:fe:f::2] helo=mail.marcansoft.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7Y-00EsSg-Ax for linux-arm-kernel@lists.infradead.org; Thu, 09 Dec 2021 04:33:30 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: hector@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id 0B6F142458; Thu, 9 Dec 2021 04:33:23 +0000 (UTC) From: Hector Martin To: Thomas Gleixner , Marc Zyngier , Rob Herring Cc: Hector Martin , Sven Peter , Alyssa Rosenzweig , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 3/6] irqchip/apple-aic: Switch to irq_domain_create_tree and sparse hwirqs Date: Thu, 9 Dec 2021 13:32:46 +0900 Message-Id: <20211209043249.65474-4-marcan@marcan.st> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211209043249.65474-1-marcan@marcan.st> References: <20211209043249.65474-1-marcan@marcan.st> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211208_203328_564715_34478F3F X-CRM114-Status: GOOD ( 20.60 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This allows us to directly use the hardware event number as the hwirq number. Since IRQ events have bit 16 set (type=1), FIQs now move to starting at hwirq number 0. This will become more important once multi-die support is introduced in a later commit. Signed-off-by: Hector Martin --- drivers/irqchip/irq-apple-aic.c | 67 ++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 1aa63580cae4..572d1af175fc 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -66,7 +66,7 @@ */ #define AIC_INFO 0x0004 -#define AIC_INFO_NR_HW GENMASK(15, 0) +#define AIC_INFO_NR_IRQ GENMASK(15, 0) #define AIC_CONFIG 0x0010 @@ -75,6 +75,7 @@ #define AIC_EVENT_TYPE GENMASK(31, 16) #define AIC_EVENT_NUM GENMASK(15, 0) +#define AIC_EVENT_TYPE_FIQ 0 /* Software use */ #define AIC_EVENT_TYPE_HW 1 #define AIC_EVENT_TYPE_IPI 4 #define AIC_EVENT_IPI_OTHER 1 @@ -158,6 +159,8 @@ #define MPIDR_CPU GENMASK(7, 0) #define MPIDR_CLUSTER GENMASK(15, 8) +#define AIC_FIQ_HWIRQ(x) (FIELD_PREP(AIC_EVENT_TYPE, AIC_EVENT_TYPE_FIQ) | \ + FIELD_PREP(AIC_EVENT_NUM, x)) #define AIC_NR_FIQ 4 #define AIC_NR_SWIPI 32 @@ -209,7 +212,7 @@ struct aic_irq_chip { void __iomem *base; struct irq_domain *hw_domain; struct irq_domain *ipi_domain; - int nr_hw; + int nr_irq; struct aic_info info; }; @@ -239,18 +242,22 @@ 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 irq = FIELD_GET(AIC_EVENT_NUM, hwirq); + + aic_ic_write(ic, AIC_MASK_SET + 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 irq = FIELD_GET(AIC_EVENT_NUM, hwirq); + + aic_ic_write(ic, AIC_MASK_CLR + MASK_REG(irq), MASK_BIT(irq)); } static void aic_irq_eoi(struct irq_data *d) @@ -278,7 +285,7 @@ static void __exception_irq_entry aic_handle_irq(struct pt_regs *regs) irq = FIELD_GET(AIC_EVENT_NUM, event); if (type == AIC_EVENT_TYPE_HW) - generic_handle_domain_irq(aic_irqc->hw_domain, irq); + generic_handle_domain_irq(aic_irqc->hw_domain, event); else if (type == AIC_EVENT_TYPE_IPI && irq == 1) aic_handle_ipi(regs); else if (event != 0) @@ -310,7 +317,7 @@ static int aic_irq_set_affinity(struct irq_data *d, else cpu = cpumask_any_and(mask_val, cpu_online_mask); - aic_ic_write(ic, AIC_TARGET_CPU + hwirq * 4, BIT(cpu)); + aic_ic_write(ic, AIC_TARGET_CPU + FIELD_GET(AIC_EVENT_NUM, hwirq) * 4, BIT(cpu)); irq_data_update_effective_affinity(d, cpumask_of(cpu)); return IRQ_SET_MASK_OK; @@ -340,9 +347,7 @@ static struct irq_chip aic_chip = { static unsigned long aic_fiq_get_idx(struct irq_data *d) { - struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); - - return irqd_to_hwirq(d) - ic->nr_hw; + return FIELD_GET(AIC_EVENT_NUM, irqd_to_hwirq(d)); } static void aic_fiq_set_mask(struct irq_data *d) @@ -430,11 +435,11 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) if (TIMER_FIRING(read_sysreg(cntp_ctl_el0))) generic_handle_domain_irq(aic_irqc->hw_domain, - aic_irqc->nr_hw + AIC_TMR_EL0_PHYS); + AIC_FIQ_HWIRQ(AIC_TMR_EL0_PHYS)); if (TIMER_FIRING(read_sysreg(cntv_ctl_el0))) generic_handle_domain_irq(aic_irqc->hw_domain, - aic_irqc->nr_hw + AIC_TMR_EL0_VIRT); + AIC_FIQ_HWIRQ(AIC_TMR_EL0_VIRT)); if (is_kernel_in_hyp_mode()) { uint64_t enabled = read_sysreg_s(SYS_IMP_APL_VM_TMR_FIQ_ENA_EL2); @@ -442,12 +447,12 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) if ((enabled & VM_TMR_FIQ_ENABLE_P) && TIMER_FIRING(read_sysreg_s(SYS_CNTP_CTL_EL02))) generic_handle_domain_irq(aic_irqc->hw_domain, - aic_irqc->nr_hw + AIC_TMR_EL02_PHYS); + AIC_FIQ_HWIRQ(AIC_TMR_EL02_PHYS)); if ((enabled & VM_TMR_FIQ_ENABLE_V) && TIMER_FIRING(read_sysreg_s(SYS_CNTV_CTL_EL02))) generic_handle_domain_irq(aic_irqc->hw_domain, - aic_irqc->nr_hw + AIC_TMR_EL02_VIRT); + AIC_FIQ_HWIRQ(AIC_TMR_EL02_VIRT)); } if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) == @@ -492,13 +497,13 @@ static struct irq_chip fiq_chip = { 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; + u32 type = FIELD_GET(AIC_EVENT_TYPE, hw); - if (hw < ic->nr_hw) { + if (type == AIC_EVENT_TYPE_HW) { irq_domain_set_info(id, irq, hw, &aic_chip, id->host_data, handle_fasteoi_irq, NULL, NULL); irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); - } else { + } else if (type == AIC_EVENT_TYPE_FIQ) { irq_set_percpu_devid(irq); irq_domain_set_info(id, irq, hw, &fiq_chip, id->host_data, handle_percpu_devid_irq, NULL, NULL); @@ -519,14 +524,15 @@ static int aic_irq_domain_translate(struct irq_domain *id, switch (fwspec->param[0]) { case AIC_IRQ: - if (fwspec->param[1] >= ic->nr_hw) + if (fwspec->param[1] >= ic->nr_irq) return -EINVAL; - *hwirq = fwspec->param[1]; + *hwirq = (FIELD_PREP(AIC_EVENT_TYPE, AIC_EVENT_TYPE_HW) | + FIELD_PREP(AIC_EVENT_NUM, fwspec->param[1])); break; case AIC_FIQ: if (fwspec->param[1] >= AIC_NR_FIQ) return -EINVAL; - *hwirq = ic->nr_hw + fwspec->param[1]; + *hwirq = AIC_FIQ_HWIRQ(fwspec->param[1]); /* * In EL1 the non-redirected registers are the guest's, @@ -535,10 +541,10 @@ static int aic_irq_domain_translate(struct irq_domain *id, if (!is_kernel_in_hyp_mode()) { switch (fwspec->param[1]) { case AIC_TMR_GUEST_PHYS: - *hwirq = ic->nr_hw + AIC_TMR_EL0_PHYS; + *hwirq = AIC_FIQ_HWIRQ(AIC_TMR_EL0_PHYS); break; case AIC_TMR_GUEST_VIRT: - *hwirq = ic->nr_hw + AIC_TMR_EL0_VIRT; + *hwirq = AIC_FIQ_HWIRQ(AIC_TMR_EL0_VIRT); break; case AIC_TMR_HV_PHYS: case AIC_TMR_HV_VIRT: @@ -894,11 +900,10 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p aic_irqc = irqc; info = aic_ic_read(irqc, AIC_INFO); - irqc->nr_hw = FIELD_GET(AIC_INFO_NR_HW, info); + irqc->nr_irq = FIELD_GET(AIC_INFO_NR_IRQ, info); - irqc->hw_domain = irq_domain_create_linear(of_node_to_fwnode(node), - irqc->nr_hw + AIC_NR_FIQ, - &aic_irq_domain_ops, irqc); + irqc->hw_domain = irq_domain_create_tree(of_node_to_fwnode(node), + &aic_irq_domain_ops, irqc); if (WARN_ON(!irqc->hw_domain)) { iounmap(irqc->base); kfree(irqc); @@ -917,11 +922,11 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p set_handle_irq(aic_handle_irq); set_handle_fiq(aic_handle_fiq); - for (i = 0; i < BITS_TO_U32(irqc->nr_hw); i++) + for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) aic_ic_write(irqc, AIC_MASK_SET + i * 4, U32_MAX); - for (i = 0; i < BITS_TO_U32(irqc->nr_hw); i++) + for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) aic_ic_write(irqc, AIC_SW_CLR + i * 4, U32_MAX); - for (i = 0; i < irqc->nr_hw; i++) + for (i = 0; i < irqc->nr_irq; i++) aic_ic_write(irqc, AIC_TARGET_CPU + i * 4, 1); if (!is_kernel_in_hyp_mode()) @@ -937,7 +942,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p vgic_set_kvm_info(&vgic_info); pr_info("Initialized with %d IRQs, %d FIQs, %d vIPIs\n", - irqc->nr_hw, AIC_NR_FIQ, AIC_NR_SWIPI); + irqc->nr_irq, AIC_NR_FIQ, AIC_NR_SWIPI); return 0; } From patchwork Thu Dec 9 04:32:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hector Martin X-Patchwork-Id: 12695439 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1CDDAC433FE for ; Thu, 9 Dec 2021 04:35:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8H5qQo5wvc6ZX3UQtkptZapfYUlOaH5HuKeZRVqU47A=; b=KGTpqL5E14YLV3 SDgI9uo9102URe7QO4TTjBRYu2RqEtRVSBkgiGlTNmZpuCzXzm4MzhuOBoif/mXDpIRtaiqzOEgS5 H1xlbgZ991q1Qp1SSZCz4Ree8TN/W3ivkPZuBDFEHkLeYIx4DIsEBN3HoOXxJgaPIf+q1Y4fSy/aN eSQ2z4lzrSVSuH2kh3/MVMNHGC1M+yMkXI/rhAMQTtEcDd7YePuU1aPEs9zVPOIVMpwgjCyGnY994 +H2P5kjfzYntv3b7zKK8bf3A11grfVvecRBWqtkr0eOXgJ3I7a7EI7+umtbDiQwn2Dh2v/6nqzvsR bIkJ05D664gzuUO3IPCg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB8B-00EsbH-An; Thu, 09 Dec 2021 04:34:07 +0000 Received: from marcansoft.com ([2a01:298:fe:f::2] helo=mail.marcansoft.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7b-00EsTf-44 for linux-arm-kernel@lists.infradead.org; Thu, 09 Dec 2021 04:33:32 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: hector@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id 2E25E4248B; Thu, 9 Dec 2021 04:33:26 +0000 (UTC) From: Hector Martin To: Thomas Gleixner , Marc Zyngier , Rob Herring Cc: Hector Martin , Sven Peter , Alyssa Rosenzweig , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 4/6] irqchip/apple-aic: Dynamically compute register offsets Date: Thu, 9 Dec 2021 13:32:47 +0900 Message-Id: <20211209043249.65474-5-marcan@marcan.st> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211209043249.65474-1-marcan@marcan.st> References: <20211209043249.65474-1-marcan@marcan.st> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211208_203331_351741_B8BD08ED X-CRM114-Status: GOOD ( 17.99 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This allows us to support AIC variants with different numbers of IRQs based on capability registers. Signed-off-by: Hector Martin --- drivers/irqchip/irq-apple-aic.c | 73 +++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 572d1af175fc..d03caed51d56 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -62,7 +62,7 @@ #include /* - * AIC registers (MMIO) + * AIC v1 registers (MMIO) */ #define AIC_INFO 0x0004 @@ -92,16 +92,14 @@ #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 + #define MASK_REG(x) (4 * ((x) >> 5)) #define MASK_BIT(x) BIT((x) & GENMASK(4, 0)) @@ -182,17 +180,31 @@ struct aic_info { int version; + /* Register offsets */ + u32 event; + u32 target_cpu; + u32 sw_set; + u32 sw_clr; + u32 mask_set; + u32 mask_clr; + /* 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, }; @@ -212,7 +224,9 @@ struct aic_irq_chip { void __iomem *base; struct irq_domain *hw_domain; struct irq_domain *ipi_domain; + int nr_irq; + int max_irq; struct aic_info info; }; @@ -247,7 +261,7 @@ static void aic_irq_mask(struct irq_data *d) u32 irq = FIELD_GET(AIC_EVENT_NUM, hwirq); - aic_ic_write(ic, AIC_MASK_SET + MASK_REG(irq), MASK_BIT(irq)); + aic_ic_write(ic, ic->info.mask_set + MASK_REG(irq), MASK_BIT(irq)); } static void aic_irq_unmask(struct irq_data *d) @@ -257,7 +271,7 @@ static void aic_irq_unmask(struct irq_data *d) u32 irq = FIELD_GET(AIC_EVENT_NUM, hwirq); - aic_ic_write(ic, AIC_MASK_CLR + MASK_REG(irq), MASK_BIT(irq)); + aic_ic_write(ic, ic->info.mask_clr + MASK_REG(irq), MASK_BIT(irq)); } static void aic_irq_eoi(struct irq_data *d) @@ -280,7 +294,7 @@ 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->base + ic->info.event); type = FIELD_GET(AIC_EVENT_TYPE, event); irq = FIELD_GET(AIC_EVENT_NUM, event); @@ -312,12 +326,15 @@ static int aic_irq_set_affinity(struct irq_data *d, struct aic_irq_chip *ic = irq_data_get_irq_chip_data(d); int cpu; + if (!ic->info.target_cpu) + return -EINVAL; + if (force) cpu = cpumask_first(mask_val); else cpu = cpumask_any_and(mask_val, cpu_online_mask); - aic_ic_write(ic, AIC_TARGET_CPU + FIELD_GET(AIC_EVENT_NUM, hwirq) * 4, BIT(cpu)); + aic_ic_write(ic, ic->info.target_cpu + FIELD_GET(AIC_EVENT_NUM, hwirq) * 4, BIT(cpu)); irq_data_update_effective_affinity(d, cpumask_of(cpu)); return IRQ_SET_MASK_OK; @@ -876,8 +893,8 @@ static struct gic_kvm_info vgic_info __initdata = { static int __init aic_of_ic_init(struct device_node *node, struct device_node *parent) { int i; + u32 off; void __iomem *regs; - u32 info; struct aic_irq_chip *irqc; const struct of_device_id *match; @@ -899,8 +916,30 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p aic_irqc = irqc; - info = aic_ic_read(irqc, AIC_INFO); - irqc->nr_irq = FIELD_GET(AIC_INFO_NR_IRQ, info); + switch (irqc->info.version) { + case 1: { + u32 info; + + info = aic_ic_read(irqc, AIC_INFO); + irqc->nr_irq = FIELD_GET(AIC_INFO_NR_IRQ, info); + irqc->max_irq = AIC_MAX_IRQ; + + off = irqc->info.target_cpu; + off += sizeof(u32) * irqc->max_irq; /* TARGET_CPU */ + + break; + } + } + + irqc->info.sw_set = off; + off += sizeof(u32) * (irqc->max_irq >> 5); /* SW_SET */ + irqc->info.sw_clr = off; + off += sizeof(u32) * (irqc->max_irq >> 5); /* SW_CLR */ + irqc->info.mask_set = off; + off += sizeof(u32) * (irqc->max_irq >> 5); /* MASK_SET */ + irqc->info.mask_clr = off; + off += sizeof(u32) * (irqc->max_irq >> 5); /* MASK_CLR */ + off += sizeof(u32) * (irqc->max_irq >> 5); /* HW_STATE */ irqc->hw_domain = irq_domain_create_tree(of_node_to_fwnode(node), &aic_irq_domain_ops, irqc); @@ -923,11 +962,11 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p set_handle_fiq(aic_handle_fiq); for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) - aic_ic_write(irqc, AIC_MASK_SET + i * 4, U32_MAX); + aic_ic_write(irqc, irqc->info.mask_set + i * 4, U32_MAX); for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) - aic_ic_write(irqc, AIC_SW_CLR + i * 4, U32_MAX); + aic_ic_write(irqc, irqc->info.sw_clr + i * 4, U32_MAX); for (i = 0; i < irqc->nr_irq; i++) - aic_ic_write(irqc, AIC_TARGET_CPU + i * 4, 1); + aic_ic_write(irqc, irqc->info.target_cpu + i * 4, 1); if (!is_kernel_in_hyp_mode()) pr_info("Kernel running in EL1, mapping interrupts"); @@ -941,8 +980,8 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p vgic_set_kvm_info(&vgic_info); - pr_info("Initialized with %d IRQs, %d FIQs, %d vIPIs\n", - irqc->nr_irq, AIC_NR_FIQ, AIC_NR_SWIPI); + pr_info("Initialized with %d/%d IRQs, %d FIQs, %d vIPIs", + irqc->nr_irq, irqc->max_irq, AIC_NR_FIQ, AIC_NR_SWIPI); return 0; } From patchwork Thu Dec 9 04:32:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hector Martin X-Patchwork-Id: 12695440 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 111C4C433F5 for ; Thu, 9 Dec 2021 04:36:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=hPhJhGpLDpCRWY6PJ2GBE1qXCF2nWBdT+G3W6d4oX8o=; b=aVPQiDw6XlptV8 1oQDKz0i10BuubQqdYNGovZns7Qs3O6h75A5wS7NQKhklyHJrOZ3bA5RDrLtq50qQ1arh/SI3HnE4 jOxnQ0EeE7D/jajcVriDD0x/LYheUnSORkkj3WmNTS58mmPLETv0QexCt/u9FJo2R5pVkoP2LbCcQ FlG994g/LS+EKJq8QdtIrn2XRWF53TaRY2kIwzsVGmYeACGFRnyNEvOE1Jyv6Z7IGkb/l4pNVmEV8 oLS6GV/4SbIIiGKTM/hgVZDXTQPe/vM6cHM/7O1TCb8Um/RNoBhp4goWzYLPoSVnDyjPwCb/EiXF7 xql8zY42aqSDobfTEubg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB8M-00Esf4-0Q; Thu, 09 Dec 2021 04:34:18 +0000 Received: from marcansoft.com ([2a01:298:fe:f::2] helo=mail.marcansoft.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7f-00EsUZ-U4 for linux-arm-kernel@lists.infradead.org; Thu, 09 Dec 2021 04:33:37 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: hector@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id 4F81641E64; Thu, 9 Dec 2021 04:33:30 +0000 (UTC) From: Hector Martin To: Thomas Gleixner , Marc Zyngier , Rob Herring Cc: Hector Martin , Sven Peter , Alyssa Rosenzweig , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 5/6] irqchip/apple-aic: Support multiple dies Date: Thu, 9 Dec 2021 13:32:48 +0900 Message-Id: <20211209043249.65474-6-marcan@marcan.st> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211209043249.65474-1-marcan@marcan.st> References: <20211209043249.65474-1-marcan@marcan.st> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211208_203336_149030_828863CC X-CRM114-Status: GOOD ( 20.41 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Multi-die support in AICv2 uses several sets of IRQ registers. Introduce a die count and compute the register group offset based on the die ID field of the hwirq number, as reported by the hardware. Signed-off-by: Hector Martin --- drivers/irqchip/irq-apple-aic.c | 75 +++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index d03caed51d56..46b7750548a0 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -72,7 +72,8 @@ #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_FIQ 0 /* Software use */ @@ -157,6 +158,9 @@ #define MPIDR_CPU GENMASK(7, 0) #define MPIDR_CLUSTER GENMASK(15, 8) +#define AIC_IRQ_HWIRQ(die, irq) (FIELD_PREP(AIC_EVENT_DIE, die) | \ + FIELD_PREP(AIC_EVENT_TYPE, AIC_EVENT_TYPE_HW) | \ + 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_NR_FIQ 4 @@ -188,6 +192,8 @@ struct aic_info { u32 mask_set; u32 mask_clr; + u32 die_stride; + /* Features */ bool fast_ipi; }; @@ -227,6 +233,8 @@ struct aic_irq_chip { int nr_irq; int max_irq; + int nr_die; + int max_die; struct aic_info info; }; @@ -259,9 +267,10 @@ 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); + u32 off = FIELD_GET(AIC_EVENT_DIE, hwirq) * ic->info.die_stride; u32 irq = FIELD_GET(AIC_EVENT_NUM, hwirq); - aic_ic_write(ic, ic->info.mask_set + MASK_REG(irq), MASK_BIT(irq)); + aic_ic_write(ic, ic->info.mask_set + off + MASK_REG(irq), MASK_BIT(irq)); } static void aic_irq_unmask(struct irq_data *d) @@ -269,9 +278,10 @@ 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); + u32 off = FIELD_GET(AIC_EVENT_DIE, hwirq) * ic->info.die_stride; u32 irq = FIELD_GET(AIC_EVENT_NUM, hwirq); - aic_ic_write(ic, ic->info.mask_clr + MASK_REG(irq), MASK_BIT(irq)); + aic_ic_write(ic, ic->info.mask_clr + off + MASK_REG(irq), MASK_BIT(irq)); } static void aic_irq_eoi(struct irq_data *d) @@ -535,28 +545,41 @@ static int aic_irq_domain_translate(struct irq_domain *id, unsigned int *type) { struct aic_irq_chip *ic = id->host_data; + u32 *args; + u32 die = 0; - if (fwspec->param_count != 3 || !is_of_node(fwspec->fwnode)) + if (fwspec->param_count < 3 || fwspec->param_count > 4 || + !is_of_node(fwspec->fwnode)) return -EINVAL; + args = &fwspec->param[1]; + + if (fwspec->param_count == 4) { + die = args[0]; + args++; + } + switch (fwspec->param[0]) { case AIC_IRQ: - if (fwspec->param[1] >= ic->nr_irq) + if (die >= ic->nr_die) + return -EINVAL; + if (args[0] >= ic->nr_irq) return -EINVAL; - *hwirq = (FIELD_PREP(AIC_EVENT_TYPE, AIC_EVENT_TYPE_HW) | - FIELD_PREP(AIC_EVENT_NUM, fwspec->param[1])); + *hwirq = AIC_IRQ_HWIRQ(die, args[0]); break; case AIC_FIQ: - if (fwspec->param[1] >= AIC_NR_FIQ) + if (die != 0) return -EINVAL; - *hwirq = AIC_FIQ_HWIRQ(fwspec->param[1]); + if (args[0] >= AIC_NR_FIQ) + return -EINVAL; + *hwirq = AIC_FIQ_HWIRQ(args[0]); /* * In EL1 the non-redirected registers are the guest's, * not EL2's, so remap the hwirqs to match. */ if (!is_kernel_in_hyp_mode()) { - switch (fwspec->param[1]) { + switch (args[0]) { case AIC_TMR_GUEST_PHYS: *hwirq = AIC_FIQ_HWIRQ(AIC_TMR_EL0_PHYS); break; @@ -575,7 +598,7 @@ static int aic_irq_domain_translate(struct irq_domain *id, return -EINVAL; } - *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; + *type = args[1] & IRQ_TYPE_SENSE_MASK; return 0; } @@ -892,8 +915,8 @@ static struct gic_kvm_info vgic_info __initdata = { static int __init aic_of_ic_init(struct device_node *node, struct device_node *parent) { - int i; - u32 off; + int i, die; + u32 off, start_off; void __iomem *regs; struct aic_irq_chip *irqc; const struct of_device_id *match; @@ -923,8 +946,9 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p info = aic_ic_read(irqc, AIC_INFO); irqc->nr_irq = FIELD_GET(AIC_INFO_NR_IRQ, info); irqc->max_irq = AIC_MAX_IRQ; + irqc->nr_die = irqc->max_die = 1; - off = irqc->info.target_cpu; + off = start_off = irqc->info.target_cpu; off += sizeof(u32) * irqc->max_irq; /* TARGET_CPU */ break; @@ -941,6 +965,8 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p off += sizeof(u32) * (irqc->max_irq >> 5); /* MASK_CLR */ off += sizeof(u32) * (irqc->max_irq >> 5); /* HW_STATE */ + irqc->info.die_stride = off - start_off; + irqc->hw_domain = irq_domain_create_tree(of_node_to_fwnode(node), &aic_irq_domain_ops, irqc); if (WARN_ON(!irqc->hw_domain)) { @@ -961,12 +987,17 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p set_handle_irq(aic_handle_irq); set_handle_fiq(aic_handle_fiq); - for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) - aic_ic_write(irqc, irqc->info.mask_set + i * 4, U32_MAX); - for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) - aic_ic_write(irqc, irqc->info.sw_clr + i * 4, U32_MAX); - for (i = 0; i < irqc->nr_irq; i++) - aic_ic_write(irqc, irqc->info.target_cpu + i * 4, 1); + off = 0; + for (die = 0; die < irqc->nr_die; die++) { + for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) + aic_ic_write(irqc, irqc->info.mask_set + off + i * 4, U32_MAX); + for (i = 0; i < BITS_TO_U32(irqc->nr_irq); i++) + aic_ic_write(irqc, irqc->info.sw_clr + off + i * 4, U32_MAX); + if (irqc->info.target_cpu) + for (i = 0; i < irqc->nr_irq; i++) + aic_ic_write(irqc, irqc->info.target_cpu + off + i * 4, 1); + off += irqc->info.die_stride; + } if (!is_kernel_in_hyp_mode()) pr_info("Kernel running in EL1, mapping interrupts"); @@ -980,8 +1011,8 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p vgic_set_kvm_info(&vgic_info); - pr_info("Initialized with %d/%d IRQs, %d FIQs, %d vIPIs", - irqc->nr_irq, irqc->max_irq, AIC_NR_FIQ, AIC_NR_SWIPI); + pr_info("Initialized with %d/%d IRQs * %d/%d die(s), %d FIQs, %d vIPIs", + irqc->nr_irq, irqc->max_irq, irqc->nr_die, irqc->max_die, AIC_NR_FIQ, AIC_NR_SWIPI); return 0; } From patchwork Thu Dec 9 04:32:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hector Martin X-Patchwork-Id: 12695441 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E5C40C433F5 for ; Thu, 9 Dec 2021 04:36:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=/TEd8sw9RkckLo/7VHNzTtuOtCc7mk5I8C5ZdOzQbm4=; b=JfVd+E/GwG/XrC eWbNR6bHSyejucz5Ap9Jp2K12A8esnJwFn2ELElna2UViWv1hS2Pk70MtNIDXNFTv2iky+QJIXgqR c2uLzS4lLgp4BBWF0b+m9bv9ilvQlNolIronRXvwTQILS3QhM2Mv4vVulDzh1W9MIE1+t9wXURuuR 5HpF3Qwozw/D723ZcL6VcvRTOiBt+ai/Cn/g4QblBx9g2q7HB27GZsLdSYelrnINDwT3yxkhxY6Lu Cyg6zpZuvNmoYwzF+OCApHfOhcOnfCM12KG2wRwtiBpbLJmPvOgbJehd7lQtWJ4+AJkTy2ZAvNq7N eWB1MSQiz4cFdDRgsA6A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB8X-00Esjx-Gg; Thu, 09 Dec 2021 04:34:29 +0000 Received: from marcansoft.com ([2a01:298:fe:f::2] helo=mail.marcansoft.com) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mvB7i-00EsVR-Ae for linux-arm-kernel@lists.infradead.org; Thu, 09 Dec 2021 04:33:40 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: hector@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id DFA3C41EA2; Thu, 9 Dec 2021 04:33:33 +0000 (UTC) From: Hector Martin To: Thomas Gleixner , Marc Zyngier , Rob Herring Cc: Hector Martin , Sven Peter , Alyssa Rosenzweig , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 6/6] irqchip/apple-aic: Add support for AICv2 Date: Thu, 9 Dec 2021 13:32:49 +0900 Message-Id: <20211209043249.65474-7-marcan@marcan.st> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211209043249.65474-1-marcan@marcan.st> References: <20211209043249.65474-1-marcan@marcan.st> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211208_203338_548123_91FB7CDA X-CRM114-Status: GOOD ( 25.92 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Introduce support for the new AICv2 hardware block in t6000/t6001 SoCs. It seems these blocks are missing the information required to compute the event register offset in the capability registers, so we specify that in the DT. Signed-off-by: Hector Martin --- drivers/irqchip/irq-apple-aic.c | 146 ++++++++++++++++++++++++++++---- 1 file changed, 128 insertions(+), 18 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 46b7750548a0..226d5232dd14 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -101,6 +101,57 @@ #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 explcitly specify the event + * register offset 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)) @@ -187,6 +238,7 @@ struct aic_info { /* Register offsets */ u32 event; u32 target_cpu; + u32 irq_cfg; u32 sw_set; u32 sw_clr; u32 mask_set; @@ -214,6 +266,14 @@ static const struct aic_info aic1_fipi_info = { .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", @@ -223,6 +283,10 @@ static const struct of_device_id aic_info_match[] = { .compatible = "apple,aic", .data = &aic1_info, }, + { + .compatible = "apple,aic2", + .data = &aic2_info, + }, {} }; @@ -368,6 +432,14 @@ static struct irq_chip aic_chip = { .irq_set_type = aic_irq_set_type, }; +static struct irq_chip aic2_chip = { + .name = "AIC2", + .irq_mask = aic_irq_mask, + .irq_unmask = aic_irq_unmask, + .irq_eoi = aic_irq_eoi, + .irq_set_type = aic_irq_set_type, +}; + /* * FIQ irqchip */ @@ -524,10 +596,15 @@ static struct irq_chip fiq_chip = { 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; u32 type = FIELD_GET(AIC_EVENT_TYPE, hw); + struct irq_chip *chip = &aic_chip; + + if (ic->info.version == 2) + chip = &aic2_chip; if (type == AIC_EVENT_TYPE_HW) { - irq_domain_set_info(id, irq, hw, &aic_chip, id->host_data, + irq_domain_set_info(id, irq, hw, chip, id->host_data, handle_fasteoi_irq, NULL, NULL); irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } else if (type == AIC_EVENT_TYPE_FIQ) { @@ -882,23 +959,25 @@ static int aic_init_cpu(unsigned int cpu) /* Commit all of the above */ isb(); - /* - * Make sure the kernel's idea of logical CPU order is the same as AIC's - * If we ever end up with a mismatch here, we will have to introduce - * a mapping table similar to what other irqchip drivers do. - */ - WARN_ON(aic_ic_read(aic_irqc, AIC_WHOAMI) != smp_processor_id()); + if (aic_irqc->info.version == 1) { + /* + * Make sure the kernel's idea of logical CPU order is the same as AIC's + * If we ever end up with a mismatch here, we will have to introduce + * a mapping table similar to what other irqchip drivers do. + */ + WARN_ON(aic_ic_read(aic_irqc, AIC_WHOAMI) != smp_processor_id()); - /* - * Always keep IPIs unmasked at the hardware level (except auto-masking - * by AIC during processing). We manage masks at the vIPI level. - */ - aic_ic_write(aic_irqc, AIC_IPI_ACK, AIC_IPI_SELF | AIC_IPI_OTHER); - if (!aic_irqc->info.fast_ipi) { - aic_ic_write(aic_irqc, AIC_IPI_MASK_SET, AIC_IPI_SELF); - aic_ic_write(aic_irqc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER); - } else { - aic_ic_write(aic_irqc, AIC_IPI_MASK_SET, AIC_IPI_SELF | AIC_IPI_OTHER); + /* + * Always keep IPIs unmasked at the hardware level (except auto-masking + * by AIC during processing). We manage masks at the vIPI level. + */ + aic_ic_write(aic_irqc, AIC_IPI_ACK, AIC_IPI_SELF | AIC_IPI_OTHER); + if (!aic_irqc->info.fast_ipi) { + aic_ic_write(aic_irqc, AIC_IPI_MASK_SET, AIC_IPI_SELF); + aic_ic_write(aic_irqc, AIC_IPI_MASK_CLR, AIC_IPI_OTHER); + } else { + aic_ic_write(aic_irqc, AIC_IPI_MASK_SET, AIC_IPI_SELF | AIC_IPI_OTHER); + } } /* Initialize the local mask state */ @@ -953,6 +1032,29 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p break; } + case 2: { + u32 info1, info3; + + info1 = aic_ic_read(irqc, AIC2_INFO1); + info3 = aic_ic_read(irqc, AIC2_INFO3); + + irqc->nr_irq = FIELD_GET(AIC2_INFO1_NR_IRQ, info1); + irqc->max_irq = FIELD_GET(AIC2_INFO3_MAX_IRQ, info3); + irqc->nr_die = FIELD_GET(AIC2_INFO1_LAST_DIE, info1) + 1; + irqc->max_die = FIELD_GET(AIC2_INFO3_MAX_DIE, info3); + + off = start_off = irqc->info.irq_cfg; + off += sizeof(u32) * irqc->max_irq; /* IRQ_CFG */ + + if (of_property_read_u32(node, "apple,event-reg", &irqc->info.event) < 0) { + pr_err("Failed to get apple,event-reg property"); + iounmap(irqc->base); + kfree(irqc); + return -ENODEV; + } + + break; + } } irqc->info.sw_set = off; @@ -999,6 +1101,13 @@ 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) { + u32 config = aic_ic_read(irqc, AIC2_CONFIG); + + config |= AIC2_CONFIG_ENABLE; + aic_ic_write(irqc, AIC2_CONFIG, config); + } + if (!is_kernel_in_hyp_mode()) pr_info("Kernel running in EL1, mapping interrupts"); @@ -1017,4 +1126,5 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p return 0; } -IRQCHIP_DECLARE(apple_m1_aic, "apple,aic", aic_of_ic_init); +IRQCHIP_DECLARE(apple_aic, "apple,aic", aic_of_ic_init); +IRQCHIP_DECLARE(apple_aic2, "apple,aic2", aic_of_ic_init);