From nobody Wed Jul 1 23:24:01 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3AE11C433F5 for ; Sun, 9 Jan 2022 14:55:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235830AbiAIOyv (ORCPT ); Sun, 9 Jan 2022 09:54:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57092 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235809AbiAIOys (ORCPT ); Sun, 9 Jan 2022 09:54:48 -0500 Received: from polaris.svanheule.net (polaris.svanheule.net [IPv6:2a00:c98:2060:a004:1::200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEB72C061748 for ; Sun, 9 Jan 2022 06:54:48 -0800 (PST) Received: from terra.local.svanheule.net (unknown [IPv6:2a02:a03f:eafe:c901:f20a:f473:2021:45ec]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id D42D928EE24; Sun, 9 Jan 2022 15:54:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1641740087; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TpkkGK1HUml0mP08FJk1cHUKfwB7mgaDR1xVUUyYboc=; b=8q5MbwPnrWK7owgLbfqfyAHRlTblYQrhuXGBdeW2QQe1bhoQ7SJBeCwDll2yYc5KwxM1iA bnQGLXOsfkuLaDchhdTzaLnFE1CGzeHAqAm2RAuAW0TmtmCKFJwPMCeySNpg+yHK7OsUr1 WECS+Le6cVPvPRvaiUCQrBgfH3sKe/jV/bRu3hgnpi8TeSa7dchbTX+oAjjcz865DC9igA sUralPlfusr77jorgQPO18MvbncBs0ezWRqMH450usDGCIlJrYzlIEFKreTbaQw6M18iSR UobK/UsFTbIAtfBLT2JD/2XaxIzcphYk1llVJ/DTM3Gk05YRaTH05zN733lrpw== From: Sander Vanheule To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: Thomas Gleixner , Marc Zyngier , Rob Herring , Birger Koblitz , Bert Vermeulen , John Crispin , Sander Vanheule Subject: [PATCH v3 1/6] irqchip/realtek-rtl: map control data to virq Date: Sun, 9 Jan 2022 15:54:32 +0100 Message-Id: <4b4936606480265db47df152f00bc2ed46340599.1641739718.git.sander@svanheule.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The driver assigned the irqchip and irq handler to the hardware irq, instead of the virq. This is incorrect, and only worked because these irq numbers happened to be the same on the devices used for testing the original driver. Fixes: 9f3a0f34b84a ("irqchip: Add support for Realtek RTL838x/RTL839x inte= rrupt controller") Signed-off-by: Sander Vanheule --- drivers/irqchip/irq-realtek-rtl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realte= k-rtl.c index fd9f275592d2..d6788dd93c7b 100644 --- a/drivers/irqchip/irq-realtek-rtl.c +++ b/drivers/irqchip/irq-realtek-rtl.c @@ -62,7 +62,7 @@ static struct irq_chip realtek_ictl_irq =3D { =20 static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_= t hw) { - irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq); + irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq); =20 return 0; } --=20 2.33.1 From nobody Wed Jul 1 23:24:01 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D3640C433F5 for ; Sun, 9 Jan 2022 14:55:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235840AbiAIOyx (ORCPT ); Sun, 9 Jan 2022 09:54:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57098 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235806AbiAIOyu (ORCPT ); Sun, 9 Jan 2022 09:54:50 -0500 Received: from polaris.svanheule.net (polaris.svanheule.net [IPv6:2a00:c98:2060:a004:1::200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D5401C06173F for ; Sun, 9 Jan 2022 06:54:49 -0800 (PST) Received: from terra.local.svanheule.net (unknown [IPv6:2a02:a03f:eafe:c901:f20a:f473:2021:45ec]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 2560428EE25; Sun, 9 Jan 2022 15:54:48 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1641740088; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RffKHmKHsI7Q9f2s/yP75xd+8RX8KcPe5WgjwZP779I=; b=aKgdGywvdtYQ6FBsFA4JvMJvNVApTc4rSA2eBojxZ2pcV7+6nAwHVHADx4BHn8DzlhlE4x ixARic/881aM4Cv9fxrP0at6s9USJwwDL17VFFgoW5Bqh0MD2H2/JWp3OM9m2NuQ4jM31J WVpIc5HZftR7ipi+mVpcPTsEQCydhviQzH9QXPy3fJGpB6Q3AcgzcGQLnCWoF8dye8raqh OVj6arnw2a0+XDe80LZZsIIa/tSPV2bWbkUI0NmrrQxx9aeY0dEGZg5T+y10hmUPrHa8eb AmPBz+Mzj4HFWQOqtMcL0jseXCIMu8S5su9kZ18IB+kwh1B4gxVLVQGHeuii4A== From: Sander Vanheule To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: Thomas Gleixner , Marc Zyngier , Rob Herring , Birger Koblitz , Bert Vermeulen , John Crispin , Sander Vanheule Subject: [PATCH v3 2/6] irqchip/realtek-rtl: fix off-by-one in routing Date: Sun, 9 Jan 2022 15:54:33 +0100 Message-Id: <177b920aa8d8610615692d0e657e509f363c85ca.1641739718.git.sander@svanheule.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" There is an offset between routing values (1..6) and the connected MIPS CPU interrupts (2..7), but no distinction was made between these two values. This issue was previously hidden during testing, because an interrupt mapping was used where for each required interrupt another (unused) routing was configured, with an offset of +1. Offset the CPU IRQ numbers by -1 to retrieve the correct routing value. Fixes: 9f3a0f34b84a ("irqchip: Add support for Realtek RTL838x/RTL839x inte= rrupt controller") Signed-off-by: Sander Vanheule --- drivers/irqchip/irq-realtek-rtl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realte= k-rtl.c index d6788dd93c7b..568614edd88f 100644 --- a/drivers/irqchip/irq-realtek-rtl.c +++ b/drivers/irqchip/irq-realtek-rtl.c @@ -95,7 +95,8 @@ static void realtek_irq_dispatch(struct irq_desc *desc) * SoC interrupts are cascaded to MIPS CPU interrupts according to the * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrup= ts - * thus go into 4 IRRs. + * thus go into 4 IRRs. A routing value of '0' means the interrupt is left + * disconnected. Routing values {1..15} connect to output lines {0..14}. */ static int __init map_interrupts(struct device_node *node, struct irq_doma= in *domain) { @@ -134,7 +135,7 @@ static int __init map_interrupts(struct device_node *no= de, struct irq_domain *do of_node_put(cpu_ictl); =20 cpu_int =3D be32_to_cpup(imap + 2); - if (cpu_int > 7) + if (cpu_int > 7 || cpu_int < 2) return -EINVAL; =20 if (!(mips_irqs_set & BIT(cpu_int))) { @@ -143,7 +144,8 @@ static int __init map_interrupts(struct device_node *no= de, struct irq_domain *do mips_irqs_set |=3D BIT(cpu_int); } =20 - regs[(soc_int * 4) / 32] |=3D cpu_int << (soc_int * 4) % 32; + /* Use routing values (1..6) for CPU interrupts (2..7) */ + regs[(soc_int * 4) / 32] |=3D (cpu_int - 1) << (soc_int * 4) % 32; imap +=3D 3; } =20 --=20 2.33.1 From nobody Wed Jul 1 23:24:01 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4C2FC433FE for ; Sun, 9 Jan 2022 14:55:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235859AbiAIOy4 (ORCPT ); Sun, 9 Jan 2022 09:54:56 -0500 Received: from polaris.svanheule.net ([84.16.241.116]:58434 "EHLO polaris.svanheule.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235821AbiAIOyv (ORCPT ); Sun, 9 Jan 2022 09:54:51 -0500 Received: from terra.local.svanheule.net (unknown [IPv6:2a02:a03f:eafe:c901:f20a:f473:2021:45ec]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 6AC8228EE26; Sun, 9 Jan 2022 15:54:49 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1641740089; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OMbIcvvI3IPuNYN8evQvKri6MZuBKmRYkZMVWhpSDAE=; b=S7jRTa+1CSDVpJcouFz9VjmlXtRouU6rbqQOMr9OTi3sDgUE9BkGv0eggwDYIv+PaTituB CmtArYLh6rCKYWkmzqVROGuomPLeXRyWbnnKUFTTHtoCTXYif6UOtfAMkK0z2HT0Sz8suG fDeko40Jmw1ohh428btqevKNFmV0dT0vxZSVHO/uTdzyvPEAd8siv2wACaDkX+c9tCF7SQ 3B7vrliSQrSLq2GW1vUI1gzKAixGGsrlbG1R8GwmDlLlztd5lgLe4SFeD+2M5YwlRlOTcl +6LukC9qT2YGNy6r4I0vhVCGtX8c99snc1DTD5CGds2X0llWEwkPMvkGmuXBTA== From: Sander Vanheule To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: Thomas Gleixner , Marc Zyngier , Rob Herring , Birger Koblitz , Bert Vermeulen , John Crispin , Sander Vanheule Subject: [PATCH v3 3/6] irqchip/realtek-rtl: clear all pending interrupts Date: Sun, 9 Jan 2022 15:54:34 +0100 Message-Id: <5082ad3cb8b4eedf55075561b93eff6570299fe1.1641739718.git.sander@svanheule.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Instead of only servicing the lowest pending interrupt line, make sure all pending SoC interrupts are serviced before exiting the chained handler. This adds a small overhead if only one interrupt is pending, but should prevent rapid re-triggering of the handler. Signed-off-by: Sander Vanheule --- drivers/irqchip/irq-realtek-rtl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realte= k-rtl.c index 568614edd88f..50a56820c99b 100644 --- a/drivers/irqchip/irq-realtek-rtl.c +++ b/drivers/irqchip/irq-realtek-rtl.c @@ -76,16 +76,20 @@ static void realtek_irq_dispatch(struct irq_desc *desc) { struct irq_chip *chip =3D irq_desc_get_chip(desc); struct irq_domain *domain; - unsigned int pending; + unsigned long pending; + unsigned int soc_int; =20 chained_irq_enter(chip, desc); pending =3D readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR)); + if (unlikely(!pending)) { spurious_interrupt(); goto out; } + domain =3D irq_desc_get_handler_data(desc); - generic_handle_domain_irq(domain, __ffs(pending)); + for_each_set_bit(soc_int, &pending, 32) + generic_handle_domain_irq(domain, soc_int); =20 out: chained_irq_exit(chip, desc); --=20 2.33.1 From nobody Wed Jul 1 23:24:01 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 130ADC433EF for ; Sun, 9 Jan 2022 14:55:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235880AbiAIOy5 (ORCPT ); Sun, 9 Jan 2022 09:54:57 -0500 Received: from polaris.svanheule.net ([84.16.241.116]:58454 "EHLO polaris.svanheule.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235828AbiAIOyw (ORCPT ); Sun, 9 Jan 2022 09:54:52 -0500 Received: from terra.local.svanheule.net (unknown [IPv6:2a02:a03f:eafe:c901:f20a:f473:2021:45ec]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id 9228D28EE27; Sun, 9 Jan 2022 15:54:50 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1641740090; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=beZnfvFxhflj3F7p8ZPExQMiCmn9XP8LYTsb7UPPuYY=; b=9oi5iDvP9y4yoaaAFVqtN9IaqAU5QqaJIx4rmg4fvLLafSFvWb6xw8U33tiKSuS1/3zvtu +whVWDidFWCFRyeNkWaUY5fjAQ94eG6QZu2XSbO+vazb3AOrceCllgp/ZFVMd0ap1kfKhG 9oDZVjsUZoJv8SNrKLYDSI6pRUp4e4PXAylrBgXaqqTSAQ5hSvs6LbHDHU6X/p0tqrIhyy SFNS6st/+/+dtlu3xompXdqC2p1yCxg4AP66G1/VLU5z/8VCHe/TGFSqlVf7cR3XELFdr/ lcvp6TYBgNEtHyUGPS/Rw1ncig3YNINBYt3SaQxW0sSHc0u2mjdtuYOKX9Cxlg== From: Sander Vanheule To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: Thomas Gleixner , Marc Zyngier , Rob Herring , Birger Koblitz , Bert Vermeulen , John Crispin , Sander Vanheule Subject: [PATCH v3 4/6] dt-bindings: interrupt-controller: realtek,rtl-intc: require parents Date: Sun, 9 Jan 2022 15:54:35 +0100 Message-Id: X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The interrupt router has 32 inputs and up to 15 outputs, and the way these are mapped to each other is runtime configurable. The outputs of this interrupt router on the other hand, are connected to a fixed set of parent interrupts. This means that "interrupt-map" is inappropriate, and rather a list of parent interrupts should be specified. Two-part compatibles are introduced to be able to require "interrupts" for new devicetrees. The relevant descriptions are extended or added to more clearly describe the inputs and outputs of this router. The old compatible, "interrupt-map" and "#address-cells", is deprecated. Interrupt specifiers for new compatibles will require two cells, to indicate the output selection. To prevent spurious changes when more SoCs are added, "allOf" is used with one "if", and the compatible enum only has one item. The example is updated to provide a correct example for RTL8380 SoCs. Signed-off-by: Sander Vanheule --- .../realtek,rtl-intc.yaml | 78 ++++++++++++++----- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/realtek= ,rtl-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/rea= ltek,rtl-intc.yaml index 9e76fff20323..aab8d44010af 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-in= tc.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-in= tc.yaml @@ -6,6 +6,10 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# =20 title: Realtek RTL SoC interrupt controller devicetree bindings =20 +description: + Interrupt router for Realtek MIPS SoCs, allowing each SoC interrupt to be + routed to one parent interrupt, or left disconnected. + maintainers: - Birger Koblitz - Bert Vermeulen @@ -13,45 +17,79 @@ maintainers: =20 properties: compatible: - const: realtek,rtl-intc + oneOf: + - items: + - enum: + - realtek,rtl8380-intc + - const: realtek,rtl-intc + - const: realtek,rtl-intc + deprecated: true =20 - "#interrupt-cells": - const: 1 + "#interrupt-cells": true =20 reg: maxItems: 1 =20 interrupts: - maxItems: 1 + minItems: 1 + maxItems: 15 + description: + List of parent interrupts, in the order that they are connected to t= his + interrupt router's outputs. =20 interrupt-controller: true =20 - "#address-cells": - const: 0 - - interrupt-map: - description: Describes mapping from SoC interrupts to CPU interrupts - required: - compatible - reg - "#interrupt-cells" - interrupt-controller - - "#address-cells" - - interrupt-map + +allOf: + - if: + properties: + compatible: + const: realtek,rtl-intc + then: + properties: + "#interrupt-cells": + const: 1 + + "#address-cells": + const: 0 + + interrupt-map: true + required: + - "#address-cells" + - interrupt-map + else: + properties: + "#interrupt-cells": + description: + Two cells to specify which line to connect to, and which outpu= t it should + be routed to. Both cells use a zero-based index. + const: 2 + required: + - interrupts =20 additionalProperties: false =20 examples: - | intc: interrupt-controller@3000 { - compatible =3D "realtek,rtl-intc"; - #interrupt-cells =3D <1>; + compatible =3D "realtek,rtl8380-intc", "realtek,rtl-intc"; + #interrupt-cells =3D <2>; interrupt-controller; - reg =3D <0x3000 0x20>; - #address-cells =3D <0>; - interrupt-map =3D - <31 &cpuintc 2>, - <30 &cpuintc 1>, - <29 &cpuintc 5>; + reg =3D <0x3000 0x18>; + + interrupt-parent =3D <&cpuintc>; + interrupts =3D <2>, <3>, <4>, <5>, <6>; + }; + + irq-consumer@0 { + reg =3D <0 4>; + interrupt-parent =3D <&intc>; + interrupts =3D + <19 3>, /* IRQ 19, routed to output 3 (cpuintc 5) */ + <18 4>; /* IRQ 18, routed to output 4 (cpuintc 6) */ }; --=20 2.33.1 From nobody Wed Jul 1 23:24:01 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1AE5C4167E for ; Sun, 9 Jan 2022 14:55:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235942AbiAIOzH (ORCPT ); Sun, 9 Jan 2022 09:55:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57120 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235847AbiAIOyy (ORCPT ); Sun, 9 Jan 2022 09:54:54 -0500 Received: from polaris.svanheule.net (polaris.svanheule.net [IPv6:2a00:c98:2060:a004:1::200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9F95EC06173F for ; Sun, 9 Jan 2022 06:54:53 -0800 (PST) Received: from terra.local.svanheule.net (unknown [IPv6:2a02:a03f:eafe:c901:f20a:f473:2021:45ec]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id B105028EE28; Sun, 9 Jan 2022 15:54:51 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1641740092; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WrbaX59ca9lhL9V4ZRttEMkg2AaMlgPLErcXwM3dPG8=; b=Eb6T0NM0UbivXLPQKUrq8VtxmpwfZYGAOCcpS3A7GbG2ubvQ5UoGosJuioiNIkjS/lBALR /KK1qmhspNDVbnu+kyIN6LGl2TRQnJ6Ew3aIWRXEsOSOHFK4+YRsMCwAgA7UOXFlEldDgY 6E3qyxu4hACK7j+Ku7V9wQIFfh5URTm44qy3hkOGUKgnjAfBc7zHLCxHhdR/sRMmPKawaY yLQEznEkBwIjbuLChy45KdXvb4dTeW3TCq15pxfqp6qpqoIe7uorxnTm6nW0fAtvqA8/QI ZIho79SQhyWDbHAoQFyROA6QK4KXtPnvEVDzUuYWNhIsiQxzU/r90FvL8Ix7yw== From: Sander Vanheule To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: Thomas Gleixner , Marc Zyngier , Rob Herring , Birger Koblitz , Bert Vermeulen , John Crispin , Sander Vanheule Subject: [PATCH v3 5/6] irqchip/realtek-rtl: use parent interrupts Date: Sun, 9 Jan 2022 15:54:36 +0100 Message-Id: <57edb463b37de4a1d63e83ca9ef9beef81e0c72a.1641739718.git.sander@svanheule.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The interrupt-map property for "realtek,rtl-intc" has been deprecated in favor of a list of parent interrupts. Drop the open-coded parser for interrupt-map, and use the first parent interrupt instead. If no parent was provided, the driver will assume that this is the first hardware interrupt of the SoC's MIPS CPU. All SoC interrupts were treated equally, independent of which output they were actually routed to. This means the driver might as well route all interrupts to the first output, and achieve the same behaviour. Without the interrupt-map property, interrupt routing information is no longer available at initialisation. Routing setup will now happen later, when a hardware interrupt is mapped by the subsystem. Signed-off-by: Sander Vanheule --- drivers/irqchip/irq-realtek-rtl.c | 133 ++++++++++++++---------------- 1 file changed, 61 insertions(+), 72 deletions(-) diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realte= k-rtl.c index 50a56820c99b..388f4a7bfb80 100644 --- a/drivers/irqchip/irq-realtek-rtl.c +++ b/drivers/irqchip/irq-realtek-rtl.c @@ -21,11 +21,33 @@ #define RTL_ICTL_IRR2 0x10 #define RTL_ICTL_IRR3 0x14 =20 +#define RTL_ICTL_NUM_INPUTS 32 + #define REG(x) (realtek_ictl_base + x) =20 static DEFINE_RAW_SPINLOCK(irq_lock); static void __iomem *realtek_ictl_base; =20 +/* + * IRR0-IRR3 store 4 bits per interrupt, but Realtek uses inverted numberi= ng, + * placing IRQ 31 in the first four bits. A routing value of '0' means the + * interrupt is left disconnected. Routing values {1..15} connect to output + * lines {0..14}. + */ +#define IRR_OFFSET(idx) (4 * (3 - (idx * 4) / 32)) +#define IRR_SHIFT(idx) ((idx * 4) % 32) + +static inline void write_irr(void __iomem *irr0, int idx, u32 value) +{ + unsigned int offset =3D IRR_OFFSET(idx); + unsigned int shift =3D IRR_SHIFT(idx); + u32 irr; + + irr =3D readl(irr0 + offset) & ~(0xf << shift); + irr |=3D (value & 0xf) << shift; + writel(irr, irr0 + offset); +} + static void realtek_ictl_unmask_irq(struct irq_data *i) { unsigned long flags; @@ -62,8 +84,14 @@ static struct irq_chip realtek_ictl_irq =3D { =20 static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_= t hw) { + unsigned long flags; + irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq); =20 + raw_spin_lock_irqsave(&irq_lock, flags); + write_irr(REG(RTL_ICTL_IRR0), hw, 1); + raw_spin_unlock_irqrestore(&irq_lock, flags); + return 0; } =20 @@ -95,90 +123,51 @@ static void realtek_irq_dispatch(struct irq_desc *desc) chained_irq_exit(chip, desc); } =20 -/* - * SoC interrupts are cascaded to MIPS CPU interrupts according to the - * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for - * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrup= ts - * thus go into 4 IRRs. A routing value of '0' means the interrupt is left - * disconnected. Routing values {1..15} connect to output lines {0..14}. - */ -static int __init map_interrupts(struct device_node *node, struct irq_doma= in *domain) -{ - struct device_node *cpu_ictl; - const __be32 *imap; - u32 imaplen, soc_int, cpu_int, tmp, regs[4]; - int ret, i, irr_regs[] =3D { - RTL_ICTL_IRR3, - RTL_ICTL_IRR2, - RTL_ICTL_IRR1, - RTL_ICTL_IRR0, - }; - u8 mips_irqs_set; - - ret =3D of_property_read_u32(node, "#address-cells", &tmp); - if (ret || tmp) - return -EINVAL; - - imap =3D of_get_property(node, "interrupt-map", &imaplen); - if (!imap || imaplen % 3) - return -EINVAL; - - mips_irqs_set =3D 0; - memset(regs, 0, sizeof(regs)); - for (i =3D 0; i < imaplen; i +=3D 3 * sizeof(u32)) { - soc_int =3D be32_to_cpup(imap); - if (soc_int > 31) - return -EINVAL; - - cpu_ictl =3D of_find_node_by_phandle(be32_to_cpup(imap + 1)); - if (!cpu_ictl) - return -EINVAL; - ret =3D of_property_read_u32(cpu_ictl, "#interrupt-cells", &tmp); - if (ret || tmp !=3D 1) - return -EINVAL; - of_node_put(cpu_ictl); - - cpu_int =3D be32_to_cpup(imap + 2); - if (cpu_int > 7 || cpu_int < 2) - return -EINVAL; - - if (!(mips_irqs_set & BIT(cpu_int))) { - irq_set_chained_handler_and_data(cpu_int, realtek_irq_dispatch, - domain); - mips_irqs_set |=3D BIT(cpu_int); - } - - /* Use routing values (1..6) for CPU interrupts (2..7) */ - regs[(soc_int * 4) / 32] |=3D (cpu_int - 1) << (soc_int * 4) % 32; - imap +=3D 3; - } - - for (i =3D 0; i < 4; i++) - writel(regs[i], REG(irr_regs[i])); - - return 0; -} - static int __init realtek_rtl_of_init(struct device_node *node, struct dev= ice_node *parent) { + struct of_phandle_args oirq; struct irq_domain *domain; - int ret; + unsigned int soc_irq; + int parent_irq; =20 realtek_ictl_base =3D of_iomap(node, 0); if (!realtek_ictl_base) return -ENXIO; =20 - /* Disable all cascaded interrupts */ + /* Disable all cascaded interrupts and clear routing */ writel(0, REG(RTL_ICTL_GIMR)); + for (soc_irq =3D 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++) + write_irr(REG(RTL_ICTL_IRR0), soc_irq, 0); + + if (WARN_ON(!of_irq_count(node))) { + /* + * If DT contains no parent interrupts, assume MIPS CPU IRQ 2 + * (HW0) is connected to the first output. This is the case for + * all known hardware anyway. "interrupt-map" is deprecated, so + * don't bother trying to parse that. + */ + oirq.np =3D of_find_compatible_node(NULL, NULL, "mti,cpu-interrupt-contr= oller"); + oirq.args_count =3D 1; + oirq.args[0] =3D 2; + + parent_irq =3D irq_create_of_mapping(&oirq); + + of_node_put(oirq.np); + } else { + parent_irq =3D of_irq_get(node, 0); + } + + if (parent_irq < 0) + return parent_irq; + else if (!parent_irq) + return -ENODEV; =20 - domain =3D irq_domain_add_simple(node, 32, 0, + domain =3D irq_domain_add_simple(node, RTL_ICTL_NUM_INPUTS, 0, &irq_domain_ops, NULL); + if (!domain) + return -ENOMEM; =20 - ret =3D map_interrupts(node, domain); - if (ret) { - pr_err("invalid interrupt map\n"); - return ret; - } + irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, domain= ); =20 return 0; } --=20 2.33.1 From nobody Wed Jul 1 23:24:01 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 457DBC4332F for ; Sun, 9 Jan 2022 14:55:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235900AbiAIOzB (ORCPT ); Sun, 9 Jan 2022 09:55:01 -0500 Received: from polaris.svanheule.net ([84.16.241.116]:58430 "EHLO polaris.svanheule.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235842AbiAIOyy (ORCPT ); Sun, 9 Jan 2022 09:54:54 -0500 Received: from terra.local.svanheule.net (unknown [IPv6:2a02:a03f:eafe:c901:f20a:f473:2021:45ec]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sander@svanheule.net) by polaris.svanheule.net (Postfix) with ESMTPSA id EE23528EE29; Sun, 9 Jan 2022 15:54:52 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=svanheule.net; s=mail1707; t=1641740093; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uLgZN6PHIuC/rHIO+5SRTARegBDS1AEMFX7pPCfaVYM=; b=QNu/LSFWfIJswwo9BaCNZtxPrOGYiPOUCeSBXIlwpo/sXKB5KmqZYRRl2+NDSfYzrdFet0 TlLmN1+umMVskSHh8xi9Yoh9NmtC8vMTT4ubcch0p7Mm3J840Hs0ec8EuuE+nm/F/jx2r/ Ixqr+AMM+7yjMRe3NyN36HapKDK4XXLr8MtU+1cwQ1i48sXOoIuYB+XdNzTwhq9aRmI5Aq cHwa1cPSgL4PMVLuyBqFlD/woW2Syfiqrkhz2Kx/+Ar6Pg56/zoSieGc4myGRS/JZnBkBv NUFxsHlXNiqparL2x9SsQed4vZqKx3j7fuJE3pynrvSW0BZ+2EGrWWiK8eVLfw== From: Sander Vanheule To: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: Thomas Gleixner , Marc Zyngier , Rob Herring , Birger Koblitz , Bert Vermeulen , John Crispin , Sander Vanheule Subject: [PATCH v3 6/6] irqchip/realtek-rtl: use per-parent domains Date: Sun, 9 Jan 2022 15:54:37 +0100 Message-Id: <8767ed87be03570ae9f1969bc3dd312d5f2caf2c.1641739718.git.sander@svanheule.net> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The interrupt router can connect each of its inputs to one of the parent interrupts. These parent interrupts may be handled differently by their interrupt controller. SoC interrupts should be treated per-parent, to maintain this expected behaviour for routed child interrupts. Rework the driver to use a separate domain for each output, using all available parents interrupts (as specified in the devicetree). Signed-off-by: Sander Vanheule --- drivers/irqchip/irq-realtek-rtl.c | 150 ++++++++++++++++++++++++------ 1 file changed, 124 insertions(+), 26 deletions(-) diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realte= k-rtl.c index 388f4a7bfb80..868eb9b25e84 100644 --- a/drivers/irqchip/irq-realtek-rtl.c +++ b/drivers/irqchip/irq-realtek-rtl.c @@ -22,12 +22,22 @@ #define RTL_ICTL_IRR3 0x14 =20 #define RTL_ICTL_NUM_INPUTS 32 +#define RTL_ICTL_NUM_OUTPUTS 15 =20 #define REG(x) (realtek_ictl_base + x) =20 static DEFINE_RAW_SPINLOCK(irq_lock); static void __iomem *realtek_ictl_base; =20 +struct realtek_ictl_output { + /* IRQ controller data */ + struct fwnode_handle *fwnode; + /* Output specific data */ + unsigned int output_index; + struct irq_domain *domain; + u32 child_mask; +}; + /* * IRR0-IRR3 store 4 bits per interrupt, but Realtek uses inverted numberi= ng, * placing IRQ 31 in the first four bits. A routing value of '0' means the @@ -37,6 +47,11 @@ static void __iomem *realtek_ictl_base; #define IRR_OFFSET(idx) (4 * (3 - (idx * 4) / 32)) #define IRR_SHIFT(idx) ((idx * 4) % 32) =20 +static inline u32 read_irr(void __iomem *irr0, int idx) +{ + return (readl(irr0 + IRR_OFFSET(idx)) >> IRR_SHIFT(idx)) & 0xf; +} + static inline void write_irr(void __iomem *irr0, int idx, u32 value) { unsigned int offset =3D IRR_OFFSET(idx); @@ -84,51 +99,128 @@ static struct irq_chip realtek_ictl_irq =3D { =20 static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_= t hw) { + struct realtek_ictl_output *output =3D d->host_data; unsigned long flags; + u32 routing_old; + int err =3D 0; + + raw_spin_lock_irqsave(&irq_lock, flags); + + /* + * Inputs can only be routed to one output, so they shouldn't end up in + * multiple domains. Perform this check in the same atomic context as + * configuring the routing to prevent races. + */ + routing_old =3D read_irr(REG(RTL_ICTL_IRR0), hw); + if (routing_old && output->output_index !=3D routing_old - 1) { + pr_err("int %ld already routed to output %d\n", + hw, routing_old - 1); + err =3D -EINVAL; + goto out; + } + + output->child_mask |=3D BIT(hw); + write_irr(REG(RTL_ICTL_IRR0), hw, output->output_index + 1); =20 irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq); =20 - raw_spin_lock_irqsave(&irq_lock, flags); - write_irr(REG(RTL_ICTL_IRR0), hw, 1); +out: raw_spin_unlock_irqrestore(&irq_lock, flags); =20 - return 0; + return err; +} + +static int intc_select(struct irq_domain *d, struct irq_fwspec *fwspec, + enum irq_domain_bus_token bus_token) +{ + struct realtek_ictl_output *output =3D d->host_data; + + if (fwspec->fwnode !=3D output->fwnode) + return false; + + /* Original specifiers only had one parameter */ + if (WARN_ON_ONCE(fwspec->param_count < 2)) + return true; + + return fwspec->param[1] =3D=3D output->output_index; } =20 static const struct irq_domain_ops irq_domain_ops =3D { .map =3D intc_map, + .select =3D intc_select, .xlate =3D irq_domain_xlate_onecell, }; =20 static void realtek_irq_dispatch(struct irq_desc *desc) { + struct realtek_ictl_output *output =3D irq_desc_get_handler_data(desc); struct irq_chip *chip =3D irq_desc_get_chip(desc); - struct irq_domain *domain; unsigned long pending; unsigned int soc_int; =20 chained_irq_enter(chip, desc); - pending =3D readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR)); + pending =3D readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR)) + & output->child_mask; =20 if (unlikely(!pending)) { spurious_interrupt(); goto out; } =20 - domain =3D irq_desc_get_handler_data(desc); - for_each_set_bit(soc_int, &pending, 32) - generic_handle_domain_irq(domain, soc_int); + for_each_set_bit(soc_int, &pending, RTL_ICTL_NUM_INPUTS) + generic_handle_domain_irq(output->domain, soc_int); =20 out: chained_irq_exit(chip, desc); } =20 +static int __init setup_parent_interrupts(struct device_node *node, int *p= arents, + unsigned int num_parents) +{ + struct realtek_ictl_output *outputs; + struct realtek_ictl_output *output; + struct irq_domain *domain; + unsigned int p; + + outputs =3D kcalloc(num_parents, sizeof(*outputs), GFP_KERNEL); + if (!outputs) + return -ENOMEM; + + for (p =3D 0; p < num_parents; p++) { + output =3D outputs + p; + + domain =3D irq_domain_add_simple(node, RTL_ICTL_NUM_INPUTS, 0, + &irq_domain_ops, output); + if (!domain) + goto domain_err; + + output->fwnode =3D of_node_to_fwnode(node); + output->output_index =3D p; + output->domain =3D domain; + + irq_set_chained_handler_and_data(parents[p], realtek_irq_dispatch, outpu= t); + } + + return 0; + +domain_err: + while (p--) { + irq_set_chained_handler_and_data(parents[p], NULL, NULL); + irq_domain_remove(outputs[p].domain); + } + + kfree(outputs); + + return -ENOMEM; +} + static int __init realtek_rtl_of_init(struct device_node *node, struct dev= ice_node *parent) { + int parent_irqs[RTL_ICTL_NUM_OUTPUTS]; struct of_phandle_args oirq; - struct irq_domain *domain; + unsigned int num_parents; unsigned int soc_irq; - int parent_irq; + unsigned int p; =20 realtek_ictl_base =3D of_iomap(node, 0); if (!realtek_ictl_base) @@ -139,37 +231,43 @@ static int __init realtek_rtl_of_init(struct device_n= ode *node, struct device_no for (soc_irq =3D 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++) write_irr(REG(RTL_ICTL_IRR0), soc_irq, 0); =20 - if (WARN_ON(!of_irq_count(node))) { + num_parents =3D of_irq_count(node); + if (num_parents > RTL_ICTL_NUM_OUTPUTS) { + pr_err("too many parent interrupts\n"); + return -EINVAL; + } + + for (p =3D 0; p < num_parents; p++) + parent_irqs[p] =3D of_irq_get(node, p); + + if (WARN_ON(!num_parents)) { /* * If DT contains no parent interrupts, assume MIPS CPU IRQ 2 * (HW0) is connected to the first output. This is the case for * all known hardware anyway. "interrupt-map" is deprecated, so * don't bother trying to parse that. + * Since this is to account for old devicetrees with one-cell + * interrupt specifiers, only one output domain is needed. */ oirq.np =3D of_find_compatible_node(NULL, NULL, "mti,cpu-interrupt-contr= oller"); oirq.args_count =3D 1; oirq.args[0] =3D 2; =20 - parent_irq =3D irq_create_of_mapping(&oirq); + parent_irqs[0] =3D irq_create_of_mapping(&oirq); + num_parents =3D 1; =20 of_node_put(oirq.np); - } else { - parent_irq =3D of_irq_get(node, 0); } =20 - if (parent_irq < 0) - return parent_irq; - else if (!parent_irq) - return -ENODEV; - - domain =3D irq_domain_add_simple(node, RTL_ICTL_NUM_INPUTS, 0, - &irq_domain_ops, NULL); - if (!domain) - return -ENOMEM; - - irq_set_chained_handler_and_data(parent_irq, realtek_irq_dispatch, domain= ); + /* Ensure we haven't collected any errors before proceeding */ + for (p =3D 0; p < num_parents; p++) { + if (parent_irqs[p] < 0) + return parent_irqs[p]; + if (!parent_irqs[p]) + return -ENODEV; + } =20 - return 0; + return setup_parent_interrupts(node, &parent_irqs[0], num_parents); } =20 IRQCHIP_DECLARE(realtek_rtl_intc, "realtek,rtl-intc", realtek_rtl_of_init); --=20 2.33.1