* [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC @ 2024-09-11 19:50 Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for " Lorenzo Bianconi ` (5 more replies) 0 siblings, 6 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 19:50 UTC (permalink / raw) To: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König Cc: linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm Introduce airoha-mfd driver in order to load pinctrl and pwm drivers for EN7581 SoC. airoha-mfd is needed since both pinctrl and pwm drivers needs to access the same memory block (gpio memory region) to configure {gio,irq}_chip and pwm functionalities respectively, so model them as childs of a parent mfd driver. Current EN7581 pinctrl driver supports the following functionalities: - pin multiplexing via chip_scu syscon - pin pull-up, pull-down, open-drain, current strength, {input,output}_enable, output_{low,high} via chip_scu syscon - gpio controller - irq controller --- Changes in v4: - add 'Limitation' description in pwm driver - fix comments in pwm driver - rely on mfd->base __iomem pointer in pwm driver, modify register offsets according to it and get rid of sgpio_cfg, flash_cfg and cycle_cfg pointers - simplify register utility routines in pwm driver - use 'generator' instead of 'waveform' suffix for pwm routines - fix possible overflow calculating duty cycle in pwm driver - do not modify pwm state in free callback in pwm driver - cap the maximum period in pwm driver - do not allow inverse polarity in pwm driver - do not set of_xlate callback in the pwm driver and allow the stack to do it - fix MAINTAINERS file for airoha pinctrl driver - fix undefined reference to __ffsdi2 in pinctrl driver - simplify airoha,en7581-gpio-sysctl.yam binding - Link to v3: https://lore.kernel.org/r/20240831-en7581-pinctrl-v3-0-98eebfb4da66@kernel.org Changes in v3: - introduce airoha-mfd driver - add pwm driver to the same series - model pinctrl and pwm drivers as childs of a parent mfd driver. - access chip-scu memory region in pinctrl driver via syscon - introduce a single airoha,en7581-gpio-sysctl.yaml binding and get rid of dedicated bindings for pinctrl and pwm - add airoha,en7581-chip-scu.yaml binding do the series - Link to v2: https://lore.kernel.org/r/20240822-en7581-pinctrl-v2-0-ba1559173a7f@kernel.org Changes in v2: - Fix compilation errors - Collapse some register mappings for gpio and irq controllers - update dt-bindings according to new register mapping - fix some dt-bindings errors - Link to v1: https://lore.kernel.org/all/cover.1723392444.git.lorenzo@kernel.org/ --- Benjamin Larsson (1): pwm: airoha: Add support for EN7581 SoC Christian Marangi (2): dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller mfd: airoha: Add support for Airoha EN7581 MFD Lorenzo Bianconi (2): dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC pinctrl: airoha: Add support for EN7581 SoC .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 + .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++ MAINTAINERS | 7 + drivers/mfd/Kconfig | 8 + drivers/mfd/Makefile | 2 + drivers/mfd/airoha-en7581-gpio-mfd.c | 72 + drivers/pinctrl/mediatek/Kconfig | 16 +- drivers/pinctrl/mediatek/Makefile | 1 + drivers/pinctrl/mediatek/pinctrl-airoha.c | 2964 ++++++++++++++++++++ drivers/pwm/Kconfig | 10 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-airoha.c | 414 +++ include/linux/mfd/airoha-en7581-mfd.h | 9 + 13 files changed, 3978 insertions(+), 1 deletion(-) --- base-commit: 264c13114bd71ddfd7b25c7b94f6cda4587eca25 change-id: 20240818-en7581-pinctrl-1bf120154be0 prerequisite-change-id: 20240705-for-6-11-bpf-a349efc08df8:v2 Best regards, -- Lorenzo Bianconi <lorenzo@kernel.org> ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC 2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi @ 2024-09-11 19:50 ` Lorenzo Bianconi 2024-09-11 21:12 ` Rob Herring (Arm) 2024-09-11 19:50 ` [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller Lorenzo Bianconi ` (4 subsequent siblings) 5 siblings, 1 reply; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 19:50 UTC (permalink / raw) To: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König Cc: linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm This patch adds the chip-scu document bindings for EN7581 SoC. The airoha chip-scu block provides a configuration interface for clock, io-muxing and other functionalities used by multiple controllers (e.g. clock, pinctrl, ecc.) on EN7581 SoC. Reviewed-by: Rob Herring (Arm) <robh@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> --- .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.yaml b/Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.yaml new file mode 100644 index 000000000000..67c449d804c2 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/airoha,en7581-chip-scu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Airoha Chip SCU Controller for EN7581 SoC + +maintainers: + - Lorenzo Bianconi <lorenzo@kernel.org> + +description: + The airoha chip-scu block provides a configuration interface for clock, + io-muxing and other functionalities used by multiple controllers (e.g. clock, + pinctrl, ecc) on EN7581 SoC. + +properties: + compatible: + items: + - enum: + - airoha,en7581-chip-scu + - const: syscon + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + syscon@1fa20000 { + compatible = "airoha,en7581-chip-scu", "syscon"; + reg = <0x0 0x1fa20000 0x0 0x388>; + }; + }; -- 2.46.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC 2024-09-11 19:50 ` [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for " Lorenzo Bianconi @ 2024-09-11 21:12 ` Rob Herring (Arm) 2024-09-11 21:46 ` Lorenzo Bianconi 0 siblings, 1 reply; 20+ messages in thread From: Rob Herring (Arm) @ 2024-09-11 21:12 UTC (permalink / raw) To: Lorenzo Bianconi Cc: AngeloGioacchino Del Regno, linux-mediatek, Conor Dooley, Matthias Brugger, Krzysztof Kozlowski, linux-gpio, Sean Wang, upstream, ansuelsmth, linux-pwm, linux-arm-kernel, Linus Walleij, Lee Jones, devicetree, Uwe Kleine-König, benjamin.larsson On Wed, 11 Sep 2024 21:50:01 +0200, Lorenzo Bianconi wrote: > This patch adds the chip-scu document bindings for EN7581 SoC. > The airoha chip-scu block provides a configuration interface for clock, > io-muxing and other functionalities used by multiple controllers (e.g. > clock, pinctrl, ecc.) on EN7581 SoC. > > Reviewed-by: Rob Herring (Arm) <robh@kernel.org> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > --- > .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 ++++++++++++++++++++++ > 1 file changed, 42 insertions(+) > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: dtschema/dtc warnings/errors: doc reference errors (make refcheckdocs): See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240911-en7581-pinctrl-v4-1-60ac93d760bb@kernel.org The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC 2024-09-11 21:12 ` Rob Herring (Arm) @ 2024-09-11 21:46 ` Lorenzo Bianconi 2024-09-12 16:43 ` Rob Herring 0 siblings, 1 reply; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 21:46 UTC (permalink / raw) To: Rob Herring (Arm) Cc: AngeloGioacchino Del Regno, linux-mediatek, Conor Dooley, Matthias Brugger, Krzysztof Kozlowski, linux-gpio, Sean Wang, upstream, ansuelsmth, linux-pwm, linux-arm-kernel, Linus Walleij, Lee Jones, devicetree, Uwe Kleine-König, benjamin.larsson [-- Attachment #1: Type: text/plain, Size: 2614 bytes --] > > On Wed, 11 Sep 2024 21:50:01 +0200, Lorenzo Bianconi wrote: > > This patch adds the chip-scu document bindings for EN7581 SoC. > > The airoha chip-scu block provides a configuration interface for clock, > > io-muxing and other functionalities used by multiple controllers (e.g. > > clock, pinctrl, ecc.) on EN7581 SoC. > > > > Reviewed-by: Rob Herring (Arm) <robh@kernel.org> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > > --- > > .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 ++++++++++++++++++++++ > > 1 file changed, 42 insertions(+) > > > > My bot found errors running 'make dt_binding_check' on your patch: > > yamllint warnings/errors: > > dtschema/dtc warnings/errors: > > > doc reference errors (make refcheckdocs): > > See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240911-en7581-pinctrl-v4-1-60ac93d760bb@kernel.org > > The base for the series is generally the latest rc1. A different dependency > should be noted in *this* patch. > > If you already ran 'make dt_binding_check' and didn't see the above > error(s), then make sure 'yamllint' is installed and dt-schema is up to > date: > > pip3 install dtschema --upgrade > > Please check and re-submit after running the above command yourself. Note > that DT_SCHEMA_FILES can be set to your schema file to speed up checking > your schema. However, it must be unset to test all examples with your schema. > Hi Rob, before posting the series I run make dt_binding_check: $ make dt_binding_check DT_SCHEMA_FILES=airoha SCHEMA Documentation/devicetree/bindings/processed-schema.json CHKDT Documentation/devicetree/bindings LINT Documentation/devicetree/bindings DTC_CHK Documentation/devicetree/bindings/arm/airoha.example.dtb DTEX Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.example.dts DTC_CHK Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.example.dtb DTC_CHK Documentation/devicetree/bindings/clock/airoha,en7523-scu.example.dtb DTC_CHK Documentation/devicetree/bindings/net/airoha,en7581-eth.example.dtb DTC_CHK Documentation/devicetree/bindings/net/airoha,en8811h.example.dtb DTC_CHK Documentation/devicetree/bindings/gpio/airoha,en7523-gpio.example.dtb DTC_CHK Documentation/devicetree/bindings/spi/airoha,en7581-snand.example.dtb DTC_CHK Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.example.dtb $yamllint --version yamllint 1.35.1 dtschema is at the latest version. Is it a false positive or am I missing something? Regards, Lorenzo [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC 2024-09-11 21:46 ` Lorenzo Bianconi @ 2024-09-12 16:43 ` Rob Herring 0 siblings, 0 replies; 20+ messages in thread From: Rob Herring @ 2024-09-12 16:43 UTC (permalink / raw) To: Lorenzo Bianconi Cc: AngeloGioacchino Del Regno, linux-mediatek, Conor Dooley, Matthias Brugger, Krzysztof Kozlowski, linux-gpio, Sean Wang, upstream, ansuelsmth, linux-pwm, linux-arm-kernel, Linus Walleij, Lee Jones, devicetree, Uwe Kleine-König, benjamin.larsson On Wed, Sep 11, 2024 at 11:46:11PM +0200, Lorenzo Bianconi wrote: > > > > On Wed, 11 Sep 2024 21:50:01 +0200, Lorenzo Bianconi wrote: > > > This patch adds the chip-scu document bindings for EN7581 SoC. > > > The airoha chip-scu block provides a configuration interface for clock, > > > io-muxing and other functionalities used by multiple controllers (e.g. > > > clock, pinctrl, ecc.) on EN7581 SoC. > > > > > > Reviewed-by: Rob Herring (Arm) <robh@kernel.org> > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > > > --- > > > .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 ++++++++++++++++++++++ > > > 1 file changed, 42 insertions(+) > > > > > > > My bot found errors running 'make dt_binding_check' on your patch: > > > > yamllint warnings/errors: > > > > dtschema/dtc warnings/errors: > > > > > > doc reference errors (make refcheckdocs): > > > > See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240911-en7581-pinctrl-v4-1-60ac93d760bb@kernel.org > > > > The base for the series is generally the latest rc1. A different dependency > > should be noted in *this* patch. > > > > If you already ran 'make dt_binding_check' and didn't see the above > > error(s), then make sure 'yamllint' is installed and dt-schema is up to > > date: > > > > pip3 install dtschema --upgrade > > > > Please check and re-submit after running the above command yourself. Note > > that DT_SCHEMA_FILES can be set to your schema file to speed up checking > > your schema. However, it must be unset to test all examples with your schema. > > > > Hi Rob, > > before posting the series I run make dt_binding_check: > > $ make dt_binding_check DT_SCHEMA_FILES=airoha Technically, you have to run it without DT_SCHEMA_FILES as sometimes there is interaction with other schemas. > SCHEMA Documentation/devicetree/bindings/processed-schema.json > CHKDT Documentation/devicetree/bindings > LINT Documentation/devicetree/bindings > DTC_CHK Documentation/devicetree/bindings/arm/airoha.example.dtb > DTEX Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.example.dts > DTC_CHK Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.example.dtb > DTC_CHK Documentation/devicetree/bindings/clock/airoha,en7523-scu.example.dtb > DTC_CHK Documentation/devicetree/bindings/net/airoha,en7581-eth.example.dtb > DTC_CHK Documentation/devicetree/bindings/net/airoha,en8811h.example.dtb > DTC_CHK Documentation/devicetree/bindings/gpio/airoha,en7523-gpio.example.dtb > DTC_CHK Documentation/devicetree/bindings/spi/airoha,en7581-snand.example.dtb > DTC_CHK Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.example.dtb > > $yamllint --version > yamllint 1.35.1 > > dtschema is at the latest version. > Is it a false positive or am I missing something? Looks like something went sideways. Will look into it. You can ignore this. Rob ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller 2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for " Lorenzo Bianconi @ 2024-09-11 19:50 ` Lorenzo Bianconi 2024-09-11 21:12 ` Rob Herring (Arm) 2024-09-12 16:44 ` Rob Herring (Arm) 2024-09-11 19:50 ` [PATCH v4 3/5] mfd: airoha: Add support for Airoha EN7581 MFD Lorenzo Bianconi ` (3 subsequent siblings) 5 siblings, 2 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 19:50 UTC (permalink / raw) To: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König Cc: linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm From: Christian Marangi <ansuelsmth@gmail.com> Add support for Airoha EN7581 GPIO System Controller which provide a register map for controlling the GPIO, pinctrl and PWM of the SoC. Schema define cells for both gpio/interrupt controller and PWM. Moreover it provides a dedicated pinctrl node for pins and config definitions. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> --- .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++++++++++++++++++++ 1 file changed, 433 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 000000000000..98396db40e67 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml @@ -0,0 +1,433 @@ +# 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 <ansuelsmth@gmail.com> + - Lorenzo Bianconi <lorenzo@kernel.org> + +description: + Airoha EN7581 SoC GPIO system controller which provided a register map + for controlling the GPIO, pins and PWM of the SoC. + +properties: + compatible: + const: airoha,en7581-gpio-sysctl + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + "#pwm-cells": + const: 3 + + pinctrl: + type: object + + $ref: /schemas/pinctrl/pinctrl.yaml + + 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 + +required: + - compatible + - reg + - interrupts + - gpio-controller + - "#gpio-cells" + - "#pwm-cells" + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + + mfd@1fbf0200 { + compatible = "airoha,en7581-gpio-sysctl"; + reg = <0x1fbf0200 0xc0>; + + interrupt-parent = <&gic>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + #pwm-cells = <3>; + + pinctrl { + 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; + }; + }; + + gswp1-led0-pins { + mux { + function = "phy1_led0"; + groups = "gpio33"; + }; + }; + + gswp2-led1-pins { + mux { + function = "phy2_led1"; + groups = "gpio44"; + }; + }; + }; + }; + +... -- 2.46.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller 2024-09-11 19:50 ` [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller Lorenzo Bianconi @ 2024-09-11 21:12 ` Rob Herring (Arm) 2024-09-11 21:48 ` Lorenzo Bianconi 2024-09-12 16:44 ` Rob Herring (Arm) 1 sibling, 1 reply; 20+ messages in thread From: Rob Herring (Arm) @ 2024-09-11 21:12 UTC (permalink / raw) To: Lorenzo Bianconi Cc: devicetree, Lee Jones, linux-arm-kernel, linux-pwm, Conor Dooley, Linus Walleij, linux-mediatek, benjamin.larsson, upstream, ansuelsmth, Sean Wang, AngeloGioacchino Del Regno, Krzysztof Kozlowski, Matthias Brugger, linux-gpio, Uwe Kleine-König On Wed, 11 Sep 2024 21:50:02 +0200, Lorenzo Bianconi wrote: > From: Christian Marangi <ansuelsmth@gmail.com> > > Add support for Airoha EN7581 GPIO System Controller which provide a > register map for controlling the GPIO, pinctrl and PWM of the SoC. > > Schema define cells for both gpio/interrupt controller and PWM. > Moreover it provides a dedicated pinctrl node for pins and config > definitions. > > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > --- > .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++++++++++++++++++++ > 1 file changed, 433 insertions(+) > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: dtschema/dtc warnings/errors: doc reference errors (make refcheckdocs): See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240911-en7581-pinctrl-v4-2-60ac93d760bb@kernel.org The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller 2024-09-11 21:12 ` Rob Herring (Arm) @ 2024-09-11 21:48 ` Lorenzo Bianconi 0 siblings, 0 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 21:48 UTC (permalink / raw) To: Rob Herring (Arm) Cc: devicetree, Lee Jones, linux-arm-kernel, linux-pwm, Conor Dooley, Linus Walleij, linux-mediatek, benjamin.larsson, upstream, ansuelsmth, Sean Wang, AngeloGioacchino Del Regno, Krzysztof Kozlowski, Matthias Brugger, linux-gpio, Uwe Kleine-König [-- Attachment #1: Type: text/plain, Size: 2768 bytes --] > > On Wed, 11 Sep 2024 21:50:02 +0200, Lorenzo Bianconi wrote: > > From: Christian Marangi <ansuelsmth@gmail.com> > > > > Add support for Airoha EN7581 GPIO System Controller which provide a > > register map for controlling the GPIO, pinctrl and PWM of the SoC. > > > > Schema define cells for both gpio/interrupt controller and PWM. > > Moreover it provides a dedicated pinctrl node for pins and config > > definitions. > > > > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> > > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > > --- > > .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++++++++++++++++++++ > > 1 file changed, 433 insertions(+) > > > > My bot found errors running 'make dt_binding_check' on your patch: > > yamllint warnings/errors: > > dtschema/dtc warnings/errors: > > > doc reference errors (make refcheckdocs): > > See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240911-en7581-pinctrl-v4-2-60ac93d760bb@kernel.org > > The base for the series is generally the latest rc1. A different dependency > should be noted in *this* patch. > > If you already ran 'make dt_binding_check' and didn't see the above > error(s), then make sure 'yamllint' is installed and dt-schema is up to > date: > > pip3 install dtschema --upgrade > > Please check and re-submit after running the above command yourself. Note > that DT_SCHEMA_FILES can be set to your schema file to speed up checking > your schema. However, it must be unset to test all examples with your schema. > Similar to the previous patch, I run the following command before posting the series: $make dt_binding_check DT_SCHEMA_FILES=airoha SCHEMA Documentation/devicetree/bindings/processed-schema.json CHKDT Documentation/devicetree/bindings LINT Documentation/devicetree/bindings DTEX Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.example.dts DTC_CHK Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.example.dtb DTC_CHK Documentation/devicetree/bindings/arm/airoha.example.dtb DTC_CHK Documentation/devicetree/bindings/arm/airoha,en7581-chip-scu.example.dtb DTC_CHK Documentation/devicetree/bindings/clock/airoha,en7523-scu.example.dtb DTC_CHK Documentation/devicetree/bindings/net/airoha,en7581-eth.example.dtb DTC_CHK Documentation/devicetree/bindings/net/airoha,en8811h.example.dtb DTC_CHK Documentation/devicetree/bindings/gpio/airoha,en7523-gpio.example.dtb DTC_CHK Documentation/devicetree/bindings/spi/airoha,en7581-snand.example.dtb DTC_CHK Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.example.dtb Regards, Lorenzo [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller 2024-09-11 19:50 ` [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller Lorenzo Bianconi 2024-09-11 21:12 ` Rob Herring (Arm) @ 2024-09-12 16:44 ` Rob Herring (Arm) 1 sibling, 0 replies; 20+ messages in thread From: Rob Herring (Arm) @ 2024-09-12 16:44 UTC (permalink / raw) To: Lorenzo Bianconi Cc: AngeloGioacchino Del Regno, Krzysztof Kozlowski, linux-pwm, ansuelsmth, Matthias Brugger, benjamin.larsson, linux-gpio, Sean Wang, Linus Walleij, linux-mediatek, Conor Dooley, devicetree, linux-arm-kernel, upstream, Lee Jones, Uwe Kleine-König On Wed, 11 Sep 2024 21:50:02 +0200, Lorenzo Bianconi wrote: > From: Christian Marangi <ansuelsmth@gmail.com> > > Add support for Airoha EN7581 GPIO System Controller which provide a > register map for controlling the GPIO, pinctrl and PWM of the SoC. > > Schema define cells for both gpio/interrupt controller and PWM. > Moreover it provides a dedicated pinctrl node for pins and config > definitions. > > Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > --- > .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++++++++++++++++++++ > 1 file changed, 433 insertions(+) > Reviewed-by: Rob Herring (Arm) <robh@kernel.org> ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 3/5] mfd: airoha: Add support for Airoha EN7581 MFD 2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for " Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller Lorenzo Bianconi @ 2024-09-11 19:50 ` Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC Lorenzo Bianconi ` (2 subsequent siblings) 5 siblings, 0 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 19:50 UTC (permalink / raw) To: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König Cc: linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm From: Christian Marangi <ansuelsmth@gmail.com> Support for Airoha EN7581 Multi Function Device that expose PINCTRL functionality and PWM functionality. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> --- drivers/mfd/Kconfig | 8 ++++ drivers/mfd/Makefile | 2 + drivers/mfd/airoha-en7581-gpio-mfd.c | 72 +++++++++++++++++++++++++++++++++++ include/linux/mfd/airoha-en7581-mfd.h | 9 +++++ 4 files changed, 91 insertions(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index bc8be2e593b6..c690378066ac 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -20,6 +20,14 @@ config MFD_CS5535 This is the core driver for CS5535/CS5536 MFD functions. This is necessary for using the board's GPIO and MFGPT functionality. +config MFD_AIROHA_EN7581 + bool "Airoha EN7581 Multi Function Device" + depends on (ARCH_AIROHA || COMPILE_TEST) && OF + select MFD_CORE + help + Support for Airoha EN7581 Multi Function Device that + expose PINCTRL functionality and PWM functionality. + config MFD_ALTERA_A10SR bool "Altera Arria10 DevKit System Resource chip" depends on ARCH_INTEL_SOCFPGA && SPI_MASTER=y && OF diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 02b651cd7535..075dbff618e0 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -256,6 +256,8 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o obj-$(CONFIG_INTEL_SOC_PMIC_MRFLD) += intel_soc_pmic_mrfld.o +obj-$(CONFIG_MFD_AIROHA_EN7581) += airoha-en7581-gpio-mfd.o + obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o diff --git a/drivers/mfd/airoha-en7581-gpio-mfd.c b/drivers/mfd/airoha-en7581-gpio-mfd.c new file mode 100644 index 000000000000..88407ce5747e --- /dev/null +++ b/drivers/mfd/airoha-en7581-gpio-mfd.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * MFD driver for Airoha EN7581 + */ + +#include <linux/io.h> +#include <linux/of.h> +#include <linux/mfd/airoha-en7581-mfd.h> +#include <linux/mfd/core.h> +#include <linux/module.h> + +static struct resource airoha_mfd_pinctrl_intr[] = { + { + .flags = IORESOURCE_IRQ, + }, +}; + +static const struct mfd_cell airoha_mfd_devs[] = { + { + .name = "pinctrl-airoha", + .resources = airoha_mfd_pinctrl_intr, + .num_resources = ARRAY_SIZE(airoha_mfd_pinctrl_intr), + }, { + .name = "pwm-airoha", + }, +}; + +static int airoha_mfd_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct airoha_mfd *mfd; + int irq; + + mfd = devm_kzalloc(dev, sizeof(*mfd), GFP_KERNEL); + if (!mfd) + return -ENOMEM; + + platform_set_drvdata(pdev, mfd); + + mfd->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mfd->base)) + return PTR_ERR(mfd->base); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + airoha_mfd_pinctrl_intr[0].start = irq; + airoha_mfd_pinctrl_intr[0].end = irq; + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, airoha_mfd_devs, + ARRAY_SIZE(airoha_mfd_devs), NULL, 0, + NULL); +} + +static const struct of_device_id airoha_mfd_of_match[] = { + { .compatible = "airoha,en7581-gpio-sysctl" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, airoha_mfd_of_match); + +static struct platform_driver airoha_mfd_driver = { + .probe = airoha_mfd_probe, + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = airoha_mfd_of_match, + }, +}; +module_platform_driver(airoha_mfd_driver); + +MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>"); +MODULE_DESCRIPTION("Driver for Airoha EN7581 MFD"); diff --git a/include/linux/mfd/airoha-en7581-mfd.h b/include/linux/mfd/airoha-en7581-mfd.h new file mode 100644 index 000000000000..25e73952a777 --- /dev/null +++ b/include/linux/mfd/airoha-en7581-mfd.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_INCLUDE_MFD_AIROHA_EN7581_MFD_H_ +#define _LINUX_INCLUDE_MFD_AIROHA_EN7581_MFD_H_ + +struct airoha_mfd { + void __iomem *base; +}; + +#endif /* _LINUX_INCLUDE_MFD_AIROHA_EN7581_MFD_H_ */ -- 2.46.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC 2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi ` (2 preceding siblings ...) 2024-09-11 19:50 ` [PATCH v4 3/5] mfd: airoha: Add support for Airoha EN7581 MFD Lorenzo Bianconi @ 2024-09-11 19:50 ` Lorenzo Bianconi 2024-09-24 7:34 ` Linus Walleij 2024-09-11 19:50 ` [PATCH v4 5/5] pwm: " Lorenzo Bianconi 2024-09-23 9:53 ` [PATCH v4 0/5] Add mfd, pinctrl and pwm support to " Christian Marangi 5 siblings, 1 reply; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 19:50 UTC (permalink / raw) To: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König Cc: linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm Introduce pinctrl driver for EN7581 SoC. Current EN7581 pinctrl driver supports the following functionalities: - pin multiplexing - pin pull-up, pull-down, open-drain, current strength, {input,output}_enable, output_{low,high} - gpio controller - irq controller Tested-by: Benjamin Larsson <benjamin.larsson@genexis.eu> Co-developed-by: Benjamin Larsson <benjamin.larsson@genexis.eu> Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> --- MAINTAINERS | 7 + drivers/pinctrl/mediatek/Kconfig | 16 +- drivers/pinctrl/mediatek/Makefile | 1 + drivers/pinctrl/mediatek/pinctrl-airoha.c | 2964 +++++++++++++++++++++++++++++ 4 files changed, 2987 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 42decde38320..b12a90b2355b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17966,6 +17966,13 @@ F: drivers/pinctrl/ F: include/dt-bindings/pinctrl/ F: include/linux/pinctrl/ +PIN CONTROLLER - AIROHA +M: Lorenzo Bianconi <lorenzo@kernel.org> +L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: Documentation/devicetree/bindings/mfd/airoha,en7581-gpio-sysctl.yaml +F: drivers/pinctrl/mediatek/pinctrl-airoha.c + PIN CONTROLLER - AMD M: Basavaraj Natikar <Basavaraj.Natikar@amd.com> M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 7af287252834..43bbf606ee7d 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only menu "MediaTek pinctrl drivers" - depends on ARCH_MEDIATEK || RALINK || COMPILE_TEST + depends on ARCH_MEDIATEK || ARCH_AIROHA || RALINK || COMPILE_TEST config EINT_MTK tristate "MediaTek External Interrupt Support" @@ -126,6 +126,20 @@ config PINCTRL_MT8127 select PINCTRL_MTK # For ARMv8 SoCs +config PINCTRL_AIROHA + tristate "Airoha pin control" + depends on OF + depends on ARM64 || COMPILE_TEST + select PINMUX + select GENERIC_PINCONF + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + select GPIOLIB + select GPIOLIB_IRQCHIP + help + Say yes here to support pin controller and gpio driver + on Airoha EN7581 SoC. + config PINCTRL_MT2712 bool "MediaTek MT2712 pin control" depends on OF diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index 680f7e8526e0..1405d434218e 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinctrl-moore.o obj-$(CONFIG_PINCTRL_MTK_PARIS) += pinctrl-paris.o # SoC Drivers +obj-$(CONFIG_PINCTRL_AIROHA) += pinctrl-airoha.o obj-$(CONFIG_PINCTRL_MT7620) += pinctrl-mt7620.o obj-$(CONFIG_PINCTRL_MT7621) += pinctrl-mt7621.o obj-$(CONFIG_PINCTRL_MT76X8) += pinctrl-mt76x8.o diff --git a/drivers/pinctrl/mediatek/pinctrl-airoha.c b/drivers/pinctrl/mediatek/pinctrl-airoha.c new file mode 100644 index 000000000000..a6fe4a7cf916 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c @@ -0,0 +1,2964 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Lorenzo Bianconi <lorenzo@kernel.org> + * Author: Benjamin Larsson <benjamin.larsson@genexis.eu> + * Author: Markus Gothe <markus.gothe@genexis.eu> + */ + +#include <dt-bindings/pinctrl/mt65xx.h> +#include <linux/bitfield.h> +#include <linux/gpio/driver.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/kernel.h> +#include <linux/mfd/airoha-en7581-mfd.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/pinctrl/consumer.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinmux.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include "../core.h" +#include "../pinconf.h" +#include "../pinmux.h" + +#define PINCTRL_PIN_GROUP(id) \ + PINCTRL_PINGROUP(#id, id##_pins, ARRAY_SIZE(id##_pins)) + +#define PINCTRL_FUNC_DESC(id) \ + { \ + .desc = { \ + .func = { \ + .name = #id, \ + .groups = id##_groups, \ + .ngroups = ARRAY_SIZE(id##_groups), \ + } \ + }, \ + .groups = id##_func_group, \ + .group_size = ARRAY_SIZE(id##_func_group), \ + } + +#define PINCTRL_CONF_DESC(p, offset, mask) \ + { \ + .pin = p, \ + .reg = { offset, mask }, \ + } + +/* MUX */ +#define REG_GPIO_2ND_I2C_MODE 0x0214 +#define GPIO_MDC_IO_MASTER_MODE_MODE BIT(14) +#define GPIO_I2C_MASTER_MODE_MODE BIT(13) +#define GPIO_I2S_MODE_MASK BIT(12) +#define GPIO_I2C_SLAVE_MODE_MODE BIT(11) +#define GPIO_LAN3_LED1_MODE_MASK BIT(10) +#define GPIO_LAN3_LED0_MODE_MASK BIT(9) +#define GPIO_LAN2_LED1_MODE_MASK BIT(8) +#define GPIO_LAN2_LED0_MODE_MASK BIT(7) +#define GPIO_LAN1_LED1_MODE_MASK BIT(6) +#define GPIO_LAN1_LED0_MODE_MASK BIT(5) +#define GPIO_LAN0_LED1_MODE_MASK BIT(4) +#define GPIO_LAN0_LED0_MODE_MASK BIT(3) +#define PON_TOD_1PPS_MODE_MASK BIT(2) +#define GSW_TOD_1PPS_MODE_MASK BIT(1) +#define GPIO_2ND_I2C_MODE_MASK BIT(0) + +#define REG_GPIO_SPI_CS1_MODE 0x0218 +#define GPIO_PCM_SPI_CS4_MODE_MASK BIT(21) +#define GPIO_PCM_SPI_CS3_MODE_MASK BIT(20) +#define GPIO_PCM_SPI_CS2_MODE_P156_MASK BIT(19) +#define GPIO_PCM_SPI_CS2_MODE_P128_MASK BIT(18) +#define GPIO_PCM_SPI_CS1_MODE_MASK BIT(17) +#define GPIO_PCM_SPI_MODE_MASK BIT(16) +#define GPIO_PCM2_MODE_MASK BIT(13) +#define GPIO_PCM1_MODE_MASK BIT(12) +#define GPIO_PCM_INT_MODE_MASK BIT(9) +#define GPIO_PCM_RESET_MODE_MASK BIT(8) +#define GPIO_SPI_QUAD_MODE_MASK BIT(4) +#define GPIO_SPI_CS4_MODE_MASK BIT(3) +#define GPIO_SPI_CS3_MODE_MASK BIT(2) +#define GPIO_SPI_CS2_MODE_MASK BIT(1) +#define GPIO_SPI_CS1_MODE_MASK BIT(0) + +#define REG_GPIO_PON_MODE 0x021c +#define GPIO_PARALLEL_NAND_MODE_MASK BIT(14) +#define GPIO_SGMII_MDIO_MODE_MASK BIT(13) +#define GPIO_PCIE_RESET2_MASK BIT(12) +#define SIPO_RCLK_MODE_MASK BIT(11) +#define GPIO_PCIE_RESET1_MASK BIT(10) +#define GPIO_PCIE_RESET0_MASK BIT(9) +#define GPIO_UART5_MODE_MASK BIT(8) +#define GPIO_UART4_MODE_MASK BIT(7) +#define GPIO_HSUART_CTS_RTS_MODE_MASK BIT(6) +#define GPIO_HSUART_MODE_MASK BIT(5) +#define GPIO_UART2_CTS_RTS_MODE_MASK BIT(4) +#define GPIO_UART2_MODE_MASK BIT(3) +#define GPIO_SIPO_MODE_MASK BIT(2) +#define GPIO_EMMC_MODE_MASK BIT(1) +#define GPIO_PON_MODE_MASK BIT(0) + +#define REG_NPU_UART_EN 0x0224 +#define JTAG_UDI_EN_MASK BIT(4) +#define JTAG_DFD_EN_MASK BIT(3) + +/* LED MAP */ +#define REG_LAN_LED0_MAPPING 0x027c +#define REG_LAN_LED1_MAPPING 0x0280 + +#define LAN4_LED_MAPPING_MASK GENMASK(18, 16) +#define LAN4_PHY4_LED_MAP BIT(18) +#define LAN4_PHY2_LED_MAP BIT(17) +#define LAN4_PHY1_LED_MAP BIT(16) +#define LAN4_PHY0_LED_MAP 0 +#define LAN4_PHY3_LED_MAP GENMASK(17, 16) + +#define LAN3_LED_MAPPING_MASK GENMASK(14, 12) +#define LAN3_PHY4_LED_MAP BIT(14) +#define LAN3_PHY2_LED_MAP BIT(13) +#define LAN3_PHY1_LED_MAP BIT(12) +#define LAN3_PHY0_LED_MAP 0 +#define LAN3_PHY3_LED_MAP GENMASK(13, 12) + +#define LAN2_LED_MAPPING_MASK GENMASK(10, 8) +#define LAN2_PHY4_LED_MAP BIT(12) +#define LAN2_PHY2_LED_MAP BIT(11) +#define LAN2_PHY1_LED_MAP BIT(10) +#define LAN2_PHY0_LED_MAP 0 +#define LAN2_PHY3_LED_MAP GENMASK(11, 10) + +#define LAN1_LED_MAPPING_MASK GENMASK(6, 4) +#define LAN1_PHY4_LED_MAP BIT(6) +#define LAN1_PHY2_LED_MAP BIT(5) +#define LAN1_PHY1_LED_MAP BIT(4) +#define LAN1_PHY0_LED_MAP 0 +#define LAN1_PHY3_LED_MAP GENMASK(5, 4) + +#define LAN0_LED_MAPPING_MASK GENMASK(2, 0) +#define LAN0_PHY4_LED_MAP BIT(3) +#define LAN0_PHY2_LED_MAP BIT(2) +#define LAN0_PHY1_LED_MAP BIT(1) +#define LAN0_PHY0_LED_MAP 0 +#define LAN0_PHY3_LED_MAP GENMASK(2, 1) + +/* CONF */ +#define REG_I2C_SDA_E2 0x001c +#define SPI_MISO_E2_MASK BIT(14) +#define SPI_MOSI_E2_MASK BIT(13) +#define SPI_CLK_E2_MASK BIT(12) +#define SPI_CS0_E2_MASK BIT(11) +#define PCIE2_RESET_E2_MASK BIT(10) +#define PCIE1_RESET_E2_MASK BIT(9) +#define PCIE0_RESET_E2_MASK BIT(8) +#define UART1_RXD_E2_MASK BIT(3) +#define UART1_TXD_E2_MASK BIT(2) +#define I2C_SCL_E2_MASK BIT(1) +#define I2C_SDA_E2_MASK BIT(0) + +#define REG_I2C_SDA_E4 0x0020 +#define SPI_MISO_E4_MASK BIT(14) +#define SPI_MOSI_E4_MASK BIT(13) +#define SPI_CLK_E4_MASK BIT(12) +#define SPI_CS0_E4_MASK BIT(11) +#define PCIE2_RESET_E4_MASK BIT(10) +#define PCIE1_RESET_E4_MASK BIT(9) +#define PCIE0_RESET_E4_MASK BIT(8) +#define UART1_RXD_E4_MASK BIT(3) +#define UART1_TXD_E4_MASK BIT(2) +#define I2C_SCL_E4_MASK BIT(1) +#define I2C_SDA_E4_MASK BIT(0) + +#define REG_GPIO_L_E2 0x0024 +#define REG_GPIO_L_E4 0x0028 +#define REG_GPIO_H_E2 0x002c +#define REG_GPIO_H_E4 0x0030 + +#define REG_I2C_SDA_PU 0x0044 +#define SPI_MISO_PU_MASK BIT(14) +#define SPI_MOSI_PU_MASK BIT(13) +#define SPI_CLK_PU_MASK BIT(12) +#define SPI_CS0_PU_MASK BIT(11) +#define PCIE2_RESET_PU_MASK BIT(10) +#define PCIE1_RESET_PU_MASK BIT(9) +#define PCIE0_RESET_PU_MASK BIT(8) +#define UART1_RXD_PU_MASK BIT(3) +#define UART1_TXD_PU_MASK BIT(2) +#define I2C_SCL_PU_MASK BIT(1) +#define I2C_SDA_PU_MASK BIT(0) + +#define REG_I2C_SDA_PD 0x0048 +#define SPI_MISO_PD_MASK BIT(14) +#define SPI_MOSI_PD_MASK BIT(13) +#define SPI_CLK_PD_MASK BIT(12) +#define SPI_CS0_PD_MASK BIT(11) +#define PCIE2_RESET_PD_MASK BIT(10) +#define PCIE1_RESET_PD_MASK BIT(9) +#define PCIE0_RESET_PD_MASK BIT(8) +#define UART1_RXD_PD_MASK BIT(3) +#define UART1_TXD_PD_MASK BIT(2) +#define I2C_SCL_PD_MASK BIT(1) +#define I2C_SDA_PD_MASK BIT(0) + +#define REG_GPIO_L_PU 0x004c +#define REG_GPIO_L_PD 0x0050 +#define REG_GPIO_H_PU 0x0054 +#define REG_GPIO_H_PD 0x0058 + +#define REG_PCIE_RESET_OD 0x018c +#define PCIE2_RESET_OD_MASK BIT(2) +#define PCIE1_RESET_OD_MASK BIT(1) +#define PCIE0_RESET_OD_MASK BIT(0) + +/* GPIOs */ +#define REG_GPIO_CTRL 0x0000 +#define REG_GPIO_DATA 0x0004 +#define REG_GPIO_INT 0x0008 +#define REG_GPIO_INT_EDGE 0x000c +#define REG_GPIO_INT_LEVEL 0x0010 +#define REG_GPIO_OE 0x0014 +#define REG_GPIO_CTRL1 0x0020 + +/* PWM MODE CONF */ +#define REG_GPIO_FLASH_MODE_CFG 0x0034 +#define GPIO15_FLASH_MODE_CFG BIT(15) +#define GPIO14_FLASH_MODE_CFG BIT(14) +#define GPIO13_FLASH_MODE_CFG BIT(13) +#define GPIO12_FLASH_MODE_CFG BIT(12) +#define GPIO11_FLASH_MODE_CFG BIT(11) +#define GPIO10_FLASH_MODE_CFG BIT(10) +#define GPIO9_FLASH_MODE_CFG BIT(9) +#define GPIO8_FLASH_MODE_CFG BIT(8) +#define GPIO7_FLASH_MODE_CFG BIT(7) +#define GPIO6_FLASH_MODE_CFG BIT(6) +#define GPIO5_FLASH_MODE_CFG BIT(5) +#define GPIO4_FLASH_MODE_CFG BIT(4) +#define GPIO3_FLASH_MODE_CFG BIT(3) +#define GPIO2_FLASH_MODE_CFG BIT(2) +#define GPIO1_FLASH_MODE_CFG BIT(1) +#define GPIO0_FLASH_MODE_CFG BIT(0) + +#define REG_GPIO_CTRL2 0x0060 +#define REG_GPIO_CTRL3 0x0064 + +/* PWM MODE CONF EXT */ +#define REG_GPIO_FLASH_MODE_CFG_EXT 0x0068 +#define GPIO51_FLASH_MODE_CFG BIT(31) +#define GPIO50_FLASH_MODE_CFG BIT(30) +#define GPIO49_FLASH_MODE_CFG BIT(29) +#define GPIO48_FLASH_MODE_CFG BIT(28) +#define GPIO47_FLASH_MODE_CFG BIT(27) +#define GPIO46_FLASH_MODE_CFG BIT(26) +#define GPIO45_FLASH_MODE_CFG BIT(25) +#define GPIO44_FLASH_MODE_CFG BIT(24) +#define GPIO43_FLASH_MODE_CFG BIT(23) +#define GPIO42_FLASH_MODE_CFG BIT(22) +#define GPIO41_FLASH_MODE_CFG BIT(21) +#define GPIO40_FLASH_MODE_CFG BIT(20) +#define GPIO39_FLASH_MODE_CFG BIT(19) +#define GPIO38_FLASH_MODE_CFG BIT(18) +#define GPIO37_FLASH_MODE_CFG BIT(17) +#define GPIO36_FLASH_MODE_CFG BIT(16) +#define GPIO31_FLASH_MODE_CFG BIT(15) +#define GPIO30_FLASH_MODE_CFG BIT(14) +#define GPIO29_FLASH_MODE_CFG BIT(13) +#define GPIO28_FLASH_MODE_CFG BIT(12) +#define GPIO27_FLASH_MODE_CFG BIT(11) +#define GPIO26_FLASH_MODE_CFG BIT(10) +#define GPIO25_FLASH_MODE_CFG BIT(9) +#define GPIO24_FLASH_MODE_CFG BIT(8) +#define GPIO23_FLASH_MODE_CFG BIT(7) +#define GPIO22_FLASH_MODE_CFG BIT(6) +#define GPIO21_FLASH_MODE_CFG BIT(5) +#define GPIO20_FLASH_MODE_CFG BIT(4) +#define GPIO19_FLASH_MODE_CFG BIT(3) +#define GPIO18_FLASH_MODE_CFG BIT(2) +#define GPIO17_FLASH_MODE_CFG BIT(1) +#define GPIO16_FLASH_MODE_CFG BIT(0) + +#define REG_GPIO_DATA1 0x0070 +#define REG_GPIO_OE1 0x0078 +#define REG_GPIO_INT1 0x007c +#define REG_GPIO_INT_EDGE1 0x0080 +#define REG_GPIO_INT_EDGE2 0x0084 +#define REG_GPIO_INT_EDGE3 0x0088 +#define REG_GPIO_INT_LEVEL1 0x008c +#define REG_GPIO_INT_LEVEL2 0x0090 +#define REG_GPIO_INT_LEVEL3 0x0094 + +#define AIROHA_NUM_GPIOS 64 +#define AIROHA_GPIO_BANK_SIZE (AIROHA_NUM_GPIOS / 2) +#define AIROHA_REG_GPIOCTRL_NUM_GPIO (AIROHA_NUM_GPIOS / 4) + +struct airoha_pinctrl_reg { + u32 offset; + u32 mask; +}; + +enum airoha_pinctrl_mux_func { + AIROHA_FUNC_MUX, + AIROHA_FUNC_PWM_MUX, + AIROHA_FUNC_PWM_EXT_MUX, +}; + +struct airoha_pinctrl_func_group { + const char *name; + struct { + enum airoha_pinctrl_mux_func mux; + u32 offset; + u32 mask; + u32 val; + } regmap[2]; + int regmap_size; +}; + +struct airoha_pinctrl_func { + const struct function_desc desc; + const struct airoha_pinctrl_func_group *groups; + u8 group_size; +}; + +struct airoha_pinctrl_conf { + u32 pin; + struct airoha_pinctrl_reg reg; +}; + +struct airoha_pinctrl_gpiochip { + struct gpio_chip chip; + + void __iomem *data[2]; + void __iomem *dir[4]; + void __iomem *out[2]; + + /* protect concurrent register accesses */ + spinlock_t lock; + void __iomem *status[2]; + void __iomem *level[4]; + void __iomem *edge[4]; + + u32 irq_type[AIROHA_NUM_GPIOS]; +}; + +struct airoha_pinctrl { + struct pinctrl_dev *ctrl; + + struct regmap *chip_scu; + /* protect concurrent register accesses */ + struct mutex mutex; + void __iomem *base; + + struct airoha_pinctrl_gpiochip gpiochip; +}; + +static struct pinctrl_pin_desc airoha_pinctrl_pins[] = { + PINCTRL_PIN(0, "uart1_txd"), + PINCTRL_PIN(1, "uart1_rxd"), + PINCTRL_PIN(2, "i2c_scl"), + PINCTRL_PIN(3, "i2c_sda"), + PINCTRL_PIN(4, "spi_cs0"), + PINCTRL_PIN(5, "spi_clk"), + PINCTRL_PIN(6, "spi_mosi"), + PINCTRL_PIN(7, "spi_miso"), + PINCTRL_PIN(13, "gpio0"), + PINCTRL_PIN(14, "gpio1"), + PINCTRL_PIN(15, "gpio2"), + PINCTRL_PIN(16, "gpio3"), + PINCTRL_PIN(17, "gpio4"), + PINCTRL_PIN(18, "gpio5"), + PINCTRL_PIN(19, "gpio6"), + PINCTRL_PIN(20, "gpio7"), + PINCTRL_PIN(21, "gpio8"), + PINCTRL_PIN(22, "gpio9"), + PINCTRL_PIN(23, "gpio10"), + PINCTRL_PIN(24, "gpio11"), + PINCTRL_PIN(25, "gpio12"), + PINCTRL_PIN(26, "gpio13"), + PINCTRL_PIN(27, "gpio14"), + PINCTRL_PIN(28, "gpio15"), + PINCTRL_PIN(29, "gpio16"), + PINCTRL_PIN(30, "gpio17"), + PINCTRL_PIN(31, "gpio18"), + PINCTRL_PIN(32, "gpio19"), + PINCTRL_PIN(33, "gpio20"), + PINCTRL_PIN(34, "gpio21"), + PINCTRL_PIN(35, "gpio22"), + PINCTRL_PIN(36, "gpio23"), + PINCTRL_PIN(37, "gpio24"), + PINCTRL_PIN(38, "gpio25"), + PINCTRL_PIN(39, "gpio26"), + PINCTRL_PIN(40, "gpio27"), + PINCTRL_PIN(41, "gpio28"), + PINCTRL_PIN(42, "gpio29"), + PINCTRL_PIN(43, "gpio30"), + PINCTRL_PIN(44, "gpio31"), + PINCTRL_PIN(45, "gpio32"), + PINCTRL_PIN(46, "gpio33"), + PINCTRL_PIN(47, "gpio34"), + PINCTRL_PIN(48, "gpio35"), + PINCTRL_PIN(49, "gpio36"), + PINCTRL_PIN(50, "gpio37"), + PINCTRL_PIN(51, "gpio38"), + PINCTRL_PIN(52, "gpio39"), + PINCTRL_PIN(53, "gpio40"), + PINCTRL_PIN(54, "gpio41"), + PINCTRL_PIN(55, "gpio42"), + PINCTRL_PIN(56, "gpio43"), + PINCTRL_PIN(57, "gpio44"), + PINCTRL_PIN(58, "gpio45"), + PINCTRL_PIN(59, "gpio46"), + PINCTRL_PIN(61, "pcie_reset0"), + PINCTRL_PIN(62, "pcie_reset1"), + PINCTRL_PIN(63, "pcie_reset2"), +}; + +static const int pon_pins[] = { 49, 50, 51, 52, 53, 54 }; +static const int pon_tod_1pps_pins[] = { 46 }; +static const int gsw_tod_1pps_pins[] = { 46 }; +static const int sipo_pins[] = { 16, 17 }; +static const int sipo_rclk_pins[] = { 16, 17, 43 }; +static const int mdio_pins[] = { 14, 15 }; +static const int uart2_pins[] = { 48, 55 }; +static const int uart2_cts_rts_pins[] = { 46, 47 }; +static const int hsuart_pins[] = { 28, 29 }; +static const int hsuart_cts_rts_pins[] = { 26, 27 }; +static const int uart4_pins[] = { 38, 39 }; +static const int uart5_pins[] = { 18, 19 }; +static const int i2c0_pins[] = { 2, 3 }; +static const int i2c1_pins[] = { 14, 15 }; +static const int jtag_udi_pins[] = { 16, 17, 18, 19, 20 }; +static const int jtag_dfd_pins[] = { 16, 17, 18, 19, 20 }; +static const int i2s_pins[] = { 26, 27, 28, 29 }; +static const int pcm1_pins[] = { 22, 23, 24, 25 }; +static const int pcm2_pins[] = { 18, 19, 20, 21 }; +static const int spi_quad_pins[] = { 32, 33 }; +static const int spi_pins[] = { 4, 5, 6, 7 }; +static const int spi_cs1_pins[] = { 34 }; +static const int pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 }; +static const int pcm_spi_int_pins[] = { 14 }; +static const int pcm_spi_rst_pins[] = { 15 }; +static const int pcm_spi_cs1_pins[] = { 43 }; +static const int pcm_spi_cs2_pins[] = { 40 }; +static const int pcm_spi_cs2_p128_pins[] = { 40 }; +static const int pcm_spi_cs2_p156_pins[] = { 40 }; +static const int pcm_spi_cs3_pins[] = { 41 }; +static const int pcm_spi_cs4_pins[] = { 42 }; +static const int emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 }; +static const int pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }; +static const int gpio0_pins[] = { 13 }; +static const int gpio1_pins[] = { 14 }; +static const int gpio2_pins[] = { 15 }; +static const int gpio3_pins[] = { 16 }; +static const int gpio4_pins[] = { 17 }; +static const int gpio5_pins[] = { 18 }; +static const int gpio6_pins[] = { 19 }; +static const int gpio7_pins[] = { 20 }; +static const int gpio8_pins[] = { 21 }; +static const int gpio9_pins[] = { 22 }; +static const int gpio10_pins[] = { 23 }; +static const int gpio11_pins[] = { 24 }; +static const int gpio12_pins[] = { 25 }; +static const int gpio13_pins[] = { 26 }; +static const int gpio14_pins[] = { 27 }; +static const int gpio15_pins[] = { 28 }; +static const int gpio16_pins[] = { 29 }; +static const int gpio17_pins[] = { 30 }; +static const int gpio18_pins[] = { 31 }; +static const int gpio19_pins[] = { 32 }; +static const int gpio20_pins[] = { 33 }; +static const int gpio21_pins[] = { 34 }; +static const int gpio22_pins[] = { 35 }; +static const int gpio23_pins[] = { 36 }; +static const int gpio24_pins[] = { 37 }; +static const int gpio25_pins[] = { 38 }; +static const int gpio26_pins[] = { 39 }; +static const int gpio27_pins[] = { 40 }; +static const int gpio28_pins[] = { 41 }; +static const int gpio29_pins[] = { 42 }; +static const int gpio30_pins[] = { 43 }; +static const int gpio31_pins[] = { 44 }; +static const int gpio33_pins[] = { 46 }; +static const int gpio34_pins[] = { 47 }; +static const int gpio35_pins[] = { 48 }; +static const int gpio36_pins[] = { 49 }; +static const int gpio37_pins[] = { 50 }; +static const int gpio38_pins[] = { 51 }; +static const int gpio39_pins[] = { 52 }; +static const int gpio40_pins[] = { 53 }; +static const int gpio41_pins[] = { 54 }; +static const int gpio42_pins[] = { 55 }; +static const int gpio43_pins[] = { 56 }; +static const int gpio44_pins[] = { 57 }; +static const int gpio45_pins[] = { 58 }; +static const int gpio46_pins[] = { 59 }; +static const int pcie_reset0_pins[] = { 61 }; +static const int pcie_reset1_pins[] = { 62 }; +static const int pcie_reset2_pins[] = { 63 }; + +static const struct pingroup airoha_pinctrl_groups[] = { + PINCTRL_PIN_GROUP(pon), + PINCTRL_PIN_GROUP(pon_tod_1pps), + PINCTRL_PIN_GROUP(gsw_tod_1pps), + PINCTRL_PIN_GROUP(sipo), + PINCTRL_PIN_GROUP(sipo_rclk), + PINCTRL_PIN_GROUP(mdio), + PINCTRL_PIN_GROUP(uart2), + PINCTRL_PIN_GROUP(uart2_cts_rts), + PINCTRL_PIN_GROUP(hsuart), + PINCTRL_PIN_GROUP(hsuart_cts_rts), + PINCTRL_PIN_GROUP(uart4), + PINCTRL_PIN_GROUP(uart5), + PINCTRL_PIN_GROUP(i2c0), + PINCTRL_PIN_GROUP(i2c1), + PINCTRL_PIN_GROUP(jtag_udi), + PINCTRL_PIN_GROUP(jtag_dfd), + PINCTRL_PIN_GROUP(i2s), + PINCTRL_PIN_GROUP(pcm1), + PINCTRL_PIN_GROUP(pcm2), + PINCTRL_PIN_GROUP(spi), + PINCTRL_PIN_GROUP(spi_quad), + PINCTRL_PIN_GROUP(spi_cs1), + PINCTRL_PIN_GROUP(pcm_spi), + PINCTRL_PIN_GROUP(pcm_spi_int), + PINCTRL_PIN_GROUP(pcm_spi_rst), + PINCTRL_PIN_GROUP(pcm_spi_cs1), + PINCTRL_PIN_GROUP(pcm_spi_cs2_p128), + PINCTRL_PIN_GROUP(pcm_spi_cs2_p156), + PINCTRL_PIN_GROUP(pcm_spi_cs2), + PINCTRL_PIN_GROUP(pcm_spi_cs3), + PINCTRL_PIN_GROUP(pcm_spi_cs4), + PINCTRL_PIN_GROUP(emmc), + PINCTRL_PIN_GROUP(pnand), + PINCTRL_PIN_GROUP(gpio0), + PINCTRL_PIN_GROUP(gpio1), + PINCTRL_PIN_GROUP(gpio2), + PINCTRL_PIN_GROUP(gpio3), + PINCTRL_PIN_GROUP(gpio4), + PINCTRL_PIN_GROUP(gpio5), + PINCTRL_PIN_GROUP(gpio6), + PINCTRL_PIN_GROUP(gpio7), + PINCTRL_PIN_GROUP(gpio8), + PINCTRL_PIN_GROUP(gpio9), + PINCTRL_PIN_GROUP(gpio10), + PINCTRL_PIN_GROUP(gpio11), + PINCTRL_PIN_GROUP(gpio12), + PINCTRL_PIN_GROUP(gpio13), + PINCTRL_PIN_GROUP(gpio14), + PINCTRL_PIN_GROUP(gpio15), + PINCTRL_PIN_GROUP(gpio16), + PINCTRL_PIN_GROUP(gpio17), + PINCTRL_PIN_GROUP(gpio18), + PINCTRL_PIN_GROUP(gpio19), + PINCTRL_PIN_GROUP(gpio20), + PINCTRL_PIN_GROUP(gpio21), + PINCTRL_PIN_GROUP(gpio22), + PINCTRL_PIN_GROUP(gpio23), + PINCTRL_PIN_GROUP(gpio24), + PINCTRL_PIN_GROUP(gpio25), + PINCTRL_PIN_GROUP(gpio26), + PINCTRL_PIN_GROUP(gpio27), + PINCTRL_PIN_GROUP(gpio28), + PINCTRL_PIN_GROUP(gpio29), + PINCTRL_PIN_GROUP(gpio30), + PINCTRL_PIN_GROUP(gpio31), + PINCTRL_PIN_GROUP(gpio33), + PINCTRL_PIN_GROUP(gpio34), + PINCTRL_PIN_GROUP(gpio35), + PINCTRL_PIN_GROUP(gpio36), + PINCTRL_PIN_GROUP(gpio37), + PINCTRL_PIN_GROUP(gpio38), + PINCTRL_PIN_GROUP(gpio39), + PINCTRL_PIN_GROUP(gpio40), + PINCTRL_PIN_GROUP(gpio41), + PINCTRL_PIN_GROUP(gpio42), + PINCTRL_PIN_GROUP(gpio43), + PINCTRL_PIN_GROUP(gpio44), + PINCTRL_PIN_GROUP(gpio45), + PINCTRL_PIN_GROUP(gpio46), + PINCTRL_PIN_GROUP(pcie_reset0), + PINCTRL_PIN_GROUP(pcie_reset1), + PINCTRL_PIN_GROUP(pcie_reset2), +}; + +static const char *const pon_groups[] = { "pon" }; +static const char *const tod_1pps_groups[] = { "pon_tod_1pps", "gsw_tod_1pps" }; +static const char *const sipo_groups[] = { "sipo", "sipo_rclk" }; +static const char *const mdio_groups[] = { "mdio" }; +static const char *const uart_groups[] = { "uart2", "uart2_cts_rts", "hsuart", + "hsuart_cts_rts", "uart4", + "uart5" }; +static const char *const i2c_groups[] = { "i2c1" }; +static const char *const jtag_groups[] = { "jtag_udi", "jtag_dfd" }; +static const char *const pcm_groups[] = { "pcm1", "pcm2" }; +static const char *const spi_groups[] = { "spi_quad", "spi_cs1" }; +static const char *const pcm_spi_groups[] = { "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" }; +static const char *const i2s_groups[] = { "i2s" }; +static const char *const emmc_groups[] = { "emmc" }; +static const char *const pnand_groups[] = { "pnand" }; +static const char *const pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1", + "pcie_reset2" }; +static const char *const pwm_groups[] = { "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" }; +static const char *const phy1_led0_groups[] = { "gpio33", "gpio34", + "gpio35", "gpio42" }; +static const char *const phy2_led0_groups[] = { "gpio33", "gpio34", + "gpio35", "gpio42" }; +static const char *const phy3_led0_groups[] = { "gpio33", "gpio34", + "gpio35", "gpio42" }; +static const char *const phy4_led0_groups[] = { "gpio33", "gpio34", + "gpio35", "gpio42" }; +static const char *const phy1_led1_groups[] = { "gpio43", "gpio44", + "gpio45", "gpio46" }; +static const char *const phy2_led1_groups[] = { "gpio43", "gpio44", + "gpio45", "gpio46" }; +static const char *const phy3_led1_groups[] = { "gpio43", "gpio44", + "gpio45", "gpio46" }; +static const char *const phy4_led1_groups[] = { "gpio43", "gpio44", + "gpio45", "gpio46" }; + +static const struct airoha_pinctrl_func_group pon_func_group[] = { + { + .name = "pon", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_PON_MODE_MASK, + GPIO_PON_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group tod_1pps_func_group[] = { + { + .name = "pon_tod_1pps", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + PON_TOD_1PPS_MODE_MASK, + PON_TOD_1PPS_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "gsw_tod_1pps", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GSW_TOD_1PPS_MODE_MASK, + GSW_TOD_1PPS_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group sipo_func_group[] = { + { + .name = "sipo", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK, + GPIO_SIPO_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "sipo_rclk", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK, + GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group mdio_func_group[] = { + { + .name = "mdio", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_SGMII_MDIO_MODE_MASK, + GPIO_SGMII_MDIO_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_MDC_IO_MASTER_MODE_MODE, + GPIO_MDC_IO_MASTER_MODE_MODE + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group uart_func_group[] = { + { + .name = "uart2", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_UART2_MODE_MASK, + GPIO_UART2_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "uart2_cts_rts", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_UART2_MODE_MASK | GPIO_UART2_CTS_RTS_MODE_MASK, + GPIO_UART2_MODE_MASK | GPIO_UART2_CTS_RTS_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "hsuart", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK, + GPIO_HSUART_MODE_MASK + }, + .regmap_size = 1, + }, + { + .name = "hsuart_cts_rts", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK, + GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "uart4", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_UART4_MODE_MASK, + GPIO_UART4_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "uart5", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_UART5_MODE_MASK, + GPIO_UART5_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group i2c_func_group[] = { + { + .name = "i2c1", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_2ND_I2C_MODE_MASK, + GPIO_2ND_I2C_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group jtag_func_group[] = { + { + .name = "jtag_udi", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_NPU_UART_EN, + JTAG_UDI_EN_MASK, + JTAG_UDI_EN_MASK + }, + .regmap_size = 1, + }, { + .name = "jtag_dfd", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_NPU_UART_EN, + JTAG_DFD_EN_MASK, + JTAG_DFD_EN_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group pcm_func_group[] = { + { + .name = "pcm1", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM1_MODE_MASK, + GPIO_PCM1_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm2", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM2_MODE_MASK, + GPIO_PCM2_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group spi_func_group[] = { + { + .name = "spi_quad", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_SPI_QUAD_MODE_MASK, + GPIO_SPI_QUAD_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "spi_cs1", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_SPI_CS1_MODE_MASK, + GPIO_SPI_CS1_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "spi_cs2", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_SPI_CS2_MODE_MASK, + GPIO_SPI_CS2_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "spi_cs3", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_SPI_CS3_MODE_MASK, + GPIO_SPI_CS3_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "spi_cs4", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_SPI_CS4_MODE_MASK, + GPIO_SPI_CS4_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group pcm_spi_func_group[] = { + { + .name = "pcm_spi", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_MODE_MASK, + GPIO_PCM_SPI_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_int", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_INT_MODE_MASK, + GPIO_PCM_INT_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_rst", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_RESET_MODE_MASK, + GPIO_PCM_RESET_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs1", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS1_MODE_MASK, + GPIO_PCM_SPI_CS1_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs2_p128", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS2_MODE_P128_MASK, + GPIO_PCM_SPI_CS2_MODE_P128_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs2_p156", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS2_MODE_P156_MASK, + GPIO_PCM_SPI_CS2_MODE_P156_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs3", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS3_MODE_MASK, + GPIO_PCM_SPI_CS3_MODE_MASK + }, + .regmap_size = 1, + }, { + .name = "pcm_spi_cs4", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_SPI_CS1_MODE, + GPIO_PCM_SPI_CS4_MODE_MASK, + GPIO_PCM_SPI_CS4_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group i2s_func_group[] = { + { + .name = "i2s", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_I2S_MODE_MASK, + GPIO_I2S_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group emmc_func_group[] = { + { + .name = "emmc", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_EMMC_MODE_MASK, + GPIO_EMMC_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group pnand_func_group[] = { + { + .name = "pnand", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_PARALLEL_NAND_MODE_MASK, + GPIO_PARALLEL_NAND_MODE_MASK + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group pcie_reset_func_group[] = { + { + .name = "pcie_reset0", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_PCIE_RESET0_MASK, + GPIO_PCIE_RESET0_MASK + }, + .regmap_size = 1, + }, { + .name = "pcie_reset1", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_PCIE_RESET1_MASK, + GPIO_PCIE_RESET1_MASK + }, + .regmap_size = 1, + }, { + .name = "pcie_reset2", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_PON_MODE, + GPIO_PCIE_RESET2_MASK, + GPIO_PCIE_RESET2_MASK + }, + .regmap_size = 1, + }, +}; + +/* PWM */ +static const struct airoha_pinctrl_func_group pwm_func_group[] = { + { + .name = "gpio0", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO0_FLASH_MODE_CFG, + GPIO0_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio1", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO1_FLASH_MODE_CFG, + GPIO1_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio2", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO2_FLASH_MODE_CFG, + GPIO2_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio3", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO3_FLASH_MODE_CFG, + GPIO3_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio4", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO4_FLASH_MODE_CFG, + GPIO4_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio5", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO5_FLASH_MODE_CFG, + GPIO5_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio6", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO6_FLASH_MODE_CFG, + GPIO6_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio7", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO7_FLASH_MODE_CFG, + GPIO7_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio8", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO8_FLASH_MODE_CFG, + GPIO8_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio9", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO9_FLASH_MODE_CFG, + GPIO9_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio10", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO10_FLASH_MODE_CFG, + GPIO10_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio11", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO11_FLASH_MODE_CFG, + GPIO11_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio12", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO12_FLASH_MODE_CFG, + GPIO12_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio13", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO13_FLASH_MODE_CFG, + GPIO13_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio14", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO14_FLASH_MODE_CFG, + GPIO14_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio15", + .regmap[0] = { + AIROHA_FUNC_PWM_MUX, + REG_GPIO_FLASH_MODE_CFG, + GPIO15_FLASH_MODE_CFG, + GPIO15_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio16", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO16_FLASH_MODE_CFG, + GPIO16_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio17", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO17_FLASH_MODE_CFG, + GPIO17_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio18", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO18_FLASH_MODE_CFG, + GPIO18_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio19", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO19_FLASH_MODE_CFG, + GPIO19_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio20", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO20_FLASH_MODE_CFG, + GPIO20_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio21", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO21_FLASH_MODE_CFG, + GPIO21_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio22", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO22_FLASH_MODE_CFG, + GPIO22_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio23", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO23_FLASH_MODE_CFG, + GPIO23_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio24", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO24_FLASH_MODE_CFG, + GPIO24_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio25", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO25_FLASH_MODE_CFG, + GPIO25_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio26", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO26_FLASH_MODE_CFG, + GPIO26_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio27", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO27_FLASH_MODE_CFG, + GPIO27_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio28", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO28_FLASH_MODE_CFG, + GPIO28_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio29", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO29_FLASH_MODE_CFG, + GPIO29_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio30", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO30_FLASH_MODE_CFG, + GPIO30_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio31", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO31_FLASH_MODE_CFG, + GPIO31_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio36", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO36_FLASH_MODE_CFG, + GPIO36_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio37", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO37_FLASH_MODE_CFG, + GPIO37_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio38", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO38_FLASH_MODE_CFG, + GPIO38_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio39", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO39_FLASH_MODE_CFG, + GPIO39_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio40", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO40_FLASH_MODE_CFG, + GPIO40_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio41", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO41_FLASH_MODE_CFG, + GPIO41_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio42", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO42_FLASH_MODE_CFG, + GPIO42_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio43", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO43_FLASH_MODE_CFG, + GPIO43_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio44", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO44_FLASH_MODE_CFG, + GPIO44_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio45", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO45_FLASH_MODE_CFG, + GPIO45_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio46", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO46_FLASH_MODE_CFG, + GPIO46_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, { + .name = "gpio47", + .regmap[0] = { + AIROHA_FUNC_PWM_EXT_MUX, + REG_GPIO_FLASH_MODE_CFG_EXT, + GPIO47_FLASH_MODE_CFG, + GPIO47_FLASH_MODE_CFG + }, + .regmap_size = 1, + }, +}; + +static const struct airoha_pinctrl_func_group phy1_led0_func_group[] = { + { + .name = "gpio33", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED0_MODE_MASK, + GPIO_LAN0_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY1_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio34", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED0_MODE_MASK, + GPIO_LAN1_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY1_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio35", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED0_MODE_MASK, + GPIO_LAN2_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY1_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio42", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY1_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group phy2_led0_func_group[] = { + { + .name = "gpio33", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED0_MODE_MASK, + GPIO_LAN0_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY2_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio34", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED0_MODE_MASK, + GPIO_LAN1_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY2_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio35", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED0_MODE_MASK, + GPIO_LAN2_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY2_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio42", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY2_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group phy3_led0_func_group[] = { + { + .name = "gpio33", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED0_MODE_MASK, + GPIO_LAN0_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY3_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio34", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED0_MODE_MASK, + GPIO_LAN1_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY3_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio35", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED0_MODE_MASK, + GPIO_LAN2_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY3_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio42", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY3_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group phy4_led0_func_group[] = { + { + .name = "gpio33", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED0_MODE_MASK, + GPIO_LAN0_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY4_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio34", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED0_MODE_MASK, + GPIO_LAN1_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY4_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio35", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED0_MODE_MASK, + GPIO_LAN2_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY4_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio42", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY4_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group phy1_led1_func_group[] = { + { + .name = "gpio43", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED1_MODE_MASK, + GPIO_LAN0_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY1_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio44", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED1_MODE_MASK, + GPIO_LAN1_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY1_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio45", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED1_MODE_MASK, + GPIO_LAN2_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY1_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio46", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY1_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group phy2_led1_func_group[] = { + { + .name = "gpio43", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED1_MODE_MASK, + GPIO_LAN0_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY2_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio44", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED1_MODE_MASK, + GPIO_LAN1_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY2_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio45", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED1_MODE_MASK, + GPIO_LAN2_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY2_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio46", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY2_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group phy3_led1_func_group[] = { + { + .name = "gpio43", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED1_MODE_MASK, + GPIO_LAN0_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY3_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio44", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED1_MODE_MASK, + GPIO_LAN1_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY3_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio45", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED1_MODE_MASK, + GPIO_LAN2_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY3_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio46", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY3_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = { + { + .name = "gpio43", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN0_LED1_MODE_MASK, + GPIO_LAN0_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN1_LED_MAPPING_MASK, + LAN1_PHY4_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio44", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN1_LED1_MODE_MASK, + GPIO_LAN1_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN2_LED_MAPPING_MASK, + LAN2_PHY4_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio45", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN2_LED1_MODE_MASK, + GPIO_LAN2_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN3_LED_MAPPING_MASK, + LAN3_PHY4_LED_MAP + }, + .regmap_size = 2, + }, { + .name = "gpio46", + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_LAN3_LED0_MODE_MASK, + GPIO_LAN3_LED0_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, + LAN4_LED_MAPPING_MASK, + LAN4_PHY4_LED_MAP + }, + .regmap_size = 2, + }, +}; + +static const struct airoha_pinctrl_func airoha_pinctrl_funcs[] = { + PINCTRL_FUNC_DESC(pon), + PINCTRL_FUNC_DESC(tod_1pps), + PINCTRL_FUNC_DESC(sipo), + PINCTRL_FUNC_DESC(mdio), + PINCTRL_FUNC_DESC(uart), + PINCTRL_FUNC_DESC(i2c), + PINCTRL_FUNC_DESC(jtag), + PINCTRL_FUNC_DESC(pcm), + PINCTRL_FUNC_DESC(spi), + PINCTRL_FUNC_DESC(pcm_spi), + PINCTRL_FUNC_DESC(i2s), + PINCTRL_FUNC_DESC(emmc), + PINCTRL_FUNC_DESC(pnand), + PINCTRL_FUNC_DESC(pcie_reset), + PINCTRL_FUNC_DESC(pwm), + PINCTRL_FUNC_DESC(phy1_led0), + PINCTRL_FUNC_DESC(phy2_led0), + PINCTRL_FUNC_DESC(phy3_led0), + PINCTRL_FUNC_DESC(phy4_led0), + PINCTRL_FUNC_DESC(phy1_led1), + PINCTRL_FUNC_DESC(phy2_led1), + PINCTRL_FUNC_DESC(phy3_led1), + PINCTRL_FUNC_DESC(phy4_led1), +}; + +static const struct airoha_pinctrl_conf airoha_pinctrl_pullup_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_PU, I2C_SDA_PU_MASK), + PINCTRL_CONF_DESC(3, REG_I2C_SDA_PU, I2C_SCL_PU_MASK), + PINCTRL_CONF_DESC(4, REG_I2C_SDA_PU, SPI_CS0_PU_MASK), + PINCTRL_CONF_DESC(5, REG_I2C_SDA_PU, SPI_CLK_PU_MASK), + PINCTRL_CONF_DESC(6, REG_I2C_SDA_PU, SPI_MOSI_PU_MASK), + PINCTRL_CONF_DESC(7, REG_I2C_SDA_PU, SPI_MISO_PU_MASK), + PINCTRL_CONF_DESC(13, REG_GPIO_L_PU, BIT(0)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_PU, BIT(1)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_PU, BIT(2)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_PU, BIT(3)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_PU, BIT(4)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_PU, BIT(5)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_PU, BIT(6)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_PU, BIT(7)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_PU, BIT(8)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_PU, BIT(9)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_PU, BIT(10)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_PU, BIT(11)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_PU, BIT(12)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_PU, BIT(13)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_PU, BIT(14)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_PU, BIT(15)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_PU, BIT(16)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_PU, BIT(17)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_PU, BIT(18)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_PU, BIT(18)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_PU, BIT(20)), + PINCTRL_CONF_DESC(34, REG_GPIO_L_PU, BIT(21)), + PINCTRL_CONF_DESC(35, REG_GPIO_L_PU, BIT(22)), + PINCTRL_CONF_DESC(36, REG_GPIO_L_PU, BIT(23)), + PINCTRL_CONF_DESC(37, REG_GPIO_L_PU, BIT(24)), + PINCTRL_CONF_DESC(38, REG_GPIO_L_PU, BIT(25)), + PINCTRL_CONF_DESC(39, REG_GPIO_L_PU, BIT(26)), + PINCTRL_CONF_DESC(40, REG_GPIO_L_PU, BIT(27)), + PINCTRL_CONF_DESC(41, REG_GPIO_L_PU, BIT(28)), + PINCTRL_CONF_DESC(42, REG_GPIO_L_PU, BIT(29)), + PINCTRL_CONF_DESC(43, REG_GPIO_L_PU, BIT(30)), + PINCTRL_CONF_DESC(44, REG_GPIO_L_PU, BIT(31)), + PINCTRL_CONF_DESC(45, REG_GPIO_H_PU, BIT(0)), + PINCTRL_CONF_DESC(46, REG_GPIO_H_PU, BIT(1)), + PINCTRL_CONF_DESC(47, REG_GPIO_H_PU, BIT(2)), + PINCTRL_CONF_DESC(48, REG_GPIO_H_PU, BIT(3)), + PINCTRL_CONF_DESC(49, REG_GPIO_H_PU, BIT(4)), + PINCTRL_CONF_DESC(50, REG_GPIO_H_PU, BIT(5)), + PINCTRL_CONF_DESC(51, REG_GPIO_H_PU, BIT(6)), + PINCTRL_CONF_DESC(52, REG_GPIO_H_PU, BIT(7)), + PINCTRL_CONF_DESC(53, REG_GPIO_H_PU, BIT(8)), + PINCTRL_CONF_DESC(54, REG_GPIO_H_PU, BIT(9)), + PINCTRL_CONF_DESC(55, REG_GPIO_H_PU, BIT(10)), + PINCTRL_CONF_DESC(56, REG_GPIO_H_PU, BIT(11)), + PINCTRL_CONF_DESC(57, REG_GPIO_H_PU, BIT(12)), + PINCTRL_CONF_DESC(58, REG_GPIO_H_PU, BIT(13)), + PINCTRL_CONF_DESC(59, REG_GPIO_H_PU, BIT(14)), + PINCTRL_CONF_DESC(61, REG_I2C_SDA_PU, PCIE0_RESET_PU_MASK), + PINCTRL_CONF_DESC(62, REG_I2C_SDA_PU, PCIE1_RESET_PU_MASK), + PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK), +}; + +static const struct airoha_pinctrl_conf airoha_pinctrl_pulldown_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_PD, I2C_SDA_PD_MASK), + PINCTRL_CONF_DESC(3, REG_I2C_SDA_PD, I2C_SCL_PD_MASK), + PINCTRL_CONF_DESC(4, REG_I2C_SDA_PD, SPI_CS0_PD_MASK), + PINCTRL_CONF_DESC(5, REG_I2C_SDA_PD, SPI_CLK_PD_MASK), + PINCTRL_CONF_DESC(6, REG_I2C_SDA_PD, SPI_MOSI_PD_MASK), + PINCTRL_CONF_DESC(7, REG_I2C_SDA_PD, SPI_MISO_PD_MASK), + PINCTRL_CONF_DESC(13, REG_GPIO_L_PD, BIT(0)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_PD, BIT(1)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_PD, BIT(2)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_PD, BIT(3)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_PD, BIT(4)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_PD, BIT(5)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_PD, BIT(6)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_PD, BIT(7)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_PD, BIT(8)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_PD, BIT(9)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_PD, BIT(10)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_PD, BIT(11)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_PD, BIT(12)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_PD, BIT(13)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_PD, BIT(14)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_PD, BIT(15)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_PD, BIT(16)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_PD, BIT(17)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_PD, BIT(18)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_PD, BIT(18)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_PD, BIT(20)), + PINCTRL_CONF_DESC(34, REG_GPIO_L_PD, BIT(21)), + PINCTRL_CONF_DESC(35, REG_GPIO_L_PD, BIT(22)), + PINCTRL_CONF_DESC(36, REG_GPIO_L_PD, BIT(23)), + PINCTRL_CONF_DESC(37, REG_GPIO_L_PD, BIT(24)), + PINCTRL_CONF_DESC(38, REG_GPIO_L_PD, BIT(25)), + PINCTRL_CONF_DESC(39, REG_GPIO_L_PD, BIT(26)), + PINCTRL_CONF_DESC(40, REG_GPIO_L_PD, BIT(27)), + PINCTRL_CONF_DESC(41, REG_GPIO_L_PD, BIT(28)), + PINCTRL_CONF_DESC(42, REG_GPIO_L_PD, BIT(29)), + PINCTRL_CONF_DESC(43, REG_GPIO_L_PD, BIT(30)), + PINCTRL_CONF_DESC(44, REG_GPIO_L_PD, BIT(31)), + PINCTRL_CONF_DESC(45, REG_GPIO_H_PD, BIT(0)), + PINCTRL_CONF_DESC(46, REG_GPIO_H_PD, BIT(1)), + PINCTRL_CONF_DESC(47, REG_GPIO_H_PD, BIT(2)), + PINCTRL_CONF_DESC(48, REG_GPIO_H_PD, BIT(3)), + PINCTRL_CONF_DESC(49, REG_GPIO_H_PD, BIT(4)), + PINCTRL_CONF_DESC(50, REG_GPIO_H_PD, BIT(5)), + PINCTRL_CONF_DESC(51, REG_GPIO_H_PD, BIT(6)), + PINCTRL_CONF_DESC(52, REG_GPIO_H_PD, BIT(7)), + PINCTRL_CONF_DESC(53, REG_GPIO_H_PD, BIT(8)), + PINCTRL_CONF_DESC(54, REG_GPIO_H_PD, BIT(9)), + PINCTRL_CONF_DESC(55, REG_GPIO_H_PD, BIT(10)), + PINCTRL_CONF_DESC(56, REG_GPIO_H_PD, BIT(11)), + PINCTRL_CONF_DESC(57, REG_GPIO_H_PD, BIT(12)), + PINCTRL_CONF_DESC(58, REG_GPIO_H_PD, BIT(13)), + PINCTRL_CONF_DESC(59, REG_GPIO_H_PD, BIT(14)), + PINCTRL_CONF_DESC(61, REG_I2C_SDA_PD, PCIE0_RESET_PD_MASK), + PINCTRL_CONF_DESC(62, REG_I2C_SDA_PD, PCIE1_RESET_PD_MASK), + PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK), +}; + +static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e2_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_E2, I2C_SDA_E2_MASK), + PINCTRL_CONF_DESC(3, REG_I2C_SDA_E2, I2C_SCL_E2_MASK), + PINCTRL_CONF_DESC(4, REG_I2C_SDA_E2, SPI_CS0_E2_MASK), + PINCTRL_CONF_DESC(5, REG_I2C_SDA_E2, SPI_CLK_E2_MASK), + PINCTRL_CONF_DESC(6, REG_I2C_SDA_E2, SPI_MOSI_E2_MASK), + PINCTRL_CONF_DESC(7, REG_I2C_SDA_E2, SPI_MISO_E2_MASK), + PINCTRL_CONF_DESC(13, REG_GPIO_L_E2, BIT(0)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_E2, BIT(1)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_E2, BIT(2)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_E2, BIT(3)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_E2, BIT(4)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_E2, BIT(5)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_E2, BIT(6)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_E2, BIT(7)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_E2, BIT(8)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_E2, BIT(9)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_E2, BIT(10)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_E2, BIT(11)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_E2, BIT(12)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_E2, BIT(13)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_E2, BIT(14)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_E2, BIT(15)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_E2, BIT(16)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_E2, BIT(17)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_E2, BIT(18)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_E2, BIT(18)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_E2, BIT(20)), + PINCTRL_CONF_DESC(34, REG_GPIO_L_E2, BIT(21)), + PINCTRL_CONF_DESC(35, REG_GPIO_L_E2, BIT(22)), + PINCTRL_CONF_DESC(36, REG_GPIO_L_E2, BIT(23)), + PINCTRL_CONF_DESC(37, REG_GPIO_L_E2, BIT(24)), + PINCTRL_CONF_DESC(38, REG_GPIO_L_E2, BIT(25)), + PINCTRL_CONF_DESC(39, REG_GPIO_L_E2, BIT(26)), + PINCTRL_CONF_DESC(40, REG_GPIO_L_E2, BIT(27)), + PINCTRL_CONF_DESC(41, REG_GPIO_L_E2, BIT(28)), + PINCTRL_CONF_DESC(42, REG_GPIO_L_E2, BIT(29)), + PINCTRL_CONF_DESC(43, REG_GPIO_L_E2, BIT(30)), + PINCTRL_CONF_DESC(44, REG_GPIO_L_E2, BIT(31)), + PINCTRL_CONF_DESC(45, REG_GPIO_H_E2, BIT(0)), + PINCTRL_CONF_DESC(46, REG_GPIO_H_E2, BIT(1)), + PINCTRL_CONF_DESC(47, REG_GPIO_H_E2, BIT(2)), + PINCTRL_CONF_DESC(48, REG_GPIO_H_E2, BIT(3)), + PINCTRL_CONF_DESC(49, REG_GPIO_H_E2, BIT(4)), + PINCTRL_CONF_DESC(50, REG_GPIO_H_E2, BIT(5)), + PINCTRL_CONF_DESC(51, REG_GPIO_H_E2, BIT(6)), + PINCTRL_CONF_DESC(52, REG_GPIO_H_E2, BIT(7)), + PINCTRL_CONF_DESC(53, REG_GPIO_H_E2, BIT(8)), + PINCTRL_CONF_DESC(54, REG_GPIO_H_E2, BIT(9)), + PINCTRL_CONF_DESC(55, REG_GPIO_H_E2, BIT(10)), + PINCTRL_CONF_DESC(56, REG_GPIO_H_E2, BIT(11)), + PINCTRL_CONF_DESC(57, REG_GPIO_H_E2, BIT(12)), + PINCTRL_CONF_DESC(58, REG_GPIO_H_E2, BIT(13)), + PINCTRL_CONF_DESC(59, REG_GPIO_H_E2, BIT(14)), + PINCTRL_CONF_DESC(61, REG_I2C_SDA_E2, PCIE0_RESET_E2_MASK), + PINCTRL_CONF_DESC(62, REG_I2C_SDA_E2, PCIE1_RESET_E2_MASK), + PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK), +}; + +static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e4_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_E4, I2C_SDA_E4_MASK), + PINCTRL_CONF_DESC(3, REG_I2C_SDA_E4, I2C_SCL_E4_MASK), + PINCTRL_CONF_DESC(4, REG_I2C_SDA_E4, SPI_CS0_E4_MASK), + PINCTRL_CONF_DESC(5, REG_I2C_SDA_E4, SPI_CLK_E4_MASK), + PINCTRL_CONF_DESC(6, REG_I2C_SDA_E4, SPI_MOSI_E4_MASK), + PINCTRL_CONF_DESC(7, REG_I2C_SDA_E4, SPI_MISO_E4_MASK), + PINCTRL_CONF_DESC(13, REG_GPIO_L_E4, BIT(0)), + PINCTRL_CONF_DESC(14, REG_GPIO_L_E4, BIT(1)), + PINCTRL_CONF_DESC(15, REG_GPIO_L_E4, BIT(2)), + PINCTRL_CONF_DESC(16, REG_GPIO_L_E4, BIT(3)), + PINCTRL_CONF_DESC(17, REG_GPIO_L_E4, BIT(4)), + PINCTRL_CONF_DESC(18, REG_GPIO_L_E4, BIT(5)), + PINCTRL_CONF_DESC(19, REG_GPIO_L_E4, BIT(6)), + PINCTRL_CONF_DESC(20, REG_GPIO_L_E4, BIT(7)), + PINCTRL_CONF_DESC(21, REG_GPIO_L_E4, BIT(8)), + PINCTRL_CONF_DESC(22, REG_GPIO_L_E4, BIT(9)), + PINCTRL_CONF_DESC(23, REG_GPIO_L_E4, BIT(10)), + PINCTRL_CONF_DESC(24, REG_GPIO_L_E4, BIT(11)), + PINCTRL_CONF_DESC(25, REG_GPIO_L_E4, BIT(12)), + PINCTRL_CONF_DESC(26, REG_GPIO_L_E4, BIT(13)), + PINCTRL_CONF_DESC(27, REG_GPIO_L_E4, BIT(14)), + PINCTRL_CONF_DESC(28, REG_GPIO_L_E4, BIT(15)), + PINCTRL_CONF_DESC(29, REG_GPIO_L_E4, BIT(16)), + PINCTRL_CONF_DESC(30, REG_GPIO_L_E4, BIT(17)), + PINCTRL_CONF_DESC(31, REG_GPIO_L_E4, BIT(18)), + PINCTRL_CONF_DESC(32, REG_GPIO_L_E4, BIT(18)), + PINCTRL_CONF_DESC(33, REG_GPIO_L_E4, BIT(20)), + PINCTRL_CONF_DESC(34, REG_GPIO_L_E4, BIT(21)), + PINCTRL_CONF_DESC(35, REG_GPIO_L_E4, BIT(22)), + PINCTRL_CONF_DESC(36, REG_GPIO_L_E4, BIT(23)), + PINCTRL_CONF_DESC(37, REG_GPIO_L_E4, BIT(24)), + PINCTRL_CONF_DESC(38, REG_GPIO_L_E4, BIT(25)), + PINCTRL_CONF_DESC(39, REG_GPIO_L_E4, BIT(26)), + PINCTRL_CONF_DESC(40, REG_GPIO_L_E4, BIT(27)), + PINCTRL_CONF_DESC(41, REG_GPIO_L_E4, BIT(28)), + PINCTRL_CONF_DESC(42, REG_GPIO_L_E4, BIT(29)), + PINCTRL_CONF_DESC(43, REG_GPIO_L_E4, BIT(30)), + PINCTRL_CONF_DESC(44, REG_GPIO_L_E4, BIT(31)), + PINCTRL_CONF_DESC(45, REG_GPIO_H_E4, BIT(0)), + PINCTRL_CONF_DESC(46, REG_GPIO_H_E4, BIT(1)), + PINCTRL_CONF_DESC(47, REG_GPIO_H_E4, BIT(2)), + PINCTRL_CONF_DESC(48, REG_GPIO_H_E4, BIT(3)), + PINCTRL_CONF_DESC(49, REG_GPIO_H_E4, BIT(4)), + PINCTRL_CONF_DESC(50, REG_GPIO_H_E4, BIT(5)), + PINCTRL_CONF_DESC(51, REG_GPIO_H_E4, BIT(6)), + PINCTRL_CONF_DESC(52, REG_GPIO_H_E4, BIT(7)), + PINCTRL_CONF_DESC(53, REG_GPIO_H_E4, BIT(8)), + PINCTRL_CONF_DESC(54, REG_GPIO_H_E4, BIT(9)), + PINCTRL_CONF_DESC(55, REG_GPIO_H_E4, BIT(10)), + PINCTRL_CONF_DESC(56, REG_GPIO_H_E4, BIT(11)), + PINCTRL_CONF_DESC(57, REG_GPIO_H_E4, BIT(12)), + PINCTRL_CONF_DESC(58, REG_GPIO_H_E4, BIT(13)), + PINCTRL_CONF_DESC(59, REG_GPIO_H_E4, BIT(14)), + PINCTRL_CONF_DESC(61, REG_I2C_SDA_E4, PCIE0_RESET_E4_MASK), + PINCTRL_CONF_DESC(62, REG_I2C_SDA_E4, PCIE1_RESET_E4_MASK), + PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK), +}; + +static const struct airoha_pinctrl_conf airoha_pinctrl_pcie_rst_od_conf[] = { + PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), + PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), + PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK), +}; + +static u32 airoha_pinctrl_rmw_unlock(void __iomem *addr, u32 mask, u32 val) +{ + val |= (readl(addr) & ~mask); + writel(val, addr); + + return val; +} + +#define airoha_pinctrl_set_unlock(addr, val) \ + airoha_pinctrl_rmw_unlock((addr), 0, (val)) +#define airoha_pinctrl_clear_unlock(addr, mask) \ + airoha_pinctrl_rmw_unlock((addr), (mask), (0)) + +static u32 airoha_pinctrl_rmw(struct airoha_pinctrl *pinctrl, + void __iomem *addr, u32 mask, u32 val) +{ + mutex_lock(&pinctrl->mutex); + val = airoha_pinctrl_rmw_unlock(addr, mask, val); + mutex_unlock(&pinctrl->mutex); + + return val; +} + +static void airoha_pinctrl_gpio_set_direction(struct airoha_pinctrl *pinctrl, + unsigned int gpio, bool input) +{ + u32 mask, index; + + /* set output enable */ + mask = BIT(gpio % AIROHA_GPIO_BANK_SIZE); + index = gpio / AIROHA_GPIO_BANK_SIZE; + airoha_pinctrl_rmw(pinctrl, pinctrl->gpiochip.out[index], + mask, !input ? mask : 0); + + /* set gpio direction */ + mask = BIT(2 * (gpio % AIROHA_REG_GPIOCTRL_NUM_GPIO)); + index = gpio / AIROHA_REG_GPIOCTRL_NUM_GPIO; + airoha_pinctrl_rmw(pinctrl, pinctrl->gpiochip.dir[index], + mask, !input ? mask : 0); +} + +static void airoha_pinctrl_gpio_set_value(struct airoha_pinctrl *pinctrl, + unsigned int gpio, bool value) +{ + u8 index = gpio / AIROHA_GPIO_BANK_SIZE; + u32 pin = gpio % AIROHA_GPIO_BANK_SIZE; + + airoha_pinctrl_rmw(pinctrl, pinctrl->gpiochip.data[index], + BIT(pin), value ? BIT(pin) : 0); +} + +static int airoha_pinctrl_gpio_get_direction(struct airoha_pinctrl *pinctrl, + unsigned int gpio) +{ + u32 val, mask = BIT(2 * (gpio % AIROHA_REG_GPIOCTRL_NUM_GPIO)); + u8 index = gpio / AIROHA_REG_GPIOCTRL_NUM_GPIO; + + val = (readl(pinctrl->gpiochip.dir[index]) & mask); + + return val ? PIN_CONFIG_OUTPUT_ENABLE : PIN_CONFIG_INPUT_ENABLE; +} + +static int airoha_pinmux_set_mux(struct pinctrl_dev *pctrl_dev, + unsigned int selector, + unsigned int group) +{ + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); + const struct airoha_pinctrl_func *func; + struct function_desc *desc; + struct group_desc *grp; + int i; + + desc = pinmux_generic_get_function(pctrl_dev, selector); + if (!desc) + return -EINVAL; + + grp = pinctrl_generic_get_group(pctrl_dev, group); + if (!grp) + return -EINVAL; + + dev_dbg(pctrl_dev->dev, "enable function %s group %s\n", + desc->func.name, grp->grp.name); + + func = desc->data; + for (i = 0; i < func->group_size; i++) { + const struct airoha_pinctrl_func_group *group; + int j; + + group = &func->groups[i]; + if (strcmp(group->name, grp->grp.name)) + continue; + + for (j = 0; j < group->regmap_size; j++) { + switch (group->regmap[j].mux) { + case AIROHA_FUNC_PWM_EXT_MUX: + case AIROHA_FUNC_PWM_MUX: { + void __iomem *addr; + + addr = pinctrl->base + group->regmap[j].offset; + airoha_pinctrl_rmw(pinctrl, addr, + group->regmap[j].mask, + group->regmap[j].val); + break; + } + default: + regmap_update_bits(pinctrl->chip_scu, + group->regmap[j].offset, + group->regmap[j].mask, + group->regmap[j].val); + break; + } + } + return 0; + } + + return -EINVAL; +} + +static int airoha_pinmux_gpio_set_direction(struct pinctrl_dev *pctrl_dev, + struct pinctrl_gpio_range *range, + unsigned int pin, bool input) +{ + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); + int gpio = pin - range->pin_base; + + airoha_pinctrl_gpio_set_direction(pinctrl, gpio, input); + + return 0; +} + +static int airoha_pinctrl_get_gpio_from_pin(struct pinctrl_dev *pctrl_dev, + int pin) +{ + struct pinctrl_gpio_range *range; + int gpio; + + range = pinctrl_find_gpio_range_from_pin_nolock(pctrl_dev, pin); + if (!range) + return -EINVAL; + + gpio = pin - range->pin_base; + if (gpio < 0) + return -EINVAL; + + return gpio; +} + +static const struct airoha_pinctrl_reg * +airoha_pinctrl_get_conf_reg(const struct airoha_pinctrl_conf *conf, + int conf_size, int pin) +{ + int i; + + for (i = 0; i < conf_size; i++) { + if (conf[i].pin == pin) + return &conf[i].reg; + } + + return NULL; +} + +static int airoha_pinctrl_get_conf(struct airoha_pinctrl *pinctrl, + const struct airoha_pinctrl_conf *conf, + int conf_size, int pin, u32 *val) +{ + const struct airoha_pinctrl_reg *reg; + + reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); + if (!reg) + return -EINVAL; + + if (regmap_read(pinctrl->chip_scu, reg->offset, val)) + return -EINVAL; + + *val = (*val & reg->mask) >> __ffs(reg->mask); + + return 0; +} + +static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl, + const struct airoha_pinctrl_conf *conf, + int conf_size, int pin, u32 val) +{ + const struct airoha_pinctrl_reg *reg = NULL; + + reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); + if (!reg) + return -EINVAL; + + + if (regmap_update_bits(pinctrl->chip_scu, reg->offset, reg->mask, + val << __ffs(reg->mask))) + return -EINVAL; + + return 0; +} + +#define airoha_pinctrl_get_pullup_conf(pinctrl, pin, val) \ + airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pullup_conf, \ + ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ + (pin), (val)) +#define airoha_pinctrl_get_pulldown_conf(pinctrl, pin, val) \ + airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ + ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ + (pin), (val)) +#define airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, val) \ + airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ + ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ + (pin), (val)) +#define airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, val) \ + airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ + ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ + (pin), (val)) +#define airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, val) \ + airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ + ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ + (pin), (val)) +#define airoha_pinctrl_set_pullup_conf(pinctrl, pin, val) \ + airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pullup_conf, \ + ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ + (pin), (val)) +#define airoha_pinctrl_set_pulldown_conf(pinctrl, pin, val) \ + airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ + ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ + (pin), (val)) +#define airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, val) \ + airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ + ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ + (pin), (val)) +#define airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, val) \ + airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ + ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ + (pin), (val)) +#define airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, val) \ + airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ + ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ + (pin), (val)) + +static int airoha_pinconf_get(struct pinctrl_dev *pctrl_dev, + unsigned int pin, unsigned long *config) +{ + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); + enum pin_config_param param = pinconf_to_config_param(*config); + u32 arg; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_UP: { + u32 pull_up, pull_down; + + if (airoha_pinctrl_get_pullup_conf(pinctrl, pin, &pull_up) || + airoha_pinctrl_get_pulldown_conf(pinctrl, pin, &pull_down)) + return -EINVAL; + + if (param == PIN_CONFIG_BIAS_PULL_UP && + !(pull_up && !pull_down)) + return -EINVAL; + else if (param == PIN_CONFIG_BIAS_PULL_DOWN && + !(pull_down && !pull_up)) + return -EINVAL; + else if (pull_up || pull_down) + return -EINVAL; + + arg = 1; + break; + } + case PIN_CONFIG_DRIVE_STRENGTH: { + u32 e2, e4; + + if (airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, &e2) || + airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, &e4)) + return -EINVAL; + + arg = e4 << 1 | e2; + break; + } + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, &arg)) + return -EINVAL; + break; + case PIN_CONFIG_OUTPUT_ENABLE: + case PIN_CONFIG_INPUT_ENABLE: { + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); + + if (gpio < 0) + return gpio; + + arg = airoha_pinctrl_gpio_get_direction(pinctrl, gpio); + if (arg != param) + return -EINVAL; + + arg = 1; + break; + } + default: + return -EOPNOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) +{ + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); + int i; + + for (i = 0; i < num_configs; i++) { + u32 param = pinconf_to_config_param(configs[i]); + u32 arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); + break; + case PIN_CONFIG_BIAS_PULL_UP: + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 1); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 1); + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); + break; + case PIN_CONFIG_DRIVE_STRENGTH: { + u32 e2 = 0, e4 = 0; + + switch (arg) { + case MTK_DRIVE_2mA: + break; + case MTK_DRIVE_4mA: + e2 = 1; + break; + case MTK_DRIVE_6mA: + e4 = 1; + break; + case MTK_DRIVE_8mA: + e2 = 1; + e4 = 1; + break; + default: + return -EINVAL; + } + + airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, e2); + airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, e4); + break; + } + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, !!arg); + break; + case PIN_CONFIG_OUTPUT_ENABLE: + case PIN_CONFIG_INPUT_ENABLE: + case PIN_CONFIG_OUTPUT: { + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); + bool input = param == PIN_CONFIG_INPUT_ENABLE; + + if (gpio < 0) + return gpio; + + airoha_pinctrl_gpio_set_direction(pinctrl, gpio, input); + if (param == PIN_CONFIG_OUTPUT) + airoha_pinctrl_gpio_set_value(pinctrl, gpio, !!arg); + break; + } + default: + return -EOPNOTSUPP; + } + } + + return 0; +} + +static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev, + unsigned int group, unsigned long *config) +{ + u32 cur_config = 0; + int i; + + for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { + if (airoha_pinconf_get(pctrl_dev, + airoha_pinctrl_groups[group].pins[i], + config)) + return -EOPNOTSUPP; + + if (i && cur_config != *config) + return -EOPNOTSUPP; + + cur_config = *config; + } + + return 0; +} + +static int airoha_pinconf_group_set(struct pinctrl_dev *pctrl_dev, + unsigned int group, unsigned long *configs, + unsigned int num_configs) +{ + int i; + + for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { + int err; + + err = airoha_pinconf_set(pctrl_dev, + airoha_pinctrl_groups[group].pins[i], + configs, num_configs); + if (err) + return err; + } + + return 0; +} + +static const struct pinconf_ops airoha_confops = { + .is_generic = true, + .pin_config_get = airoha_pinconf_get, + .pin_config_set = airoha_pinconf_set, + .pin_config_group_get = airoha_pinconf_group_get, + .pin_config_group_set = airoha_pinconf_group_set, + .pin_config_config_dbg_show = pinconf_generic_dump_config, +}; + +static const struct pinctrl_ops airoha_pctlops = { + .get_groups_count = pinctrl_generic_get_group_count, + .get_group_name = pinctrl_generic_get_group_name, + .get_group_pins = pinctrl_generic_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static const struct pinmux_ops airoha_pmxops = { + .get_functions_count = pinmux_generic_get_function_count, + .get_function_name = pinmux_generic_get_function_name, + .get_function_groups = pinmux_generic_get_function_groups, + .gpio_set_direction = airoha_pinmux_gpio_set_direction, + .set_mux = airoha_pinmux_set_mux, + .strict = true, +}; + +static struct pinctrl_desc airoha_pinctrl_desc = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + .pctlops = &airoha_pctlops, + .pmxops = &airoha_pmxops, + .confops = &airoha_confops, + .pins = airoha_pinctrl_pins, + .npins = ARRAY_SIZE(airoha_pinctrl_pins), +}; + +static void airoha_pinctrl_gpio_set(struct gpio_chip *chip, unsigned int gpio, + int value) +{ + struct airoha_pinctrl *pinctrl = gpiochip_get_data(chip); + + airoha_pinctrl_gpio_set_value(pinctrl, gpio, value); +} + +static int airoha_pinctrl_gpio_get(struct gpio_chip *chip, unsigned int gpio) +{ + struct airoha_pinctrl *pinctrl = gpiochip_get_data(chip); + u8 index = gpio / AIROHA_GPIO_BANK_SIZE; + u32 pin = gpio % AIROHA_GPIO_BANK_SIZE; + + return !!(readl(pinctrl->gpiochip.data[index]) & BIT(pin)); +} + +static int airoha_pinctrl_gpio_direction_output(struct gpio_chip *chip, + unsigned int gpio, int value) +{ + int err; + + err = pinctrl_gpio_direction_output(chip, gpio); + if (err) + return err; + + airoha_pinctrl_gpio_set(chip, gpio, value); + + return 0; +} + +static void airoha_pinctrl_gpio_irq_unmask(struct irq_data *data) +{ + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; + u32 mask = GENMASK(2 * offset + 1, 2 * offset); + struct airoha_pinctrl_gpiochip *gpiochip; + u32 val = BIT(2 * offset); + unsigned long flags; + + gpiochip = irq_data_get_irq_chip_data(data); + if (WARN_ON_ONCE(data->hwirq >= ARRAY_SIZE(gpiochip->irq_type))) + return; + + spin_lock_irqsave(&gpiochip->lock, flags); + + switch (gpiochip->irq_type[data->hwirq] & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_LEVEL_LOW: + val = val << 1; + fallthrough; + case IRQ_TYPE_LEVEL_HIGH: + airoha_pinctrl_rmw_unlock(gpiochip->level[index], mask, val); + break; + case IRQ_TYPE_EDGE_FALLING: + val = val << 1; + fallthrough; + case IRQ_TYPE_EDGE_RISING: + airoha_pinctrl_rmw_unlock(gpiochip->edge[index], mask, val); + break; + case IRQ_TYPE_EDGE_BOTH: + airoha_pinctrl_set_unlock(gpiochip->edge[index], mask); + break; + default: + break; + } + + spin_unlock_irqrestore(&gpiochip->lock, flags); +} + +static void airoha_pinctrl_gpio_irq_mask(struct irq_data *data) +{ + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; + u32 mask = GENMASK(2 * offset + 1, 2 * offset); + struct airoha_pinctrl_gpiochip *gpiochip; + unsigned long flags; + + gpiochip = irq_data_get_irq_chip_data(data); + + spin_lock_irqsave(&gpiochip->lock, flags); + + airoha_pinctrl_clear_unlock(gpiochip->edge[index], mask); + airoha_pinctrl_clear_unlock(gpiochip->level[index], mask); + + spin_unlock_irqrestore(&gpiochip->lock, flags); +} + +static int airoha_pinctrl_gpio_irq_type(struct irq_data *data, + unsigned int type) +{ + struct airoha_pinctrl_gpiochip *gpiochip; + unsigned long flags; + + gpiochip = irq_data_get_irq_chip_data(data); + if (data->hwirq >= ARRAY_SIZE(gpiochip->irq_type)) + return -EINVAL; + + spin_lock_irqsave(&gpiochip->lock, flags); + + if (type == IRQ_TYPE_PROBE) { + if (gpiochip->irq_type[data->hwirq]) + goto unlock; + + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + } + gpiochip->irq_type[data->hwirq] = type & IRQ_TYPE_SENSE_MASK; +unlock: + spin_unlock_irqrestore(&gpiochip->lock, flags); + + return 0; +} + +static irqreturn_t airoha_pinctrl_gpio_irq_handler(int irq, void *data) +{ + struct airoha_pinctrl_gpiochip *gpiochip; + bool handled = false; + int i; + + gpiochip = container_of(data, struct airoha_pinctrl_gpiochip, chip); + for (i = 0; i < ARRAY_SIZE(gpiochip->status); i++) { + unsigned long status = readl(gpiochip->status[i]); + struct gpio_irq_chip *girq = &gpiochip->chip.irq; + int irq; + + for_each_set_bit(irq, &status, AIROHA_GPIO_BANK_SIZE) { + u32 offset = irq + i * AIROHA_GPIO_BANK_SIZE; + + generic_handle_irq(irq_find_mapping(girq->domain, + offset)); + writel(BIT(irq), gpiochip->status[i]); + } + handled |= !!status; + } + + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, + struct platform_device *pdev) +{ + struct gpio_chip *chip = &pinctrl->gpiochip.chip; + struct gpio_irq_chip *girq = &chip->irq; + struct device *dev = &pdev->dev; + int irq, err; + + pinctrl->gpiochip.data[0] = pinctrl->base + REG_GPIO_DATA; + pinctrl->gpiochip.data[1] = pinctrl->base + REG_GPIO_DATA1; + pinctrl->gpiochip.dir[0] = pinctrl->base + REG_GPIO_CTRL; + pinctrl->gpiochip.dir[1] = pinctrl->base + REG_GPIO_CTRL1; + pinctrl->gpiochip.dir[2] = pinctrl->base + REG_GPIO_CTRL2; + pinctrl->gpiochip.dir[3] = pinctrl->base + REG_GPIO_CTRL3; + pinctrl->gpiochip.out[0] = pinctrl->base + REG_GPIO_OE; + pinctrl->gpiochip.out[1] = pinctrl->base + REG_GPIO_OE1; + + chip->parent = dev; + chip->label = dev_name(dev); + chip->request = gpiochip_generic_request; + chip->free = gpiochip_generic_free; + chip->direction_input = pinctrl_gpio_direction_input; + chip->direction_output = airoha_pinctrl_gpio_direction_output; + chip->set = airoha_pinctrl_gpio_set; + chip->get = airoha_pinctrl_gpio_get; + chip->base = -1; + chip->ngpio = AIROHA_NUM_GPIOS; + + if (!of_property_read_bool(dev->of_node, "interrupt-controller")) + goto out; + + pinctrl->gpiochip.status[0] = pinctrl->base + REG_GPIO_INT; + pinctrl->gpiochip.status[1] = pinctrl->base + REG_GPIO_INT1; + pinctrl->gpiochip.level[0] = pinctrl->base + REG_GPIO_INT_LEVEL; + pinctrl->gpiochip.level[1] = pinctrl->base + REG_GPIO_INT_LEVEL1; + pinctrl->gpiochip.level[2] = pinctrl->base + REG_GPIO_INT_LEVEL2; + pinctrl->gpiochip.level[3] = pinctrl->base + REG_GPIO_INT_LEVEL3; + pinctrl->gpiochip.edge[0] = pinctrl->base + REG_GPIO_INT_EDGE; + pinctrl->gpiochip.edge[1] = pinctrl->base + REG_GPIO_INT_EDGE1; + pinctrl->gpiochip.edge[2] = pinctrl->base + REG_GPIO_INT_EDGE2; + pinctrl->gpiochip.edge[3] = pinctrl->base + REG_GPIO_INT_EDGE3; + + spin_lock_init(&pinctrl->gpiochip.lock); + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + err = devm_request_irq(dev, irq, airoha_pinctrl_gpio_irq_handler, + IRQF_SHARED, dev_name(dev), chip); + if (err) { + dev_err(dev, "error requesting irq %d: %d\n", irq, err); + return err; + } + + girq->chip = devm_kzalloc(dev, sizeof(*girq->chip), GFP_KERNEL); + if (!girq->chip) + return -ENOMEM; + + girq->chip->name = dev_name(dev); + girq->chip->irq_unmask = airoha_pinctrl_gpio_irq_unmask; + girq->chip->irq_mask = airoha_pinctrl_gpio_irq_mask; + girq->chip->irq_mask_ack = airoha_pinctrl_gpio_irq_mask; + girq->chip->irq_set_type = airoha_pinctrl_gpio_irq_type; + girq->chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; +out: + return devm_gpiochip_add_data(dev, chip, pinctrl); +} + +static int airoha_pinctrl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct airoha_pinctrl *pinctrl; + struct airoha_mfd *mfd; + struct regmap *map; + int err, i; + + /* Assign parent MFD of_node to dev */ + device_set_of_node_from_dev(dev, dev->parent); + mfd = dev_get_drvdata(dev->parent); + + pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL); + if (!pinctrl) + return -ENOMEM; + + mutex_init(&pinctrl->mutex); + pinctrl->base = mfd->base; + + map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); + if (IS_ERR(map)) + return PTR_ERR(map); + + pinctrl->chip_scu = map; + + err = devm_pinctrl_register_and_init(dev, &airoha_pinctrl_desc, + pinctrl, &pinctrl->ctrl); + if (err) + return err; + + /* build pin groups */ + for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_groups); i++) { + const struct pingroup *grp = &airoha_pinctrl_groups[i]; + + err = pinctrl_generic_add_group(pinctrl->ctrl, grp->name, + grp->pins, grp->npins, + (void *)grp); + if (err < 0) { + dev_err(&pdev->dev, "Failed to register group %s\n", + grp->name); + return err; + } + } + + /* build functions */ + for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_funcs); i++) { + const struct airoha_pinctrl_func *func; + + func = &airoha_pinctrl_funcs[i]; + err = pinmux_generic_add_function(pinctrl->ctrl, + func->desc.func.name, + func->desc.func.groups, + func->desc.func.ngroups, + (void *)func); + if (err < 0) { + dev_err(dev, "Failed to register function %s\n", + func->desc.func.name); + return err; + } + } + + err = pinctrl_enable(pinctrl->ctrl); + if (err) + return err; + + /* build gpio-chip */ + return airoha_pinctrl_add_gpiochip(pinctrl, pdev); +} + +static struct platform_driver airoha_pinctrl_driver = { + .probe = airoha_pinctrl_probe, + .driver = { + .name = "pinctrl-airoha", + }, +}; +module_platform_driver(airoha_pinctrl_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); +MODULE_AUTHOR("Benjamin Larsson <benjamin.larsson@genexis.eu>"); +MODULE_AUTHOR("Markus Gothe <markus.gothe@genexis.eu>"); +MODULE_DESCRIPTION("Pinctrl driver for Airoha SoC"); -- 2.46.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC 2024-09-11 19:50 ` [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC Lorenzo Bianconi @ 2024-09-24 7:34 ` Linus Walleij 2024-09-24 10:12 ` Lorenzo Bianconi 0 siblings, 1 reply; 20+ messages in thread From: Linus Walleij @ 2024-09-24 7:34 UTC (permalink / raw) To: Lorenzo Bianconi Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm Hi Lorenzo / Benjamin, thanks for your patch! This is a real nice driver, I like the design of the pin database to support this pretty complex pin controller. Some comments and nits: On Wed, Sep 11, 2024 at 9:51 PM Lorenzo Bianconi <lorenzo@kernel.org> wrote: > Introduce pinctrl driver for EN7581 SoC. Current EN7581 pinctrl driver > supports the following functionalities: > - pin multiplexing > - pin pull-up, pull-down, open-drain, current strength, > {input,output}_enable, output_{low,high} > - gpio controller > - irq controller > > Tested-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > Co-developed-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> (...) > +#include <dt-bindings/pinctrl/mt65xx.h> > +#include <linux/bitfield.h> Isn't just <linux/bits.h> enough for what you're using? > +#include <linux/gpio/driver.h> > +#include <linux/interrupt.h> > +#include <linux/io.h> > +#include <linux/irq.h> > +#include <linux/irqdomain.h> > +#include <linux/kernel.h> What do you use from kernel.h? We usually use more fingrained headers these days. (...) > +#include <linux/mfd/airoha-en7581-mfd.h> > +#include <linux/mfd/syscon.h> > +#include <linux/of.h> > +#include <linux/of_irq.h> > +#include <linux/of_platform.h> > +#include <linux/pinctrl/consumer.h> Why do you need the consumer header? (...) > +static u32 airoha_pinctrl_rmw_unlock(void __iomem *addr, u32 mask, u32 val) > +{ > + val |= (readl(addr) & ~mask); > + writel(val, addr); > + > + return val; > +} > + > +#define airoha_pinctrl_set_unlock(addr, val) \ > + airoha_pinctrl_rmw_unlock((addr), 0, (val)) > +#define airoha_pinctrl_clear_unlock(addr, mask) \ > + airoha_pinctrl_rmw_unlock((addr), (mask), (0)) > + > +static u32 airoha_pinctrl_rmw(struct airoha_pinctrl *pinctrl, > + void __iomem *addr, u32 mask, u32 val) > +{ > + mutex_lock(&pinctrl->mutex); > + val = airoha_pinctrl_rmw_unlock(addr, mask, val); > + mutex_unlock(&pinctrl->mutex); > + > + return val; > +} Thus looks like a reimplementation of regmap-mmio, can't you just use regmap MMIO? You use it for the SCU access already... If you persist with this solution, please use a guard: #include <linux/cleanup.h> guard(mutex)(&pinctrl->mutex); And the lock will be released when you exit the function. > +static int airoha_pinctrl_get_gpio_from_pin(struct pinctrl_dev *pctrl_dev, > + int pin) > +{ > + struct pinctrl_gpio_range *range; > + int gpio; > + > + range = pinctrl_find_gpio_range_from_pin_nolock(pctrl_dev, pin); > + if (!range) > + return -EINVAL; > + > + gpio = pin - range->pin_base; > + if (gpio < 0) > + return -EINVAL; > + > + return gpio; > +} This function is just used here: > +static int airoha_pinconf_get(struct pinctrl_dev *pctrl_dev, > + unsigned int pin, unsigned long *config) > +{ > + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); > + enum pin_config_param param = pinconf_to_config_param(*config); > + u32 arg; > + > + switch (param) { > + case PIN_CONFIG_BIAS_PULL_DOWN: > + case PIN_CONFIG_BIAS_DISABLE: > + case PIN_CONFIG_BIAS_PULL_UP: { > + u32 pull_up, pull_down; > + > + if (airoha_pinctrl_get_pullup_conf(pinctrl, pin, &pull_up) || > + airoha_pinctrl_get_pulldown_conf(pinctrl, pin, &pull_down)) > + return -EINVAL; > + > + if (param == PIN_CONFIG_BIAS_PULL_UP && > + !(pull_up && !pull_down)) > + return -EINVAL; > + else if (param == PIN_CONFIG_BIAS_PULL_DOWN && > + !(pull_down && !pull_up)) > + return -EINVAL; > + else if (pull_up || pull_down) > + return -EINVAL; > + > + arg = 1; > + break; > + } > + case PIN_CONFIG_DRIVE_STRENGTH: { > + u32 e2, e4; > + > + if (airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, &e2) || > + airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, &e4)) > + return -EINVAL; > + > + arg = e4 << 1 | e2; > + break; > + } > + case PIN_CONFIG_DRIVE_OPEN_DRAIN: > + if (airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, &arg)) > + return -EINVAL; > + break; > + case PIN_CONFIG_OUTPUT_ENABLE: > + case PIN_CONFIG_INPUT_ENABLE: { > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); > + > + if (gpio < 0) > + return gpio; > + > + arg = airoha_pinctrl_gpio_get_direction(pinctrl, gpio); I don't see why a pin would have to exist in a GPIO range in order to be set as output or input? Can't you just set up the pin as requested and not care whether it has a corresponding GPIO range? Is it over-reuse of the GPIO code? I'd say just set up the pin instead. > +static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev, > + unsigned int pin, unsigned long *configs, > + unsigned int num_configs) > +{ > + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); > + int i; > + > + for (i = 0; i < num_configs; i++) { > + u32 param = pinconf_to_config_param(configs[i]); > + u32 arg = pinconf_to_config_argument(configs[i]); > + > + switch (param) { > + case PIN_CONFIG_BIAS_DISABLE: > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); > + break; > + case PIN_CONFIG_BIAS_PULL_UP: > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 1); > + break; > + case PIN_CONFIG_BIAS_PULL_DOWN: > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 1); > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); > + break; > + case PIN_CONFIG_DRIVE_STRENGTH: { > + u32 e2 = 0, e4 = 0; > + > + switch (arg) { > + case MTK_DRIVE_2mA: > + break; > + case MTK_DRIVE_4mA: > + e2 = 1; > + break; > + case MTK_DRIVE_6mA: > + e4 = 1; > + break; > + case MTK_DRIVE_8mA: > + e2 = 1; > + e4 = 1; > + break; > + default: > + return -EINVAL; > + } > + > + airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, e2); > + airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, e4); > + break; > + } > + case PIN_CONFIG_DRIVE_OPEN_DRAIN: > + airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, !!arg); > + break; > + case PIN_CONFIG_OUTPUT_ENABLE: > + case PIN_CONFIG_INPUT_ENABLE: > + case PIN_CONFIG_OUTPUT: { > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); > + bool input = param == PIN_CONFIG_INPUT_ENABLE; > + > + if (gpio < 0) > + return gpio; > + > + airoha_pinctrl_gpio_set_direction(pinctrl, gpio, input); > + if (param == PIN_CONFIG_OUTPUT) > + airoha_pinctrl_gpio_set_value(pinctrl, gpio, !!arg); > + break; Dito. No need to reuse the GPIO set direction function. Make a helper that just work on the pin instead, and perhaps the GPIO set direction can use that instead. > +static int airoha_pinctrl_gpio_direction_output(struct gpio_chip *chip, > + unsigned int gpio, int value) > +{ > + int err; > + > + err = pinctrl_gpio_direction_output(chip, gpio); > + if (err) > + return err; > + > + airoha_pinctrl_gpio_set(chip, gpio, value); Hm I get a bit confused by the similarly named helpers I guess... > +static void airoha_pinctrl_gpio_irq_unmask(struct irq_data *data) > +{ > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; > + u32 mask = GENMASK(2 * offset + 1, 2 * offset); > + struct airoha_pinctrl_gpiochip *gpiochip; > + u32 val = BIT(2 * offset); > + unsigned long flags; > + > + gpiochip = irq_data_get_irq_chip_data(data); > + if (WARN_ON_ONCE(data->hwirq >= ARRAY_SIZE(gpiochip->irq_type))) > + return; > + > + spin_lock_irqsave(&gpiochip->lock, flags); Use a scoped guard here guard(spinlock_irqsave)(&gpiochip->lock); > +static void airoha_pinctrl_gpio_irq_mask(struct irq_data *data) > +{ > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; > + u32 mask = GENMASK(2 * offset + 1, 2 * offset); > + struct airoha_pinctrl_gpiochip *gpiochip; > + unsigned long flags; > + > + gpiochip = irq_data_get_irq_chip_data(data); > + > + spin_lock_irqsave(&gpiochip->lock, flags); Dito > +static int airoha_pinctrl_gpio_irq_type(struct irq_data *data, > + unsigned int type) > +{ > + struct airoha_pinctrl_gpiochip *gpiochip; > + unsigned long flags; > + > + gpiochip = irq_data_get_irq_chip_data(data); > + if (data->hwirq >= ARRAY_SIZE(gpiochip->irq_type)) > + return -EINVAL; > + > + spin_lock_irqsave(&gpiochip->lock, flags); Dito > + girq->chip = devm_kzalloc(dev, sizeof(*girq->chip), GFP_KERNEL); > + if (!girq->chip) > + return -ENOMEM; > + > + girq->chip->name = dev_name(dev); > + girq->chip->irq_unmask = airoha_pinctrl_gpio_irq_unmask; > + girq->chip->irq_mask = airoha_pinctrl_gpio_irq_mask; > + girq->chip->irq_mask_ack = airoha_pinctrl_gpio_irq_mask; > + girq->chip->irq_set_type = airoha_pinctrl_gpio_irq_type; > + girq->chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE; > + girq->default_type = IRQ_TYPE_NONE; > + girq->handler = handle_simple_irq; If the irqchip is immutable it is const and there is no point to malloc it. Just static const struct irq_chip airoha_gpio_irq_chip = {... And assign it: girq = &g->gc.irq; gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip); Yours, Linus Walleij ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC 2024-09-24 7:34 ` Linus Walleij @ 2024-09-24 10:12 ` Lorenzo Bianconi 2024-09-24 21:22 ` Lorenzo Bianconi 2024-10-02 12:58 ` Linus Walleij 0 siblings, 2 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-24 10:12 UTC (permalink / raw) To: Linus Walleij Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm [-- Attachment #1: Type: text/plain, Size: 14003 bytes --] > Hi Lorenzo / Benjamin, > > thanks for your patch! > > This is a real nice driver, I like the design of the pin database to support > this pretty complex pin controller. Hi Linus, thx for the review, some questions inline. Regards, Lorenzo > > Some comments and nits: > > On Wed, Sep 11, 2024 at 9:51 PM Lorenzo Bianconi <lorenzo@kernel.org> wrote: > > > Introduce pinctrl driver for EN7581 SoC. Current EN7581 pinctrl driver > > supports the following functionalities: > > - pin multiplexing > > - pin pull-up, pull-down, open-drain, current strength, > > {input,output}_enable, output_{low,high} > > - gpio controller > > - irq controller > > > > Tested-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > > Co-developed-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > > Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> > > (...) > > > +#include <dt-bindings/pinctrl/mt65xx.h> > > +#include <linux/bitfield.h> > > Isn't just <linux/bits.h> enough for what you're using? ack, I will fix it in v5 > > > +#include <linux/gpio/driver.h> > > +#include <linux/interrupt.h> > > +#include <linux/io.h> > > +#include <linux/irq.h> > > +#include <linux/irqdomain.h> > > +#include <linux/kernel.h> > > What do you use from kernel.h? We usually use more fingrained > headers these days. ack, I will remove it in v5 > > (...) > > > +#include <linux/mfd/airoha-en7581-mfd.h> > > +#include <linux/mfd/syscon.h> > > +#include <linux/of.h> > > +#include <linux/of_irq.h> > > +#include <linux/of_platform.h> > > +#include <linux/pinctrl/consumer.h> > > Why do you need the consumer header? we need it for pinctrl_gpio_direction_output() and pinctrl_gpio_direction_input() for direction_input and direction_output callbacks. > > (...) > > > +static u32 airoha_pinctrl_rmw_unlock(void __iomem *addr, u32 mask, u32 val) > > +{ > > + val |= (readl(addr) & ~mask); > > + writel(val, addr); > > + > > + return val; > > +} > > + > > +#define airoha_pinctrl_set_unlock(addr, val) \ > > + airoha_pinctrl_rmw_unlock((addr), 0, (val)) > > +#define airoha_pinctrl_clear_unlock(addr, mask) \ > > + airoha_pinctrl_rmw_unlock((addr), (mask), (0)) > > + > > +static u32 airoha_pinctrl_rmw(struct airoha_pinctrl *pinctrl, > > + void __iomem *addr, u32 mask, u32 val) > > +{ > > + mutex_lock(&pinctrl->mutex); > > + val = airoha_pinctrl_rmw_unlock(addr, mask, val); > > + mutex_unlock(&pinctrl->mutex); > > + > > + return val; > > +} > > Thus looks like a reimplementation of regmap-mmio, can't you just use > regmap MMIO? You use it for the SCU access already... > > If you persist with this solution, please use a guard: > > #include <linux/cleanup.h> > > guard(mutex)(&pinctrl->mutex); > > And the lock will be released when you exit the function. I am fine to switch to regmap but I guess we need to enable fast_io since it can run even in interrupt context. Btw, I figured out even airoha_pinctrl_rmw needs to grab a spin_lock since we can exec a led trigger (like timer) where we run airoha_pinctrl_rmw in interrupt context (so it should be fine to use a single regmap for it). However, I guess we need to keep the spin_lock in airoha_pinctrl_gpiochip since we need to grab it in airoha_pinctrl_gpio_irq_unmask() and airoha_pinctrl_gpio_irq_type() (we access irq_type array there). A possible solution would be to keep the local spin_lock and set disable_locking. What do you think? Do you prefer to switch to regmap or keep the current implementation using 'guard(spinlock_irqsave)' instead? > > > +static int airoha_pinctrl_get_gpio_from_pin(struct pinctrl_dev *pctrl_dev, > > + int pin) > > +{ > > + struct pinctrl_gpio_range *range; > > + int gpio; > > + > > + range = pinctrl_find_gpio_range_from_pin_nolock(pctrl_dev, pin); > > + if (!range) > > + return -EINVAL; > > + > > + gpio = pin - range->pin_base; > > + if (gpio < 0) > > + return -EINVAL; > > + > > + return gpio; > > +} > > This function is just used here: it is used in airoha_pinconf_get()/airoha_pinconf_set() > > > +static int airoha_pinconf_get(struct pinctrl_dev *pctrl_dev, > > + unsigned int pin, unsigned long *config) > > +{ > > + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); > > + enum pin_config_param param = pinconf_to_config_param(*config); > > + u32 arg; > > + > > + switch (param) { > > + case PIN_CONFIG_BIAS_PULL_DOWN: > > + case PIN_CONFIG_BIAS_DISABLE: > > + case PIN_CONFIG_BIAS_PULL_UP: { > > + u32 pull_up, pull_down; > > + > > + if (airoha_pinctrl_get_pullup_conf(pinctrl, pin, &pull_up) || > > + airoha_pinctrl_get_pulldown_conf(pinctrl, pin, &pull_down)) > > + return -EINVAL; > > + > > + if (param == PIN_CONFIG_BIAS_PULL_UP && > > + !(pull_up && !pull_down)) > > + return -EINVAL; > > + else if (param == PIN_CONFIG_BIAS_PULL_DOWN && > > + !(pull_down && !pull_up)) > > + return -EINVAL; > > + else if (pull_up || pull_down) > > + return -EINVAL; > > + > > + arg = 1; > > + break; > > + } > > + case PIN_CONFIG_DRIVE_STRENGTH: { > > + u32 e2, e4; > > + > > + if (airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, &e2) || > > + airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, &e4)) > > + return -EINVAL; > > + > > + arg = e4 << 1 | e2; > > + break; > > + } > > + case PIN_CONFIG_DRIVE_OPEN_DRAIN: > > + if (airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, &arg)) > > + return -EINVAL; > > + break; > > + case PIN_CONFIG_OUTPUT_ENABLE: > > + case PIN_CONFIG_INPUT_ENABLE: { > > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); > > + > > + if (gpio < 0) > > + return gpio; > > + > > + arg = airoha_pinctrl_gpio_get_direction(pinctrl, gpio); > > I don't see why a pin would have to exist in a GPIO range in order to > be set as output or input? > > Can't you just set up the pin as requested and not care whether > it has a corresponding GPIO range? > > Is it over-reuse of the GPIO code? I'd say just set up the pin instead. Do you mean to get rid of PIN_CONFIG_OUTPUT_ENABLE, PIN_CONFIG_INPUT_ENABLE (and even PIN_CONFIG_OUTPUT in airoha_pinconf_set()) here? E.g. we need PIN_CONFIG_OUTPUT_ENABLE to enable pwm for pwm-leds: &mfd { ... pio: pinctrl { ... pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins { function = "pwm"; pins = "gpio18"; output-enable; }; }; }; > > > +static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev, > > + unsigned int pin, unsigned long *configs, > > + unsigned int num_configs) > > +{ > > + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); > > + int i; > > + > > + for (i = 0; i < num_configs; i++) { > > + u32 param = pinconf_to_config_param(configs[i]); > > + u32 arg = pinconf_to_config_argument(configs[i]); > > + > > + switch (param) { > > + case PIN_CONFIG_BIAS_DISABLE: > > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); > > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); > > + break; > > + case PIN_CONFIG_BIAS_PULL_UP: > > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); > > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 1); > > + break; > > + case PIN_CONFIG_BIAS_PULL_DOWN: > > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 1); > > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); > > + break; > > + case PIN_CONFIG_DRIVE_STRENGTH: { > > + u32 e2 = 0, e4 = 0; > > + > > + switch (arg) { > > + case MTK_DRIVE_2mA: > > + break; > > + case MTK_DRIVE_4mA: > > + e2 = 1; > > + break; > > + case MTK_DRIVE_6mA: > > + e4 = 1; > > + break; > > + case MTK_DRIVE_8mA: > > + e2 = 1; > > + e4 = 1; > > + break; > > + default: > > + return -EINVAL; > > + } > > + > > + airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, e2); > > + airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, e4); > > + break; > > + } > > + case PIN_CONFIG_DRIVE_OPEN_DRAIN: > > + airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, !!arg); > > + break; > > + case PIN_CONFIG_OUTPUT_ENABLE: > > + case PIN_CONFIG_INPUT_ENABLE: > > + case PIN_CONFIG_OUTPUT: { > > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); > > + bool input = param == PIN_CONFIG_INPUT_ENABLE; > > + > > + if (gpio < 0) > > + return gpio; > > + > > + airoha_pinctrl_gpio_set_direction(pinctrl, gpio, input); > > + if (param == PIN_CONFIG_OUTPUT) > > + airoha_pinctrl_gpio_set_value(pinctrl, gpio, !!arg); > > + break; > > Dito. No need to reuse the GPIO set direction function. Make a helper > that just work on the pin instead, and perhaps the GPIO set direction > can use that instead. ack, I will fix it in v5. > > > +static int airoha_pinctrl_gpio_direction_output(struct gpio_chip *chip, > > + unsigned int gpio, int value) > > +{ > > + int err; > > + > > + err = pinctrl_gpio_direction_output(chip, gpio); > > + if (err) > > + return err; > > + > > + airoha_pinctrl_gpio_set(chip, gpio, value); > > Hm I get a bit confused by the similarly named helpers I guess... Naming is always hard, I will try to improve :) > > > +static void airoha_pinctrl_gpio_irq_unmask(struct irq_data *data) > > +{ > > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; > > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; > > + u32 mask = GENMASK(2 * offset + 1, 2 * offset); > > + struct airoha_pinctrl_gpiochip *gpiochip; > > + u32 val = BIT(2 * offset); > > + unsigned long flags; > > + > > + gpiochip = irq_data_get_irq_chip_data(data); > > + if (WARN_ON_ONCE(data->hwirq >= ARRAY_SIZE(gpiochip->irq_type))) > > + return; > > + > > + spin_lock_irqsave(&gpiochip->lock, flags); > > Use a scoped guard here > > guard(spinlock_irqsave)(&gpiochip->lock); > > > +static void airoha_pinctrl_gpio_irq_mask(struct irq_data *data) > > +{ > > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; > > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; > > + u32 mask = GENMASK(2 * offset + 1, 2 * offset); > > + struct airoha_pinctrl_gpiochip *gpiochip; > > + unsigned long flags; > > + > > + gpiochip = irq_data_get_irq_chip_data(data); > > + > > + spin_lock_irqsave(&gpiochip->lock, flags); > > Dito > > > +static int airoha_pinctrl_gpio_irq_type(struct irq_data *data, > > + unsigned int type) > > +{ > > + struct airoha_pinctrl_gpiochip *gpiochip; > > + unsigned long flags; > > + > > + gpiochip = irq_data_get_irq_chip_data(data); > > + if (data->hwirq >= ARRAY_SIZE(gpiochip->irq_type)) > > + return -EINVAL; > > + > > + spin_lock_irqsave(&gpiochip->lock, flags); > > Dito > > > + girq->chip = devm_kzalloc(dev, sizeof(*girq->chip), GFP_KERNEL); > > + if (!girq->chip) > > + return -ENOMEM; > > + > > + girq->chip->name = dev_name(dev); > > + girq->chip->irq_unmask = airoha_pinctrl_gpio_irq_unmask; > > + girq->chip->irq_mask = airoha_pinctrl_gpio_irq_mask; > > + girq->chip->irq_mask_ack = airoha_pinctrl_gpio_irq_mask; > > + girq->chip->irq_set_type = airoha_pinctrl_gpio_irq_type; > > + girq->chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE; > > + girq->default_type = IRQ_TYPE_NONE; > > + girq->handler = handle_simple_irq; > > If the irqchip is immutable it is const and there is no point to malloc it. > > Just > > static const struct irq_chip airoha_gpio_irq_chip = {... > > And assign it: > > girq = &g->gc.irq; > gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip); ack, I will fix it in v5. Regards, Lorenzo > > Yours, > Linus Walleij [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC 2024-09-24 10:12 ` Lorenzo Bianconi @ 2024-09-24 21:22 ` Lorenzo Bianconi 2024-10-02 12:58 ` Linus Walleij 1 sibling, 0 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-24 21:22 UTC (permalink / raw) To: Linus Walleij Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm [-- Attachment #1: Type: text/plain, Size: 10267 bytes --] [...] > > I am fine to switch to regmap but I guess we need to enable fast_io > since it can run even in interrupt context. Btw, I figured out even > airoha_pinctrl_rmw needs to grab a spin_lock since we can exec a led > trigger (like timer) where we run airoha_pinctrl_rmw in interrupt context > (so it should be fine to use a single regmap for it). > However, I guess we need to keep the spin_lock in airoha_pinctrl_gpiochip > since we need to grab it in airoha_pinctrl_gpio_irq_unmask() and > airoha_pinctrl_gpio_irq_type() (we access irq_type array there). > A possible solution would be to keep the local spin_lock and set > disable_locking. What do you think? Do you prefer to switch to regmap or > keep the current implementation using 'guard(spinlock_irqsave)' instead? I reworked the code using regmap APIs and setting disable_locking flag in order to keep the spinlock local (I switch to guard(spinlock) as well). Thx for pointing this out, the code is simpler and more readable, I will add it in v5. > > > > > > +static int airoha_pinctrl_get_gpio_from_pin(struct pinctrl_dev *pctrl_dev, > > > + int pin) > > > +{ > > > + struct pinctrl_gpio_range *range; > > > + int gpio; > > > + > > > + range = pinctrl_find_gpio_range_from_pin_nolock(pctrl_dev, pin); > > > + if (!range) > > > + return -EINVAL; > > > + > > > + gpio = pin - range->pin_base; > > > + if (gpio < 0) > > > + return -EINVAL; > > > + > > > + return gpio; > > > +} > > > > This function is just used here: > > it is used in airoha_pinconf_get()/airoha_pinconf_set() > > > [...] > > > + case PIN_CONFIG_OUTPUT_ENABLE: > > > + case PIN_CONFIG_INPUT_ENABLE: { > > > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); > > > + > > > + if (gpio < 0) > > > + return gpio; > > > + > > > + arg = airoha_pinctrl_gpio_get_direction(pinctrl, gpio); > > > > I don't see why a pin would have to exist in a GPIO range in order to > > be set as output or input? > > > > Can't you just set up the pin as requested and not care whether > > it has a corresponding GPIO range? > > > > Is it over-reuse of the GPIO code? I'd say just set up the pin instead. > > Do you mean to get rid of PIN_CONFIG_OUTPUT_ENABLE, PIN_CONFIG_INPUT_ENABLE > (and even PIN_CONFIG_OUTPUT in airoha_pinconf_set()) here? > E.g. we need PIN_CONFIG_OUTPUT_ENABLE to enable pwm for pwm-leds: > > &mfd { > ... > pio: pinctrl { > ... > pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins { > function = "pwm"; > pins = "gpio18"; > output-enable; > }; > }; > }; I reworked the code here in order to not explicitly use gpio value in airoha_pinconf_get/airoha_pinconf_set routines. However, we need to switch from pin to gpio configuring data/direction/out hw registers since: - not all pins can be used as gpio (actually we can configure just pins in the range [13, 59]) - data, dir and out hw register are indexed using gpio id and not pin one. (e.g BIT(0) in data[0] refers to GPIO0 and not to PIN0). Regards, Lorenzo > > > > > > +static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev, > > > + unsigned int pin, unsigned long *configs, > > > + unsigned int num_configs) > > > +{ > > > + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); > > > + int i; > > > + > > > + for (i = 0; i < num_configs; i++) { > > > + u32 param = pinconf_to_config_param(configs[i]); > > > + u32 arg = pinconf_to_config_argument(configs[i]); > > > + > > > + switch (param) { > > > + case PIN_CONFIG_BIAS_DISABLE: > > > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); > > > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); > > > + break; > > > + case PIN_CONFIG_BIAS_PULL_UP: > > > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); > > > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 1); > > > + break; > > > + case PIN_CONFIG_BIAS_PULL_DOWN: > > > + airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 1); > > > + airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); > > > + break; > > > + case PIN_CONFIG_DRIVE_STRENGTH: { > > > + u32 e2 = 0, e4 = 0; > > > + > > > + switch (arg) { > > > + case MTK_DRIVE_2mA: > > > + break; > > > + case MTK_DRIVE_4mA: > > > + e2 = 1; > > > + break; > > > + case MTK_DRIVE_6mA: > > > + e4 = 1; > > > + break; > > > + case MTK_DRIVE_8mA: > > > + e2 = 1; > > > + e4 = 1; > > > + break; > > > + default: > > > + return -EINVAL; > > > + } > > > + > > > + airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, e2); > > > + airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, e4); > > > + break; > > > + } > > > + case PIN_CONFIG_DRIVE_OPEN_DRAIN: > > > + airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, !!arg); > > > + break; > > > + case PIN_CONFIG_OUTPUT_ENABLE: > > > + case PIN_CONFIG_INPUT_ENABLE: > > > + case PIN_CONFIG_OUTPUT: { > > > + int gpio = airoha_pinctrl_get_gpio_from_pin(pctrl_dev, pin); > > > + bool input = param == PIN_CONFIG_INPUT_ENABLE; > > > + > > > + if (gpio < 0) > > > + return gpio; > > > + > > > + airoha_pinctrl_gpio_set_direction(pinctrl, gpio, input); > > > + if (param == PIN_CONFIG_OUTPUT) > > > + airoha_pinctrl_gpio_set_value(pinctrl, gpio, !!arg); > > > + break; > > > > Dito. No need to reuse the GPIO set direction function. Make a helper > > that just work on the pin instead, and perhaps the GPIO set direction > > can use that instead. > > ack, I will fix it in v5. > > > > > > +static int airoha_pinctrl_gpio_direction_output(struct gpio_chip *chip, > > > + unsigned int gpio, int value) > > > +{ > > > + int err; > > > + > > > + err = pinctrl_gpio_direction_output(chip, gpio); > > > + if (err) > > > + return err; > > > + > > > + airoha_pinctrl_gpio_set(chip, gpio, value); > > > > Hm I get a bit confused by the similarly named helpers I guess... > > Naming is always hard, I will try to improve :) > > > > > > +static void airoha_pinctrl_gpio_irq_unmask(struct irq_data *data) > > > +{ > > > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; > > > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; > > > + u32 mask = GENMASK(2 * offset + 1, 2 * offset); > > > + struct airoha_pinctrl_gpiochip *gpiochip; > > > + u32 val = BIT(2 * offset); > > > + unsigned long flags; > > > + > > > + gpiochip = irq_data_get_irq_chip_data(data); > > > + if (WARN_ON_ONCE(data->hwirq >= ARRAY_SIZE(gpiochip->irq_type))) > > > + return; > > > + > > > + spin_lock_irqsave(&gpiochip->lock, flags); > > > > Use a scoped guard here > > > > guard(spinlock_irqsave)(&gpiochip->lock); > > > > > +static void airoha_pinctrl_gpio_irq_mask(struct irq_data *data) > > > +{ > > > + u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_GPIO; > > > + u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_GPIO; > > > + u32 mask = GENMASK(2 * offset + 1, 2 * offset); > > > + struct airoha_pinctrl_gpiochip *gpiochip; > > > + unsigned long flags; > > > + > > > + gpiochip = irq_data_get_irq_chip_data(data); > > > + > > > + spin_lock_irqsave(&gpiochip->lock, flags); > > > > Dito > > > > > +static int airoha_pinctrl_gpio_irq_type(struct irq_data *data, > > > + unsigned int type) > > > +{ > > > + struct airoha_pinctrl_gpiochip *gpiochip; > > > + unsigned long flags; > > > + > > > + gpiochip = irq_data_get_irq_chip_data(data); > > > + if (data->hwirq >= ARRAY_SIZE(gpiochip->irq_type)) > > > + return -EINVAL; > > > + > > > + spin_lock_irqsave(&gpiochip->lock, flags); > > > > Dito > > > > > + girq->chip = devm_kzalloc(dev, sizeof(*girq->chip), GFP_KERNEL); > > > + if (!girq->chip) > > > + return -ENOMEM; > > > + > > > + girq->chip->name = dev_name(dev); > > > + girq->chip->irq_unmask = airoha_pinctrl_gpio_irq_unmask; > > > + girq->chip->irq_mask = airoha_pinctrl_gpio_irq_mask; > > > + girq->chip->irq_mask_ack = airoha_pinctrl_gpio_irq_mask; > > > + girq->chip->irq_set_type = airoha_pinctrl_gpio_irq_type; > > > + girq->chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE; > > > + girq->default_type = IRQ_TYPE_NONE; > > > + girq->handler = handle_simple_irq; > > > > If the irqchip is immutable it is const and there is no point to malloc it. > > > > Just > > > > static const struct irq_chip airoha_gpio_irq_chip = {... > > > > And assign it: > > > > girq = &g->gc.irq; > > gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip); > > ack, I will fix it in v5. > > Regards, > Lorenzo > > > > > Yours, > > Linus Walleij [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC 2024-09-24 10:12 ` Lorenzo Bianconi 2024-09-24 21:22 ` Lorenzo Bianconi @ 2024-10-02 12:58 ` Linus Walleij 2024-10-02 15:36 ` Lorenzo Bianconi 1 sibling, 1 reply; 20+ messages in thread From: Linus Walleij @ 2024-10-02 12:58 UTC (permalink / raw) To: Lorenzo Bianconi Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm Hi Lorenzo, so these comments: On Tue, Sep 24, 2024 at 12:12 PM Lorenzo Bianconi <lorenzo@kernel.org> wrote: > > > +#include <linux/pinctrl/consumer.h> > > > > Why do you need the consumer header? > > we need it for pinctrl_gpio_direction_output() and > pinctrl_gpio_direction_input() for direction_input and direction_output > callbacks. I looked it over again and it looks good, I was just confused. > > > + arg = airoha_pinctrl_gpio_get_direction(pinctrl, gpio); > > > > I don't see why a pin would have to exist in a GPIO range in order to > > be set as output or input? > > > > Can't you just set up the pin as requested and not care whether > > it has a corresponding GPIO range? > > > > Is it over-reuse of the GPIO code? I'd say just set up the pin instead. > > Do you mean to get rid of PIN_CONFIG_OUTPUT_ENABLE, PIN_CONFIG_INPUT_ENABLE > (and even PIN_CONFIG_OUTPUT in airoha_pinconf_set()) here? > E.g. we need PIN_CONFIG_OUTPUT_ENABLE to enable pwm for pwm-leds: I was mainly thinking that the airoha_pinctrl_gpio_get_direction() is limited to pins that are used for GPIO. The callback should be usable on any pins, no matter if they can be muxed to GPIO or not? > &mfd { > ... > pio: pinctrl { > ... > pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins { > function = "pwm"; > pins = "gpio18"; > output-enable; > }; > }; > }; Like this one. Which I think works. It's the name of the function which confuses me: airoha_pinctrl_gpio_get_direction() and anything else that is used directly from the airoha_pinconf_set() function doesn't really care if the pin is used as GPIO or not does it? Can you rename the functions just e.g. airoha_pinctrl_get_direction() because it has nothing to do with GPIO. It's jus pin control. Also some defines are confusing this way: + /* set output enable */ + mask = BIT(gpio % AIROHA_GPIO_BANK_SIZE); + index = gpio / AIROHA_GPIO_BANK_SIZE; + airoha_pinctrl_rmw(pinctrl, pinctrl->gpiochip.out[index], + mask, !input ? mask : 0); Variables named "gpio" and AIROHA_GPIO_BANK_SIZE despite it is used for pins that are not (in the Linux sense) GPIO all the time. This is a big confusion for the mind. Can you rename the variable from "gpio" to "pin" or so and the AIROHA_GPIO_BANK_SIZE to AIROHA_PIN_BANK_SIZE etc so it is clear what is going on? I understand that the datasheet might be talking about "GPIO this and GPIO that" but what hardware engineers mean with GPIO is something else than what Linux mean: for them it means "it can be muxed so it is kinda-general-purpose-kinda" but in Linux this has a strict meaning: it can be used by the gpiolib to control individual lines. I think this would make it easier for me (and possibly others) ton understand the driver. Yours, Linus Walleij ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC 2024-10-02 12:58 ` Linus Walleij @ 2024-10-02 15:36 ` Lorenzo Bianconi 0 siblings, 0 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-10-02 15:36 UTC (permalink / raw) To: Linus Walleij Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm [-- Attachment #1: Type: text/plain, Size: 3332 bytes --] > Hi Lorenzo, > > so these comments: > > On Tue, Sep 24, 2024 at 12:12 PM Lorenzo Bianconi <lorenzo@kernel.org> wrote: > > > > > +#include <linux/pinctrl/consumer.h> > > > > > > Why do you need the consumer header? > > > > we need it for pinctrl_gpio_direction_output() and > > pinctrl_gpio_direction_input() for direction_input and direction_output > > callbacks. > > I looked it over again and it looks good, I was just confused. ack, no worries. > > > > > + arg = airoha_pinctrl_gpio_get_direction(pinctrl, gpio); > > > > > > I don't see why a pin would have to exist in a GPIO range in order to > > > be set as output or input? > > > > > > Can't you just set up the pin as requested and not care whether > > > it has a corresponding GPIO range? > > > > > > Is it over-reuse of the GPIO code? I'd say just set up the pin instead. > > > > Do you mean to get rid of PIN_CONFIG_OUTPUT_ENABLE, PIN_CONFIG_INPUT_ENABLE > > (and even PIN_CONFIG_OUTPUT in airoha_pinconf_set()) here? > > E.g. we need PIN_CONFIG_OUTPUT_ENABLE to enable pwm for pwm-leds: > > I was mainly thinking that the > airoha_pinctrl_gpio_get_direction() is limited to pins that are > used for GPIO. > > The callback should be usable on any pins, no matter if they > can be muxed to GPIO or not? > > > &mfd { > > ... > > pio: pinctrl { > > ... > > pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins { > > function = "pwm"; > > pins = "gpio18"; > > output-enable; > > }; > > }; > > }; > > Like this one. > > Which I think works. > > It's the name of the function which confuses me: > airoha_pinctrl_gpio_get_direction() and anything else that > is used directly from the airoha_pinconf_set() function > doesn't really care if the pin is used as GPIO or not does > it? > > Can you rename the functions just e.g. airoha_pinctrl_get_direction() > because it has nothing to do with GPIO. It's jus pin control. ack, I will do in v6 > > Also some defines are confusing this way: > > + /* set output enable */ > + mask = BIT(gpio % AIROHA_GPIO_BANK_SIZE); > + index = gpio / AIROHA_GPIO_BANK_SIZE; > + airoha_pinctrl_rmw(pinctrl, pinctrl->gpiochip.out[index], > + mask, !input ? mask : 0); > > Variables named "gpio" and AIROHA_GPIO_BANK_SIZE despite > it is used for pins that are not (in the Linux sense) GPIO all the time. > This is a big confusion for the mind. > > Can you rename the variable from "gpio" to "pin" or so > and the AIROHA_GPIO_BANK_SIZE to AIROHA_PIN_BANK_SIZE > etc so it is clear what is going on? ack, I will do in v6 > > I understand that the datasheet might be talking about > "GPIO this and GPIO that" but what hardware engineers mean > with GPIO is something else than what Linux mean: for them > it means "it can be muxed so it is kinda-general-purpose-kinda" > but in Linux this has a strict meaning: it can be used by the > gpiolib to control individual lines. > > I think this would make it easier for me (and possibly others) > ton understand the driver. ack. Regards, Lorenzo > > Yours, > Linus Walleij [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 5/5] pwm: airoha: Add support for EN7581 SoC 2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi ` (3 preceding siblings ...) 2024-09-11 19:50 ` [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC Lorenzo Bianconi @ 2024-09-11 19:50 ` Lorenzo Bianconi 2024-09-23 9:53 ` [PATCH v4 0/5] Add mfd, pinctrl and pwm support to " Christian Marangi 5 siblings, 0 replies; 20+ messages in thread From: Lorenzo Bianconi @ 2024-09-11 19:50 UTC (permalink / raw) To: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König Cc: linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, ansuelsmth, linux-pwm From: Benjamin Larsson <benjamin.larsson@genexis.eu> Introduce driver for PWM module available on EN7581 SoC. Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> --- drivers/pwm/Kconfig | 10 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-airoha.c | 414 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 425 insertions(+) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 3e53838990f5..0a78bda0707d 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -47,6 +47,16 @@ config PWM_AB8500 To compile this driver as a module, choose M here: the module will be called pwm-ab8500. +config PWM_AIROHA + tristate "Airoha PWM support" + depends on ARCH_AIROHA || COMPILE_TEST + depends on OF + 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 0be4f3e6dd43..7ee61822d88d 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PWM) += core.o obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.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 000000000000..bab2e15e06e7 --- /dev/null +++ b/drivers/pwm/pwm-airoha.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 Markus Gothe <markus.gothe@genexis.eu> + * + * 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 <linux/bitfield.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/mfd/airoha-en7581-mfd.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/gpio.h> +#include <linux/bitops.h> +#include <asm/div64.h> + +#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)) + +struct airoha_pwm { + void __iomem *base; + + struct device_node *np; + u64 initialized; + + struct { + /* Bitmask of PWM channels using this bucket */ + u64 used; + u64 period_ns; + u64 duty_ns; + } bucket[8]; +}; + +/* + * 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 u32 airoha_pwm_rmw(struct airoha_pwm *pc, u32 addr, u32 mask, u32 val) +{ + val |= (readl(pc->base + addr) & ~mask); + writel(val, pc->base + addr); + + return val; +} + +#define airoha_pwm_set_bits(pc, addr, val) \ + airoha_pwm_rmw((pc), (addr), (val), (val)) + +#define airoha_pwm_clear_bit(pc, addr, mask) \ + airoha_pwm_rmw(pc, addr, mask, 0) + +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 = 3, sipo_clock_delay = 1; + u32 val, sipo_clock_divisor = 32; + + if (!(pc->initialized >> PWM_NUM_GPIO)) + return 0; + + /* Select the right shift register chip */ + if (of_property_read_bool(pc->np, "hc74595")) + airoha_pwm_set_bits(pc, REG_SIPO_FLASH_MODE_CFG, + SERIAL_GPIO_MODE); + else + airoha_pwm_clear_bit(pc, REG_SIPO_FLASH_MODE_CFG, + SERIAL_GPIO_MODE); + + if (!of_property_read_u32(pc->np, "sipo-clock-divisor", + &sipo_clock_divisor)) { + 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 */ + writel(clk_divr_val, pc->base + REG_SGPIO_CLK_DIVR); + + of_property_read_u32(pc->np, "sipo-clock-delay", &sipo_clock_delay); + 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--; + writel(sipo_clock_delay, pc->base + REG_SGPIO_CLK_DLY); + + /* + * 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 (readl_poll_timeout(pc->base + REG_SGPIO_LED_DATA, val, + !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10, + 200 * USEC_PER_MSEC)) + return -ETIMEDOUT; + + airoha_pwm_clear_bit(pc, REG_SGPIO_LED_DATA, SGPIO_LED_DATA_DATA); + if (readl_poll_timeout(pc->base + REG_SGPIO_LED_DATA, val, + !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10, + 200 * USEC_PER_MSEC)) + return -ETIMEDOUT; + + /* Set SIPO in PWM mode */ + airoha_pwm_set_bits(pc, 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; + airoha_pwm_rmw(pc, 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; + airoha_pwm_rmw(pc, 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 + */ + airoha_pwm_clear_bit(pc, addr, GPIO_FLASH_EN(hwpwm % 8)); + return; + } + + mask = GPIO_FLASH_SETID_MASK(hwpwm % 8); + val = ((index & 7) << __ffs(mask)) & mask; + airoha_pwm_rmw(pc, addr, mask, val); + airoha_pwm_set_bits(pc, 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)) + airoha_pwm_clear_bit(pc, 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_mfd *mfd; + struct airoha_pwm *pc; + struct pwm_chip *chip; + + /* Assign parent MFD of_node to dev */ + device_set_of_node_from_dev(dev, dev->parent); + mfd = dev_get_drvdata(dev->parent); + + chip = devm_pwmchip_alloc(dev, PWM_NUM_GPIO + PWM_NUM_SIPO, + sizeof(*pc)); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + pc = pwmchip_get_drvdata(chip); + pc->np = dev->of_node; + pc->base = mfd->base; + chip->ops = &airoha_pwm_ops; + + return devm_pwmchip_add(&pdev->dev, chip); +} + +static struct platform_driver airoha_pwm_driver = { + .driver = { + .name = "pwm-airoha", + }, + .probe = airoha_pwm_probe, +}; +module_platform_driver(airoha_pwm_driver); + +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); +MODULE_AUTHOR("Markus Gothe <markus.gothe@genexis.eu>"); +MODULE_AUTHOR("Benjamin Larsson <benjamin.larsson@genexis.eu>"); +MODULE_DESCRIPTION("Airoha EN7581 PWM driver"); +MODULE_LICENSE("GPL"); -- 2.46.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC 2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi ` (4 preceding siblings ...) 2024-09-11 19:50 ` [PATCH v4 5/5] pwm: " Lorenzo Bianconi @ 2024-09-23 9:53 ` Christian Marangi 2024-09-25 9:47 ` Lee Jones 5 siblings, 1 reply; 20+ messages in thread From: Christian Marangi @ 2024-09-23 9:53 UTC (permalink / raw) To: Lorenzo Bianconi Cc: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Lee Jones, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, linux-pwm On Wed, Sep 11, 2024 at 09:50:00PM +0200, Lorenzo Bianconi wrote: > Introduce airoha-mfd driver in order to load pinctrl and pwm drivers for > EN7581 SoC. airoha-mfd is needed since both pinctrl and pwm drivers > needs to access the same memory block (gpio memory region) to configure > {gio,irq}_chip and pwm functionalities respectively, so model them as > childs of a parent mfd driver. > Current EN7581 pinctrl driver supports the following functionalities: > - pin multiplexing via chip_scu syscon > - pin pull-up, pull-down, open-drain, current strength, > {input,output}_enable, output_{low,high} via chip_scu syscon > - gpio controller > - irq controller > > --- > Changes in v4: > - add 'Limitation' description in pwm driver > - fix comments in pwm driver > - rely on mfd->base __iomem pointer in pwm driver, modify register > offsets according to it and get rid of sgpio_cfg, flash_cfg and > cycle_cfg pointers > - simplify register utility routines in pwm driver > - use 'generator' instead of 'waveform' suffix for pwm routines > - fix possible overflow calculating duty cycle in pwm driver > - do not modify pwm state in free callback in pwm driver > - cap the maximum period in pwm driver > - do not allow inverse polarity in pwm driver > - do not set of_xlate callback in the pwm driver and allow the stack to > do it > - fix MAINTAINERS file for airoha pinctrl driver > - fix undefined reference to __ffsdi2 in pinctrl driver > - simplify airoha,en7581-gpio-sysctl.yam binding > - Link to v3: https://lore.kernel.org/r/20240831-en7581-pinctrl-v3-0-98eebfb4da66@kernel.org > > Changes in v3: > - introduce airoha-mfd driver > - add pwm driver to the same series > - model pinctrl and pwm drivers as childs of a parent mfd driver. > - access chip-scu memory region in pinctrl driver via syscon > - introduce a single airoha,en7581-gpio-sysctl.yaml binding and get rid > of dedicated bindings for pinctrl and pwm > - add airoha,en7581-chip-scu.yaml binding do the series > - Link to v2: https://lore.kernel.org/r/20240822-en7581-pinctrl-v2-0-ba1559173a7f@kernel.org > > Changes in v2: > - Fix compilation errors > - Collapse some register mappings for gpio and irq controllers > - update dt-bindings according to new register mapping > - fix some dt-bindings errors > - Link to v1: https://lore.kernel.org/all/cover.1723392444.git.lorenzo@kernel.org/ > > --- > Benjamin Larsson (1): > pwm: airoha: Add support for EN7581 SoC > > Christian Marangi (2): > dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller > mfd: airoha: Add support for Airoha EN7581 MFD > > Lorenzo Bianconi (2): > dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC > pinctrl: airoha: Add support for EN7581 SoC > > .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 + > .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++ > MAINTAINERS | 7 + > drivers/mfd/Kconfig | 8 + > drivers/mfd/Makefile | 2 + > drivers/mfd/airoha-en7581-gpio-mfd.c | 72 + > drivers/pinctrl/mediatek/Kconfig | 16 +- > drivers/pinctrl/mediatek/Makefile | 1 + > drivers/pinctrl/mediatek/pinctrl-airoha.c | 2964 ++++++++++++++++++++ > drivers/pwm/Kconfig | 10 + > drivers/pwm/Makefile | 1 + > drivers/pwm/pwm-airoha.c | 414 +++ > include/linux/mfd/airoha-en7581-mfd.h | 9 + > 13 files changed, 3978 insertions(+), 1 deletion(-) > --- > base-commit: 264c13114bd71ddfd7b25c7b94f6cda4587eca25 > change-id: 20240818-en7581-pinctrl-1bf120154be0 > prerequisite-change-id: 20240705-for-6-11-bpf-a349efc08df8:v2 > > Hi, any news with this? Rob reviewed the DT schemas and he is ok with them. Any other comments for the MFD driver and/or the pinctrl or PWM driver? -- Ansuel ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC 2024-09-23 9:53 ` [PATCH v4 0/5] Add mfd, pinctrl and pwm support to " Christian Marangi @ 2024-09-25 9:47 ` Lee Jones 2024-09-25 9:51 ` Christian Marangi 0 siblings, 1 reply; 20+ messages in thread From: Lee Jones @ 2024-09-25 9:47 UTC (permalink / raw) To: Christian Marangi Cc: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, linux-pwm On Mon, 23 Sep 2024, Christian Marangi wrote: > On Wed, Sep 11, 2024 at 09:50:00PM +0200, Lorenzo Bianconi wrote: > > Introduce airoha-mfd driver in order to load pinctrl and pwm drivers for > > EN7581 SoC. airoha-mfd is needed since both pinctrl and pwm drivers > > needs to access the same memory block (gpio memory region) to configure > > {gio,irq}_chip and pwm functionalities respectively, so model them as > > childs of a parent mfd driver. > > Current EN7581 pinctrl driver supports the following functionalities: > > - pin multiplexing via chip_scu syscon > > - pin pull-up, pull-down, open-drain, current strength, > > {input,output}_enable, output_{low,high} via chip_scu syscon > > - gpio controller > > - irq controller > > > > --- > > Changes in v4: > > - add 'Limitation' description in pwm driver > > - fix comments in pwm driver > > - rely on mfd->base __iomem pointer in pwm driver, modify register > > offsets according to it and get rid of sgpio_cfg, flash_cfg and > > cycle_cfg pointers > > - simplify register utility routines in pwm driver > > - use 'generator' instead of 'waveform' suffix for pwm routines > > - fix possible overflow calculating duty cycle in pwm driver > > - do not modify pwm state in free callback in pwm driver > > - cap the maximum period in pwm driver > > - do not allow inverse polarity in pwm driver > > - do not set of_xlate callback in the pwm driver and allow the stack to > > do it > > - fix MAINTAINERS file for airoha pinctrl driver > > - fix undefined reference to __ffsdi2 in pinctrl driver > > - simplify airoha,en7581-gpio-sysctl.yam binding > > - Link to v3: https://lore.kernel.org/r/20240831-en7581-pinctrl-v3-0-98eebfb4da66@kernel.org > > > > Changes in v3: > > - introduce airoha-mfd driver > > - add pwm driver to the same series > > - model pinctrl and pwm drivers as childs of a parent mfd driver. > > - access chip-scu memory region in pinctrl driver via syscon > > - introduce a single airoha,en7581-gpio-sysctl.yaml binding and get rid > > of dedicated bindings for pinctrl and pwm > > - add airoha,en7581-chip-scu.yaml binding do the series > > - Link to v2: https://lore.kernel.org/r/20240822-en7581-pinctrl-v2-0-ba1559173a7f@kernel.org > > > > Changes in v2: > > - Fix compilation errors > > - Collapse some register mappings for gpio and irq controllers > > - update dt-bindings according to new register mapping > > - fix some dt-bindings errors > > - Link to v1: https://lore.kernel.org/all/cover.1723392444.git.lorenzo@kernel.org/ > > > > --- > > Benjamin Larsson (1): > > pwm: airoha: Add support for EN7581 SoC > > > > Christian Marangi (2): > > dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller > > mfd: airoha: Add support for Airoha EN7581 MFD > > > > Lorenzo Bianconi (2): > > dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC > > pinctrl: airoha: Add support for EN7581 SoC > > > > .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 + > > .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++ > > MAINTAINERS | 7 + > > drivers/mfd/Kconfig | 8 + > > drivers/mfd/Makefile | 2 + > > drivers/mfd/airoha-en7581-gpio-mfd.c | 72 + > > drivers/pinctrl/mediatek/Kconfig | 16 +- > > drivers/pinctrl/mediatek/Makefile | 1 + > > drivers/pinctrl/mediatek/pinctrl-airoha.c | 2964 ++++++++++++++++++++ > > drivers/pwm/Kconfig | 10 + > > drivers/pwm/Makefile | 1 + > > drivers/pwm/pwm-airoha.c | 414 +++ > > include/linux/mfd/airoha-en7581-mfd.h | 9 + > > 13 files changed, 3978 insertions(+), 1 deletion(-) > > --- > > base-commit: 264c13114bd71ddfd7b25c7b94f6cda4587eca25 > > change-id: 20240818-en7581-pinctrl-1bf120154be0 > > prerequisite-change-id: 20240705-for-6-11-bpf-a349efc08df8:v2 > > > > > > Hi, > > any news with this? Rob reviewed the DT schemas and he is ok with them. > > Any other comments for the MFD driver and/or the pinctrl or PWM driver? Note that the merge-window is still open. Some maintainers, myself included, use this lull to prioritise other things. This set is on my list and will be dealt with shortly. -- Lee Jones [李琼斯] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC 2024-09-25 9:47 ` Lee Jones @ 2024-09-25 9:51 ` Christian Marangi 0 siblings, 0 replies; 20+ messages in thread From: Christian Marangi @ 2024-09-25 9:51 UTC (permalink / raw) To: Lee Jones Cc: Lorenzo Bianconi, Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno, Uwe Kleine-König, linux-mediatek, linux-gpio, devicetree, linux-arm-kernel, upstream, benjamin.larsson, linux-pwm On Wed, Sep 25, 2024 at 10:47:38AM +0100, Lee Jones wrote: > On Mon, 23 Sep 2024, Christian Marangi wrote: > > > On Wed, Sep 11, 2024 at 09:50:00PM +0200, Lorenzo Bianconi wrote: > > > Introduce airoha-mfd driver in order to load pinctrl and pwm drivers for > > > EN7581 SoC. airoha-mfd is needed since both pinctrl and pwm drivers > > > needs to access the same memory block (gpio memory region) to configure > > > {gio,irq}_chip and pwm functionalities respectively, so model them as > > > childs of a parent mfd driver. > > > Current EN7581 pinctrl driver supports the following functionalities: > > > - pin multiplexing via chip_scu syscon > > > - pin pull-up, pull-down, open-drain, current strength, > > > {input,output}_enable, output_{low,high} via chip_scu syscon > > > - gpio controller > > > - irq controller > > > > > > --- > > > Changes in v4: > > > - add 'Limitation' description in pwm driver > > > - fix comments in pwm driver > > > - rely on mfd->base __iomem pointer in pwm driver, modify register > > > offsets according to it and get rid of sgpio_cfg, flash_cfg and > > > cycle_cfg pointers > > > - simplify register utility routines in pwm driver > > > - use 'generator' instead of 'waveform' suffix for pwm routines > > > - fix possible overflow calculating duty cycle in pwm driver > > > - do not modify pwm state in free callback in pwm driver > > > - cap the maximum period in pwm driver > > > - do not allow inverse polarity in pwm driver > > > - do not set of_xlate callback in the pwm driver and allow the stack to > > > do it > > > - fix MAINTAINERS file for airoha pinctrl driver > > > - fix undefined reference to __ffsdi2 in pinctrl driver > > > - simplify airoha,en7581-gpio-sysctl.yam binding > > > - Link to v3: https://lore.kernel.org/r/20240831-en7581-pinctrl-v3-0-98eebfb4da66@kernel.org > > > > > > Changes in v3: > > > - introduce airoha-mfd driver > > > - add pwm driver to the same series > > > - model pinctrl and pwm drivers as childs of a parent mfd driver. > > > - access chip-scu memory region in pinctrl driver via syscon > > > - introduce a single airoha,en7581-gpio-sysctl.yaml binding and get rid > > > of dedicated bindings for pinctrl and pwm > > > - add airoha,en7581-chip-scu.yaml binding do the series > > > - Link to v2: https://lore.kernel.org/r/20240822-en7581-pinctrl-v2-0-ba1559173a7f@kernel.org > > > > > > Changes in v2: > > > - Fix compilation errors > > > - Collapse some register mappings for gpio and irq controllers > > > - update dt-bindings according to new register mapping > > > - fix some dt-bindings errors > > > - Link to v1: https://lore.kernel.org/all/cover.1723392444.git.lorenzo@kernel.org/ > > > > > > --- > > > Benjamin Larsson (1): > > > pwm: airoha: Add support for EN7581 SoC > > > > > > Christian Marangi (2): > > > dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller > > > mfd: airoha: Add support for Airoha EN7581 MFD > > > > > > Lorenzo Bianconi (2): > > > dt-bindings: arm: airoha: Add the chip-scu node for EN7581 SoC > > > pinctrl: airoha: Add support for EN7581 SoC > > > > > > .../bindings/arm/airoha,en7581-chip-scu.yaml | 42 + > > > .../bindings/mfd/airoha,en7581-gpio-sysctl.yaml | 433 +++ > > > MAINTAINERS | 7 + > > > drivers/mfd/Kconfig | 8 + > > > drivers/mfd/Makefile | 2 + > > > drivers/mfd/airoha-en7581-gpio-mfd.c | 72 + > > > drivers/pinctrl/mediatek/Kconfig | 16 +- > > > drivers/pinctrl/mediatek/Makefile | 1 + > > > drivers/pinctrl/mediatek/pinctrl-airoha.c | 2964 ++++++++++++++++++++ > > > drivers/pwm/Kconfig | 10 + > > > drivers/pwm/Makefile | 1 + > > > drivers/pwm/pwm-airoha.c | 414 +++ > > > include/linux/mfd/airoha-en7581-mfd.h | 9 + > > > 13 files changed, 3978 insertions(+), 1 deletion(-) > > > --- > > > base-commit: 264c13114bd71ddfd7b25c7b94f6cda4587eca25 > > > change-id: 20240818-en7581-pinctrl-1bf120154be0 > > > prerequisite-change-id: 20240705-for-6-11-bpf-a349efc08df8:v2 > > > > > > > > > > Hi, > > > > any news with this? Rob reviewed the DT schemas and he is ok with them. > > > > Any other comments for the MFD driver and/or the pinctrl or PWM driver? > > Note that the merge-window is still open. Some maintainers, myself > included, use this lull to prioritise other things. This set is on my > list and will be dealt with shortly. > Wasn't aware the merge window was still open and sorry for the noise. Thanks for the feedback! -- Ansuel ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2024-10-02 15:36 UTC | newest] Thread overview: 20+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-09-11 19:50 [PATCH v4 0/5] Add mfd, pinctrl and pwm support to EN7581 SoC Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 1/5] dt-bindings: arm: airoha: Add the chip-scu node for " Lorenzo Bianconi 2024-09-11 21:12 ` Rob Herring (Arm) 2024-09-11 21:46 ` Lorenzo Bianconi 2024-09-12 16:43 ` Rob Herring 2024-09-11 19:50 ` [PATCH v4 2/5] dt-bindings: mfd: Add support for Airoha EN7581 GPIO System Controller Lorenzo Bianconi 2024-09-11 21:12 ` Rob Herring (Arm) 2024-09-11 21:48 ` Lorenzo Bianconi 2024-09-12 16:44 ` Rob Herring (Arm) 2024-09-11 19:50 ` [PATCH v4 3/5] mfd: airoha: Add support for Airoha EN7581 MFD Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 4/5] pinctrl: airoha: Add support for EN7581 SoC Lorenzo Bianconi 2024-09-24 7:34 ` Linus Walleij 2024-09-24 10:12 ` Lorenzo Bianconi 2024-09-24 21:22 ` Lorenzo Bianconi 2024-10-02 12:58 ` Linus Walleij 2024-10-02 15:36 ` Lorenzo Bianconi 2024-09-11 19:50 ` [PATCH v4 5/5] pwm: " Lorenzo Bianconi 2024-09-23 9:53 ` [PATCH v4 0/5] Add mfd, pinctrl and pwm support to " Christian Marangi 2024-09-25 9:47 ` Lee Jones 2024-09-25 9:51 ` Christian Marangi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).