From patchwork Tue Jul 23 11:27:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Conor Dooley X-Patchwork-Id: 13739950 X-Patchwork-Delegate: mail@conchuod.ie 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 BD1FDC3DA49 for ; Tue, 23 Jul 2024 11:28:33 +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=t0MG5VrsFJdwf7tD+nA7yTlY0M2XkufDhJpboYnyC8A=; b=g1tLJHfJpZPFiD XSTawA0VnkjzEPJ2HeKvDHzwbwvOj5hq/6W4cae0knnfZ6SkZSZzQuayhxRKfC1LK2BuwnY9V0czI BkXLgmloWKt6qViS7gHHxtWeaoUWAfMWXQNBMaeRUL7lNrnaugZhlONWmilr/k8q2WtVc3U2vDAAx BZdPWTzROiHxehFfsB/MpkjSnWtYfWHaprlB6yjLZUZNsCb8p0Jdx76fCnTC4oHZzENm9V8Xn01X8 D1rFCBdZb+55f2gmMTdcyJiQoEJdn+CXWr8fRwbIY62OOAiOQoJsHvM0QyrJAavITrzZ/ONjw50uo 6Ley7Orp0atM/UmObt7g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgy-0000000CGh0-22jN; Tue, 23 Jul 2024 11:28:28 +0000 Received: from esa.microchip.iphmx.com ([68.232.153.233]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgs-0000000CGeE-47KA for linux-riscv@lists.infradead.org; Tue, 23 Jul 2024 11:28:24 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1721734103; x=1753270103; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BY9RX9OmhdiwEixbfaIsfq/KameCCnfNFWrW+iwHgQc=; b=gJQlAFSFj9oKlsYUJGhAHsiYtUwlQnIptQtXx6XMrR7keKMppC/BxjbP n/ETSI5DT2oLVB8kkEH7x2+EocLxMlnJ5uu8ZF/Q5cYySyN9V6GDFPO1Y L3KUyy3T7UAej2XROdYDpAGZNEGyyUFnkM83NEnCTyqh6FGpTdFLqPFIv znlol2j3pQZdRhlqBaNr1VcovHGQzTfgNA93O2yPvLA6p5thB1eT0HwkI zzJEAKR2UAtgD8/HFWSpBYU46ZnEC6O001UOh/S4KkB66sh4M5Hf5eJ5z rYiXltpdfrbfB6eP4VOAw5ugwUBX5ozeyPjez2E2R+JPC2d7AAEOeyqnl g==; X-CSE-ConnectionGUID: S6DrTYNTSQStcH62wvxgTw== X-CSE-MsgGUID: jdFJGOP4SlSGNjM3ngZfIA== X-IronPort-AV: E=Sophos;i="6.09,230,1716274800"; d="scan'208";a="29574952" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 23 Jul 2024 04:28:19 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Tue, 23 Jul 2024 04:28:02 -0700 Received: from wendy.microchip.com (10.10.85.11) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Tue, 23 Jul 2024 04:28:00 -0700 From: Conor Dooley To: CC: , , Marc Zyngier , Daire McNamara , "Linus Walleij" , Bartosz Golaszewski , "Rob Herring" , Krzysztof Kozlowski , "Thomas Gleixner" , Paul Walmsley , Palmer Dabbelt , , , Subject: [RFC v7 1/6] dt-bindings: gpio: fix microchip,mpfs-gpio interrupt descriptions Date: Tue, 23 Jul 2024 12:27:10 +0100 Message-ID: <20240723-trash-issuing-e2bdd55b764e@wendy> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240723-supervise-drown-d5d3b303e7fd@wendy> References: <20240723-supervise-drown-d5d3b303e7fd@wendy> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3445; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=BY9RX9OmhdiwEixbfaIsfq/KameCCnfNFWrW+iwHgQc=; b=owGbwMvMwCFWscWwfUFT0iXG02pJDGnzJ/cH1BazWMXpyim07n7hOkPoNHPk80lTHsj7HORz/Txn X3pfRykLgxgHg6yYIkvi7b4WqfV/XHY497yFmcPKBDKEgYtTACZydQ8jw5opU+9Y9M4u2LPv/8//zt 80r9z9cjhU3Vbv4iozjXpb8xsM//Qm2gm97fJ0+PxJ7UaT+zEJtsfXr+wySp17hnG/9710TSYA X-Developer-Key: i=conor.dooley@microchip.com; a=openpgp; fpr=F9ECA03CF54F12CD01F1655722E2C55B37CF380C X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240723_042823_057980_6D119581 X-CRM114-Status: GOOD ( 12.57 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org The microchip,mpfs-gpio binding suffered greatly due to being written with a narrow minded view of the controller, and the interrupt bits ended up incorrect. It was mistakenly assumed that the interrupt configuration was set by platform firmware, based on the FPGA configuration, and that the GPIO DT nodes were the only way to really communicate interrupt configuration to software. Instead, the mux should be a device in its own right, and the GPIO controllers should be connected to it, rather than to the PLIC. Now that a binding exists for that mux, try to fix the misconceptions in the GPIO controller binding. Firstly, it's not possible for this controller to have fewer than 14 GPIOs, and thus 14 interrupts also. There are three controllers, with 14, 24 & 32 GPIOs each. The example is wacky too - it follows from the incorrect understanding that the GPIO controllers are connected to the PLIC directly. They are not however, with a mux sitting in between. Update the example to use the mux as a parent, and the interrupt numbers at the mux for GPIO2 as the example - rather than the strange looking, repeated <53>. Signed-off-by: Conor Dooley Reviewed-by: Krzysztof Kozlowski --- .../bindings/gpio/microchip,mpfs-gpio.yaml | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml b/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml index d61569b3f15b2..eb7dbf1668285 100644 --- a/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml @@ -22,7 +22,7 @@ properties: interrupts: description: Interrupt mapping, one per GPIO. Maximum 32 GPIOs. - minItems: 1 + minItems: 14 maxItems: 32 interrupt-controller: true @@ -39,9 +39,7 @@ properties: ngpios: description: The number of GPIOs available. - minimum: 1 - maximum: 32 - default: 32 + enum: [14, 24, 32] gpio-controller: true gpio-line-names: true @@ -81,6 +79,7 @@ required: - reg - "#gpio-cells" - gpio-controller + - ngpios - clocks additionalProperties: false @@ -91,18 +90,19 @@ examples: compatible = "microchip,mpfs-gpio"; reg = <0x20122000 0x1000>; clocks = <&clkcfg 25>; - interrupt-parent = <&plic>; + interrupt-parent = <&irqmux>; gpio-controller; #gpio-cells = <2>; + ngpios = <32>; interrupt-controller; - #interrupt-cells = <1>; - interrupts = <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>; + #interrupt-cells = <2>; + interrupts = <64>, <65>, <66>, <67>, + <68>, <69>, <70>, <71>, + <72>, <73>, <74>, <75>, + <76>, <77>, <78>, <79>, + <80>, <81>, <82>, <83>, + <84>, <85>, <86>, <87>, + <88>, <89>, <90>, <91>, + <92>, <93>, <94>, <95>; }; ... From patchwork Tue Jul 23 11:27:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Conor Dooley X-Patchwork-Id: 13739951 X-Patchwork-Delegate: mail@conchuod.ie 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 08831C3DA70 for ; Tue, 23 Jul 2024 11:28:34 +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=CvKHU7W4+8KUMybe+drDb531FlL+RHaH+dyspDEbQRc=; b=PiNkmV4AnQe4fA 1Sj/rmMJkTQUVjtvE7uDsTYCDDh1W+1LwRbA46Pahw5YHG3SwW+5Y74MiP5XamoGQRbl7loCDKwHp 7le1SIg0QX1JzPYNCmL3vvZJXRG5z/a0SgS9Q+K21qrYt356LtZxN0qD9lOcsDDxxArXd6gMEMxmc rZUo23KYWD4FmoO67VBr6iuWeVS5JRF6xFh26wMPXTgwBdvDdgjPyHCinoSrpPjwcHn3p9rbVuSxh GGZVVEl1mr7A44YuOFKlEG2azo57hWWeMZQub8lVqKMt/a51UGYuruB3K73Lw1NE1UYqC0JJLeTsl vUMHy6ZICy0tDHvw/qFg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgz-0000000CGhH-0URx; Tue, 23 Jul 2024 11:28:29 +0000 Received: from esa.microchip.iphmx.com ([68.232.153.233]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgt-0000000CGet-065K for linux-riscv@lists.infradead.org; Tue, 23 Jul 2024 11:28:24 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1721734103; x=1753270103; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6aVvjVowW9Wu+EIEcex8bxj0klOHutOMqoPmSgWOOqw=; b=bEXycyLTVSc8WkcuWdq2RylwJ6P9ZxKHT7BGKxa32RF5mVlzRNpsoGSa Ra7GyLJtDs2V5PfB40fKiFkxnJEqfUxD1s7hTnE/SDe6P43Dc3zTsrnBD Wwm+X9CGxYM6T0FBtjP6HH0o8Ism05rDXJix0q0DLfbrkJ/Q7AExJEJFH hzNT9jq3KOKPbZaHvUyC7mwDjw21wn8p4yx4M5goTQqaB69Qhmn+WO9+/ JXppc9YRTVYoP0QgXgWf6itDrl3/u696ONtefYcHqtFrFX0qsX1F62zMB 5VnYy93dsUhzz8d7lT53sbbf2PKNXAaIireAT/mSkhxuyzn0v9zyAIoPn Q==; X-CSE-ConnectionGUID: S6DrTYNTSQStcH62wvxgTw== X-CSE-MsgGUID: Oc+XHPzzQEGWFtnBlzp9Bg== X-IronPort-AV: E=Sophos;i="6.09,230,1716274800"; d="scan'208";a="29574953" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 23 Jul 2024 04:28:19 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Tue, 23 Jul 2024 04:28:09 -0700 Received: from wendy.microchip.com (10.10.85.11) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Tue, 23 Jul 2024 04:28:06 -0700 From: Conor Dooley To: CC: , , Marc Zyngier , Daire McNamara , "Linus Walleij" , Bartosz Golaszewski , "Rob Herring" , Krzysztof Kozlowski , "Thomas Gleixner" , Paul Walmsley , Palmer Dabbelt , , , Subject: [RFC v7 2/6] dt-bindings: interrupt-controller: document PolarFire SoC's gpio interrupt mux Date: Tue, 23 Jul 2024 12:27:11 +0100 Message-ID: <20240723-uncouple-enforcer-7c48e4a4fefe@wendy> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240723-supervise-drown-d5d3b303e7fd@wendy> References: <20240723-supervise-drown-d5d3b303e7fd@wendy> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3570; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=6aVvjVowW9Wu+EIEcex8bxj0klOHutOMqoPmSgWOOqw=; b=owGbwMvMwCFWscWwfUFT0iXG02pJDGnzJ/fvPrujVDn3ikZUmUtEaYLhwiYpk0t3l5+crHYgY5vF kpxDHaUsDGIcDLJiiiyJt/tapNb/cdnh3PMWZg4rE8gQBi5OAZiIOCfDX/mTgiFaXoHfTtVwTftw3f vEqgXved/r/tBkPM8pHCy7kYXhf6TmyUvzXJ2iP/0XkWHd6y55TPLv87iVNS+0r3JPO3CjgQUA X-Developer-Key: i=conor.dooley@microchip.com; a=openpgp; fpr=F9ECA03CF54F12CD01F1655722E2C55B37CF380C X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240723_042823_092481_472FB013 X-CRM114-Status: GOOD ( 14.63 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org On PolarFire SoC there are more GPIO interrupts than there are interrupt lines available on the PLIC, and a runtime configurable mux is used to decide which interrupts are assigned direct connections to the PLIC & which are relegated to sharing a line. This mux is, in our reference configuration, written by platform firmware during boot based on the FPGA's configuration. Signed-off-by: Conor Dooley --- .../microchip,mpfs-gpio-irq-mux.yaml | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/microchip,mpfs-gpio-irq-mux.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/microchip,mpfs-gpio-irq-mux.yaml b/Documentation/devicetree/bindings/interrupt-controller/microchip,mpfs-gpio-irq-mux.yaml new file mode 100644 index 0000000000000..89ed3a630eef3 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/microchip,mpfs-gpio-irq-mux.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/microchip,mpfs-gpio-irq-mux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip Polarfire SoC GPIO Interrupt Mux + +maintainers: + - Conor Dooley + +description: | + There are 3 GPIO controllers on this SoC, of which: + - GPIO controller 0 has 14 GPIOs + - GPIO controller 1 has 24 GPIOs + - GPIO controller 2 has 32 GPIOs + + All GPIOs are capable of generating interrupts, for a total of 70. + There are only 41 IRQs available however, so a configurable mux is used to + ensure all GPIOs can be used for interrupt generation. + 38 of the 41 interrupts are in what the documentation calls "direct mode", + as they provide an exclusive connection from a GPIO to the PLIC. + The 3 remaining interrupts are used to mux the interrupts which do not have + a exclusive connection, one for each GPIO controller. + +properties: + compatible: + const: microchip,mpfs-gpio-irq-mux + + reg: + maxItems: 1 + + interrupt-controller: true + + "#interrupt-cells": + const: 1 + + interrupts: + description: + The first 38 entries must be the "direct" interrupts, for exclusive + connections to the PLIC. The final 3 entries must be the + "non-direct"/muxed connections for each of GPIO controller 0, 1 & 2 + respectively. + maxItems: 41 + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +required: + - compatible + - reg + - interrupts + - "#interrupt-cells" + - interrupt-controller + +additionalProperties: false + +examples: + - | + irqmux: interrupt-controller@20002054 { + compatible = "microchip,mpfs-gpio-irq-mux"; + reg = <0x20002054 0x4>; + interrupt-parent = <&plic>; + interrupt-controller; + #interrupt-cells = <1>; + status = "okay"; + interrupts = <13>, <14>, <15>, <16>, + <17>, <18>, <19>, <20>, + <21>, <22>, <23>, <24>, + <25>, <26>, <27>, <28>, + <29>, <30>, <31>, <32>, + <33>, <34>, <35>, <36>, + <37>, <38>, <39>, <40>, + <41>, <42>, <43>, <44>, + <45>, <46>, <47>, <48>, + <49>, <50>, <51>, <52>, + <53>; + }; +... From patchwork Tue Jul 23 11:27:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Conor Dooley X-Patchwork-Id: 13739952 X-Patchwork-Delegate: mail@conchuod.ie 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 9068CC3DA7F for ; Tue, 23 Jul 2024 11:28:34 +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=NMcMprtaieyREnBdYSbHMi63XG0kqZC5gXVXWm8QSR0=; b=BVyBjO/EVoAljZ CJk+4rS9NQ7jLH19jwFDPmsO3IJiAEUes6C03pGKVYboad5etsV1xROBYLAuc62kArdO4I1bFdrdq XWAUCAd1rLUKDheMWqrOVPjOtdFgEOilgEv/3ZeyCr/L3DvKJld/3Wt5ICVjMfQLzP2KLVXqwVe4p ltTmnnKbpC7iEr9cK/IZCtZB8Bi4XGaFaOX38Ui30RD0tPYfBO6r3YiaG+Hne7gTY5iK1zgWq4m+1 U2GU/afCbczIH2Kf2X50ubbxRpyroqXqgIgcxlMKCPMZwxt2ODLRk/VO7DQQDDy/RKk/8IfGpEAwd uFHprFZ5LMM8gcn8Uw4Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgz-0000000CGhd-33zH; Tue, 23 Jul 2024 11:28:29 +0000 Received: from esa.microchip.iphmx.com ([68.232.153.233]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgu-0000000CGeE-1PCC for linux-riscv@lists.infradead.org; Tue, 23 Jul 2024 11:28:25 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1721734105; x=1753270105; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=CsrygMY0NxxMA3gHMzButnMVxrGDWdwJPdZ6u63oMS8=; b=bUUvWoG9lTGcmqqUFfR9WAYgceAt/pPI+Xp8OtxivkvGhZ0ykjN8//rf A5jdLaY+iO3H5HYPH2DQSUwb8HTkwpXT4OUTd/KOc2BtATwwXUFcM596Y HNmBoDn7KM5aI3A6r0+EOJwkAmYqTnLd01gIUp7HFZA7ToKunX8L0SoHb /LGcAScQ7cxZwv1NVhxbKePzJVrvfsea+H1w7Zs/PB2bIjBPv0LhAycKR vw5PVTFdKwqWRYiR4Wf0Poyo8MnFV0HyjZhSvriYa/7vmMqbBExu0j6lL U/j7Q+RZxTzELlk+09C5tYjetpX3BRmSV6Go4NRI+rZoq24hALleR/ZOB A==; X-CSE-ConnectionGUID: S6DrTYNTSQStcH62wvxgTw== X-CSE-MsgGUID: 5nh63x7SS/qg7QgYEfGAKA== X-IronPort-AV: E=Sophos;i="6.09,230,1716274800"; d="scan'208";a="29574955" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 23 Jul 2024 04:28:20 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Tue, 23 Jul 2024 04:28:13 -0700 Received: from wendy.microchip.com (10.10.85.11) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Tue, 23 Jul 2024 04:28:10 -0700 From: Conor Dooley To: CC: , , Marc Zyngier , Daire McNamara , "Linus Walleij" , Bartosz Golaszewski , "Rob Herring" , Krzysztof Kozlowski , "Thomas Gleixner" , Paul Walmsley , Palmer Dabbelt , , , Subject: [RFC v7 3/6] irqchip: add mpfs gpio interrupt mux Date: Tue, 23 Jul 2024 12:27:12 +0100 Message-ID: <20240723-flatworm-cornflake-8023212f6584@wendy> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240723-supervise-drown-d5d3b303e7fd@wendy> References: <20240723-supervise-drown-d5d3b303e7fd@wendy> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=13683; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=CsrygMY0NxxMA3gHMzButnMVxrGDWdwJPdZ6u63oMS8=; b=owGbwMvMwCFWscWwfUFT0iXG02pJDGnzJ0/YdyXK+qTsivLef7LOVlJsNb2rrFV43p+9eHz+jFOu AbJVHaUsDGIcDLJiiiyJt/tapNb/cdnh3PMWZg4rE8gQBi5OAZhIrCfD/0p7+UzGbL7y+Au1m9YdK+ 94PEstYPl6n3nd8YXHdEVtpzMybBbw2f6JZcrnRx/n/HKdfnQHr3SZ1gmTmVMbi2/I2jHmswAA X-Developer-Key: i=conor.dooley@microchip.com; a=openpgp; fpr=F9ECA03CF54F12CD01F1655722E2C55B37CF380C X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240723_042824_422058_E06A0A8C X-CRM114-Status: GOOD ( 37.36 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org On PolarFire SoC there are more GPIO interrupts than there are interrupt lines available on the PLIC, and a runtime configurable mux is used to decide which interrupts are assigned direct connections to the PLIC & which are relegated to sharing a line. This mux is, in our reference configuration, written by platform firmware during boot based on the FPGA's configuration. Add a driver so that Linux can figure out this mapping and correctly map the GPIO interrupts to their parents on the PLIC. Signed-off-by: Conor Dooley --- Please read my cover letter for the things I'm unsure of on the interrupt side. --- drivers/irqchip/Kconfig | 11 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-mpfs-mux.c | 333 +++++++++++++++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 drivers/irqchip/irq-mpfs-mux.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 14464716bacbb..2b951dbd559c7 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -706,6 +706,17 @@ config MCHP_EIC help Support for Microchip External Interrupt Controller. +config POLARFIRE_SOC_IRQ_MUX + bool "Microchip PolarFire SoC's GPIO IRQ Mux" + depends on ARCH_MICROCHIP_POLARFIRE + default y + help + Support for the interrupt mux on Polarfire SoC. It sits between + the GPIO controllers and the PLIC, as only 35 interrupts are shared + between 3 GPIO controllers with 32 interrupts each. Configuration of + the mux is done by the platform firmware, this driver is responsible + for reading that configuration and setting up correct routing. + config SUNPLUS_SP7021_INTC bool "Sunplus SP7021 interrupt controller" if COMPILE_TEST default SOC_SP7021 diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index d9dc3d99aaa86..cf2f417c8d7fc 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -123,4 +123,5 @@ obj-$(CONFIG_WPCM450_AIC) += irq-wpcm450-aic.o obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o +obj-$(CONFIG_POLARFIRE_SOC_IRQ_MUX) += irq-mpfs-mux.o obj-$(CONFIG_SUNPLUS_SP7021_INTC) += irq-sp7021-intc.o diff --git a/drivers/irqchip/irq-mpfs-mux.c b/drivers/irqchip/irq-mpfs-mux.c new file mode 100644 index 0000000000000..b093cae399700 --- /dev/null +++ b/drivers/irqchip/irq-mpfs-mux.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip PolarFire SoC (MPFS) GPIO IRQ MUX + * + * Author: Conor Dooley + */ + +#define pr_fmt(fmt) "mpfs-irq-mux: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPFS_MUX_NUM_IRQS 41 +#define MPFS_MUX_NUM_DIRECT_IRQS 38 +#define MPFS_MUX_NUM_NON_DIRECT_IRQS 3 +#define MPFS_MAX_IRQS_PER_GPIO 32 +#define MPFS_NUM_IRQS_GPIO0 14 +#define MPFS_NUM_IRQS_GPIO1 24 +#define MPFS_NUM_IRQS_GPIO2 32 +#define MPFS_NUM_IRQS_GPIO02_SHIFT 0 +#define MPFS_NUM_IRQS_GPIO1_SHIFT 14 + +/* + * There are 3 GPIO controllers on this SoC, of which: + * - GPIO controller 0 has 14 GPIOs + * - GPIO controller 1 has 24 GPIOs + * - GPIO controller 2 has 32 GPIOs + * + * All GPIOs are capable of generating interrupts, for a total of 70. + * There are only 41 IRQs available however, so a configurable mux is used to + * ensure all GPIOs can be used for interrupt generation. + * 38 of the 41 interrupts are in what the documentation calls "direct mode", + * as they provide an exclusive connection from a GPIO to the PLIC. + * The 3 remaining interrupts are used to mux the interrupts which do not have + * a exclusive connection, one for each GPIO controller. + * A register is used to set this configuration of this mux, depending on how + * the "MSS Configurator" (FPGA configuration tool) has set things up. + * This is done by the platform's firmware, so access from Linux is read-only. + * + * Documentation also refers to GPIO controller 0 & 1 as "pad" GPIO controllers + * and GPIO controller 2 as the "fabric" GPIO controller. Despite that wording, + * all 3 are "hard" peripherals. + * + * The mux has a single register, where bits 0 to 13 mux between GPIO controller + * 1's 14 GPIOs and GPIO controller 2's first 14 GPIOs. The remaining bits mux + * between the first 18 GPIOs of controller 1 and the last 18 GPIOS of + * controller 2. If a bit in the mux's control register is set, the + * corresponding interrupt line for GPIO controller 0 or 1 will be put in + * "non-direct" mode. If cleared, the "fabric" controller's will. + * + * Register layout: + * GPIO 1 interrupt line 17 | mux bit 31 | GPIO 2 interrupt line 31 + * ... | ... | ... + * ... | ... | ... + * GPIO 1 interrupt line 0 | mux bit 14 | GPIO 2 interrupt line 14 + * GPIO 0 interrupt line 13 | mux bit 13 | GPIO 2 interrupt line 13 + * ... | ... | ... + * ... | ... | ... + * GPIO 0 interrupt line 0 | mux bit 0 | GPIO 2 interrupt line 0 + * + * That leaves 6 exclusive, or "direct", interrupts remaining. These are + * used by GPIO controller 1's lines 18 to 23. + */ + +struct mpfs_irq_mux_bank_config { + u32 mask; + u8 shift; +}; + +static const struct mpfs_irq_mux_bank_config mpfs_irq_mux_bank_configs[3] = { + {GENMASK(MPFS_NUM_IRQS_GPIO0 - 1, 0), MPFS_NUM_IRQS_GPIO02_SHIFT}, + {GENMASK(MPFS_NUM_IRQS_GPIO1 - 1, 0), MPFS_NUM_IRQS_GPIO1_SHIFT}, + {GENMASK(MPFS_NUM_IRQS_GPIO2 - 1, 0), MPFS_NUM_IRQS_GPIO02_SHIFT}, +}; + +struct mpfs_irq_mux_irqchip { + struct irq_domain *domain; + int bank; + int irq; + u8 offset; +}; + +struct mpfs_irq_mux { + void __iomem *reg; + u32 mux_config; + struct mpfs_irq_mux_irqchip nondirect_irqchips[MPFS_MUX_NUM_NON_DIRECT_IRQS]; + int parent_irqs[MPFS_MUX_NUM_DIRECT_IRQS]; +}; + +/* + * There is no "control" hardware in this mux, and as such there is no ability + * to mask at this level. As the irq has been disconnected from the hierarchy, + * there's no parent irqchip from which to use mask functions either. + */ +static void mpfs_irq_mux_irq_mask(struct irq_data *d) {} +static void mpfs_irq_mux_irq_unmask(struct irq_data *d) {} + +static struct irq_chip mpfs_irq_mux_nondirect_irq_chip = { + .name = "MPFS GPIO Interrupt Mux", + .irq_mask = mpfs_irq_mux_irq_mask, + .irq_unmask = mpfs_irq_mux_irq_unmask, + .flags = IRQCHIP_IMMUTABLE, +}; + +static struct irq_chip mpfs_irq_mux_irq_chip = { + .name = "MPFS GPIO Interrupt Mux", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_type = irq_chip_set_type_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .flags = IRQCHIP_IMMUTABLE, +}; + +/* + * Returns an unsigned long, where a set bit indicates the corresponding + * interrupt is in non-direct/muxed mode for that bank/GPIO controller. + */ +static inline unsigned long mpfs_irq_mux_get_muxed_irqs(struct mpfs_irq_mux *priv, + unsigned int bank) +{ + unsigned long mux_config = priv->mux_config, muxed_irqs = -1; + struct mpfs_irq_mux_bank_config bank_config = mpfs_irq_mux_bank_configs[bank]; + + /* + * If a bit is set in the mux, GPIO the corresponding interrupt from + * controller 2 is direct and that controllers 0 or 1 is muxed. + * Invert the bits in the configuration register, so that set bits + * equate to non-direct mode, for GPIO controller 2. + */ + if (bank == 2u) + mux_config = ~mux_config; + + muxed_irqs &= bank_config.mask; + muxed_irqs &= mux_config >> bank_config.shift; + + return muxed_irqs; +} + +static void mpfs_irq_mux_nondirect_handler(struct irq_desc *desc) +{ + struct mpfs_irq_mux_irqchip *irqchip_data = irq_desc_get_handler_data(desc); + struct mpfs_irq_mux *priv = container_of(irqchip_data, struct mpfs_irq_mux, + nondirect_irqchips[irqchip_data->bank]); + unsigned long muxed_irqs; + int pos; + + chained_irq_enter(irq_desc_get_chip(desc), desc); + + muxed_irqs = mpfs_irq_mux_get_muxed_irqs(priv, irqchip_data->bank); + + for_each_set_bit(pos, &muxed_irqs, MPFS_MAX_IRQS_PER_GPIO) + generic_handle_domain_irq(irqchip_data->domain, irqchip_data->offset + pos); + + chained_irq_exit(irq_desc_get_chip(desc), desc); +} + +static bool mpfs_irq_mux_is_direct(struct mpfs_irq_mux *priv, struct irq_fwspec *fwspec) +{ + unsigned int bank, line; + u32 muxed_irqs; + + bank = fwspec->param[0] / MPFS_MAX_IRQS_PER_GPIO; + line = fwspec->param[0] % MPFS_MAX_IRQS_PER_GPIO; + + muxed_irqs = mpfs_irq_mux_get_muxed_irqs(priv, bank); + + if (BIT(line) & muxed_irqs) + return false; + + return true; +} + +static int mpfs_irq_mux_translate(struct irq_domain *d, struct irq_fwspec *fwspec, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (!is_of_node(fwspec->fwnode)) + return -EINVAL; + + return irq_domain_translate_onecell(d, fwspec, out_hwirq, out_type); +} + +static int mpfs_irq_mux_nondirect_alloc(struct irq_domain *d, unsigned int virq, + struct irq_fwspec *fwspec, struct mpfs_irq_mux *priv) +{ + unsigned int bank = fwspec->param[0] / MPFS_MAX_IRQS_PER_GPIO; + + if (bank > 2) + return -EINVAL; + + priv->nondirect_irqchips[bank].domain = d; + + irq_domain_set_hwirq_and_chip(d, virq, fwspec->param[0], + &mpfs_irq_mux_nondirect_irq_chip, priv); + irq_set_chained_handler_and_data(virq, handle_untracked_irq, + &priv->nondirect_irqchips[bank]); + + return irq_domain_disconnect_hierarchy(d->parent, virq); +} + +static int mpfs_irq_mux_alloc(struct irq_domain *d, unsigned int virq, + unsigned int nr_irqs, void *arg) +{ + struct mpfs_irq_mux *priv = d->host_data; + struct irq_fwspec *fwspec = arg; + struct irq_fwspec parent_fwspec; + unsigned int bank, line, irq; + + if (!mpfs_irq_mux_is_direct(priv, fwspec)) + return mpfs_irq_mux_nondirect_alloc(d, virq, fwspec, priv); + + bank = fwspec->param[0] / MPFS_MAX_IRQS_PER_GPIO; + line = fwspec->param[0] % MPFS_MAX_IRQS_PER_GPIO; + irq = line + mpfs_irq_mux_bank_configs[bank].shift; + + parent_fwspec.fwnode = d->parent->fwnode; + parent_fwspec.param[0] = priv->parent_irqs[irq]; + parent_fwspec.param_count = 1; + + irq_domain_set_hwirq_and_chip(d, virq, fwspec->param[0], &mpfs_irq_mux_irq_chip, priv); + + return irq_domain_alloc_irqs_parent(d, virq, 1, &parent_fwspec); +} + +static const struct irq_domain_ops mpfs_irq_mux_domain_ops = { + .translate = mpfs_irq_mux_translate, + .alloc = mpfs_irq_mux_alloc, + .free = irq_domain_free_irqs_common, +}; + +static int mpfs_irq_mux_probe(struct platform_device *pdev) +{ + struct device_node *node, *parent; + struct device *dev = &pdev->dev; + struct mpfs_irq_mux *priv; + struct irq_domain *hier_domain, *parent_domain; + int i, ret = 0; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* + * This is clearly unacceptable - there's a significant re-write of + * the devicetree handling for this device required however to get + * rid of this. It'll be fixed for !RFC. + */ + node = to_of_node(dev->fwnode); + priv->reg = of_iomap(node, 0); + if (!priv->reg) { + ret = -ENODEV; + goto out_free_priv; + } + + priv->mux_config = readl(priv->reg); + + for (i = 0; i < MPFS_MUX_NUM_DIRECT_IRQS; i++) { + struct of_phandle_args parent_irq; + int ret; + + ret = of_irq_parse_one(node, i, &parent_irq); + if (ret) { + ret = -ENODEV; + goto out_unmap; + } + + /* + * The parent irqs are saved off for the first 38 interrupts + * from the devicetree entry so that they can be used in the + * domains alloc callback to allocate irqs from the parent irq + * chip directly. + */ + priv->parent_irqs[i] = parent_irq.args[0]; + } + + parent = of_irq_find_parent(node); + parent_domain = irq_find_host(parent); + hier_domain = irq_domain_add_hierarchy(parent_domain, 0, MPFS_MAX_IRQS_PER_GPIO * 3, + node, &mpfs_irq_mux_domain_ops, priv); + if (!hier_domain) { + dev_err(dev, "failed to add hierarchical domain\n"); + ret = -ENODEV; + goto out_unmap; + } + + /* + * The last 3 interrupts must be the non-direct/muxed ones, per + * the dt-binding. + */ + for (i = 0; i < MPFS_MUX_NUM_NON_DIRECT_IRQS; i++) { + int irq_index = i + MPFS_MUX_NUM_DIRECT_IRQS; + + priv->nondirect_irqchips[i].bank = i; + priv->nondirect_irqchips[i].irq = irq_of_parse_and_map(node, irq_index); + priv->nondirect_irqchips[i].offset = i * MPFS_MAX_IRQS_PER_GPIO; + irq_set_chained_handler_and_data(priv->nondirect_irqchips[i].irq, + mpfs_irq_mux_nondirect_handler, + &priv->nondirect_irqchips[i]); + } + + dev_dbg(dev, "mux configuration %x\n", priv->mux_config); + + return 0; + +out_unmap: + iounmap(priv->reg); + +out_free_priv: + kfree(priv); + + return ret; +} + +static const struct of_device_id mpfs_irq_mux_match[] = { + { .compatible = "microchip,mpfs-gpio-irq-mux" }, + +}; + +static struct platform_driver mpfs_irq_mux_driver = { + .driver = { + .name = "mpfs_irq_mux", + .of_match_table = mpfs_irq_mux_match, + }, + .probe = mpfs_irq_mux_probe, +}; +builtin_platform_driver(mpfs_irq_mux_driver); From patchwork Tue Jul 23 11:27:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Conor Dooley X-Patchwork-Id: 13739953 X-Patchwork-Delegate: mail@conchuod.ie 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 6EF20C3DA49 for ; Tue, 23 Jul 2024 11:28:37 +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=o5eEzR4v5bMrp79c9mOJa/5uicpxLCoRBYtLEDgotOE=; b=U0hdfJ/OKtguOl eZoH1AVpsDwlNPOewI+VV6UV/aqTcAxO08Fj+j5Lk5Hs/zNB9mxIyrDljCL4Ql1WGBvz37AjKeOkp XqX4W4ykRb05DloTw2gR1zD3SdONkJVGuobu4jHhIUx9STkAWVC1zOtmeIl2vu5i++vn+XUv/t96K 6EJt4KcrevxrLxyBJGhubHW8FPr2UkfKtI5TA2M+QlwVSksnfKXOXfIN5s3ElXbeyYJN/UK0u8Fnk Z30cJ7L6JFaD9ne+hwilIsWJZWobT3CyTNzuRENw3gypt+mxUcW6uOCi5BS3outJWrqB5mAvwddrk jkczyGD8tAouIjEpn62w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgu-0000000CGfZ-0W5G; Tue, 23 Jul 2024 11:28:24 +0000 Received: from esa.microchip.iphmx.com ([68.232.153.233]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDgq-0000000CGeF-3srk for linux-riscv@lists.infradead.org; Tue, 23 Jul 2024 11:28:22 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1721734101; x=1753270101; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mwLzMK344LrlkXY++0l/Gj9MNq2rK0oWALq4fCAT0Wc=; b=17ghRJk4vTfwcSMdZE2x/RrN94LiqFPfbF3SFhwjZbZbSq4vmBmCFt+g OLhhIEKc9sKIDYuC0aPQopamCqH9X87lEjYdKcIMrP7KSpO9eKSMZR2Wa NEnWfHmZY0o+Yyh+ZgUr5atU6SYY73cQ31qE6w4jOdaXUKv1TmtLAPW8N dJeMhqyZXqi8XslgnjXgc9tVpYvAtSveBjVqM2jI0xzj9h2iAjQRC0AUC xG0a3KfZJT4C9teOg2uRqoy/Eicuosf0xiqjnu+tpUhM31eVHM97QFhMH plQLjtOCmIgANI5mN05VgJFwOjqQLZihoUQVILDbSKkkbeSfyjcCnyL/8 A==; X-CSE-ConnectionGUID: Bzp89j1bQnG7Qha2jIBWKQ== X-CSE-MsgGUID: 9Xz4Jg1zS/eGyBpnXKYMhQ== X-IronPort-AV: E=Sophos;i="6.09,230,1716274800"; d="scan'208";a="260469138" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa5.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 23 Jul 2024 04:28:19 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Tue, 23 Jul 2024 04:28:16 -0700 Received: from wendy.microchip.com (10.10.85.11) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Tue, 23 Jul 2024 04:28:14 -0700 From: Conor Dooley To: CC: , , Marc Zyngier , Daire McNamara , "Linus Walleij" , Bartosz Golaszewski , "Rob Herring" , Krzysztof Kozlowski , "Thomas Gleixner" , Paul Walmsley , Palmer Dabbelt , , , , Lewis Hanly Subject: [RFC v7 4/6] gpio: mpfs: add polarfire soc gpio support Date: Tue, 23 Jul 2024 12:27:13 +0100 Message-ID: <20240723-underage-wheat-7dd65c2158e7@wendy> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240723-supervise-drown-d5d3b303e7fd@wendy> References: <20240723-supervise-drown-d5d3b303e7fd@wendy> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=11480; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=oRvlKxILF3owTWo7rBvagSB5lR8hjMzfhJvA3BN3F3o=; b=owGbwMvMwCFWscWwfUFT0iXG02pJDGnzJ09odPZe6X9rlmqfj8APvQbZhn2Fz1ZPF429MLFs7bnr u4OiO0pZGMQ4GGTFFFkSb/e1SK3/47LDuectzBxWJpAhDFycAjCRB22MDG33FgjbiGk8k56vsGrNJp Y/6QFvzk2cmZrM8y450liDKZ7hv6caf391p3jw85Mfd3G6BllcWxDdraKxv0EvJaBT6NcJNgA= X-Developer-Key: i=conor.dooley@microchip.com; a=openpgp; fpr=F9ECA03CF54F12CD01F1655722E2C55B37CF380C X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240723_042821_010606_43F93E96 X-CRM114-Status: GOOD ( 24.93 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org From: Lewis Hanly Add a driver to support the Polarfire SoC gpio controller Signed-off-by: Lewis Hanly Signed-off-by: Conor Dooley Reviewed-by: Linus Walleij Reviewed-by: Linus Walleij --- Unchanged from last list submission, I'm looking for comments on the other patches in the series at the moment. --- drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-mpfs.c | 320 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) create mode 100644 drivers/gpio/gpio-mpfs.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3dbddec070281..78fe494e3722c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -549,6 +549,13 @@ config GPIO_PL061 help Say yes here to support the PrimeCell PL061 GPIO device. +config GPIO_POLARFIRE_SOC + bool "Microchip FPGA GPIO support" + depends on OF_GPIO + select GPIOLIB_IRQCHIP + help + Say yes here to support the GPIO device on Microchip FPGAs. + config GPIO_PXA bool "PXA GPIO support" depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index e2a53013780e5..dd6ba21bce76e 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -132,6 +132,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o +obj-$(CONFIG_GPIO_POLARFIRE_SOC) += gpio-mpfs.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o diff --git a/drivers/gpio/gpio-mpfs.c b/drivers/gpio/gpio-mpfs.c new file mode 100644 index 0000000000000..1ac0526ba1029 --- /dev/null +++ b/drivers/gpio/gpio-mpfs.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: (GPL-2.0) +/* + * Microchip PolarFire SoC (MPFS) GPIO controller driver + * + * Copyright (c) 2018-2022 Microchip Technology Inc. and its subsidiaries + * + * Author: Lewis Hanly + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPFS_GPIO_CTRL(i) (0x4 * (i)) +#define MAX_NUM_GPIO 32 +#define MPFS_GPIO_EN_INT 3 +#define MPFS_GPIO_EN_OUT_BUF BIT(2) +#define MPFS_GPIO_EN_IN BIT(1) +#define MPFS_GPIO_EN_OUT BIT(0) + +#define MPFS_GPIO_TYPE_INT_EDGE_BOTH 0x80 +#define MPFS_GPIO_TYPE_INT_EDGE_NEG 0x60 +#define MPFS_GPIO_TYPE_INT_EDGE_POS 0x40 +#define MPFS_GPIO_TYPE_INT_LEVEL_LOW 0x20 +#define MPFS_GPIO_TYPE_INT_LEVEL_HIGH 0x00 +#define MPFS_GPIO_TYPE_INT_MASK GENMASK(7, 5) +#define MPFS_IRQ_REG 0x80 +#define MPFS_INP_REG 0x84 +#define MPFS_OUTP_REG 0x88 + +struct mpfs_gpio_chip { + void __iomem *base; + struct clk *clk; + raw_spinlock_t lock; + struct gpio_chip gc; +}; + +static void mpfs_gpio_assign_bit(void __iomem *addr, unsigned int bit_offset, bool value) +{ + unsigned long reg = readl(addr); + + __assign_bit(bit_offset, ®, value); + writel(reg, addr); +} + +static int mpfs_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio_index) +{ + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + u32 gpio_cfg; + unsigned long flags; + + raw_spin_lock_irqsave(&mpfs_gpio->lock, flags); + + gpio_cfg = readl(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index)); + gpio_cfg |= MPFS_GPIO_EN_IN; + gpio_cfg &= ~(MPFS_GPIO_EN_OUT | MPFS_GPIO_EN_OUT_BUF); + writel(gpio_cfg, mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index)); + + raw_spin_unlock_irqrestore(&mpfs_gpio->lock, flags); + + return 0; +} + +static int mpfs_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio_index, int value) +{ + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + u32 gpio_cfg; + unsigned long flags; + + raw_spin_lock_irqsave(&mpfs_gpio->lock, flags); + + gpio_cfg = readl(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index)); + gpio_cfg |= MPFS_GPIO_EN_OUT | MPFS_GPIO_EN_OUT_BUF; + gpio_cfg &= ~MPFS_GPIO_EN_IN; + writel(gpio_cfg, mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index)); + + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_OUTP_REG, gpio_index, value); + + raw_spin_unlock_irqrestore(&mpfs_gpio->lock, flags); + + return 0; +} + +static int mpfs_gpio_get_direction(struct gpio_chip *gc, + unsigned int gpio_index) +{ + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + u32 gpio_cfg; + + gpio_cfg = readl(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index)); + if (gpio_cfg & MPFS_GPIO_EN_IN) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; +} + +static int mpfs_gpio_get(struct gpio_chip *gc, + unsigned int gpio_index) +{ + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + + return !!(readl(mpfs_gpio->base + MPFS_INP_REG) & BIT(gpio_index)); +} + +static void mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int value) +{ + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + unsigned long flags; + + raw_spin_lock_irqsave(&mpfs_gpio->lock, flags); + + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_OUTP_REG, + gpio_index, value); + + raw_spin_unlock_irqrestore(&mpfs_gpio->lock, flags); +} + +static int mpfs_gpio_irq_set_type(struct irq_data *data, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + int gpio_index = irqd_to_hwirq(data); + u32 interrupt_type; + u32 gpio_cfg; + unsigned long flags; + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_BOTH; + break; + case IRQ_TYPE_EDGE_FALLING: + interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_NEG; + break; + case IRQ_TYPE_EDGE_RISING: + interrupt_type = MPFS_GPIO_TYPE_INT_EDGE_POS; + break; + case IRQ_TYPE_LEVEL_HIGH: + interrupt_type = MPFS_GPIO_TYPE_INT_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + interrupt_type = MPFS_GPIO_TYPE_INT_LEVEL_LOW; + break; + } + + raw_spin_lock_irqsave(&mpfs_gpio->lock, flags); + + gpio_cfg = readl(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index)); + gpio_cfg &= ~MPFS_GPIO_TYPE_INT_MASK; + gpio_cfg |= interrupt_type; + writel(gpio_cfg, mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index)); + + raw_spin_unlock_irqrestore(&mpfs_gpio->lock, flags); + + return 0; +} + +static void mpfs_gpio_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + int gpio_index = irqd_to_hwirq(data); + + gpiochip_enable_irq(gc, gpio_index); + mpfs_gpio_direction_input(gc, gpio_index); + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, gpio_index, 1); + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index), + MPFS_GPIO_EN_INT, 1); +} + +static void mpfs_gpio_irq_mask(struct irq_data *data) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + int gpio_index = irqd_to_hwirq(data); + + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, gpio_index, 1); + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index), + MPFS_GPIO_EN_INT, 0); + gpiochip_disable_irq(gc, gpio_index); +} + +static const struct irq_chip mpfs_gpio_irqchip = { + .name = "mpfs", + .irq_set_type = mpfs_gpio_irq_set_type, + .irq_mask = mpfs_gpio_irq_mask, + .irq_unmask = mpfs_gpio_irq_unmask, + .flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void mpfs_gpio_irq_handler(struct irq_desc *desc) +{ + struct irq_chip *irqchip = irq_desc_get_chip(desc); + struct mpfs_gpio_chip *mpfs_gpio = + gpiochip_get_data(irq_desc_get_handler_data(desc)); + unsigned long status; + int offset; + + chained_irq_enter(irqchip, desc); + + status = readl(mpfs_gpio->base + MPFS_IRQ_REG); + for_each_set_bit(offset, &status, mpfs_gpio->gc.ngpio) { + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, offset, 1); + generic_handle_irq(irq_find_mapping(mpfs_gpio->gc.irq.domain, offset)); + } + + chained_irq_exit(irqchip, desc); +} + +static int mpfs_gpio_probe(struct platform_device *pdev) +{ + struct clk *clk; + struct device *dev = &pdev->dev; + struct device_node *node = pdev->dev.of_node; + struct mpfs_gpio_chip *mpfs_gpio; + struct gpio_irq_chip *girq; + int i, ret, ngpios, nirqs; + + mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL); + if (!mpfs_gpio) + return -ENOMEM; + + mpfs_gpio->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mpfs_gpio->base)) + return dev_err_probe(dev, PTR_ERR(mpfs_gpio->base), "failed to ioremap memory resource\n"); + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "devm_clk_get failed\n"); + + ret = clk_prepare_enable(clk); + if (ret) + return dev_err_probe(dev, ret, "failed to enable clock\n"); + + mpfs_gpio->clk = clk; + + ngpios = MAX_NUM_GPIO; + device_property_read_u32(dev, "ngpios", &ngpios); + if (ngpios > MAX_NUM_GPIO) + ngpios = MAX_NUM_GPIO; + + raw_spin_lock_init(&mpfs_gpio->lock); + mpfs_gpio->gc.direction_input = mpfs_gpio_direction_input; + mpfs_gpio->gc.direction_output = mpfs_gpio_direction_output; + mpfs_gpio->gc.get_direction = mpfs_gpio_get_direction; + mpfs_gpio->gc.get = mpfs_gpio_get; + mpfs_gpio->gc.set = mpfs_gpio_set; + mpfs_gpio->gc.base = -1; + mpfs_gpio->gc.ngpio = ngpios; + mpfs_gpio->gc.label = dev_name(dev); + mpfs_gpio->gc.parent = dev; + mpfs_gpio->gc.owner = THIS_MODULE; + + nirqs = of_irq_count(node); + if (nirqs > MAX_NUM_GPIO) { + ret = -ENXIO; + goto cleanup_clock; + } + girq = &mpfs_gpio->gc.irq; + gpio_irq_chip_set_chip(girq, &mpfs_gpio_irqchip); + girq->handler = handle_simple_irq; + girq->parent_handler = mpfs_gpio_irq_handler; + girq->default_type = IRQ_TYPE_NONE; + girq->num_parents = nirqs; + girq->parents = devm_kcalloc(&pdev->dev, nirqs, + sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) { + ret = -ENOMEM; + goto cleanup_clock; + } + for (i = 0; i < nirqs; i++) + girq->parents[i] = platform_get_irq(pdev, i); + + ret = gpiochip_add_data(&mpfs_gpio->gc, mpfs_gpio); + if (ret) + goto cleanup_clock; + + platform_set_drvdata(pdev, mpfs_gpio); + + return 0; + +cleanup_clock: + clk_disable_unprepare(mpfs_gpio->clk); + return ret; +} + +static int mpfs_gpio_remove(struct platform_device *pdev) +{ + struct mpfs_gpio_chip *mpfs_gpio = platform_get_drvdata(pdev); + + gpiochip_remove(&mpfs_gpio->gc); + clk_disable_unprepare(mpfs_gpio->clk); + + return 0; +} + +static const struct of_device_id mpfs_gpio_of_ids[] = { + { .compatible = "microchip,mpfs-gpio", }, + { /* end of list */ } +}; + +static struct platform_driver mpfs_gpio_driver = { + .probe = mpfs_gpio_probe, + .driver = { + .name = "microchip,mpfs-gpio", + .of_match_table = mpfs_gpio_of_ids, + }, + .remove = mpfs_gpio_remove, +}; +builtin_platform_driver(mpfs_gpio_driver); From patchwork Tue Jul 23 11:27:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Conor Dooley X-Patchwork-Id: 13739954 X-Patchwork-Delegate: mail@conchuod.ie 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 E788CC3DA49 for ; Tue, 23 Jul 2024 11:28:44 +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=roEn6qBwR+ILw4AkmtTjyxQC53hgtp3QvCsd4UKlxw4=; b=qvyintDDB8leW1 9xTIYD6QZh+J5E3yHyqU99oey5yN2OqDahX7OTvRhRycpuOPV+TXVnOsnVsizckRnnQ4g8Cm5dB+p 87KW+/vb7N87rD1y0BJN0dIo+C3OJSjqQ77X6RHoaZlXgx3Pf2CCxNnp31nPal17hb7R5Urotzt6b bTP1Gc2ZlBNijTIXeyLORmm3zOdBjitC32dwFqCIfwBpmxRv0BVioa9VDWgZ9rSJ8ROT5PAhCKEgJ X2om4cOos+LUyCTJRjt76808baDrCeKBK9zxhqwoI2lQXa5Q7lK8wy+f6r2ttiPeJdqtSQ9bDJTtl cTBfeVdL7RBMcwwEATAQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDhB-0000000CGmY-3QL4; Tue, 23 Jul 2024 11:28:41 +0000 Received: from esa.microchip.iphmx.com ([68.232.153.233]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDh8-0000000CGkM-3nGh for linux-riscv@lists.infradead.org; Tue, 23 Jul 2024 11:28:40 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1721734118; x=1753270118; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ucm8XGSvUldvd/bc2uyFIRcCiSr1Ximdbh0xRa+hE+Q=; b=owlVCThXRKdKKvA3I9zjjWiTgCQC9O1gEFrsvohntHKW9tljsSDWbtTQ lM5E688c3bkPeGox3b9NzrsP+YPjl1tGu1PQbakUCCiM5sm2m6CxAj4Xn jihnWpSck37h5XvUhSeFH/Q0vCD81cUb+p74NRE7VlwfmeXDZDPDmN5y1 93skZDRBN9Zgzih7okWpEWQi0Zi4kHXTlcKDU9Grd0O34lL+JrUqHxNiG dWzhC45hZs9QNkfZoHjH4ndMBw/eMJ1/PqJKjumTzBuAKvj34h06hFau/ LOq5Nhr8CU9xSt8lIsvinj5Bjgu46momqImH9+g8McA1JgneFHu+QI5OD g==; X-CSE-ConnectionGUID: urgFf+kjT1Coy3E8dV+nGA== X-CSE-MsgGUID: NdOsJdXTT0q1UVuWrE8VRg== X-IronPort-AV: E=Sophos;i="6.09,230,1716274800"; d="scan'208";a="32335706" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa1.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 23 Jul 2024 04:28:38 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Tue, 23 Jul 2024 04:28:20 -0700 Received: from wendy.microchip.com (10.10.85.11) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Tue, 23 Jul 2024 04:28:17 -0700 From: Conor Dooley To: CC: , , Marc Zyngier , Daire McNamara , "Linus Walleij" , Bartosz Golaszewski , "Rob Herring" , Krzysztof Kozlowski , "Thomas Gleixner" , Paul Walmsley , Palmer Dabbelt , , , Subject: [RFC v7 5/6] gpio: mpfs: pass gpio line number as irq data Date: Tue, 23 Jul 2024 12:27:14 +0100 Message-ID: <20240723-handoff-race-33160609553f@wendy> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240723-supervise-drown-d5d3b303e7fd@wendy> References: <20240723-supervise-drown-d5d3b303e7fd@wendy> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6470; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=Ucm8XGSvUldvd/bc2uyFIRcCiSr1Ximdbh0xRa+hE+Q=; b=owGbwMvMwCFWscWwfUFT0iXG02pJDGnzJ0+YukcmPfZuz4P/5Vu65G/3V+9aXPHx6unjGh/ebMs0 1V1a11HKwiDGwSArpsiSeLuvRWr9H5cdzj1vYeawMoEMYeDiFICJGHMxMtzhkZ83zzDnwR3pvaeZvs m+uhDCftMndUVD27G855Gyhc8Z/kepmi0xObLx8d1Fa9ZX7bx0OF1W7SbfD3+PqXa1Jzo7TfkA X-Developer-Key: i=conor.dooley@microchip.com; a=openpgp; fpr=F9ECA03CF54F12CD01F1655722E2C55B37CF380C X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240723_042838_998745_17F7442A X-CRM114-Status: GOOD ( 20.26 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org Since the interrupt mux is going to provide us a 1:1 mapping for interrupts, and it is no longer correct to hit all of the set bits in the interrupt handler, store the GPIO that "owns" an interrupt in its data pointer, so that we can determine which bit to clear. Signed-off-by: Conor Dooley --- This patch will need to be squashed, I've kept it apart for illustrative purposes. --- drivers/gpio/gpio-mpfs.c | 85 +++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/drivers/gpio/gpio-mpfs.c b/drivers/gpio/gpio-mpfs.c index 1ac0526ba1029..b92f094964822 100644 --- a/drivers/gpio/gpio-mpfs.c +++ b/drivers/gpio/gpio-mpfs.c @@ -43,6 +43,7 @@ struct mpfs_gpio_chip { struct clk *clk; raw_spinlock_t lock; struct gpio_chip gc; + u8 irq_data[MAX_NUM_GPIO]; }; static void mpfs_gpio_assign_bit(void __iomem *addr, unsigned int bit_offset, bool value) @@ -129,7 +130,7 @@ static int mpfs_gpio_irq_set_type(struct irq_data *data, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(data); struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); - int gpio_index = irqd_to_hwirq(data); + int gpio_index = irqd_to_hwirq(data) % 32; u32 interrupt_type; u32 gpio_cfg; unsigned long flags; @@ -168,11 +169,10 @@ static void mpfs_gpio_irq_unmask(struct irq_data *data) { struct gpio_chip *gc = irq_data_get_irq_chip_data(data); struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); - int gpio_index = irqd_to_hwirq(data); + int gpio_index = irqd_to_hwirq(data) % 32; gpiochip_enable_irq(gc, gpio_index); mpfs_gpio_direction_input(gc, gpio_index); - mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, gpio_index, 1); mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index), MPFS_GPIO_EN_INT, 1); } @@ -181,19 +181,18 @@ static void mpfs_gpio_irq_mask(struct irq_data *data) { struct gpio_chip *gc = irq_data_get_irq_chip_data(data); struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); - int gpio_index = irqd_to_hwirq(data); + int gpio_index = irqd_to_hwirq(data) % 32; - mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, gpio_index, 1); mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_GPIO_CTRL(gpio_index), MPFS_GPIO_EN_INT, 0); gpiochip_disable_irq(gc, gpio_index); } static const struct irq_chip mpfs_gpio_irqchip = { - .name = "mpfs", + .name = "MPFS GPIO", .irq_set_type = mpfs_gpio_irq_set_type, - .irq_mask = mpfs_gpio_irq_mask, - .irq_unmask = mpfs_gpio_irq_unmask, + .irq_mask = mpfs_gpio_irq_mask, + .irq_unmask = mpfs_gpio_irq_unmask, .flags = IRQCHIP_IMMUTABLE | IRQCHIP_MASK_ON_SUSPEND, GPIOCHIP_IRQ_RESOURCE_HELPERS, }; @@ -201,18 +200,24 @@ static const struct irq_chip mpfs_gpio_irqchip = { static void mpfs_gpio_irq_handler(struct irq_desc *desc) { struct irq_chip *irqchip = irq_desc_get_chip(desc); - struct mpfs_gpio_chip *mpfs_gpio = - gpiochip_get_data(irq_desc_get_handler_data(desc)); + void *handler_data = irq_desc_get_handler_data(desc); + struct gpio_chip *gc = irq_data_get_irq_chip_data(&desc->irq_data); + struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + u8 gpio_index = *((u8 *)handler_data); unsigned long status; - int offset; + + /* + * Since the parent may be a muxed/"non-direct" interrupt, this + * interrupt may not be for us. + */ + status = readl(mpfs_gpio->base + MPFS_IRQ_REG); + if (!(status & BIT(gpio_index))) + return; chained_irq_enter(irqchip, desc); - status = readl(mpfs_gpio->base + MPFS_IRQ_REG); - for_each_set_bit(offset, &status, mpfs_gpio->gc.ngpio) { - mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, offset, 1); - generic_handle_irq(irq_find_mapping(mpfs_gpio->gc.irq.domain, offset)); - } + generic_handle_irq(irq_find_mapping(mpfs_gpio->gc.irq.domain, gpio_index)); + mpfs_gpio_assign_bit(mpfs_gpio->base + MPFS_IRQ_REG, gpio_index, 1); chained_irq_exit(irqchip, desc); } @@ -222,6 +227,7 @@ static int mpfs_gpio_probe(struct platform_device *pdev) struct clk *clk; struct device *dev = &pdev->dev; struct device_node *node = pdev->dev.of_node; + void **irq_data = NULL; struct mpfs_gpio_chip *mpfs_gpio; struct gpio_irq_chip *girq; int i, ret, ngpios, nirqs; @@ -232,7 +238,8 @@ static int mpfs_gpio_probe(struct platform_device *pdev) mpfs_gpio->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mpfs_gpio->base)) - return dev_err_probe(dev, PTR_ERR(mpfs_gpio->base), "failed to ioremap memory resource\n"); + return dev_err_probe(dev, PTR_ERR(mpfs_gpio->base), + "failed to ioremap memory resource\n"); clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) @@ -266,20 +273,42 @@ static int mpfs_gpio_probe(struct platform_device *pdev) ret = -ENXIO; goto cleanup_clock; } + girq = &mpfs_gpio->gc.irq; - gpio_irq_chip_set_chip(girq, &mpfs_gpio_irqchip); - girq->handler = handle_simple_irq; - girq->parent_handler = mpfs_gpio_irq_handler; - girq->default_type = IRQ_TYPE_NONE; girq->num_parents = nirqs; - girq->parents = devm_kcalloc(&pdev->dev, nirqs, - sizeof(*girq->parents), GFP_KERNEL); - if (!girq->parents) { - ret = -ENOMEM; - goto cleanup_clock; + + if (girq->num_parents) { + gpio_irq_chip_set_chip(girq, &mpfs_gpio_irqchip); + girq->parent_handler = mpfs_gpio_irq_handler; + + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), GFP_KERNEL); + irq_data = devm_kmalloc_array(&pdev->dev, girq->num_parents, + sizeof(*irq_data), GFP_KERNEL); + + if (!girq->parents || !irq_data) { + ret = -ENOMEM; + goto cleanup_clock; + } + + for (i = 0; i < girq->num_parents; i++) { + ret = platform_get_irq(pdev, i); + if (ret < 0) + goto cleanup_clock; + + girq->parents[i] = ret; + mpfs_gpio->irq_data[i] = i; + irq_data[i] = &mpfs_gpio->irq_data[i]; + + irq_set_chip_data(ret, &mpfs_gpio->gc); + irq_set_handler(ret, handle_simple_irq); + } + + girq->parent_handler_data_array = irq_data; + girq->per_parent_data = true; + girq->handler = handle_simple_irq; + girq->default_type = IRQ_TYPE_NONE; } - for (i = 0; i < nirqs; i++) - girq->parents[i] = platform_get_irq(pdev, i); ret = gpiochip_add_data(&mpfs_gpio->gc, mpfs_gpio); if (ret) From patchwork Tue Jul 23 11:27:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Conor Dooley X-Patchwork-Id: 13739955 X-Patchwork-Delegate: mail@conchuod.ie 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 0E666C3DA49 for ; Tue, 23 Jul 2024 11:28:55 +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=B+gJmrLK+SwxjQkBLN1Tnx2i70dVK7arRhoYI5S8IAs=; b=EUJCycvyUHkWj9 fxPvZ50mlyBktstpArCkjohn7YvXBFuliNOTgHGVeVdwW98j4Cyd34b81e0TtH9sRID5bCvqv5Wh7 DY0LRZW0zWVrtmch3mUHlwRTPQqlLFS/gEo1q89chmjM7zKeXopPKc6VC41+tbVAdYG3LXxexcnao 80tQc2OmqhyzbhW1fRwvVnG1bzyqUU/NWLDdA2pMlMWCcsgP9JaAnKWPuzoS/eI0XxQzgTYDC4sHs +anaNIZsvqvlmUxr+TQnoKLjjdSLIx2tmxm3nybEZmCY+sFIiOrRAVEZaJgVG4jnfBXteb32TSoTL r11KZaxyJzck/5Wsy9HQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDhM-0000000CGtK-1S2w; Tue, 23 Jul 2024 11:28:52 +0000 Received: from esa.microchip.iphmx.com ([68.232.153.233]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sWDhJ-0000000CGqw-2Br1 for linux-riscv@lists.infradead.org; Tue, 23 Jul 2024 11:28:50 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1721734130; x=1753270130; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0BnMHbAdBH79ScPTvVNbtezh5vCswpZdpOoIuQ4RzEE=; b=zwHqgf9uOef8BKZyrBzU/K8FQIGXKQJrbpc7OhPviiHxitbc/RNIRdgS 9Yqw6K1QIVowthpM4Ua7NfR9tofhOo3n842gEENEIbmTL7HRYQ8Cj5ZtY dOXFBafC8OGoG55j30OdHpphrYUYprRRtyBABKvv03lvDxghKMQ3D7VYr 5frVuEbz0U3lCewOPJVPC3iXnhfNQFZUlN/SIzZBRKNZLgIVJLqzPpfAn 3sWDHiUW7YTrzR9aUENfxsgnOUlZ6XL8KhylWg/umM1Ip4ZzIo2CycB9m vxlX3niAGEmGQtjmldcw336OxvyUCXXaWv2JzQEWQRWYzlozcVmwWglqL A==; X-CSE-ConnectionGUID: ogbmHU+kQ5yxZ4OX2mUEtQ== X-CSE-MsgGUID: Y70jeUQRQ8adVIWl7jhXaw== X-IronPort-AV: E=Sophos;i="6.09,230,1716274800"; d="scan'208";a="29574987" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa3.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 23 Jul 2024 04:28:49 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Tue, 23 Jul 2024 04:28:24 -0700 Received: from wendy.microchip.com (10.10.85.11) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Tue, 23 Jul 2024 04:28:21 -0700 From: Conor Dooley To: CC: , , Marc Zyngier , Daire McNamara , "Linus Walleij" , Bartosz Golaszewski , "Rob Herring" , Krzysztof Kozlowski , "Thomas Gleixner" , Paul Walmsley , Palmer Dabbelt , , , Subject: [RFC v7 6/6] riscv: dts: microchip: update gpio interrupts to better match the SoC Date: Tue, 23 Jul 2024 12:27:15 +0100 Message-ID: <20240723-framing-chaos-9f8e2df8889d@wendy> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240723-supervise-drown-d5d3b303e7fd@wendy> References: <20240723-supervise-drown-d5d3b303e7fd@wendy> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=5034; i=conor.dooley@microchip.com; h=from:subject:message-id; bh=0BnMHbAdBH79ScPTvVNbtezh5vCswpZdpOoIuQ4RzEE=; b=owGbwMvMwCFWscWwfUFT0iXG02pJDGnzJ0+c/rLzj6Ppc85Px9Je/mcOm3vjiVrjRbV1iqs22S4J sjB901HKwiDGwSArpsiSeLuvRWr9H5cdzj1vYeawMoEMYeDiFICJcJYw/C/J9V7+K11BZNH0Rcf1vT czOGzLV//19JlVpFygvVjf13BGhpOWzN8z95a/mrlzou3PjANBLCaiLZLJzdY+MxdZxjTo8AEA X-Developer-Key: i=conor.dooley@microchip.com; a=openpgp; fpr=F9ECA03CF54F12CD01F1655722E2C55B37CF380C X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240723_042849_591628_5ED467BB X-CRM114-Status: GOOD ( 14.47 ) X-BeenThere: linux-riscv@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-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org There are 3 GPIO controllers on this SoC, of which: - GPIO controller 0 has 14 GPIOs - GPIO controller 1 has 24 GPIOs - GPIO controller 2 has 32 GPIOs All GPIOs are capable of generating interrupts, for a total of 70. There are only 41 IRQs available however, so a configurable mux is used to ensure all GPIOs can be used for interrupt generation. 38 of the 41 interrupts are in what the documentation calls "direct mode", as they provide an exclusive connection from a GPIO to the PLIC. The 3 remaining interrupts are used to mux the interrupts which do not have a exclusive connection, one for each GPIO controller. Setting of the mux should be done by the platform's firmware at boot, based on the output of the "MSS Configurator" (FPGA configuration tool). The microchip,mpfs-gpio binding suffered greatly due to being written with a narrow minded view of the controller, and the interrupt bits ended up incorrect. It was mistakenly assumed that the interrupt configuration was set by platform firmware, based on the FPGA configuration, and that the GPIO DT nodes were the only way to really communicate interrupt configuration to software. Instead, the mux should be a device in its own right, and the GPIO controllers should be connected to it, rather than to the PLIC. Now that a binding exists for that mux, fix the inaccurate description of the interrupt controller hierarchy. Signed-off-by: Conor Dooley --- .../boot/dts/microchip/mpfs-icicle-kit.dts | 8 --- arch/riscv/boot/dts/microchip/mpfs.dtsi | 50 +++++++++++++++++-- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts index f80df225f72b4..7a9822d2a8819 100644 --- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts +++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts @@ -83,14 +83,6 @@ &core_pwm0 { }; &gpio2 { - interrupts = <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>, - <53>, <53>, <53>, <53>; status = "okay"; }; diff --git a/arch/riscv/boot/dts/microchip/mpfs.dtsi b/arch/riscv/boot/dts/microchip/mpfs.dtsi index 9883ca3554c50..e31e0aacb943b 100644 --- a/arch/riscv/boot/dts/microchip/mpfs.dtsi +++ b/arch/riscv/boot/dts/microchip/mpfs.dtsi @@ -465,39 +465,79 @@ mac1: ethernet@20112000 { status = "disabled"; }; - gpio0: gpio@20120000 { - compatible = "microchip,mpfs-gpio"; - reg = <0x0 0x20120000 0x0 0x1000>; + irqmux: interrupt-controller@20002054 { + compatible = "microchip,mpfs-gpio-irq-mux"; + reg = <0x0 0x20002054 0x0 0x4>; interrupt-parent = <&plic>; interrupt-controller; #interrupt-cells = <1>; + interrupts = <13>, <14>, <15>, <16>, + <17>, <18>, <19>, <20>, + <21>, <22>, <23>, <24>, + <25>, <26>, <27>, <28>, + <29>, <30>, <31>, <32>, + <33>, <34>, <35>, <36>, + <37>, <38>, <39>, <40>, + <41>, <42>, <43>, <44>, + <45>, <46>, <47>, <48>, + <49>, <50>, <51>, <52>, + <53>; + }; + + gpio0: gpio@20120000 { + compatible = "microchip,mpfs-gpio"; + reg = <0x0 0x20120000 0x0 0x1000>; + interrupt-parent = <&irqmux>; + interrupt-controller; + #interrupt-cells = <1>; + interrupts = <0>, <1>, <2>, <3>, + <4>, <5>, <6>, <7>, + <8>, <9>, <10>, <11>, + <12>, <13>; clocks = <&clkcfg CLK_GPIO0>; gpio-controller; #gpio-cells = <2>; + ngpios = <14>; status = "disabled"; }; gpio1: gpio@20121000 { compatible = "microchip,mpfs-gpio"; reg = <0x0 0x20121000 0x0 0x1000>; - interrupt-parent = <&plic>; + interrupt-parent = <&irqmux>; interrupt-controller; #interrupt-cells = <1>; + interrupts = <32>, <33>, <34>, <35>, + <36>, <37>, <38>, <39>, + <40>, <41>, <42>, <43>, + <44>, <45>, <46>, <47>, + <48>, <49>, <50>, <51>, + <52>, <53>, <54>, <55>; clocks = <&clkcfg CLK_GPIO1>; gpio-controller; #gpio-cells = <2>; + ngpios = <24>; status = "disabled"; }; gpio2: gpio@20122000 { compatible = "microchip,mpfs-gpio"; reg = <0x0 0x20122000 0x0 0x1000>; - interrupt-parent = <&plic>; + interrupt-parent = <&irqmux>; interrupt-controller; #interrupt-cells = <1>; + interrupts = <64>, <65>, <66>, <67>, + <68>, <69>, <70>, <71>, + <72>, <73>, <74>, <75>, + <76>, <77>, <78>, <79>, + <80>, <81>, <82>, <83>, + <84>, <85>, <86>, <87>, + <88>, <89>, <90>, <91>, + <92>, <93>, <94>, <95>; clocks = <&clkcfg CLK_GPIO2>; gpio-controller; #gpio-cells = <2>; + ngpios = <32>; status = "disabled"; };