From patchwork Fri Oct 18 13:19:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 836866 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 899C11E49F; Fri, 18 Oct 2024 13:19:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729257578; cv=none; b=Bp0WWOn1yeNcTYbKtfn8ze3yy0h4C9igb9b9Wfs3IXylyhks+TzmxFSM8nnAqgKK3dybqLGBRym32Min2QcF9uC94tpdQUY+jDEfvWZ7IAqFNj1yN8dH5GhSEYhquNScNzZKd2txsmQRLhmeJQ0S+rnr4YqMex1NfyFughvwKME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729257578; c=relaxed/simple; bh=GrfG1jDQUfa9fYmjYVqIGLJiprqJM7qjHzBVK8Ve3Pw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=M85GQf2+EeIZvFa0nT60UsOXPxVn9+T/tAXrqPK4W1Ww3WGAvnsF9osNKRaZPIn3dEgeBY4q/lc2Sgq1yOOPJXk+4FUvBhyEwhrfq09duQ1W/Px6Unx2OW3F6N9r4WmcS4QPHjjL6oPpyeW0A15Ui1ND2bFbhWgQH9ih1g+6cSE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vO+du4mL; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vO+du4mL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C7C23C4CEC3; Fri, 18 Oct 2024 13:19:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729257578; bh=GrfG1jDQUfa9fYmjYVqIGLJiprqJM7qjHzBVK8Ve3Pw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=vO+du4mLbOsj1bOV2j/ImQP2ynxt5IceQWXJfobk1xM2EiZ+72/Zf5fqilZgg5SWg 4/7AwLDU3VLT113fBnyIOwpWTo9yKgwXL46pFiOGN+szwUygBFmdyhZJONvZyCk1J9 k6U/2mCc2axD8wnP4E+P/Q44i+3eOL0+U2yIMQR/bzKngPGUr7ktsJirLLvjTCPa+6 iJ+7ukwgTt/jY5g0Qm4VP0B/S0+AW+T4TemUT895d5EjPOvshPdaAYvO3MXRLsRNC1 nLD7pNwzyr2knJl1AzGK/twBydaD8iEnYVjNkWYViZ/o5TeBtVP/A5eDkSiKPCuXzG 1qtpjtD/wuc+g== From: Lorenzo Bianconi Date: Fri, 18 Oct 2024 15:19:03 +0200 Subject: [PATCH v8 2/6] dt-bindings: pinctrl: airoha: Add EN7581 pinctrl Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241018-en7581-pinctrl-v8-2-b676b966a1d1@kernel.org> References: <20241018-en7581-pinctrl-v8-0-b676b966a1d1@kernel.org> In-Reply-To: <20241018-en7581-pinctrl-v8-0-b676b966a1d1@kernel.org> To: Lorenzo Bianconi , Linus Walleij , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Sean Wang , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: linux-mediatek@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, upstream@airoha.com, benjamin.larsson@genexis.eu, ansuelsmth@gmail.com, linux-pwm@vger.kernel.org X-Mailer: b4 0.14.2 Introduce device-tree binding documentation for Airoha EN7581 pinctrl controller. Reviewed-by: Rob Herring (Arm) Reviewed-by: Linus Walleij Signed-off-by: Lorenzo Bianconi Reviewed-by: AngeloGioacchino Del Regno --- .../bindings/pinctrl/airoha,en7581-pinctrl.yaml | 400 +++++++++++++++++++++ 1 file changed, 400 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b2601d698dcd41c3ef32af547ea41be0d6904ae6 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml @@ -0,0 +1,400 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/airoha,en7581-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Airoha EN7581 Pin Controller + +maintainers: + - Lorenzo Bianconi + +description: + The Airoha's EN7581 Pin controller is used to control SoC pins. + +properties: + compatible: + const: airoha,en7581-pinctrl + + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + +allOf: + - $ref: pinctrl.yaml# + +required: + - compatible + - interrupts + - gpio-controller + - "#gpio-cells" + - interrupt-controller + - "#interrupt-cells" + +patternProperties: + '-pins$': + type: object + + patternProperties: + '^mux(-|$)': + type: object + + description: + pinmux configuration nodes. + + $ref: /schemas/pinctrl/pinmux-node.yaml + + properties: + function: + description: + A string containing the name of the function to mux to the group. + enum: [pon, tod_1pps, sipo, mdio, uart, i2c, jtag, pcm, spi, + pcm_spi, i2s, emmc, pnand, pcie_reset, pwm, phy1_led0, + phy2_led0, phy3_led0, phy4_led0, phy1_led1, phy2_led1, + phy3_led1, phy4_led1] + + groups: + description: + An array of strings. Each string contains the name of a group. + + required: + - function + - groups + + allOf: + - if: + properties: + function: + const: pon + then: + properties: + groups: + enum: [pon] + - if: + properties: + function: + const: tod_1pps + then: + properties: + groups: + enum: [pon_tod_1pps, gsw_tod_1pps] + - if: + properties: + function: + const: sipo + then: + properties: + groups: + enum: [sipo, sipo_rclk] + - if: + properties: + function: + const: mdio + then: + properties: + groups: + enum: [mdio] + - if: + properties: + function: + const: uart + then: + properties: + groups: + items: + enum: [uart2, uart2_cts_rts, hsuart, hsuart_cts_rts, + uart4, uart5] + maxItems: 2 + - if: + properties: + function: + const: i2c + then: + properties: + groups: + enum: [i2c1] + - if: + properties: + function: + const: jtag + then: + properties: + groups: + enum: [jtag_udi, jtag_dfd] + - if: + properties: + function: + const: pcm + then: + properties: + groups: + enum: [pcm1, pcm2] + - if: + properties: + function: + const: spi + then: + properties: + groups: + items: + enum: [spi_quad, spi_cs1] + maxItems: 2 + - if: + properties: + function: + const: pcm_spi + then: + properties: + groups: + items: + enum: [pcm_spi, pcm_spi_int, pcm_spi_rst, pcm_spi_cs1, + pcm_spi_cs2_p156, pcm_spi_cs2_p128, pcm_spi_cs3, + pcm_spi_cs4] + maxItems: 7 + - if: + properties: + function: + const: i2c + then: + properties: + groups: + enum: [i2s] + - if: + properties: + function: + const: emmc + then: + properties: + groups: + enum: [emmc] + - if: + properties: + function: + const: pnand + then: + properties: + groups: + enum: [pnand] + - if: + properties: + function: + const: pcie_reset + then: + properties: + groups: + enum: [pcie_reset0, pcie_reset1, pcie_reset2] + - if: + properties: + function: + const: pwm + then: + properties: + groups: + enum: [gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, + gpio7, gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, + gpio14, gpio15, gpio16, gpio17, gpio18, gpio19, + gpio20, gpio21, gpio22, gpio23, gpio24, gpio25, + gpio26, gpio27, gpio28, gpio29, gpio30, gpio31, + gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, + gpio42, gpio43, gpio44, gpio45, gpio46, gpio47] + - if: + properties: + function: + const: phy1_led0 + then: + properties: + groups: + enum: [gpio33, gpio34, gpio35, gpio42] + - if: + properties: + function: + const: phy2_led0 + then: + properties: + groups: + enum: [gpio33, gpio34, gpio35, gpio42] + - if: + properties: + function: + const: phy3_led0 + then: + properties: + groups: + enum: [gpio33, gpio34, gpio35, gpio42] + - if: + properties: + function: + const: phy4_led0 + then: + properties: + groups: + enum: [gpio33, gpio34, gpio35, gpio42] + - if: + properties: + function: + const: phy1_led1 + then: + properties: + groups: + enum: [gpio43, gpio44, gpio45, gpio46] + - if: + properties: + function: + const: phy2_led1 + then: + properties: + groups: + enum: [gpio43, gpio44, gpio45, gpio46] + - if: + properties: + function: + const: phy3_led1 + then: + properties: + groups: + enum: [gpio43, gpio44, gpio45, gpio46] + - if: + properties: + function: + const: phy4_led1 + then: + properties: + groups: + enum: [gpio43, gpio44, gpio45, gpio46] + + additionalProperties: false + + '^conf(-|$)': + type: object + + description: + pinconf configuration nodes. + + $ref: /schemas/pinctrl/pincfg-node.yaml + + properties: + pins: + description: + An array of strings. Each string contains the name of a pin. + items: + enum: [uart1_txd, uart1_rxd, i2c_scl, i2c_sda, spi_cs0, spi_clk, + spi_mosi, spi_miso, gpio0, gpio1, gpio2, gpio3, gpio4, + gpio5, gpio6, gpio7, gpio8, gpio9, gpio10, gpio11, gpio12, + gpio13, gpio14, gpio15, gpio16, gpio17, gpio18, gpio19, + gpio20, gpio21, gpio22, gpio23, gpio24, gpio25, gpio26, + gpio27, gpio28, gpio29, gpio30, gpio31, gpio32, gpio33, + gpio34, gpio35, gpio36, gpio37, gpio38, gpio39, gpio40, + gpio41, gpio42, gpio43, gpio44, gpio45, gpio46, + pcie_reset0, pcie_reset1, pcie_reset2] + minItems: 1 + maxItems: 58 + + bias-disable: true + + bias-pull-up: true + + bias-pull-down: true + + input-enable: true + + output-enable: true + + output-low: true + + output-high: true + + drive-open-drain: true + + drive-strength: + description: + Selects the drive strength for MIO pins, in mA. + enum: [2, 4, 6, 8] + + required: + - pins + + additionalProperties: false + + additionalProperties: false + +additionalProperties: false + +examples: + - | + #include + + pinctrl { + compatible = "airoha,en7581-pinctrl"; + + interrupt-parent = <&gic>; + interrupts = ; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + pcie1-rst-pins { + conf { + pins = "pcie_reset1"; + drive-open-drain = <1>; + }; + }; + + pwm-pins { + mux { + function = "pwm"; + groups = "gpio18"; + }; + }; + + spi-pins { + mux { + function = "spi"; + groups = "spi_quad", "spi_cs1"; + }; + }; + + uart2-pins { + mux { + function = "uart"; + groups = "uart2", "uart2_cts_rts"; + }; + }; + + uar5-pins { + mux { + function = "uart"; + groups = "uart5"; + }; + }; + + mmc-pins { + mux { + function = "emmc"; + groups = "emmc"; + }; + }; + + mdio-pins { + mux { + function = "mdio"; + groups = "mdio"; + }; + + conf { + pins = "gpio2"; + output-enable; + }; + }; + }; From patchwork Fri Oct 18 13:19:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 836865 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA41D1E49F; Fri, 18 Oct 2024 13:19:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729257585; cv=none; b=VvfmJ9JxVC/GGuhBlxjsJI7XCE4dZruhRMtg3ikBMiVrIuLCbMlM19QpnmUL4hHlcgchjLb1DKIVqTjCcVjBJZiQiM7CLFhEBf+Ln5QB1NUYIrS3zGNq/oRRO2lCiadTYEynXcm49RCOLT4DM4EupFFSPBgqpQJhc+ShwA1F1pg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729257585; c=relaxed/simple; bh=zrSswidO56FtbeNZMQXSi7aPMw7zkb3G9ZpSYil9sWg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XJLzX5YPh8pKijocrCsuaBhigNCb6agcgkhhfjgyp8/drk8yNhBMNey7K1Ug6w5Kz3PybkU5ZgQOUqf4HyVxmNTnvZxaYbC/OgHBzKAbupISOQL8YIXgkpUKgY06149H3QuetNCDgSLRp3Y0BxY8SMIZclU0sZPDOZRuyFb4/wU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cVwEx1dz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cVwEx1dz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3927C4CEC3; Fri, 18 Oct 2024 13:19:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729257585; bh=zrSswidO56FtbeNZMQXSi7aPMw7zkb3G9ZpSYil9sWg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cVwEx1dzwq0/4S+QwX1asXIQjHRbpsThO945b7eYKqXudCoRw8boZLYRx/u9EU3Pi LaDxry7jk+HANB9efMEUKphic8FVt05Eej3wNEi0GIM4+2feIO1JX344ybEH7uE5Gj XJ75fb2uR6Cf3IZ887nc5kxqg15/0rvuzbANw6GPDB5Ciw3urh9B6PXbqtdSVbNYYP QwYyxnm/xOQ2gENzonsYwn5u5fWC57k3FxWXWtQMZLzOWpCmARn7GXuPERN9sWj5Ca 5q4E/Tdbv+IqdoCNLzO2wGhibNgeEn8tC1vJSsaxJ6LERwfZeIrvYubTNwh3jYMk9r BVkY3AtUF4ZZA== From: Lorenzo Bianconi Date: Fri, 18 Oct 2024 15:19:05 +0200 Subject: [PATCH v8 4/6] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241018-en7581-pinctrl-v8-4-b676b966a1d1@kernel.org> References: <20241018-en7581-pinctrl-v8-0-b676b966a1d1@kernel.org> In-Reply-To: <20241018-en7581-pinctrl-v8-0-b676b966a1d1@kernel.org> To: Lorenzo Bianconi , Linus Walleij , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Sean Wang , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: linux-mediatek@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, upstream@airoha.com, benjamin.larsson@genexis.eu, ansuelsmth@gmail.com, linux-pwm@vger.kernel.org X-Mailer: b4 0.14.2 From: Christian Marangi Add support for Airoha EN7581 GPIO System Controller which provide a register map for controlling the GPIO, pinctrl and PWM of the SoC via dedicated pinctrl and pwm child nodes. Signed-off-by: Christian Marangi Reviewed-by: Linus Walleij Reviewed-by: Rob Herring (Arm) Reviewed-by: AngeloGioacchino Del Regno Co-developed-by: Lorenzo Bianconi Signed-off-by: Lorenzo Bianconi --- .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 90 ++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml b/Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4a81ed82ef34dc2b99594098584cc77f67f276c8 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/airoha,en7581-gpio-sysctl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Airoha EN7581 GPIO System Controller + +maintainers: + - Christian Marangi + - Lorenzo Bianconi + +description: + Airoha EN7581 SoC GPIO system controller which provided a register map + for controlling the GPIO, pins and PWM of the SoC. + +properties: + compatible: + items: + - const: airoha,en7581-gpio-sysctl + - const: syscon + - const: simple-mfd + + reg: + maxItems: 1 + + pinctrl: + type: object + $ref: /schemas/pinctrl/airoha,en7581-pinctrl.yaml + description: + Child node definition for EN7581 Pin controller + + pwm: + type: object + $ref: /schemas/pwm/airoha,en7581-pwm.yaml + description: + Child node definition for EN7581 PWM controller + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + + system-controller@1fbf0200 { + compatible = "airoha,en7581-gpio-sysctl", "syscon", "simple-mfd"; + reg = <0x1fbf0200 0xc0>; + + pinctrl { + compatible = "airoha,en7581-pinctrl"; + + interrupt-parent = <&gic>; + interrupts = ; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + mmc-pins { + mux { + function = "emmc"; + groups = "emmc"; + }; + }; + + mdio-pins { + mux { + function = "mdio"; + groups = "mdio"; + }; + + conf { + pins = "gpio2"; + output-enable; + }; + }; + }; + + pwm { + compatible = "airoha,en7581-pwm"; + + #pwm-cells = <3>; + }; + }; From patchwork Fri Oct 18 13:19:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 836864 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B6BE1D54D6; Fri, 18 Oct 2024 13:19:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729257591; cv=none; b=PRRIHnZa/PA7Q60/DAawCrqB21EbAsNq/5pZl4+QuN/9cTWpsxu3ATOx7yd0XyTIg0wVXtlollq1hEAPlLv3lMNt8j8OTOTO9o37Vuzeh1Nw/9XGXDg03E2iIjluxGWj+yJl7tpermC7gVwQ/9YX5RNy/NSHs/vpLduSOr9ClgI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729257591; c=relaxed/simple; bh=UPp5Q7zXtm4wkB8ImKE9gyBbsU4Xd+bAPVQriYvz69M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gIguL8e3qIyMqcGLphPheRkkPLPeNMxeU55hnXsD+HiqtwScqHaGkzW+1amd1z7LYU8IRCAPvyU6fAeWJppSwMknPkBAhApwSavixFdbPTj78v7bPfxzJefsE1HiCQ9BhkZdbAII9p5EibXDhAUmEM4QOmWlxxRgfZ1fQjb8JcY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Wrd1PGYc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Wrd1PGYc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B7671C4CEC6; Fri, 18 Oct 2024 13:19:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729257591; bh=UPp5Q7zXtm4wkB8ImKE9gyBbsU4Xd+bAPVQriYvz69M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Wrd1PGYcsdb5dHZKtr1sKHoF2cGH+zE3iLS2zgW/2m0ryoZ1EQQcnu7Q4KuVVeoes Pr+rJcIHrDJVY7HoWhsvJhSvmhxFBk8NewBRmCMVyoTm40gfppEniXsHyjpt4iy7lO mWyGAnbw/sOP+iKltoHXr/PCdkIgg2gnlJE27TWwJrHEzNcQKH4d9p40TTN4yjYzq3 nhY7dI+CJgpPBio1ChD9zdBRJlt1wrNoBS4oS4ZI7bdJYT1vsQN+0p2FdbTV2K6gdv ORnkkdMKNqgBETZx85PWzBwa48Z3yewyDuEwDC7FOGxe2dkbbRwF4QzhHsoi2wPW8b SJDmA7k0Z+RuA== From: Lorenzo Bianconi Date: Fri, 18 Oct 2024 15:19:07 +0200 Subject: [PATCH v8 6/6] pwm: airoha: Add support for EN7581 SoC Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241018-en7581-pinctrl-v8-6-b676b966a1d1@kernel.org> References: <20241018-en7581-pinctrl-v8-0-b676b966a1d1@kernel.org> In-Reply-To: <20241018-en7581-pinctrl-v8-0-b676b966a1d1@kernel.org> To: Lorenzo Bianconi , Linus Walleij , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Sean Wang , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: linux-mediatek@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, upstream@airoha.com, benjamin.larsson@genexis.eu, ansuelsmth@gmail.com, linux-pwm@vger.kernel.org X-Mailer: b4 0.14.2 From: Benjamin Larsson Introduce driver for PWM module available on EN7581 SoC. Signed-off-by: Benjamin Larsson Co-developed-by: Lorenzo Bianconi Signed-off-by: Lorenzo Bianconi Reviewed-by: AngeloGioacchino Del Regno --- drivers/pwm/Kconfig | 11 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-airoha.c | 421 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 433 insertions(+) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 0915c1e7df16d451e987dcc5f10e0b57edc32ee1..99aa87136c272555c10102590fcf9f911161c3d3 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -54,6 +54,17 @@ config PWM_ADP5585 This option enables support for the PWM function found in the Analog Devices ADP5585. +config PWM_AIROHA + tristate "Airoha PWM support" + depends on ARCH_AIROHA || COMPILE_TEST + depends on OF + select REGMAP_MMIO + help + Generic PWM framework driver for Airoha SoC. + + To compile this driver as a module, choose M here: the module + will be called pwm-airoha. + config PWM_APPLE tristate "Apple SoC PWM support" depends on ARCH_APPLE || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 9081e0c0e9e09713fe05479c257eebe5f02b91e9..fbf7723d845807fd1e2893c6ea4f736785841b0d 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_PWM) += core.o obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o obj-$(CONFIG_PWM_ADP5585) += pwm-adp5585.o +obj-$(CONFIG_PWM_AIROHA) += pwm-airoha.o obj-$(CONFIG_PWM_APPLE) += pwm-apple.o obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o diff --git a/drivers/pwm/pwm-airoha.c b/drivers/pwm/pwm-airoha.c new file mode 100644 index 0000000000000000000000000000000000000000..71cf7a930ff69faa94207dc995ca6f94c713dac6 --- /dev/null +++ b/drivers/pwm/pwm-airoha.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 Markus Gothe + * + * Limitations: + * - No disable bit, so a disabled PWM is simulated by setting duty_cycle to 0 + * - Only 8 concurrent waveform generators are available for 8 combinations of + * duty_cycle and period. Waveform generators are shared between 16 GPIO + * pins and 17 SIPO GPIO pins. + * - Supports only normal polarity. + * - On configuration the currently running period is completed. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_SGPIO_LED_DATA 0x0024 +#define SGPIO_LED_DATA_SHIFT_FLAG BIT(31) +#define SGPIO_LED_DATA_DATA GENMASK(16, 0) + +#define REG_SGPIO_CLK_DIVR 0x0028 +#define REG_SGPIO_CLK_DLY 0x002c + +#define REG_SIPO_FLASH_MODE_CFG 0x0030 +#define SERIAL_GPIO_FLASH_MODE BIT(1) +#define SERIAL_GPIO_MODE BIT(0) + +#define REG_GPIO_FLASH_PRD_SET(_n) (0x003c + ((_n) << 2)) +#define GPIO_FLASH_PRD_MASK(_n) GENMASK(15 + ((_n) << 4), ((_n) << 4)) + +#define REG_GPIO_FLASH_MAP(_n) (0x004c + ((_n) << 2)) +#define GPIO_FLASH_SETID_MASK(_n) GENMASK(2 + ((_n) << 2), ((_n) << 2)) +#define GPIO_FLASH_EN(_n) BIT(3 + ((_n) << 2)) + +#define REG_SIPO_FLASH_MAP(_n) (0x0054 + ((_n) << 2)) + +#define REG_CYCLE_CFG_VALUE(_n) (0x0098 + ((_n) << 2)) +#define WAVE_GEN_CYCLE_MASK(_n) GENMASK(7 + ((_n) << 3), ((_n) << 3)) + +#define PWM_NUM_BUCKETS 8 + +struct airoha_pwm_bucket { + /* Bitmask of PWM channels using this bucket */ + u64 used; + u64 period_ns; + u64 duty_ns; +}; + +struct airoha_pwm { + struct regmap *regmap; + + struct device_node *np; + u64 initialized; + + struct airoha_pwm_bucket bucket[PWM_NUM_BUCKETS]; +}; + +/* + * The first 16 GPIO pins, GPIO0-GPIO15, are mapped into 16 PWM channels, 0-15. + * The SIPO GPIO pins are 17 pins which are mapped into 17 PWM channels, 16-32. + * However, we've only got 8 concurrent waveform generators and can therefore + * only use up to 8 different combinations of duty cycle and period at a time. + */ +#define PWM_NUM_GPIO 16 +#define PWM_NUM_SIPO 17 + +/* The PWM hardware supports periods between 4 ms and 1 s */ +#define PERIOD_MIN_NS (4 * NSEC_PER_MSEC) +#define PERIOD_MAX_NS (1 * NSEC_PER_SEC) +/* It is represented internally as 1/250 s between 1 and 250 */ +#define PERIOD_MIN 1 +#define PERIOD_MAX 250 +/* Duty cycle is relative with 255 corresponding to 100% */ +#define DUTY_FULL 255 + +static int airoha_pwm_get_generator(struct airoha_pwm *pc, u64 duty_ns, + u64 period_ns) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) { + if (!pc->bucket[i].used) + continue; + + if (duty_ns == pc->bucket[i].duty_ns && + period_ns == pc->bucket[i].period_ns) + return i; + + /* + * Unlike duty cycle zero, which can be handled by + * disabling PWM, a generator is needed for full duty + * cycle but it can be reused regardless of period + */ + if (duty_ns == DUTY_FULL && pc->bucket[i].duty_ns == DUTY_FULL) + return i; + } + + return -1; +} + +static void airoha_pwm_release_bucket_config(struct airoha_pwm *pc, + unsigned int hwpwm) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) + pc->bucket[i].used &= ~BIT_ULL(hwpwm); +} + +static int airoha_pwm_consume_generator(struct airoha_pwm *pc, + u64 duty_ns, u64 period_ns, + unsigned int hwpwm) +{ + int id = airoha_pwm_get_generator(pc, duty_ns, period_ns); + + if (id < 0) { + int i; + + /* find an unused waveform generator */ + for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) { + if (!(pc->bucket[i].used & ~BIT_ULL(hwpwm))) { + id = i; + break; + } + } + } + + if (id >= 0) { + airoha_pwm_release_bucket_config(pc, hwpwm); + pc->bucket[id].used |= BIT_ULL(hwpwm); + pc->bucket[id].period_ns = period_ns; + pc->bucket[id].duty_ns = duty_ns; + } + + return id; +} + +static int airoha_pwm_sipo_init(struct airoha_pwm *pc) +{ + u32 clk_divr_val, sipo_clock_delay, sipo_clock_divisor; + u32 val; + + if (!(pc->initialized >> PWM_NUM_GPIO)) + return 0; + + /* + * Select the right shift register chip. + * By default 74HC164 is assumed. With this enabled + * 74HC595 chip is used that requires the latch pin + * to be triggered to apply the configuration. + */ + if (of_property_read_bool(pc->np, "airoha,74hc595-mode")) + regmap_set_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG, + SERIAL_GPIO_MODE); + else + regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG, + SERIAL_GPIO_MODE); + + if (of_property_read_u32(pc->np, "airoha,sipo-clock-divisor", + &sipo_clock_divisor)) + sipo_clock_divisor = 32; + + switch (sipo_clock_divisor) { + case 4: + clk_divr_val = 0; + break; + case 8: + clk_divr_val = 1; + break; + case 16: + clk_divr_val = 2; + break; + case 32: + clk_divr_val = 3; + break; + default: + return -EINVAL; + } + /* Configure shift register timings */ + regmap_write(pc->regmap, REG_SGPIO_CLK_DIVR, clk_divr_val); + + if (of_property_read_u32(pc->np, "airoha,sipo-clock-delay", + &sipo_clock_delay)) + sipo_clock_delay = 1; + + if (sipo_clock_delay < 1 || sipo_clock_delay > sipo_clock_divisor / 2) + return -EINVAL; + + /* + * The actual delay is sclkdly + 1 so subtract 1 from + * sipo-clock-delay to calculate the register value + */ + sipo_clock_delay--; + regmap_write(pc->regmap, REG_SGPIO_CLK_DLY, sipo_clock_delay); + + /* + * It it necessary to after muxing explicitly shift out all + * zeroes to initialize the shift register before enabling PWM + * mode because in PWM mode SIPO will not start shifting until + * it needs to output a non-zero value (bit 31 of led_data + * indicates shifting in progress and it must return to zero + * before led_data can be written or PWM mode can be set) + */ + if (regmap_read_poll_timeout(pc->regmap, REG_SGPIO_LED_DATA, val, + !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10, + 200 * USEC_PER_MSEC)) + return -ETIMEDOUT; + + regmap_clear_bits(pc->regmap, REG_SGPIO_LED_DATA, SGPIO_LED_DATA_DATA); + if (regmap_read_poll_timeout(pc->regmap, REG_SGPIO_LED_DATA, val, + !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10, + 200 * USEC_PER_MSEC)) + return -ETIMEDOUT; + + /* Set SIPO in PWM mode */ + regmap_set_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG, + SERIAL_GPIO_FLASH_MODE); + + return 0; +} + +static void airoha_pwm_calc_bucket_config(struct airoha_pwm *pc, int index, + u64 duty_ns, u64 period_ns) +{ + u32 period, duty, mask, val; + u64 tmp; + + tmp = duty_ns * DUTY_FULL; + duty = clamp_val(div64_u64(tmp, period_ns), 0, DUTY_FULL); + tmp = period_ns * 25; + period = clamp_val(div64_u64(tmp, 100000000), PERIOD_MIN, PERIOD_MAX); + + /* Configure frequency divisor */ + mask = WAVE_GEN_CYCLE_MASK(index % 4); + val = (period << __ffs(mask)) & mask; + regmap_update_bits(pc->regmap, REG_CYCLE_CFG_VALUE(index / 4), + mask, val); + + /* Configure duty cycle */ + duty = ((DUTY_FULL - duty) << 8) | duty; + mask = GPIO_FLASH_PRD_MASK(index % 2); + val = (duty << __ffs(mask)) & mask; + regmap_update_bits(pc->regmap, REG_GPIO_FLASH_PRD_SET(index / 2), + mask, val); +} + +static void airoha_pwm_config_flash_map(struct airoha_pwm *pc, + unsigned int hwpwm, int index) +{ + u32 addr, mask, val; + + if (hwpwm < PWM_NUM_GPIO) { + addr = REG_GPIO_FLASH_MAP(hwpwm / 8); + } else { + addr = REG_SIPO_FLASH_MAP(hwpwm / 8); + hwpwm -= PWM_NUM_GPIO; + } + + if (index < 0) { + /* + * Change of waveform takes effect immediately but + * disabling has some delay so to prevent glitching + * only the enable bit is touched when disabling + */ + regmap_clear_bits(pc->regmap, addr, GPIO_FLASH_EN(hwpwm % 8)); + return; + } + + mask = GPIO_FLASH_SETID_MASK(hwpwm % 8); + val = ((index & 7) << __ffs(mask)) & mask; + regmap_update_bits(pc->regmap, addr, mask, val); + regmap_set_bits(pc->regmap, addr, GPIO_FLASH_EN(hwpwm % 8)); +} + +static int airoha_pwm_config(struct airoha_pwm *pc, struct pwm_device *pwm, + u64 duty_ns, u64 period_ns) +{ + int index = -1; + + index = airoha_pwm_consume_generator(pc, duty_ns, period_ns, + pwm->hwpwm); + if (index < 0) + return -EBUSY; + + if (!(pc->initialized & BIT_ULL(pwm->hwpwm)) && + pwm->hwpwm >= PWM_NUM_GPIO) + airoha_pwm_sipo_init(pc); + + if (index >= 0) { + airoha_pwm_calc_bucket_config(pc, index, duty_ns, period_ns); + airoha_pwm_config_flash_map(pc, pwm->hwpwm, index); + } else { + airoha_pwm_config_flash_map(pc, pwm->hwpwm, index); + airoha_pwm_release_bucket_config(pc, pwm->hwpwm); + } + + pc->initialized |= BIT_ULL(pwm->hwpwm); + + return 0; +} + +static void airoha_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct airoha_pwm *pc = pwmchip_get_drvdata(chip); + + /* Disable PWM and release the waveform */ + airoha_pwm_config_flash_map(pc, pwm->hwpwm, -1); + airoha_pwm_release_bucket_config(pc, pwm->hwpwm); + + pc->initialized &= ~BIT_ULL(pwm->hwpwm); + if (!(pc->initialized >> PWM_NUM_GPIO)) + regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG, + SERIAL_GPIO_FLASH_MODE); +} + +static int airoha_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct airoha_pwm *pc = pwmchip_get_drvdata(chip); + u64 duty = state->enabled ? state->duty_cycle : 0; + u64 period = state->period; + + /* Only normal polarity is supported */ + if (state->polarity == PWM_POLARITY_INVERSED) + return -EINVAL; + + if (!state->enabled) { + airoha_pwm_disable(chip, pwm); + return 0; + } + + if (period < PERIOD_MIN_NS) + return -EINVAL; + + if (period > PERIOD_MAX_NS) + period = PERIOD_MAX_NS; + + return airoha_pwm_config(pc, pwm, duty, period); +} + +static int airoha_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct airoha_pwm *pc = pwmchip_get_drvdata(chip); + int i; + + /* find hwpwm in waveform generator bucket */ + for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) { + if (pc->bucket[i].used & BIT_ULL(pwm->hwpwm)) { + state->enabled = pc->initialized & BIT_ULL(pwm->hwpwm); + state->polarity = PWM_POLARITY_NORMAL; + state->period = pc->bucket[i].period_ns; + state->duty_cycle = pc->bucket[i].duty_ns; + break; + } + } + + if (i == ARRAY_SIZE(pc->bucket)) + state->enabled = false; + + return 0; +} + +static const struct pwm_ops airoha_pwm_ops = { + .get_state = airoha_pwm_get_state, + .apply = airoha_pwm_apply, +}; + +static int airoha_pwm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct airoha_pwm *pc; + struct pwm_chip *chip; + + chip = devm_pwmchip_alloc(dev, PWM_NUM_GPIO + PWM_NUM_SIPO, + sizeof(*pc)); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + chip->ops = &airoha_pwm_ops; + pc = pwmchip_get_drvdata(chip); + pc->np = dev->of_node; + + pc->regmap = device_node_to_regmap(dev->parent->of_node); + if (IS_ERR(pc->regmap)) + return PTR_ERR(pc->regmap); + + return devm_pwmchip_add(&pdev->dev, chip); +} + +static const struct of_device_id airoha_pwm_of_match[] = { + { .compatible = "airoha,en7581-pwm" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, airoha_pwm_of_match); + +static struct platform_driver airoha_pwm_driver = { + .driver = { + .name = "pwm-airoha", + .of_match_table = airoha_pwm_of_match, + }, + .probe = airoha_pwm_probe, +}; +module_platform_driver(airoha_pwm_driver); + +MODULE_AUTHOR("Lorenzo Bianconi "); +MODULE_AUTHOR("Markus Gothe "); +MODULE_AUTHOR("Benjamin Larsson "); +MODULE_DESCRIPTION("Airoha EN7581 PWM driver"); +MODULE_LICENSE("GPL");