diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-02 15:47:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-02 15:47:18 -0700 |
commit | bc3b3f4bfbded031a11c4284106adddbfacd05bb (patch) | |
tree | ce31309cc4c4dc85f89ee136154dd8ee38eef925 | |
parent | 11786191e2d946410cf5fde482b10cdd5356e76c (diff) | |
parent | c42f69b4207e104229242c3d9da43b55d4b95d6d (diff) |
Merge tag 'pinctrl-v5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij:
"This is the bulk of pin control changes for the v5.7 kernel cycle.
There are no core changes this time, only driver developments:
- New driver for the Dialog Semiconductor DA9062 Power Management
Integrated Circuit (PMIC).
- Renesas SH-PFC has improved consistency, with group and register
checks in the configuration checker.
- New subdriver for the Qualcomm IPQ6018.
- Add the RGMII pin control functionality to Qualcomm IPQ8064.
- Performance and code quality cleanups in the Mediatek driver.
- Improve the Broadcom BCM2835 support to cover all the GPIOs that
exist in it.
- The Allwinner/Sunxi driver properly masks non-wakeup IRQs on
suspend.
- Add some missing groups and functions to the Ingenic driver.
- Convert some of the Freescale device tree bindings to use the new
and all improved JSON YAML markup.
- Refactorings and support for the SFIO/GPIO in the Tegra194 SoC
driver.
- Support high impedance mode in the Spreadtrum/Unisoc driver"
* tag 'pinctrl-v5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (64 commits)
pinctrl: qcom: fix compilation error
pinctrl: qcom: use scm_call to route GPIO irq to Apps
pinctrl: sprd: Add pin high impedance mode support
pinctrl: sprd: Use the correct pin output configuration
pinctrl: tegra: Add SFIO/GPIO programming on Tegra194
pinctrl: tegra: Renumber the GG.0 and GG.1 pins
pinctrl: tegra: Do not add default pin range on Tegra194
pinctrl: tegra: Pass struct tegra_pmx for pin range check
pinctrl: tegra: Fix "Scmitt" -> "Schmitt" typo
pinctrl: tegra: Fix whitespace issues for improved readability
pinctrl: mediatek: Use scnprintf() for avoiding potential buffer overflow
pinctrl: freescale: drop the dependency on ARM64 for i.MX8M
Revert "pinctrl: mvebu: armada-37xx: use use platform api"
dt-bindings: pinctrl: at91: Fix a typo ("descibe")
pinctrl: meson: add tsin pinctrl for meson gxbb/gxl/gxm
pinctrl: sprd: Fix the kconfig warning
pinctrl: ingenic: add hdmi-ddc pin control group
pinctrl: sirf/atlas7: Replace zero-length array with flexible-array member
pinctrl: sprd: Allow the SPRD pinctrl driver building into a module
pinctrl: Export some needed symbols at module load time
...
64 files changed, 3350 insertions, 743 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt index eb39f5051159..e8abbdad7b5d 100644 --- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt @@ -38,7 +38,7 @@ Bank: 3 (A, B and C) 0xffffffff 0x7fff3ccf /* pioB */ 0xffffffff 0x007fffff /* pioC */ -For each peripheral/bank we will descibe in a u32 if a pin can be +For each peripheral/bank we will describe in a u32 if a pin can be configured in it by putting 1 to the pin bit (1 << pin) Let's take the pioA on peripheral B diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.txt deleted file mode 100644 index e4e01c05cf83..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.txt +++ /dev/null @@ -1,36 +0,0 @@ -* Freescale IMX8MM IOMUX Controller - -Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory -for common binding part and usage. - -Required properties: -- compatible: "fsl,imx8mm-iomuxc" -- reg: should contain the base physical address and size of the iomuxc - registers. - -Required properties in sub-nodes: -- fsl,pins: each entry consists of 6 integers and represents the mux and config - setting for one pin. The first 5 integers <mux_reg conf_reg input_reg mux_val - input_val> are specified using a PIN_FUNC_ID macro, which can be found in - <arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h>. The last integer CONFIG is - the pad setting value like pull-up on this pin. Please refer to i.MX8M Mini - Reference Manual for detailed CONFIG settings. - -Examples: - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; -}; - -iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mm-iomuxc"; - reg = <0x0 0x30330000 0x0 0x10000>; - - pinctrl_uart1: uart1grp { - fsl,pins = < - MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140 - MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140 - >; - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.yaml new file mode 100644 index 000000000000..d98a3866add8 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mm-pinctrl.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imx8mm-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale IMX8MM IOMUX Controller + +maintainers: + - Anson Huang <Anson.Huang@nxp.com> + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + const: fsl,imx8mm-iomuxc + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers <mux_reg conf_reg input_reg + mux_val input_val> are specified using a PIN_FUNC_ID macro, which can + be found in <arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h>. The last + integer CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MX8M Mini Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + + required: + - fsl,pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + # Pinmux controller node + - | + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx8mm-iomuxc"; + reg = <0x30330000 0x10000>; + + pinctrl_uart2: uart2grp { + fsl,pins = + <0x23C 0x4A4 0x4FC 0x0 0x0 0x140>, + <0x240 0x4A8 0x000 0x0 0x0 0x140>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.txt deleted file mode 100644 index 330716c971b9..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.txt +++ /dev/null @@ -1,39 +0,0 @@ -* Freescale IMX8MN IOMUX Controller - -Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory -for common binding part and usage. - -Required properties: -- compatible: "fsl,imx8mn-iomuxc" -- reg: should contain the base physical address and size of the iomuxc - registers. - -Required properties in sub-nodes: -- fsl,pins: each entry consists of 6 integers and represents the mux and config - setting for one pin. The first 5 integers <mux_reg conf_reg input_reg mux_val - input_val> are specified using a PIN_FUNC_ID macro, which can be found in - <arch/arm64/boot/dts/freescale/imx8mn-pinfunc.h>. The last integer CONFIG is - the pad setting value like pull-up on this pin. Please refer to i.MX8M Nano - Reference Manual for detailed CONFIG settings. - -Examples: - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; -}; - -iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mn-iomuxc"; - reg = <0x0 0x30330000 0x0 0x10000>; - - pinctrl_uart1: uart1grp { - fsl,pins = < - MX8MN_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140 - MX8MN_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140 - MX8MN_IOMUXC_UART3_RXD_UART1_DCE_CTS_B 0x140 - MX8MN_IOMUXC_UART3_TXD_UART1_DCE_RTS_B 0x140 - MX8MN_IOMUXC_SD1_DATA4_GPIO2_IO6 0x19 - >; - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.yaml new file mode 100644 index 000000000000..b9aa180e07e4 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mn-pinctrl.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imx8mn-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale IMX8MN IOMUX Controller + +maintainers: + - Anson Huang <Anson.Huang@nxp.com> + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + const: fsl,imx8mn-iomuxc + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers <mux_reg conf_reg input_reg + mux_val input_val> are specified using a PIN_FUNC_ID macro, which can + be found in <arch/arm64/boot/dts/freescale/imx8mn-pinfunc.h>. The last + integer CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MX8M Nano Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + + required: + - fsl,pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + # Pinmux controller node + - | + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx8mn-iomuxc"; + reg = <0x30330000 0x10000>; + + pinctrl_uart2: uart2grp { + fsl,pins = + <0x23C 0x4A4 0x4FC 0x0 0x0 0x140>, + <0x240 0x4A8 0x000 0x0 0x0 0x140>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml index 2e31e120395e..6297e78418cf 100644 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mp-pinctrl.yaml @@ -30,8 +30,6 @@ patternProperties: properties: fsl,pins: - allOf: - - $ref: /schemas/types.yaml#/definitions/uint32-array description: each entry consists of 6 integers and represents the mux and config setting for one pin. The first 5 integers <mux_reg conf_reg input_reg @@ -39,6 +37,22 @@ patternProperties: be found in <arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h>. The last integer CONFIG is the pad setting value like pull-up on this pin. Please refer to i.MX8M Plus Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. required: - fsl,pins @@ -59,10 +73,9 @@ examples: reg = <0x30330000 0x10000>; pinctrl_uart2: uart2grp { - fsl,pins = < - 0x228 0x488 0x5F0 0x0 0x6 0x49 - 0x228 0x488 0x000 0x0 0x0 0x49 - >; + fsl,pins = + <0x228 0x488 0x5F0 0x0 0x6 0x49>, + <0x228 0x488 0x000 0x0 0x0 0x49>; }; }; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt deleted file mode 100644 index 66de75090458..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt +++ /dev/null @@ -1,36 +0,0 @@ -* Freescale IMX8MQ IOMUX Controller - -Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory -for common binding part and usage. - -Required properties: -- compatible: "fsl,imx8mq-iomuxc" -- reg: should contain the base physical address and size of the iomuxc - registers. - -Required properties in sub-nodes: -- fsl,pins: each entry consists of 6 integers and represents the mux and config - setting for one pin. The first 5 integers <mux_reg conf_reg input_reg mux_val - input_val> are specified using a PIN_FUNC_ID macro, which can be found in - imx8mq-pinfunc.h under device tree source folder. The last integer CONFIG is - the pad setting value like pull-up on this pin. Please refer to i.MX8M Quad - Reference Manual for detailed CONFIG settings. - -Examples: - -&uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; -}; - -iomuxc: pinctrl@30330000 { - compatible = "fsl,imx8mq-iomuxc"; - reg = <0x0 0x30330000 0x0 0x10000>; - - pinctrl_uart1: uart1grp { - fsl,pins = < - MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49 - MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49 - >; - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.yaml new file mode 100644 index 000000000000..b30c704fcfa1 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imx8mq-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale IMX8MQ IOMUX Controller + +maintainers: + - Anson Huang <Anson.Huang@nxp.com> + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + const: fsl,imx8mq-iomuxc + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers <mux_reg conf_reg input_reg + mux_val input_val> are specified using a PIN_FUNC_ID macro, which can + be found in <arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h>. The last + integer CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MX8M Quad Reference Manual for detailed CONFIG settings. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-matrix + - items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + + required: + - fsl,pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + # Pinmux controller node + - | + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx8mq-iomuxc"; + reg = <0x30330000 0x10000>; + + pinctrl_uart1: uart1grp { + fsl,pins = + <0x234 0x49C 0x4F4 0x0 0x0 0x49>, + <0x238 0x4A0 0x4F4 0x0 0x0 0x49>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml new file mode 100644 index 000000000000..63d1cfe86c6e --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml @@ -0,0 +1,153 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,ipq6018-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. IPQ6018 TLMM block + +maintainers: + - Sricharan R <sricharan@codeaurora.org> + +description: | + This binding describes the Top Level Mode Multiplexer block found in the + IPQ6018 platform. + +properties: + compatible: + const: qcom,ipq6018-pinctrl + + reg: + maxItems: 1 + + interrupts: + description: Specifies the TLMM summary IRQ + maxItems: 1 + + interrupt-controller: true + + '#interrupt-cells': + description: + Specifies the PIN numbers and Flags, as defined in defined in + include/dt-bindings/interrupt-controller/irq.h + const: 2 + + gpio-controller: true + + '#gpio-cells': + description: Specifying the pin number and flags, as defined in + include/dt-bindings/gpio/gpio.h + const: 2 + + gpio-ranges: + maxItems: 1 + +#PIN CONFIGURATION NODES +patternProperties: + '-pinmux$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + allOf: + - $ref: "/schemas/pinctrl/pincfg-node.yaml" + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + oneOf: + - pattern: "^gpio([1-9]|[1-7][0-9]|80)$" + - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, + sdc2_data, qdsd_cmd, qdsd_data0, qdsd_data1, qdsd_data2, + qdsd_data3 ] + minItems: 1 + maxItems: 4 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + enum: [ adsp_ext, alsp_int, atest_bbrx0, atest_bbrx1, atest_char, + atest_char0, atest_char1, atest_char2, atest_char3, atest_combodac, + atest_gpsadc0, atest_gpsadc1, atest_tsens, atest_wlan0, + atest_wlan1, backlight_en, bimc_dte0, bimc_dte1, blsp1_i2c, + blsp2_i2c, blsp3_i2c, blsp4_i2c, blsp5_i2c, blsp6_i2c, blsp1_spi, + blsp1_spi_cs1, blsp1_spi_cs2, blsp1_spi_cs3, blsp2_spi, + blsp2_spi_cs1, blsp2_spi_cs2, blsp2_spi_cs3, blsp3_spi, + blsp3_spi_cs1, blsp3_spi_cs2, blsp3_spi_cs3, blsp4_spi, blsp5_spi, + blsp6_spi, blsp1_uart, blsp2_uart, blsp1_uim, blsp2_uim, cam1_rst, + cam1_standby, cam_mclk0, cam_mclk1, cci_async, cci_i2c, cci_timer0, + cci_timer1, cci_timer2, cdc_pdm0, codec_mad, dbg_out, display_5v, + dmic0_clk, dmic0_data, dsi_rst, ebi0_wrcdc, euro_us, ext_lpass, + flash_strobe, gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, + gcc_gp2_clk_b, gcc_gp3_clk_a, gcc_gp3_clk_b, gpio, gsm0_tx0, + gsm0_tx1, gsm1_tx0, gsm1_tx1, gyro_accl, kpsns0, kpsns1, kpsns2, + ldo_en, ldo_update, mag_int, mdp_vsync, modem_tsync, m_voc, + nav_pps, nav_tsync, pa_indicator, pbs0, pbs1, pbs2, pri_mi2s, + pri_mi2s_ws, prng_rosc, pwr_crypto_enabled_a, pwr_crypto_enabled_b, + pwr_modem_enabled_a, pwr_modem_enabled_b, pwr_nav_enabled_a, + pwr_nav_enabled_b, qdss_ctitrig_in_a0, qdss_ctitrig_in_a1, + qdss_ctitrig_in_b0, qdss_ctitrig_in_b1, qdss_ctitrig_out_a0, + qdss_ctitrig_out_a1, qdss_ctitrig_out_b0, qdss_ctitrig_out_b1, + qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b, + qdss_tracedata_a, qdss_tracedata_b, reset_n, sd_card, sd_write, + sec_mi2s, smb_int, ssbi_wtr0, ssbi_wtr1, uim1, uim2, uim3, + uim_batt, wcss_bt, wcss_fm, wcss_wlan, webcam1_rst ] + + drive-strength: + enum: [2, 4, 6, 8, 10, 12, 14, 16] + default: 2 + description: + Selects the drive strength for the specified pins, in mA. + + bias-pull-down: true + + bias-pull-up: true + + bias-disable: true + + output-high: true + + output-low: true + + required: + - pins + - function + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - interrupt-controller + - '#interrupt-cells' + - gpio-controller + - '#gpio-cells' + - gpio-ranges + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + tlmm: pinctrl@1000000 { + compatible = "qcom,ipq6018-pinctrl"; + reg = <0x01000000 0x300000>; + interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm 0 80>; + + serial3-pinmux { + pins = "gpio44", "gpio45"; + function = "blsp2_uart"; + drive-strength = <8>; + bias-pull-down; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 6849e8ddf55a..0ffb16414b9b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2743,8 +2743,8 @@ L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) L: openbmc@lists.ozlabs.org (moderated for non-subscribers) L: linux-gpio@vger.kernel.org S: Maintained -F: drivers/pinctrl/aspeed/ F: Documentation/devicetree/bindings/pinctrl/aspeed,* +F: drivers/pinctrl/aspeed/ ASPEED SCU INTERRUPT CONTROLLER DRIVER M: Eddie James <eajames@linux.ibm.com> @@ -4958,6 +4958,7 @@ F: drivers/leds/leds-da90??.c F: drivers/mfd/da903x.c F: drivers/mfd/da90??-*.c F: drivers/mfd/da91??-*.c +F: drivers/pinctrl/pinctrl-da90??.c F: drivers/power/supply/da9052-battery.c F: drivers/power/supply/da91??-*.c F: drivers/regulator/da903x.c @@ -13267,21 +13268,13 @@ K: \b(clone_args|kernel_clone_args)\b PIN CONTROL SUBSYSTEM M: Linus Walleij <linus.walleij@linaro.org> L: linux-gpio@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git F: Documentation/devicetree/bindings/pinctrl/ F: Documentation/driver-api/pinctl.rst F: drivers/pinctrl/ F: include/linux/pinctrl/ -PIN CONTROLLER - MICROCHIP AT91 -M: Ludovic Desroches <ludovic.desroches@microchip.com> -L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -L: linux-gpio@vger.kernel.org -S: Supported -F: drivers/pinctrl/pinctrl-at91* -F: drivers/gpio/gpio-sama5d2-piobu.c - PIN CONTROLLER - FREESCALE M: Dong Aisheng <aisheng.dong@nxp.com> M: Fabio Estevam <festevam@gmail.com> @@ -13290,14 +13283,14 @@ M: Stefan Agner <stefan@agner.ch> R: Pengutronix Kernel Team <kernel@pengutronix.de> L: linux-gpio@vger.kernel.org S: Maintained -F: drivers/pinctrl/freescale/ F: Documentation/devicetree/bindings/pinctrl/fsl,* +F: drivers/pinctrl/freescale/ PIN CONTROLLER - INTEL M: Mika Westerberg <mika.westerberg@linux.intel.com> M: Andy Shevchenko <andy@kernel.org> -T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git F: drivers/pinctrl/intel/ PIN CONTROLLER - MEDIATEK @@ -13308,18 +13301,26 @@ F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt F: drivers/pinctrl/mediatek/ +PIN CONTROLLER - MICROCHIP AT91 +M: Ludovic Desroches <ludovic.desroches@microchip.com> +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: linux-gpio@vger.kernel.org +S: Supported +F: drivers/gpio/gpio-sama5d2-piobu.c +F: drivers/pinctrl/pinctrl-at91* + PIN CONTROLLER - QUALCOMM M: Bjorn Andersson <bjorn.andersson@linaro.org> -S: Maintained L: linux-arm-msm@vger.kernel.org +S: Maintained F: Documentation/devicetree/bindings/pinctrl/qcom,*.txt F: drivers/pinctrl/qcom/ PIN CONTROLLER - RENESAS M: Geert Uytterhoeven <geert+renesas@glider.be> L: linux-renesas-soc@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git sh-pfc S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git sh-pfc F: drivers/pinctrl/pinctrl-rz* F: drivers/pinctrl/sh-pfc/ @@ -13329,12 +13330,12 @@ M: Krzysztof Kozlowski <krzk@kernel.org> M: Sylwester Nawrocki <s.nawrocki@samsung.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) -Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung.git +Q: https://patchwork.kernel.org/project/linux-samsung-soc/list/ +F: Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt F: drivers/pinctrl/samsung/ F: include/dt-bindings/pinctrl/samsung.h -F: Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt PIN CONTROLLER - SINGLE M: Tony Lindgren <tony@atomide.com> @@ -13347,8 +13348,8 @@ F: drivers/pinctrl/pinctrl-single.c PIN CONTROLLER - ST SPEAR M: Viresh Kumar <vireshk@kernel.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -W: http://www.st.com/spear S: Maintained +W: http://www.st.com/spear F: drivers/pinctrl/spear/ PISTACHIO SOC SUPPORT diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 00fb91feba70..86bde1e30a60 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -149,6 +149,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, return &gdev->descs[hwnum]; } +EXPORT_SYMBOL_GPL(gpiochip_get_desc); /** * desc_to_gpio - convert a GPIO descriptor to the integer namespace diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index df0ef69dd474..834c59950d1c 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -126,6 +126,18 @@ config PINCTRL_DA850_PUPD Driver for TI DA850/OMAP-L138/AM18XX pinconf. Used to control pullup/pulldown pin groups. +config PINCTRL_DA9062 + tristate "Dialog Semiconductor DA9062 PMIC pinctrl and GPIO Support" + depends on MFD_DA9062 + select GPIOLIB + help + The Dialog DA9062 PMIC provides multiple GPIOs that can be muxed for + different functions. This driver bundles a pinctrl driver to select the + function muxing and a GPIO driver to handle the GPIO when the GPIO + function is selected. + + Say yes to enable pinctrl and GPIO support for the DA9062 PMIC. + config PINCTRL_DIGICOLOR bool depends on OF && (ARCH_DIGICOLOR || COMPILE_TEST) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 879f312bfb75..0b36a1cfca8a 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o +obj-$(CONFIG_PINCTRL_DA9062) += pinctrl-da9062.o obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_GEMINI) += pinctrl-gemini.o diff --git a/drivers/pinctrl/actions/pinctrl-s700.c b/drivers/pinctrl/actions/pinctrl-s700.c index 771d6fd50b45..47a4ccd9fed4 100644 --- a/drivers/pinctrl/actions/pinctrl-s700.c +++ b/drivers/pinctrl/actions/pinctrl-s700.c @@ -1125,317 +1125,317 @@ static const struct owl_pingroup s700_groups[] = { }; static const char * const nor_groups[] = { - "lcd0_d18", - "i2s_d0", - "i2s0_pcm0", - "i2s1_pcm0", - "i2s_d1", - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", - "lcd0_d2", - "lvds_ee_pn", - "uart2_rx_tx", - "spi0_i2c_pcm", - "lvds_e_pn", - "sd0_d0", - "sd0_d1", - "sd0_d2_d3", - "sd1_d0_d3", - "sd0_cmd", - "sd1_cmd", - "sens0_ckout", - "sen0_pclk", + "lcd0_d18_mfp", + "i2s_d0_mfp", + "i2s0_pcm0_mfp", + "i2s1_pcm0_mfp", + "i2s_d1_mfp", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "lcd0_d2_mfp", + "lvds_ee_pn_mfp", + "uart2_rx_tx_mfp", + "spi0_i2c_pcm_mfp", + "lvds_e_pn_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", + "sd0_d2_d3_mfp", + "sd1_d0_d3_mfp", + "sd0_cmd_mfp", + "sd1_cmd_mfp", + "sens0_ckout_mfp", + "sen0_pclk_mfp", }; static const char * const eth_rmii_groups[] = { - "rgmii_txd23", - "rgmii_rxd2", - "rgmii_rxd3", - "rgmii_txd01", - "rgmii_txd0", - "rgmii_txd1", - "rgmii_txen", - "rgmii_rxen", - "rgmii_rxd1", - "rgmii_rxd0", - "rgmii_ref_clk", + "rgmii_txd23_mfp", + "rgmii_rxd2_mfp", + "rgmii_rxd3_mfp", + "rgmii_txd01_mfp", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", + "rgmii_txen_mfp", + "rgmii_rxen_mfp", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", + "rgmii_ref_clk_mfp", "eth_smi_dummy", }; static const char * const eth_smii_groups[] = { - "rgmii_txd0", - "rgmii_txd1", - "rgmii_rxd0", - "rgmii_rxd1", - "rgmii_ref_clk", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", + "rgmii_rxd0_mfp", + "rgmii_rxd1_mfp", + "rgmii_ref_clk_mfp", "eth_smi_dummy", }; static const char * const spi0_groups[] = { - "dsi_dn0", - "dsi_dp2", - "dsi_dp0", - "uart2_rx_tx", - "spi0_i2c_pcm", - "dsi_dn2", + "dsi_dn0_mfp", + "dsi_dp2_mfp", + "dsi_dp0_mfp", + "uart2_rx_tx_mfp", + "spi0_i2c_pcm_mfp", + "dsi_dn2_mfp", }; static const char * const spi1_groups[] = { - "uart0_rx", - "uart0_tx", + "uart0_rx_mfp", + "uart0_tx_mfp", "i2c0_mfp", }; static const char * const spi2_groups[] = { - "rgmii_txd01", - "rgmii_txd0", - "rgmii_txd1", - "rgmii_ref_clk", - "dnand_acle_ce0", + "rgmii_txd01_mfp", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", + "rgmii_ref_clk_mfp", + "dnand_acle_ce0_mfp", }; static const char * const spi3_groups[] = { - "rgmii_txen", - "rgmii_rxen", - "rgmii_rxd1", - "rgmii_rxd0", + "rgmii_txen_mfp", + "rgmii_rxen_mfp", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", }; static const char * const sens0_groups[] = { - "csi_cn_cp", - "sens0_ckout", - "csi_dn_dp", - "sen0_pclk", + "csi_cn_cp_mfp", + "sens0_ckout_mfp", + "csi_dn_dp_mfp", + "sen0_pclk_mfp", }; static const char * const sens1_groups[] = { - "lcd0_d18", - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", - "sens0_ckout", - "pcm1_in", - "pcm1_clk", - "pcm1_sync", - "pcm1_out", + "lcd0_d18_mfp", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "sens0_ckout_mfp", + "pcm1_in_mfp", + "pcm1_clk_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const uart0_groups[] = { - "uart2_rtsb", - "uart2_ctsb", - "uart0_rx", - "uart0_tx", + "uart2_rtsb_mfp", + "uart2_ctsb_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", }; static const char * const uart1_groups[] = { - "sd0_d2_d3", + "sd0_d2_d3_mfp", "i2c0_mfp", }; static const char * const uart2_groups[] = { - "rgmii_txen", - "rgmii_rxen", - "rgmii_rxd1", - "rgmii_rxd0", - "dsi_dn0", - "dsi_dp2", - "dsi_dp0", - "uart2_rx_tx", - "dsi_dn2", - "uart2_rtsb", - "uart2_ctsb", - "sd0_d0", - "sd0_d1", - "sd0_d2_d3", - "uart0_rx", - "uart0_tx", + "rgmii_txen_mfp", + "rgmii_rxen_mfp", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", + "dsi_dn0_mfp", + "dsi_dp2_mfp", + "dsi_dp0_mfp", + "uart2_rx_tx_mfp", + "dsi_dn2_mfp", + "uart2_rtsb_mfp", + "uart2_ctsb_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", + "sd0_d2_d3_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", "i2c0_mfp", "uart2_dummy" }; static const char * const uart3_groups[] = { - "rgmii_txd23", - "rgmii_rxd2", - "rgmii_rxd3", - "uart3_rtsb", - "uart3_ctsb", + "rgmii_txd23_mfp", + "rgmii_rxd2_mfp", + "rgmii_rxd3_mfp", + "uart3_rtsb_mfp", + "uart3_ctsb_mfp", "uart3_dummy" }; static const char * const uart4_groups[] = { - "rgmii_txd01", - "rgmii_ref_clk", - "ks_out0", - "ks_out1", + "rgmii_txd01_mfp", + "rgmii_ref_clk_mfp", + "ks_out0_mfp", + "ks_out1_mfp", }; static const char * const uart5_groups[] = { - "rgmii_rxd1", - "rgmii_rxd0", - "ks_out0", - "ks_out2", - "uart3_rtsb", - "uart3_ctsb", - "sd0_d0", - "sd0_d1", + "rgmii_rxd1_mfp", + "rgmii_rxd0_mfp", + "ks_out0_mfp", + "ks_out2_mfp", + "uart3_rtsb_mfp", + "uart3_ctsb_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", }; static const char * const uart6_groups[] = { - "rgmii_txd0", - "rgmii_txd1", + "rgmii_txd0_mfp", + "rgmii_txd1_mfp", }; static const char * const i2s0_groups[] = { - "i2s_d0", - "i2s_pcm1", - "i2s0_pcm0", + "i2s_d0_mfp", + "i2s_pcm1_mfp", + "i2s0_pcm0_mfp", }; static const char * const i2s1_groups[] = { - "i2s1_pcm0", - "i2s_d1", + "i2s1_pcm0_mfp", + "i2s_d1_mfp", "i2s1_dummy", - "spi0_i2c_pcm", - "uart0_rx", - "uart0_tx", + "spi0_i2c_pcm_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", }; static const char * const pcm1_groups[] = { - "i2s_pcm1", - "spi0_i2c_pcm", - "uart0_rx", - "uart0_tx", - "pcm1_in", - "pcm1_clk", - "pcm1_sync", - "pcm1_out", + "i2s_pcm1_mfp", + "spi0_i2c_pcm_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", + "pcm1_in_mfp", + "pcm1_clk_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const pcm0_groups[] = { - "i2s0_pcm0", - "i2s1_pcm0", - "uart2_rx_tx", - "spi0_i2c_pcm", + "i2s0_pcm0_mfp", + "i2s1_pcm0_mfp", + "uart2_rx_tx_mfp", + "spi0_i2c_pcm_mfp", }; static const char * const ks_groups[] = { - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", }; static const char * const jtag_groups[] = { - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out1", - "sd0_d0", - "sd0_d2_d3", - "sd0_cmd", - "sd0_clk", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out1_mfp", + "sd0_d0_mfp", + "sd0_d2_d3_mfp", + "sd0_cmd_mfp", + "sd0_clk_mfp", }; static const char * const pwm0_groups[] = { - "rgmii_rxd2", - "rgmii_txen", - "ks_in2", - "sen0_pclk", + "rgmii_rxd2_mfp", + "rgmii_txen_mfp", + "ks_in2_mfp", + "sen0_pclk_mfp", }; static const char * const pwm1_groups[] = { - "rgmii_rxen", - "ks_in1", - "ks_in3", - "sens0_ckout", + "rgmii_rxen_mfp", + "ks_in1_mfp", + "ks_in3_mfp", + "sens0_ckout_mfp", }; static const char * const pwm2_groups[] = { - "lcd0_d18", - "rgmii_rxd3", - "rgmii_rxd1", - "ks_out0", - "ks_out2", + "lcd0_d18_mfp", + "rgmii_rxd3_mfp", + "rgmii_rxd1_mfp", + "ks_out0_mfp", + "ks_out2_mfp", }; static const char * const pwm3_groups[] = { - "rgmii_rxd0", - "ks_out1", - "lcd0_d2", + "rgmii_rxd0_mfp", + "ks_out1_mfp", + "lcd0_d2_mfp", }; static const char * const pwm4_groups[] = { - "lcd0_d18", - "rgmii_txd01", - "rgmii_txd0", - "ks_in0", - "pcm1_in", - "nand_ceb3", + "lcd0_d18_mfp", + "rgmii_txd01_mfp", + "rgmii_txd0_mfp", + "ks_in0_mfp", + "pcm1_in_mfp", + "nand_ceb3_mfp", }; static const char * const pwm5_groups[] = { - "rgmii_txd1", - "ks_in1", - "pcm1_clk", - "nand_ceb2", + "rgmii_txd1_mfp", + "ks_in1_mfp", + "pcm1_clk_mfp", + "nand_ceb2_mfp", }; static const char * const p0_groups[] = { - "ks_in2", - "ks_in0", + "ks_in2_mfp", + "ks_in0_mfp", }; static const char * const sd0_groups[] = { - "ks_out0", - "ks_out1", - "ks_out2", - "lcd0_d2", - "dsi_dp3", - "dsi_dp0", - "sd0_d0", - "sd0_d1", - "sd0_d2_d3", - "sd1_d0_d3", - "sd0_cmd", - "sd0_clk", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "lcd0_d2_mfp", + "dsi_dp3_mfp", + "dsi_dp0_mfp", + "sd0_d0_mfp", + "sd0_d1_mfp", + "sd0_d2_d3_mfp", + "sd1_d0_d3_mfp", + "sd0_cmd_mfp", + "sd0_clk_mfp", }; static const char * const sd1_groups[] = { - "dsi_dp2", - "mfp1_16_14", - "lcd0_d2", - "mfp1_16_14_d17", - "dsi_dp3", - "dsi_dn3", - "dsi_dnp1_cp_d2", - "dsi_dnp1_cp_d17", - "dsi_dn2", - "sd1_d0_d3", - "sd1_cmd", + "dsi_dp2_mfp", + "mfp1_16_14_mfp", + "lcd0_d2_mfp", + "mfp1_16_14_d17_mfp", + "dsi_dp3_mfp", + "dsi_dn3_mfp", + "dsi_dnp1_cp_d2_mfp", + "dsi_dnp1_cp_d17_mfp", + "dsi_dn2_mfp", + "sd1_d0_d3_mfp", + "sd1_cmd_mfp", "sd1_dummy", }; static const char * const sd2_groups[] = { - "dnand_data_wr", + "dnand_data_wr_mfp", }; static const char * const i2c0_groups[] = { - "uart0_rx", - "uart0_tx", - "i2c0_mfp", + "uart0_rx_mfp", + "uart0_tx_mfp", + "i2c0_mfp_mfp", }; static const char * const i2c1_groups[] = { @@ -1448,85 +1448,85 @@ static const char * const i2c2_groups[] = { }; static const char * const i2c3_groups[] = { - "uart2_rx_tx", - "pcm1_sync", - "pcm1_out", + "uart2_rx_tx_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const lvds_groups[] = { - "lvds_o_pn", - "lvds_ee_pn", - "lvds_e_pn", + "lvds_o_pn_mfp", + "lvds_ee_pn_mfp", + "lvds_e_pn_mfp", }; static const char * const bt_groups[] = { - "i2s_pcm1", - "i2s0_pcm0", - "i2s1_pcm0", - "ks_in2", - "ks_in1", - "ks_in0", - "ks_in3", - "ks_out0", - "ks_out1", - "ks_out2", - "lvds_o_pn", - "lvds_ee_pn", - "pcm1_in", - "pcm1_clk", - "pcm1_sync", - "pcm1_out", + "i2s_pcm1_mfp", + "i2s0_pcm0_mfp", + "i2s1_pcm0_mfp", + "ks_in2_mfp", + "ks_in1_mfp", + "ks_in0_mfp", + "ks_in3_mfp", + "ks_out0_mfp", + "ks_out1_mfp", + "ks_out2_mfp", + "lvds_o_pn_mfp", + "lvds_ee_pn_mfp", + "pcm1_in_mfp", + "pcm1_clk_mfp", + "pcm1_sync_mfp", + "pcm1_out_mfp", }; static const char * const lcd0_groups[] = { - "lcd0_d18", - "lcd0_d2", - "mfp1_16_14_d17", - "lvds_o_pn", - "dsi_dp3", - "dsi_dn3", - "lvds_ee_pn", - "dsi_dnp1_cp_d2", - "dsi_dnp1_cp_d17", - "lvds_e_pn", + "lcd0_d18_mfp", + "lcd0_d2_mfp", + "mfp1_16_14_d17_mfp", + "lvds_o_pn_mfp", + "dsi_dp3_mfp", + "dsi_dn3_mfp", + "lvds_ee_pn_mfp", + "dsi_dnp1_cp_d2_mfp", + "dsi_dnp1_cp_d17_mfp", + "lvds_e_pn_mfp", }; static const char * const usb30_groups[] = { - "ks_in1", + "ks_in1_mfp", }; static const char * const clko_25m_groups[] = { - "clko_25m", + "clko_25m_mfp", }; static const char * const mipi_csi_groups[] = { - "csi_cn_cp", - "csi_dn_dp", + "csi_cn_cp_mfp", + "csi_dn_dp_mfp", }; static const char * const dsi_groups[] = { - "dsi_dn0", - "dsi_dp2", - "dsi_dp3", - "dsi_dn3", - "dsi_dp0", - "dsi_dnp1_cp_d2", - "dsi_dnp1_cp_d17", - "dsi_dn2", + "dsi_dn0_mfp", + "dsi_dp2_mfp", + "dsi_dp3_mfp", + "dsi_dn3_mfp", + "dsi_dp0_mfp", + "dsi_dnp1_cp_d2_mfp", + "dsi_dnp1_cp_d17_mfp", + "dsi_dn2_mfp", "dsi_dummy", }; static const char * const nand_groups[] = { - "dnand_data_wr", - "dnand_acle_ce0", - "nand_ceb2", - "nand_ceb3", + "dnand_data_wr_mfp", + "dnand_acle_ce0_mfp", + "nand_ceb2_mfp", + "nand_ceb3_mfp", "nand_dummy", }; static const char * const spdif_groups[] = { - "uart0_tx", + "uart0_tx_mfp", }; static const char * const sirq0_groups[] = { diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 0de1a3a96984..06bd2b70af3c 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -37,12 +37,10 @@ #define MODULE_NAME "pinctrl-bcm2835" #define BCM2835_NUM_GPIOS 54 +#define BCM2711_NUM_GPIOS 58 #define BCM2835_NUM_BANKS 2 #define BCM2835_NUM_IRQS 3 -#define BCM2835_PIN_BITMAP_SZ \ - DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8) - /* GPIO register offsets */ #define GPFSEL0 0x0 /* Function Select */ #define GPSET0 0x1c /* Pin Output Set */ @@ -81,10 +79,11 @@ struct bcm2835_pinctrl { /* note: locking assumes each bank will have its own unsigned long */ unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; - unsigned int irq_type[BCM2835_NUM_GPIOS]; + unsigned int irq_type[BCM2711_NUM_GPIOS]; struct pinctrl_dev *pctl_dev; struct gpio_chip gpio_chip; + struct pinctrl_desc pctl_desc; struct pinctrl_gpio_range gpio_range; raw_spinlock_t irq_lock[BCM2835_NUM_BANKS]; @@ -147,6 +146,10 @@ static struct pinctrl_pin_desc bcm2835_gpio_pins[] = { BCM2835_GPIO_PIN(51), BCM2835_GPIO_PIN(52), BCM2835_GPIO_PIN(53), + BCM2835_GPIO_PIN(54), + BCM2835_GPIO_PIN(55), + BCM2835_GPIO_PIN(56), + BCM2835_GPIO_PIN(57), }; /* one pin per group */ @@ -205,6 +208,10 @@ static const char * const bcm2835_gpio_groups[] = { "gpio51", "gpio52", "gpio53", + "gpio54", + "gpio55", + "gpio56", + "gpio57", }; enum bcm2835_fsel { @@ -322,7 +329,10 @@ static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offse if (fsel > BCM2835_FSEL_GPIO_OUT) return -EINVAL; - return (fsel == BCM2835_FSEL_GPIO_IN); + if (fsel == BCM2835_FSEL_GPIO_IN) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -355,6 +365,22 @@ static const struct gpio_chip bcm2835_gpio_chip = { .can_sleep = false, }; +static const struct gpio_chip bcm2711_gpio_chip = { + .label = "pinctrl-bcm2711", + .owner = THIS_MODULE, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .direction_input = bcm2835_gpio_direction_input, + .direction_output = bcm2835_gpio_direction_output, + .get_direction = bcm2835_gpio_get_direction, + .get = bcm2835_gpio_get, + .set = bcm2835_gpio_set, + .set_config = gpiochip_generic_config, + .base = -1, + .ngpio = BCM2711_NUM_GPIOS, + .can_sleep = false, +}; + static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, unsigned int bank, u32 mask) { @@ -401,7 +427,7 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc) bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000); bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); break; - case 2: /* IRQ2 covers GPIOs 46-53 */ + case 2: /* IRQ2 covers GPIOs 46-57 */ bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); break; } @@ -620,7 +646,7 @@ static struct irq_chip bcm2835_gpio_irq_chip = { static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) { - return ARRAY_SIZE(bcm2835_gpio_groups); + return BCM2835_NUM_GPIOS; } static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev, @@ -778,7 +804,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, err = of_property_read_u32_index(np, "brcm,pins", i, &pin); if (err) goto out; - if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) { + if (pin >= pc->pctl_desc.npins) { dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", np, pin); err = -EINVAL; @@ -854,7 +880,7 @@ static int bcm2835_pmx_get_function_groups(struct pinctrl_dev *pctldev, { /* every pin can do every function */ *groups = bcm2835_gpio_groups; - *num_groups = ARRAY_SIZE(bcm2835_gpio_groups); + *num_groups = BCM2835_NUM_GPIOS; return 0; } @@ -1054,29 +1080,62 @@ static const struct pinconf_ops bcm2711_pinconf_ops = { .pin_config_set = bcm2711_pinconf_set, }; -static struct pinctrl_desc bcm2835_pinctrl_desc = { +static const struct pinctrl_desc bcm2835_pinctrl_desc = { .name = MODULE_NAME, .pins = bcm2835_gpio_pins, - .npins = ARRAY_SIZE(bcm2835_gpio_pins), + .npins = BCM2835_NUM_GPIOS, .pctlops = &bcm2835_pctl_ops, .pmxops = &bcm2835_pmx_ops, .confops = &bcm2835_pinconf_ops, .owner = THIS_MODULE, }; -static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { +static const struct pinctrl_desc bcm2711_pinctrl_desc = { + .name = "pinctrl-bcm2711", + .pins = bcm2835_gpio_pins, + .npins = BCM2711_NUM_GPIOS, + .pctlops = &bcm2835_pctl_ops, + .pmxops = &bcm2835_pmx_ops, + .confops = &bcm2711_pinconf_ops, + .owner = THIS_MODULE, +}; + +static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { .name = MODULE_NAME, .npins = BCM2835_NUM_GPIOS, }; +static const struct pinctrl_gpio_range bcm2711_pinctrl_gpio_range = { + .name = "pinctrl-bcm2711", + .npins = BCM2711_NUM_GPIOS, +}; + +struct bcm_plat_data { + const struct gpio_chip *gpio_chip; + const struct pinctrl_desc *pctl_desc; + const struct pinctrl_gpio_range *gpio_range; +}; + +static const struct bcm_plat_data bcm2835_plat_data = { + .gpio_chip = &bcm2835_gpio_chip, + .pctl_desc = &bcm2835_pinctrl_desc, + .gpio_range = &bcm2835_pinctrl_gpio_range, +}; + +static const struct bcm_plat_data bcm2711_plat_data = { + .gpio_chip = &bcm2711_gpio_chip, + .pctl_desc = &bcm2711_pinctrl_desc, + .gpio_range = &bcm2711_pinctrl_gpio_range, +}; + static const struct of_device_id bcm2835_pinctrl_match[] = { { .compatible = "brcm,bcm2835-gpio", - .data = &bcm2835_pinconf_ops, + .data = &bcm2835_plat_data, }, { .compatible = "brcm,bcm2711-gpio", - .data = &bcm2711_pinconf_ops, + .data = &bcm2711_plat_data, }, {} }; @@ -1085,14 +1144,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + const struct bcm_plat_data *pdata; struct bcm2835_pinctrl *pc; struct gpio_irq_chip *girq; struct resource iomem; int err, i; const struct of_device_id *match; - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS); - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS); + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS); + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS); pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); if (!pc) @@ -1111,7 +1171,13 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(pc->base)) return PTR_ERR(pc->base); - pc->gpio_chip = bcm2835_gpio_chip; + match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); + if (!match) + return -EINVAL; + + pdata = match->data; + + pc->gpio_chip = *pdata->gpio_chip; pc->gpio_chip.parent = dev; pc->gpio_chip.of_node = np; @@ -1162,19 +1228,14 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) return err; } - match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); - if (match) { - bcm2835_pinctrl_desc.confops = - (const struct pinconf_ops *)match->data; - } - - pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); + pc->pctl_desc = *pdata->pctl_desc; + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); if (IS_ERR(pc->pctl_dev)) { gpiochip_remove(&pc->gpio_chip); return PTR_ERR(pc->pctl_dev); } - pc->gpio_range = bcm2835_pinctrl_gpio_range; + pc->gpio_range = *pdata->gpio_range; pc->gpio_range.base = pc->gpio_chip.base; pc->gpio_range.gc = &pc->gpio_chip; pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index 25166217c3e0..a38f0d5f47ce 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -363,7 +363,10 @@ static int iproc_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); unsigned int shift = IPROC_GPIO_SHIFT(gpio); - return !(readl(chip->base + offset) & BIT(shift)); + if (readl(chip->base + offset) & BIT(shift)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static void iproc_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index f23c55e22195..821242bb4b16 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -176,6 +176,7 @@ const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin) return desc->name; } +EXPORT_SYMBOL_GPL(pin_get_name); /* Deletes a range of pin descriptors */ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev, diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig index de775a85a51e..c784663b00ad 100644 --- a/drivers/pinctrl/freescale/Kconfig +++ b/drivers/pinctrl/freescale/Kconfig @@ -125,28 +125,28 @@ config PINCTRL_IMX7ULP config PINCTRL_IMX8MM bool "IMX8MM pinctrl driver" - depends on ARCH_MXC && ARM64 + depends on ARCH_MXC select PINCTRL_IMX help Say Y here to enable the imx8mm pinctrl driver config PINCTRL_IMX8MN bool "IMX8MN pinctrl driver" - depends on ARCH_MXC && ARM64 + depends on ARCH_MXC select PINCTRL_IMX help Say Y here to enable the imx8mn pinctrl driver config PINCTRL_IMX8MP bool "IMX8MP pinctrl driver" - depends on ARCH_MXC && ARM64 + depends on ARCH_MXC select PINCTRL_IMX help Say Y here to enable the imx8mp pinctrl driver config PINCTRL_IMX8MQ bool "IMX8MQ pinctrl driver" - depends on ARCH_MXC && ARM64 + depends on ARCH_MXC select PINCTRL_IMX help Say Y here to enable the imx8mq pinctrl driver diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6765.c b/drivers/pinctrl/mediatek/pinctrl-mt6765.c index 32451e8693be..905dae8c3fd8 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c @@ -1070,15 +1070,12 @@ static const struct mtk_pin_soc mt6765_data = { .ngrps = ARRAY_SIZE(mtk_pins_mt6765), .eint_hw = &mt6765_eint_hw, .gpio_m = 0, - .ies_present = true, .base_names = mt6765_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt6765_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set, - .bias_disable_get = mtk_pinconf_bias_disable_get, - .bias_set = mtk_pinconf_bias_set, - .bias_get = mtk_pinconf_bias_get, - .drive_set = mtk_pinconf_drive_set_rev1, - .drive_get = mtk_pinconf_drive_get_rev1, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .drive_set = mtk_pinconf_drive_set_raw, + .drive_get = mtk_pinconf_drive_get_raw, .adv_pull_get = mtk_pinconf_adv_pull_get, .adv_pull_set = mtk_pinconf_adv_pull_set, }; diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8183.c b/drivers/pinctrl/mediatek/pinctrl-mt8183.c index 9a74d5025be6..60318339b618 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c @@ -554,13 +554,10 @@ static const struct mtk_pin_soc mt8183_data = { .ngrps = ARRAY_SIZE(mtk_pins_mt8183), .eint_hw = &mt8183_eint_hw, .gpio_m = 0, - .ies_present = true, .base_names = mt8183_pinctrl_register_base_names, .nbase_names = ARRAY_SIZE(mt8183_pinctrl_register_base_names), - .bias_disable_set = mtk_pinconf_bias_disable_set_rev1, - .bias_disable_get = mtk_pinconf_bias_disable_get_rev1, - .bias_set = mtk_pinconf_bias_set_rev1, - .bias_get = mtk_pinconf_bias_get_rev1, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, .drive_set = mtk_pinconf_drive_set_rev1, .drive_get = mtk_pinconf_drive_get_rev1, .adv_pull_get = mtk_pinconf_adv_pull_get, diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c index 20e1c890e73b..d3169a87e1b3 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c @@ -6,6 +6,7 @@ * */ +#include <dt-bindings/pinctrl/mt65xx.h> #include <linux/device.h> #include <linux/err.h> #include <linux/gpio/driver.h> @@ -66,34 +67,44 @@ static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, int field, struct mtk_pin_field *pfd) { - const struct mtk_pin_field_calc *c, *e; + const struct mtk_pin_field_calc *c; const struct mtk_pin_reg_calc *rc; + int start = 0, end, check; + bool found = false; u32 bits; if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) { rc = &hw->soc->reg_cal[field]; } else { dev_dbg(hw->dev, - "Not support field %d for pin %d (%s)\n", - field, desc->number, desc->name); + "Not support field %d for this soc\n", field); return -ENOTSUPP; } - c = rc->range; - e = c + rc->nranges; + end = rc->nranges - 1; - while (c < e) { - if (desc->number >= c->s_pin && desc->number <= c->e_pin) + while (start <= end) { + check = (start + end) >> 1; + if (desc->number >= rc->range[check].s_pin + && desc->number <= rc->range[check].e_pin) { + found = true; + break; + } else if (start == end) break; - c++; + else if (desc->number < rc->range[check].s_pin) + end = check - 1; + else + start = check + 1; } - if (c >= e) { + if (!found) { dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n", field, desc->number, desc->name); return -ENOTSUPP; } + c = rc->range + check; + if (c->i_base > hw->nbase - 1) { dev_err(hw->dev, "Invalid base for field %d for pin = %d (%s)\n", @@ -182,6 +193,9 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, if (err) return err; + if (value < 0 || value > pf.mask) + return -EINVAL; + if (!pf.next) mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos, (value & pf.mask) << pf.bitpos); @@ -502,6 +516,226 @@ int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw, return 0; } +/* Combo for the following pull register type: + * 1. PU + PD + * 2. PULLSEL + PULLEN + * 3. PUPD + R0 + R1 + */ +static int mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, pu, pd; + + if (arg == MTK_DISABLE) { + pu = 0; + pd = 0; + } else if ((arg == MTK_ENABLE) && pullup) { + pu = 1; + pd = 0; + } else if ((arg == MTK_ENABLE) && !pullup) { + pu = 0; + pd = 1; + } else { + err = -EINVAL; + goto out; + } + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, pu); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd); + +out: + return err; +} + +static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, enable; + + if (arg == MTK_DISABLE) + enable = 0; + else if (arg == MTK_ENABLE) + enable = 1; + else { + err = -EINVAL; + goto out; + } + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup); + +out: + return err; +} + +static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err, r0, r1; + + if ((arg == MTK_DISABLE) || (arg == MTK_PUPD_SET_R1R0_00)) { + pullup = 0; + r0 = 0; + r1 = 0; + } else if (arg == MTK_PUPD_SET_R1R0_01) { + r0 = 1; + r1 = 0; + } else if (arg == MTK_PUPD_SET_R1R0_10) { + r0 = 0; + r1 = 1; + } else if (arg == MTK_PUPD_SET_R1R0_11) { + r0 = 1; + r1 = 1; + } else { + err = -EINVAL; + goto out; + } + + /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */ + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, !pullup); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, r0); + if (err) + goto out; + + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, r1); + +out: + return err; +} + +static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err, pu, pd; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd); + if (err) + goto out; + + if (pu == 0 && pd == 0) { + *pullup = 0; + *enable = MTK_DISABLE; + } else if (pu == 1 && pd == 0) { + *pullup = 1; + *enable = MTK_ENABLE; + } else if (pu == 0 && pd == 1) { + *pullup = 0; + *enable = MTK_ENABLE; + } else + err = -EINVAL; + +out: + return err; +} + +static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable); + +out: + return err; +} + +static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err, r0, r1; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, pullup); + if (err) + goto out; + /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */ + *pullup = !(*pullup); + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &r0); + if (err) + goto out; + + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &r1); + if (err) + goto out; + + if ((r1 == 0) && (r0 == 0)) + *enable = MTK_PUPD_SET_R1R0_00; + else if ((r1 == 0) && (r0 == 1)) + *enable = MTK_PUPD_SET_R1R0_01; + else if ((r1 == 1) && (r0 == 0)) + *enable = MTK_PUPD_SET_R1R0_10; + else if ((r1 == 1) && (r0 == 1)) + *enable = MTK_PUPD_SET_R1R0_11; + else + err = -EINVAL; + +out: + return err; +} + +int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 arg) +{ + int err; + + err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg); + if (!err) + goto out; + + err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg); + if (!err) + goto out; + + err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg); + +out: + return err; +} + +int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable) +{ + int err; + + err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable); + if (!err) + goto out; + + err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable); + if (!err) + goto out; + + err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable); + +out: + return err; +} + /* Revision 0 */ int mtk_pinconf_drive_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, u32 arg) @@ -593,6 +827,18 @@ int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw, return 0; } +int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 arg) +{ + return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV, arg); +} + +int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, int *val) +{ + return mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, val); +} + int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, u32 arg) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h index 1b7da42aa1d5..27df08736396 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h @@ -216,6 +216,11 @@ struct mtk_pin_soc { int (*bias_get)(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, int *res); + int (*bias_set_combo)(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 pullup, u32 arg); + int (*bias_get_combo)(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 *pullup, u32 *arg); + int (*drive_set)(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, u32 arg); int (*drive_get)(struct mtk_pinctrl *hw, @@ -277,6 +282,12 @@ int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw, int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, int *res); +int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 pullup, u32 enable); +int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, + u32 *pullup, u32 *enable); int mtk_pinconf_drive_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, u32 arg); @@ -288,6 +299,11 @@ int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw, int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, int *val); +int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, u32 arg); +int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw, + const struct mtk_pin_desc *desc, int *val); + int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc, bool pullup, u32 arg); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 67f8444f7a0c..a02ad10ec6fa 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -804,7 +804,10 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned offset) pctl->devdata->spec_dir_set(®_addr, offset); regmap_read(pctl->regmap1, reg_addr, &read_val); - return !(read_val & bit); + if (read_val & bit) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int mtk_gpio_get(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c index 923264d0e9ef..3853ec3a2a8e 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.c +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c @@ -78,93 +78,88 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, { struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); u32 param = pinconf_to_config_param(*config); - int val, val2, err, reg, ret = 1; + int pullup, err, reg, ret = 1; const struct mtk_pin_desc *desc; + if (pin >= hw->soc->npins) { + err = -EINVAL; + goto out; + } desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; switch (param) { case PIN_CONFIG_BIAS_DISABLE: - if (hw->soc->bias_disable_get) { - err = hw->soc->bias_disable_get(hw, desc, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } - break; case PIN_CONFIG_BIAS_PULL_UP: - if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 1, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } - break; case PIN_CONFIG_BIAS_PULL_DOWN: - if (hw->soc->bias_get) { - err = hw->soc->bias_get(hw, desc, 0, &ret); + if (hw->soc->bias_get_combo) { + err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret); if (err) - return err; + goto out; + if (param == PIN_CONFIG_BIAS_DISABLE) { + if (ret == MTK_PUPD_SET_R1R0_00) + ret = MTK_DISABLE; + } else if (param == PIN_CONFIG_BIAS_PULL_UP) { + /* When desire to get pull-up value, return + * error if current setting is pull-down + */ + if (!pullup) + err = -EINVAL; + } else if (param == PIN_CONFIG_BIAS_PULL_DOWN) { + /* When desire to get pull-down value, return + * error if current setting is pull-up + */ + if (pullup) + err = -EINVAL; + } } else { - return -ENOTSUPP; + err = -ENOTSUPP; } break; case PIN_CONFIG_SLEW_RATE: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val); - if (err) - return err; - - if (!val) - return -EINVAL; - + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret); break; case PIN_CONFIG_INPUT_ENABLE: case PIN_CONFIG_OUTPUT_ENABLE: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret); if (err) - return err; - - /* HW takes input mode as zero; output mode as non-zero */ - if ((val && param == PIN_CONFIG_INPUT_ENABLE) || - (!val && param == PIN_CONFIG_OUTPUT_ENABLE)) - return -EINVAL; + goto out; + /* CONFIG Current direction return value + * ------------- ----------------- ---------------------- + * OUTPUT_ENABLE output 1 (= HW value) + * input 0 (= HW value) + * INPUT_ENABLE output 0 (= reverse HW value) + * input 1 (= reverse HW value) + */ + if (param == PIN_CONFIG_INPUT_ENABLE) + ret = !ret; break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret); if (err) - return err; - - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2); - if (err) - return err; + goto out; + /* return error when in output mode + * because schmitt trigger only work in input mode + */ + if (ret) { + err = -EINVAL; + goto out; + } - if (val || !val2) - return -EINVAL; + err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret); break; case PIN_CONFIG_DRIVE_STRENGTH: - if (hw->soc->drive_get) { + if (hw->soc->drive_get) err = hw->soc->drive_get(hw, desc, &ret); - if (err) - return err; - } else { + else err = -ENOTSUPP; - } break; case MTK_PIN_CONFIG_TDSEL: case MTK_PIN_CONFIG_RDSEL: reg = (param == MTK_PIN_CONFIG_TDSEL) ? PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; - - err = mtk_hw_get_value(hw, desc, reg, &val); - if (err) - return err; - - ret = val; - + err = mtk_hw_get_value(hw, desc, reg, &ret); break; case MTK_PIN_CONFIG_PU_ADV: case MTK_PIN_CONFIG_PD_ADV: @@ -173,28 +168,24 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, pullup = param == MTK_PIN_CONFIG_PU_ADV; err = hw->soc->adv_pull_get(hw, desc, pullup, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } + } else + err = -ENOTSUPP; break; case MTK_PIN_CONFIG_DRV_ADV: - if (hw->soc->adv_drive_get) { + if (hw->soc->adv_drive_get) err = hw->soc->adv_drive_get(hw, desc, &ret); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; default: - return -ENOTSUPP; + err = -ENOTSUPP; } - *config = pinconf_to_config_packed(param, ret); +out: + if (!err) + *config = pinconf_to_config_packed(param, ret); - return 0; + return err; } static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, @@ -206,64 +197,55 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, int err = 0; u32 reg; + if (pin >= hw->soc->npins) { + err = -EINVAL; + goto err; + } desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; switch ((u32)param) { case PIN_CONFIG_BIAS_DISABLE: - if (hw->soc->bias_disable_set) { - err = hw->soc->bias_disable_set(hw, desc); - if (err) - return err; - } else { - return -ENOTSUPP; - } + if (hw->soc->bias_set_combo) + err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE); + else + err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_UP: - if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 1); - if (err) - return err; - } else { - return -ENOTSUPP; - } + if (hw->soc->bias_set_combo) + err = hw->soc->bias_set_combo(hw, desc, 1, arg); + else + err = -ENOTSUPP; break; case PIN_CONFIG_BIAS_PULL_DOWN: - if (hw->soc->bias_set) { - err = hw->soc->bias_set(hw, desc, 0); - if (err) - return err; - } else { - return -ENOTSUPP; - } + if (hw->soc->bias_set_combo) + err = hw->soc->bias_set_combo(hw, desc, 0, arg); + else + err = -ENOTSUPP; break; case PIN_CONFIG_OUTPUT_ENABLE: err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_DISABLE); - if (err) + /* Keep set direction to consider the case that a GPIO pin + * does not have SMT control + */ + if (err != -ENOTSUPP) goto err; err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_OUTPUT); - if (err) - goto err; break; case PIN_CONFIG_INPUT_ENABLE: - if (hw->soc->ies_present) { - mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, - MTK_ENABLE); - } + /* regard all non-zero value as enable */ + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg); + if (err) + goto err; err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT); - if (err) - goto err; break; case PIN_CONFIG_SLEW_RATE: - err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, - arg); - if (err) - goto err; - + /* regard all non-zero value as enable */ + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, !!arg); break; case PIN_CONFIG_OUTPUT: err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, @@ -273,41 +255,29 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, arg); - if (err) - goto err; break; + case PIN_CONFIG_INPUT_SCHMITT: case PIN_CONFIG_INPUT_SCHMITT_ENABLE: /* arg = 1: Input mode & SMT enable ; * arg = 0: Output mode & SMT disable */ - arg = arg ? 2 : 1; - err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, - arg & 1); + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !arg); if (err) goto err; - err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, - !!(arg & 2)); - if (err) - goto err; + err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, !!arg); break; case PIN_CONFIG_DRIVE_STRENGTH: - if (hw->soc->drive_set) { + if (hw->soc->drive_set) err = hw->soc->drive_set(hw, desc, arg); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; case MTK_PIN_CONFIG_TDSEL: case MTK_PIN_CONFIG_RDSEL: reg = (param == MTK_PIN_CONFIG_TDSEL) ? PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; - err = mtk_hw_set_value(hw, desc, reg, arg); - if (err) - goto err; break; case MTK_PIN_CONFIG_PU_ADV: case MTK_PIN_CONFIG_PD_ADV: @@ -317,20 +287,14 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, pullup = param == MTK_PIN_CONFIG_PU_ADV; err = hw->soc->adv_pull_set(hw, desc, pullup, arg); - if (err) - return err; - } else { - return -ENOTSUPP; - } + } else + err = -ENOTSUPP; break; case MTK_PIN_CONFIG_DRV_ADV: - if (hw->soc->adv_drive_set) { + if (hw->soc->adv_drive_set) err = hw->soc->adv_drive_set(hw, desc, arg); - if (err) - return err; - } else { - return -ENOTSUPP; - } + else + err = -ENOTSUPP; break; default: err = -ENOTSUPP; @@ -575,12 +539,120 @@ static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev, return 0; } +static int mtk_hw_get_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio, int field) +{ + const struct mtk_pin_desc *desc; + int value, err; + + if (gpio >= hw->soc->npins) + return -EINVAL; + + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; + + err = mtk_hw_get_value(hw, desc, field, &value); + if (err) + return err; + + return value; +} + +#define mtk_pctrl_get_pinmux(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_MODE) + +#define mtk_pctrl_get_direction(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DIR) + +#define mtk_pctrl_get_out(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DO) + +#define mtk_pctrl_get_in(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DI) + +#define mtk_pctrl_get_smt(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_SMT) + +#define mtk_pctrl_get_ies(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_IES) + +#define mtk_pctrl_get_driving(hw, gpio) \ + mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DRV) + +ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw, + unsigned int gpio, char *buf, unsigned int bufLen) +{ + int pinmux, pullup, pullen, len = 0, r1 = -1, r0 = -1; + const struct mtk_pin_desc *desc; + + if (gpio >= hw->soc->npins) + return -EINVAL; + + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; + pinmux = mtk_pctrl_get_pinmux(hw, gpio); + if (pinmux >= hw->soc->nfuncs) + pinmux -= hw->soc->nfuncs; + + mtk_pinconf_bias_get_combo(hw, desc, &pullup, &pullen); + if (pullen == MTK_PUPD_SET_R1R0_00) { + pullen = 0; + r1 = 0; + r0 = 0; + } else if (pullen == MTK_PUPD_SET_R1R0_01) { + pullen = 1; + r1 = 0; + r0 = 1; + } else if (pullen == MTK_PUPD_SET_R1R0_10) { + pullen = 1; + r1 = 1; + r0 = 0; + } else if (pullen == MTK_PUPD_SET_R1R0_11) { + pullen = 1; + r1 = 1; + r0 = 1; + } else if (pullen != MTK_DISABLE && pullen != MTK_ENABLE) { + pullen = 0; + } + len += scnprintf(buf + len, bufLen - len, + "%03d: %1d%1d%1d%1d%02d%1d%1d%1d%1d", + gpio, + pinmux, + mtk_pctrl_get_direction(hw, gpio), + mtk_pctrl_get_out(hw, gpio), + mtk_pctrl_get_in(hw, gpio), + mtk_pctrl_get_driving(hw, gpio), + mtk_pctrl_get_smt(hw, gpio), + mtk_pctrl_get_ies(hw, gpio), + pullen, + pullup); + + if (r1 != -1) { + len += scnprintf(buf + len, bufLen - len, " (%1d %1d)\n", + r1, r0); + } else { + len += scnprintf(buf + len, bufLen - len, "\n"); + } + + return len; +} + +#define PIN_DBG_BUF_SZ 96 +static void mtk_pctrl_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned int gpio) +{ + struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); + char buf[PIN_DBG_BUF_SZ]; + + (void)mtk_pctrl_show_one_pin(hw, gpio, buf, PIN_DBG_BUF_SZ); + + seq_printf(s, "%s", buf); +} + static const struct pinctrl_ops mtk_pctlops = { .dt_node_to_map = mtk_pctrl_dt_node_to_map, .dt_free_map = pinctrl_utils_free_map, .get_groups_count = mtk_pctrl_get_groups_count, .get_group_name = mtk_pctrl_get_group_name, .get_group_pins = mtk_pctrl_get_group_pins, + .pin_dbg_show = mtk_pctrl_dbg_show, }; static int mtk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) @@ -677,6 +749,7 @@ static const struct pinconf_ops mtk_confops = { .pin_config_get = mtk_pinconf_get, .pin_config_group_get = mtk_pconf_group_get, .pin_config_group_set = mtk_pconf_group_set, + .is_generic = true, }; static struct pinctrl_desc mtk_desc = { @@ -693,13 +766,19 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) const struct mtk_pin_desc *desc; int value, err; + if (gpio >= hw->soc->npins) + return -EINVAL; + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &value); if (err) return err; - return !value; + if (value) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) @@ -708,6 +787,9 @@ static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) const struct mtk_pin_desc *desc; int value, err; + if (gpio >= hw->soc->npins) + return -EINVAL; + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value); @@ -722,6 +804,9 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) struct mtk_pinctrl *hw = gpiochip_get_data(chip); const struct mtk_pin_desc *desc; + if (gpio >= hw->soc->npins) + return; + desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value); @@ -729,12 +814,22 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio) { + struct mtk_pinctrl *hw = gpiochip_get_data(chip); + + if (gpio >= hw->soc->npins) + return -EINVAL; + return pinctrl_gpio_direction_input(chip->base + gpio); } static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio, int value) { + struct mtk_pinctrl *hw = gpiochip_get_data(chip); + + if (gpio >= hw->soc->npins) + return -EINVAL; + mtk_gpio_set(chip, gpio, value); return pinctrl_gpio_direction_output(chip->base + gpio); diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.h b/drivers/pinctrl/mediatek/pinctrl-paris.h index 3d43771074e6..afb7650fd25b 100644 --- a/drivers/pinctrl/mediatek/pinctrl-paris.h +++ b/drivers/pinctrl/mediatek/pinctrl-paris.h @@ -60,6 +60,9 @@ int mtk_paris_pinctrl_probe(struct platform_device *pdev, const struct mtk_pin_soc *soc); +ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw, + unsigned int gpio, char *buf, unsigned int bufLen); + extern const struct dev_pm_ops mtk_paris_pinctrl_pm_ops; #endif /* __PINCTRL_PARIS_H */ diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c index 926b9997159a..d130c635f74b 100644 --- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c +++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c @@ -231,10 +231,24 @@ static const unsigned int hdmi_hpd_pins[] = { GPIOH_0 }; static const unsigned int hdmi_sda_pins[] = { GPIOH_1 }; static const unsigned int hdmi_scl_pins[] = { GPIOH_2 }; +static const unsigned int tsin_a_d_valid_pins[] = { GPIOY_0 }; +static const unsigned int tsin_a_sop_pins[] = { GPIOY_1 }; +static const unsigned int tsin_a_clk_pins[] = { GPIOY_2 }; +static const unsigned int tsin_a_d0_pins[] = { GPIOY_3 }; +static const unsigned int tsin_a_dp_pins[] = { + GPIOY_4, GPIOY_5, GPIOY_6, GPIOY_7, GPIOY_8, GPIOY_9, GPIOY_10 +}; + +static const unsigned int tsin_a_fail_pins[] = { GPIOY_11 }; static const unsigned int i2s_out_ch23_y_pins[] = { GPIOY_8 }; static const unsigned int i2s_out_ch45_y_pins[] = { GPIOY_9 }; static const unsigned int i2s_out_ch67_y_pins[] = { GPIOY_10 }; +static const unsigned int tsin_b_d_valid_pins[] = { GPIOX_6 }; +static const unsigned int tsin_b_sop_pins[] = { GPIOX_7 }; +static const unsigned int tsin_b_clk_pins[] = { GPIOX_8 }; +static const unsigned int tsin_b_d0_pins[] = { GPIOX_9 }; + static const unsigned int spdif_out_y_pins[] = { GPIOY_12 }; static const unsigned int gen_clk_out_pins[] = { GPIOY_15 }; @@ -437,12 +451,22 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = { GROUP(pwm_a_x, 3, 17), GROUP(pwm_e, 2, 30), GROUP(pwm_f_x, 3, 18), + GROUP(tsin_b_d_valid, 3, 9), + GROUP(tsin_b_sop, 3, 8), + GROUP(tsin_b_clk, 3, 10), + GROUP(tsin_b_d0, 3, 7), /* Bank Y */ GROUP(uart_cts_c, 1, 17), GROUP(uart_rts_c, 1, 16), GROUP(uart_tx_c, 1, 19), GROUP(uart_rx_c, 1, 18), + GROUP(tsin_a_fail, 3, 3), + GROUP(tsin_a_d_valid, 3, 2), + GROUP(tsin_a_sop, 3, 1), + GROUP(tsin_a_clk, 3, 0), + GROUP(tsin_a_d0, 3, 4), + GROUP(tsin_a_dp, 3, 5), GROUP(pwm_a_y, 1, 21), GROUP(pwm_f_y, 1, 20), GROUP(i2s_out_ch23_y, 1, 5), @@ -601,6 +625,15 @@ static const char * const gpio_periphs_groups[] = { "GPIOX_20", "GPIOX_21", "GPIOX_22", }; +static const char * const tsin_a_groups[] = { + "tsin_a_clk", "tsin_a_sop", "tsin_a_d_valid", "tsin_a_d0", + "tsin_a_dp", "tsin_a_fail", +}; + +static const char * const tsin_b_groups[] = { + "tsin_b_clk", "tsin_b_sop", "tsin_b_d_valid", "tsin_b_d0", +}; + static const char * const emmc_groups[] = { "emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds", }; @@ -792,6 +825,8 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = { FUNCTION(i2s_out), FUNCTION(spdif_out), FUNCTION(gen_clk_out), + FUNCTION(tsin_a), + FUNCTION(tsin_b), }; static struct meson_pmx_func meson_gxbb_aobus_functions[] = { diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c index 2ac921c83da9..32552d795bb2 100644 --- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c +++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c @@ -241,6 +241,17 @@ static const unsigned int tsin_a_dp_pins[] = { GPIODV_1, GPIODV_2, GPIODV_3, GPIODV_4, GPIODV_5, GPIODV_6, GPIODV_7, }; +static const unsigned int tsin_b_clk_pins[] = { GPIOH_6 }; +static const unsigned int tsin_b_d0_pins[] = { GPIOH_7 }; +static const unsigned int tsin_b_sop_pins[] = { GPIOH_8 }; +static const unsigned int tsin_b_d_valid_pins[] = { GPIOH_9 }; + +static const unsigned int tsin_b_fail_z4_pins[] = { GPIOZ_4 }; +static const unsigned int tsin_b_clk_z3_pins[] = { GPIOZ_3 }; +static const unsigned int tsin_b_d0_z2_pins[] = { GPIOZ_2 }; +static const unsigned int tsin_b_sop_z1_pins[] = { GPIOZ_1 }; +static const unsigned int tsin_b_d_valid_z0_pins[] = { GPIOZ_0 }; + static const struct pinctrl_pin_desc meson_gxl_aobus_pins[] = { MESON_PIN(GPIOAO_0), MESON_PIN(GPIOAO_1), @@ -438,6 +449,11 @@ static struct meson_pmx_group meson_gxl_periphs_groups[] = { GROUP(eth_txd1, 4, 12), GROUP(eth_txd2, 4, 11), GROUP(eth_txd3, 4, 10), + GROUP(tsin_b_fail_z4, 3, 15), + GROUP(tsin_b_clk_z3, 3, 16), + GROUP(tsin_b_d0_z2, 3, 17), + GROUP(tsin_b_sop_z1, 3, 18), + GROUP(tsin_b_d_valid_z0, 3, 19), GROUP(pwm_c, 3, 20), GROUP(i2s_out_ch23_z, 3, 26), GROUP(i2s_out_ch45_z, 3, 25), @@ -454,6 +470,10 @@ static struct meson_pmx_group meson_gxl_periphs_groups[] = { GROUP(i2s_out_lr_clk, 6, 24), GROUP(i2s_out_ch01, 6, 23), GROUP(spdif_out_h, 6, 28), + GROUP(tsin_b_d0, 6, 17), + GROUP(tsin_b_sop, 6, 18), + GROUP(tsin_b_d_valid, 6, 19), + GROUP(tsin_b_clk, 6, 20), /* Bank DV */ GROUP(uart_tx_b, 2, 16), @@ -689,6 +709,12 @@ static const char * const tsin_a_groups[] = { "tsin_a_dp", "tsin_a_fail", }; +static const char * const tsin_b_groups[] = { + "tsin_b_clk", "tsin_b_sop", "tsin_b_d_valid", "tsin_b_d0", + "tsin_b_clk_z3", "tsin_b_sop_z1", "tsin_b_d_valid_z0", "tsin_b_d0_z2", + "tsin_b_fail_z4", +}; + static const char * const gpio_aobus_groups[] = { "GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4", "GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9", @@ -764,6 +790,7 @@ static struct meson_pmx_func meson_gxl_periphs_functions[] = { FUNCTION(spdif_out), FUNCTION(eth_led), FUNCTION(tsin_a), + FUNCTION(tsin_b), }; static struct meson_pmx_func meson_gxl_aobus_functions[] = { diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 243fba254175..5f125bd6279d 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -15,6 +15,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinctrl.h> @@ -402,7 +403,10 @@ static int armada_37xx_gpio_get_direction(struct gpio_chip *chip, mask = BIT(offset); regmap_read(info->regmap, reg, &val); - return !(val & mask); + if (val & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int armada_37xx_gpio_direction_output(struct gpio_chip *chip, @@ -738,14 +742,7 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev, return ret; } - nr_irq_parent = platform_irq_count(pdev); - if (nr_irq_parent < 0) { - if (nr_irq_parent != -EPROBE_DEFER) - dev_err(dev, "Couldn't determine irq count: %pe\n", - ERR_PTR(nr_irq_parent)); - return nr_irq_parent; - } - + nr_irq_parent = of_irq_count(np); spin_lock_init(&info->irq_lock); if (!nr_irq_parent) { @@ -782,7 +779,7 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev, if (!girq->parents) return -ENOMEM; for (i = 0; i < nr_irq_parent; i++) { - int irq = platform_get_irq(pdev, i); + int irq = irq_of_parse_and_map(np, i); if (irq < 0) continue; diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 95f864dfdef4..ca7bbe4164c0 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -831,11 +831,14 @@ static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned offset) clk_enable(nmk_chip->clk); - dir = !(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset)); + dir = readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset); clk_disable(nmk_chip->clk); - return dir; + if (dir) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 9eb86309c70b..dfef471201f6 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -286,6 +286,7 @@ out: kfree(cfg); return ret; } +EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config); int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 73aff6591de2..1fe62a35bb12 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -46,7 +46,10 @@ static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset) pin_reg = readl(gpio_dev->base + offset * 4); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - return !(pin_reg & BIT(OUTPUT_ENABLE_OFF)); + if (pin_reg & BIT(OUTPUT_ENABLE_OFF)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int amd_gpio_direction_input(struct gpio_chip *gc, unsigned offset) diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 207f266e9cf2..52386ad29f28 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -1414,7 +1414,10 @@ static int at91_gpio_get_direction(struct gpio_chip *chip, unsigned offset) u32 osr; osr = readl_relaxed(pio + PIO_OSR); - return !(osr & mask); + if (osr & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index be5b645815e5..207cbae3a7bf 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c @@ -149,13 +149,16 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip, * going to change the value soon anyway. Default to output. */ if ((val & AXP20X_GPIO_FUNCTIONS) > 2) - return 0; + return GPIO_LINE_DIRECTION_OUT; /* * The GPIO directions are the three lowest values. * 2 is input, 0 and 1 are output */ - return val & 2; + if (val & 2) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static int axp20x_gpio_output(struct gpio_chip *chip, unsigned int offset, diff --git a/drivers/pinctrl/pinctrl-da9062.c b/drivers/pinctrl/pinctrl-da9062.c new file mode 100644 index 000000000000..1c08579f0198 --- /dev/null +++ b/drivers/pinctrl/pinctrl-da9062.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Dialog DA9062 pinctrl and GPIO driver. + * Based on DA9055 GPIO driver. + * + * TODO: + * - add pinmux and pinctrl support (gpio alternate mode) + * + * Documents: + * [1] https://www.dialog-semiconductor.com/sites/default/files/da9062_datasheet_3v6.pdf + * + * Copyright (C) 2019 Pengutronix, Marco Felsch <kernel@pengutronix.de> + */ +#include <linux/bits.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <linux/gpio/driver.h> + +#include <linux/mfd/da9062/core.h> +#include <linux/mfd/da9062/registers.h> + +/* + * We need this get the gpio_desc from a <gpio_chip,offset> tuple to decide if + * the gpio is active low without a vendor specific dt-binding. + */ +#include "../gpio/gpiolib.h" + +#define DA9062_TYPE(offset) (4 * (offset % 2)) +#define DA9062_PIN_SHIFT(offset) (4 * (offset % 2)) +#define DA9062_PIN_ALTERNATE 0x00 /* gpio alternate mode */ +#define DA9062_PIN_GPI 0x01 /* gpio in */ +#define DA9062_PIN_GPO_OD 0x02 /* gpio out open-drain */ +#define DA9062_PIN_GPO_PP 0x03 /* gpio out push-pull */ +#define DA9062_GPIO_NUM 5 + +struct da9062_pctl { + struct da9062 *da9062; + struct gpio_chip gc; + unsigned int pin_config[DA9062_GPIO_NUM]; +}; + +static int da9062_pctl_get_pin_mode(struct da9062_pctl *pctl, + unsigned int offset) +{ + struct regmap *regmap = pctl->da9062->regmap; + int ret, val; + + ret = regmap_read(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), &val); + if (ret < 0) + return ret; + + val >>= DA9062_PIN_SHIFT(offset); + val &= DA9062AA_GPIO0_PIN_MASK; + + return val; +} + +static int da9062_pctl_set_pin_mode(struct da9062_pctl *pctl, + unsigned int offset, unsigned int mode_req) +{ + struct regmap *regmap = pctl->da9062->regmap; + unsigned int mode = mode_req; + unsigned int mask; + int ret; + + mode &= DA9062AA_GPIO0_PIN_MASK; + mode <<= DA9062_PIN_SHIFT(offset); + mask = DA9062AA_GPIO0_PIN_MASK << DA9062_PIN_SHIFT(offset); + + ret = regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), + mask, mode); + if (!ret) + pctl->pin_config[offset] = mode_req; + + return ret; +} + +static int da9062_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + int gpio_mode, val; + int ret; + + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return gpio_mode; + + switch (gpio_mode) { + case DA9062_PIN_ALTERNATE: + return -ENOTSUPP; + case DA9062_PIN_GPI: + ret = regmap_read(regmap, DA9062AA_STATUS_B, &val); + if (ret < 0) + return ret; + break; + case DA9062_PIN_GPO_OD: + case DA9062_PIN_GPO_PP: + ret = regmap_read(regmap, DA9062AA_GPIO_MODE0_4, &val); + if (ret < 0) + return ret; + } + + return !!(val & BIT(offset)); +} + +static void da9062_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + + regmap_update_bits(regmap, DA9062AA_GPIO_MODE0_4, BIT(offset), + value << offset); +} + +static int da9062_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + int gpio_mode; + + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return gpio_mode; + + switch (gpio_mode) { + case DA9062_PIN_ALTERNATE: + return -ENOTSUPP; + case DA9062_PIN_GPI: + return GPIO_LINE_DIRECTION_IN; + case DA9062_PIN_GPO_OD: + case DA9062_PIN_GPO_PP: + return GPIO_LINE_DIRECTION_OUT; + } + + return -EINVAL; +} + +static int da9062_gpio_direction_input(struct gpio_chip *gc, + unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); + unsigned int gpi_type; + int ret; + + ret = da9062_pctl_set_pin_mode(pctl, offset, DA9062_PIN_GPI); + if (ret) + return ret; + + /* + * If the gpio is active low we should set it in hw too. No worries + * about gpio_get() because we read and return the gpio-level. So the + * gpiolib active_low handling is still correct. + * + * 0 - active low, 1 - active high + */ + gpi_type = !gpiod_is_active_low(desc); + + return regmap_update_bits(regmap, DA9062AA_GPIO_0_1 + (offset >> 1), + DA9062AA_GPIO0_TYPE_MASK << DA9062_TYPE(offset), + gpi_type << DA9062_TYPE(offset)); +} + +static int da9062_gpio_direction_output(struct gpio_chip *gc, + unsigned int offset, int value) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + unsigned int pin_config = pctl->pin_config[offset]; + int ret; + + ret = da9062_pctl_set_pin_mode(pctl, offset, pin_config); + if (ret) + return ret; + + da9062_gpio_set(gc, offset, value); + + return 0; +} + +static int da9062_gpio_set_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct regmap *regmap = pctl->da9062->regmap; + int gpio_mode; + + /* + * We need to meet the following restrictions [1, Figure 18]: + * - PIN_CONFIG_BIAS_PULL_DOWN -> only allowed if the pin is used as + * gpio input + * - PIN_CONFIG_BIAS_PULL_UP -> only allowed if the pin is used as + * gpio output open-drain. + */ + + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_BIAS_DISABLE: + return regmap_update_bits(regmap, DA9062AA_CONFIG_K, + BIT(offset), 0); + case PIN_CONFIG_BIAS_PULL_DOWN: + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return -EINVAL; + else if (gpio_mode != DA9062_PIN_GPI) + return -ENOTSUPP; + return regmap_update_bits(regmap, DA9062AA_CONFIG_K, + BIT(offset), BIT(offset)); + case PIN_CONFIG_BIAS_PULL_UP: + gpio_mode = da9062_pctl_get_pin_mode(pctl, offset); + if (gpio_mode < 0) + return -EINVAL; + else if (gpio_mode != DA9062_PIN_GPO_OD) + return -ENOTSUPP; + return regmap_update_bits(regmap, DA9062AA_CONFIG_K, + BIT(offset), BIT(offset)); + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + return da9062_pctl_set_pin_mode(pctl, offset, + DA9062_PIN_GPO_OD); + case PIN_CONFIG_DRIVE_PUSH_PULL: + return da9062_pctl_set_pin_mode(pctl, offset, + DA9062_PIN_GPO_PP); + default: + return -ENOTSUPP; + } +} + +static int da9062_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +{ + struct da9062_pctl *pctl = gpiochip_get_data(gc); + struct da9062 *da9062 = pctl->da9062; + + return regmap_irq_get_virq(da9062->regmap_irq, + DA9062_IRQ_GPI0 + offset); +} + +static const struct gpio_chip reference_gc = { + .owner = THIS_MODULE, + .get = da9062_gpio_get, + .set = da9062_gpio_set, + .get_direction = da9062_gpio_get_direction, + .direction_input = da9062_gpio_direction_input, + .direction_output = da9062_gpio_direction_output, + .set_config = da9062_gpio_set_config, + .to_irq = da9062_gpio_to_irq, + .can_sleep = true, + .ngpio = DA9062_GPIO_NUM, + .base = -1, +}; + +static int da9062_pctl_probe(struct platform_device *pdev) +{ + struct device *parent = pdev->dev.parent; + struct da9062_pctl *pctl; + int i; + + pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + + pctl->da9062 = dev_get_drvdata(parent); + if (!pctl->da9062) + return -EINVAL; + + if (!device_property_present(parent, "gpio-controller")) + return 0; + + for (i = 0; i < ARRAY_SIZE(pctl->pin_config); i++) + pctl->pin_config[i] = DA9062_PIN_GPO_PP; + + /* + * Currently the driver handles only the GPIO support. The + * pinctrl/pinmux support can be added later if needed. + */ + pctl->gc = reference_gc; + pctl->gc.label = dev_name(&pdev->dev); + pctl->gc.parent = &pdev->dev; +#ifdef CONFIG_OF_GPIO + pctl->gc.of_node = parent->of_node; +#endif + + platform_set_drvdata(pdev, pctl); + + return devm_gpiochip_add_data(&pdev->dev, &pctl->gc, pctl); +} + +static struct platform_driver da9062_pctl_driver = { + .probe = da9062_pctl_probe, + .driver = { + .name = "da9062-gpio", + }, +}; +module_platform_driver(da9062_pctl_driver); + +MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de>"); +MODULE_DESCRIPTION("DA9062 PMIC pinctrl and GPIO Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:da9062-gpio"); diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index 96f04d121ebd..7f5376ce7fb1 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -4,6 +4,7 @@ * * Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net> * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> + * Copyright (c) 2017, 2019 Paul Boddie <paul@boddie.org.uk> */ #include <linux/compiler.h> @@ -900,6 +901,7 @@ static int jz4780_mmc0_8bit_a_pins[] = { 0x04, 0x05, 0x06, 0x07, 0x18, }; static int jz4780_i2c3_pins[] = { 0x6a, 0x6b, }; static int jz4780_i2c4_e_pins[] = { 0x8c, 0x8d, }; static int jz4780_i2c4_f_pins[] = { 0xb9, 0xb8, }; +static int jz4780_hdmi_ddc_pins[] = { 0xb9, 0xb8, }; static int jz4780_uart2_data_funcs[] = { 1, 1, }; static int jz4780_uart2_hwflow_funcs[] = { 1, 1, }; @@ -908,6 +910,7 @@ static int jz4780_mmc0_8bit_a_funcs[] = { 1, 1, 1, 1, 1, }; static int jz4780_i2c3_funcs[] = { 1, 1, }; static int jz4780_i2c4_e_funcs[] = { 1, 1, }; static int jz4780_i2c4_f_funcs[] = { 1, 1, }; +static int jz4780_hdmi_ddc_funcs[] = { 0, 0, }; static const struct group_desc jz4780_groups[] = { INGENIC_PIN_GROUP("uart0-data", jz4770_uart0_data), @@ -950,6 +953,7 @@ static const struct group_desc jz4780_groups[] = { INGENIC_PIN_GROUP("i2c3-data", jz4780_i2c3), INGENIC_PIN_GROUP("i2c4-data-e", jz4780_i2c4_e), INGENIC_PIN_GROUP("i2c4-data-f", jz4780_i2c4_f), + INGENIC_PIN_GROUP("hdmi-ddc", jz4780_hdmi_ddc), INGENIC_PIN_GROUP("cim-data", jz4770_cim_8bit), INGENIC_PIN_GROUP("lcd-24bit", jz4770_lcd_24bit), { "lcd-no-pins", }, @@ -982,6 +986,7 @@ static const char *jz4780_nemc_groups[] = { static const char *jz4780_i2c3_groups[] = { "i2c3-data", }; static const char *jz4780_i2c4_groups[] = { "i2c4-data-e", "i2c4-data-f", }; static const char *jz4780_cim_groups[] = { "cim-data", }; +static const char *jz4780_hdmi_ddc_groups[] = { "hdmi-ddc", }; static const struct function_desc jz4780_functions[] = { { "uart0", jz4770_uart0_groups, ARRAY_SIZE(jz4770_uart0_groups), }, @@ -1014,6 +1019,8 @@ static const struct function_desc jz4780_functions[] = { { "pwm5", jz4770_pwm5_groups, ARRAY_SIZE(jz4770_pwm5_groups), }, { "pwm6", jz4770_pwm6_groups, ARRAY_SIZE(jz4770_pwm6_groups), }, { "pwm7", jz4770_pwm7_groups, ARRAY_SIZE(jz4770_pwm7_groups), }, + { "hdmi-ddc", jz4780_hdmi_ddc_groups, + ARRAY_SIZE(jz4780_hdmi_ddc_groups), }, }; static const struct ingenic_chip_info jz4780_chip_info = { @@ -1437,6 +1444,19 @@ static int x1830_mmc1_4bit_pins[] = { 0x45, 0x46, 0x47, }; static int x1830_i2c0_pins[] = { 0x0c, 0x0d, }; static int x1830_i2c1_pins[] = { 0x39, 0x3a, }; static int x1830_i2c2_pins[] = { 0x5b, 0x5c, }; +static int x1830_lcd_rgb_18bit_pins[] = { + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, +}; +static int x1830_lcd_slcd_8bit_pins[] = { + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x6c, 0x6d, + 0x69, 0x72, 0x73, 0x7b, 0x7a, +}; +static int x1830_lcd_slcd_16bit_pins[] = { + 0x6e, 0x6f, 0x70, 0x71, 0x76, 0x77, 0x78, 0x79, +}; static int x1830_pwm_pwm0_b_pins[] = { 0x31, }; static int x1830_pwm_pwm0_c_pins[] = { 0x4b, }; static int x1830_pwm_pwm1_b_pins[] = { 0x32, }; @@ -1486,6 +1506,16 @@ static int x1830_mmc1_4bit_funcs[] = { 0, 0, 0, }; static int x1830_i2c0_funcs[] = { 1, 1, }; static int x1830_i2c1_funcs[] = { 0, 0, }; static int x1830_i2c2_funcs[] = { 1, 1, }; +static int x1830_lcd_rgb_18bit_funcs[] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; +static int x1830_lcd_slcd_8bit_funcs[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; +static int x1830_lcd_slcd_16bit_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, }; static int x1830_pwm_pwm0_b_funcs[] = { 0, }; static int x1830_pwm_pwm0_c_funcs[] = { 1, }; static int x1830_pwm_pwm1_b_funcs[] = { 0, }; @@ -1534,6 +1564,10 @@ static const struct group_desc x1830_groups[] = { INGENIC_PIN_GROUP("i2c0-data", x1830_i2c0), INGENIC_PIN_GROUP("i2c1-data", x1830_i2c1), INGENIC_PIN_GROUP("i2c2-data", x1830_i2c2), + INGENIC_PIN_GROUP("lcd-rgb-18bit", x1830_lcd_rgb_18bit), + INGENIC_PIN_GROUP("lcd-slcd-8bit", x1830_lcd_slcd_8bit), + INGENIC_PIN_GROUP("lcd-slcd-16bit", x1830_lcd_slcd_16bit), + { "lcd-no-pins", }, INGENIC_PIN_GROUP("pwm0-b", x1830_pwm_pwm0_b), INGENIC_PIN_GROUP("pwm0-c", x1830_pwm_pwm0_c), INGENIC_PIN_GROUP("pwm1-b", x1830_pwm_pwm1_b), @@ -1572,6 +1606,9 @@ static const char *x1830_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", }; static const char *x1830_i2c0_groups[] = { "i2c0-data", }; static const char *x1830_i2c1_groups[] = { "i2c1-data", }; static const char *x1830_i2c2_groups[] = { "i2c2-data", }; +static const char *x1830_lcd_groups[] = { + "lcd-rgb-18bit", "lcd-slcd-8bit", "lcd-slcd-16bit", "lcd-no-pins", +}; static const char *x1830_pwm0_groups[] = { "pwm0-b", "pwm0-c", }; static const char *x1830_pwm1_groups[] = { "pwm1-b", "pwm1-c", }; static const char *x1830_pwm2_groups[] = { "pwm2-c-8", "pwm2-c-13", }; @@ -1593,6 +1630,7 @@ static const struct function_desc x1830_functions[] = { { "i2c0", x1830_i2c0_groups, ARRAY_SIZE(x1830_i2c0_groups), }, { "i2c1", x1830_i2c1_groups, ARRAY_SIZE(x1830_i2c1_groups), }, { "i2c2", x1830_i2c2_groups, ARRAY_SIZE(x1830_i2c2_groups), }, + { "lcd", x1830_lcd_groups, ARRAY_SIZE(x1830_lcd_groups), }, { "pwm0", x1830_pwm0_groups, ARRAY_SIZE(x1830_pwm0_groups), }, { "pwm1", x1830_pwm1_groups, ARRAY_SIZE(x1830_pwm1_groups), }, { "pwm2", x1830_pwm2_groups, ARRAY_SIZE(x1830_pwm2_groups), }, @@ -1916,13 +1954,19 @@ static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) struct ingenic_pinctrl *jzpc = jzgc->jzpc; unsigned int pin = gc->base + offset; - if (jzpc->info->version >= ID_JZ4760) - return ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1); + if (jzpc->info->version >= ID_JZ4760) { + if (ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1)) + return GPIO_LINE_DIRECTION_IN; + return GPIO_LINE_DIRECTION_OUT; + } if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT)) - return true; + return GPIO_LINE_DIRECTION_IN; + + if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR)) + return GPIO_LINE_DIRECTION_OUT; - return !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR); + return GPIO_LINE_DIRECTION_IN; } static const struct pinctrl_ops ingenic_pctlops = { @@ -2158,7 +2202,8 @@ static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, break; default: - unreachable(); + /* unreachable */ + break; } } diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index eb3dd0d46d6c..ed8eac6c1494 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -604,7 +604,10 @@ static int ocelot_gpio_get_direction(struct gpio_chip *chip, regmap_read(info->map, REG(OCELOT_GPIO_OE, info, offset), &val); - return !(val & BIT(offset % 32)); + if (val & BIT(offset % 32)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int ocelot_gpio_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c index 674b7b5919df..5a312279b3c7 100644 --- a/drivers/pinctrl/pinctrl-oxnas.c +++ b/drivers/pinctrl/pinctrl-oxnas.c @@ -756,7 +756,10 @@ static int oxnas_gpio_get_direction(struct gpio_chip *chip, struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); u32 mask = BIT(offset); - return !(readl_relaxed(bank->reg_base + OUTPUT_EN) & mask); + if (readl_relaxed(bank->reg_base + OUTPUT_EN) & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int oxnas_gpio_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c index e5d6d3f9753e..a6e2a4a4ca95 100644 --- a/drivers/pinctrl/pinctrl-pic32.c +++ b/drivers/pinctrl/pinctrl-pic32.c @@ -1990,7 +1990,10 @@ static int pic32_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct pic32_gpio_bank *bank = gpiochip_get_data(chip); - return !!(readl(bank->reg_base + TRIS_REG) & BIT(offset)); + if (readl(bank->reg_base + TRIS_REG) & BIT(offset)) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static void pic32_gpio_irq_ack(struct irq_data *data) diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c index fa370c171cad..ec761ba2a2da 100644 --- a/drivers/pinctrl/pinctrl-pistachio.c +++ b/drivers/pinctrl/pinctrl-pistachio.c @@ -1166,7 +1166,10 @@ static int pistachio_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { struct pistachio_gpio_bank *bank = gpiochip_get_data(chip); - return !(gpio_readl(bank, GPIO_OUTPUT_EN) & BIT(offset)); + if (gpio_readl(bank, GPIO_OUTPUT_EN) & BIT(offset)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int pistachio_gpio_get(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/pinctrl/pinctrl-rk805.c b/drivers/pinctrl/pinctrl-rk805.c index 26adbe9d6d42..cccbe072274e 100644 --- a/drivers/pinctrl/pinctrl-rk805.c +++ b/drivers/pinctrl/pinctrl-rk805.c @@ -184,7 +184,7 @@ static int rk805_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) /* default output*/ if (!pci->pin_cfg[offset].dir_msk) - return 0; + return GPIO_LINE_DIRECTION_OUT; ret = regmap_read(pci->rk808->regmap, pci->pin_cfg[offset].reg, @@ -194,7 +194,10 @@ static int rk805_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) return ret; } - return !(val & pci->pin_cfg[offset].dir_msk); + if (val & pci->pin_cfg[offset].dir_msk) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static const struct gpio_chip rk805_gpio_chip = { diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index fc9a2a9959d9..098951346339 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -2549,7 +2549,10 @@ static int rockchip_gpio_get_direction(struct gpio_chip *chip, unsigned offset) data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); clk_disable(bank->clk); - return !(data & BIT(offset)); + if (data & BIT(offset)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } /* diff --git a/drivers/pinctrl/pinctrl-rza1.c b/drivers/pinctrl/pinctrl-rza1.c index 617585be6a7d..da2d8365c690 100644 --- a/drivers/pinctrl/pinctrl-rza1.c +++ b/drivers/pinctrl/pinctrl-rza1.c @@ -777,7 +777,10 @@ static int rza1_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) { struct rza1_port *port = gpiochip_get_data(chip); - return !!rza1_get_bit(port, RZA1_PM_REG, gpio); + if (rza1_get_bit(port, RZA1_PM_REG, gpio)) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static int rza1_gpio_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-rza2.c b/drivers/pinctrl/pinctrl-rza2.c index a205964e839b..c5bf98c86b2b 100644 --- a/drivers/pinctrl/pinctrl-rza2.c +++ b/drivers/pinctrl/pinctrl-rza2.c @@ -135,10 +135,10 @@ static int rza2_chip_get_direction(struct gpio_chip *chip, unsigned int offset) reg16 = (reg16 >> (pin * 2)) & RZA2_PDR_MASK; if (reg16 == RZA2_PDR_OUTPUT) - return 0; + return GPIO_LINE_DIRECTION_OUT; if (reg16 == RZA2_PDR_INPUT) - return 1; + return GPIO_LINE_DIRECTION_IN; /* * This GPIO controller has a default Hi-Z state that is not input or @@ -146,7 +146,7 @@ static int rza2_chip_get_direction(struct gpio_chip *chip, unsigned int offset) */ rza2_pin_to_gpio(priv->base, offset, 1); - return 1; + return GPIO_LINE_DIRECTION_IN; } static int rza2_chip_direction_input(struct gpio_chip *chip, diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 4f39a7945d01..7b8c7a0b13de 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -746,7 +746,10 @@ static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset) function = st_pctl_get_pin_function(&pc, offset); if (function) { st_pinconf_get_direction(&pc, offset, &config); - return !ST_PINCONF_UNPACK_OE(config); + if (ST_PINCONF_UNPACK_OE(config)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } /* @@ -758,7 +761,10 @@ static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset) direction |= ((value >> offset) & 0x1) << i; } - return (direction == ST_GPIO_DIRECTION_IN); + if (direction == ST_GPIO_DIRECTION_IN) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } /* Pinctrl Groups */ @@ -996,6 +1002,7 @@ static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev, unsigned int function; int offset = st_gpio_pin(pin_id); char f[16]; + int oe; mutex_unlock(&pctldev->mutex); pc = st_get_pio_control(pctldev, pin_id); @@ -1008,10 +1015,11 @@ static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev, else snprintf(f, 5, "GPIO"); + oe = st_gpio_get_direction(&pc_to_bank(pc)->gpio_chip, offset); seq_printf(s, "[OE:%d,PU:%ld,OD:%ld]\t%s\n" "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld," "de:%ld,rt-clk:%ld,rt-delay:%ld]", - !st_gpio_get_direction(&pc_to_bank(pc)->gpio_chip, offset), + (oe == GPIO_LINE_DIRECTION_OUT), ST_PINCONF_UNPACK_PU(config), ST_PINCONF_UNPACK_OD(config), f, diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 16723797fa7c..60100b45f5e5 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -134,10 +134,14 @@ static int stmfx_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ret = regmap_read(pctl->stmfx->map, reg, &val); /* * On stmfx, gpio pins direction is (0)input, (1)output. - * .get_direction returns 0=out, 1=in */ + if (ret) + return ret; - return ret ? ret : !(val & mask); + if (val & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int stmfx_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) @@ -223,6 +227,13 @@ static int stmfx_pinconf_get(struct pinctrl_dev *pctldev, dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin); if (dir < 0) return dir; + + /* + * Currently the gpiolib IN is 1 and OUT is 0 but let's not count + * on it just to be on the safe side also in the future :) + */ + dir = (dir == GPIO_LINE_DIRECTION_IN) ? 1 : 0; + type = stmfx_pinconf_get_type(pctl, pin); if (type < 0) return type; @@ -360,7 +371,7 @@ static void stmfx_pinconf_dbg_show(struct pinctrl_dev *pctldev, if (val < 0) return; - if (!dir) { + if (dir == GPIO_LINE_DIRECTION_OUT) { seq_printf(s, "output %s ", val ? "high" : "low"); if (type) seq_printf(s, "open drain %s internal pull-up ", diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 566665931a04..6e74bd87d959 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -391,13 +391,16 @@ static int sx150x_gpio_get_direction(struct gpio_chip *chip, int ret; if (sx150x_pin_is_oscio(pctl, offset)) - return false; + return GPIO_LINE_DIRECTION_OUT; ret = regmap_read(pctl->regmap, pctl->data->reg_dir, &value); if (ret < 0) return ret; - return !!(value & BIT(offset)); + if (value & BIT(offset)) + return GPIO_LINE_DIRECTION_IN; + + return GPIO_LINE_DIRECTION_OUT; } static int sx150x_gpio_get(struct gpio_chip *chip, unsigned int offset) @@ -687,7 +690,7 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, if (ret < 0) return ret; - if (ret) + if (ret == GPIO_LINE_DIRECTION_IN) return -EINVAL; ret = sx150x_gpio_get(&pctl->gpio, pin); diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 811af2f81c39..c5d4428f1f94 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -50,6 +50,16 @@ config PINCTRL_IPQ8074 Qualcomm Technologies Inc. IPQ8074 platform. Select this for IPQ8074. +config PINCTRL_IPQ6018 + tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver" + depends on GPIOLIB && OF + select PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for + the Qualcomm Technologies Inc. TLMM block found on the + Qualcomm Technologies Inc. IPQ6018 platform. Select this for + IPQ6018. + config PINCTRL_MSM8660 tristate "Qualcomm 8660 pin controller driver" depends on GPIOLIB && OF diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index c2c2f9ad6827..d9e09045a776 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o obj-$(CONFIG_PINCTRL_IPQ4019) += pinctrl-ipq4019.o obj-$(CONFIG_PINCTRL_IPQ8064) += pinctrl-ipq8064.o obj-$(CONFIG_PINCTRL_IPQ8074) += pinctrl-ipq8074.o +obj-$(CONFIG_PINCTRL_IPQ6018) += pinctrl-ipq6018.o obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c new file mode 100644 index 000000000000..38c33a778cb8 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c @@ -0,0 +1,1107 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-msm.h" + +#define FUNCTION(fname) \ + [msm_mux_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define REG_SIZE 0x1000 +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + msm_mux_gpio, /* gpio mode */ \ + msm_mux_##f1, \ + msm_mux_##f2, \ + msm_mux_##f3, \ + msm_mux_##f4, \ + msm_mux_##f5, \ + msm_mux_##f6, \ + msm_mux_##f7, \ + msm_mux_##f8, \ + msm_mux_##f9 \ + }, \ + .nfuncs = 10, \ + .ctl_reg = REG_SIZE * id, \ + .io_reg = 0x4 + REG_SIZE * id, \ + .intr_cfg_reg = 0x8 + REG_SIZE * id, \ + .intr_status_reg = 0xc + REG_SIZE * id, \ + .intr_target_reg = 0x8 + REG_SIZE * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 3, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +static const struct pinctrl_pin_desc ipq6018_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); + +enum ipq6018_functions { + msm_mux_atest_char, + msm_mux_atest_char0, + msm_mux_atest_char1, + msm_mux_atest_char2, + msm_mux_atest_char3, + msm_mux_audio0, + msm_mux_audio1, + msm_mux_audio2, + msm_mux_audio3, + msm_mux_audio_rxbclk, + msm_mux_audio_rxfsync, + msm_mux_audio_rxmclk, + msm_mux_audio_rxmclkin, + msm_mux_audio_txbclk, + msm_mux_audio_txfsync, + msm_mux_audio_txmclk, + msm_mux_audio_txmclkin, + msm_mux_blsp0_i2c, + msm_mux_blsp0_spi, + msm_mux_blsp0_uart, + msm_mux_blsp1_i2c, + msm_mux_blsp1_spi, + msm_mux_blsp1_uart, + msm_mux_blsp2_i2c, + msm_mux_blsp2_spi, + msm_mux_blsp2_uart, + msm_mux_blsp3_i2c, + msm_mux_blsp3_spi, + msm_mux_blsp3_uart, + msm_mux_blsp4_i2c, + msm_mux_blsp4_spi, + msm_mux_blsp4_uart, + msm_mux_blsp5_i2c, + msm_mux_blsp5_uart, + msm_mux_burn0, + msm_mux_burn1, + msm_mux_cri_trng, + msm_mux_cri_trng0, + msm_mux_cri_trng1, + msm_mux_cxc0, + msm_mux_cxc1, + msm_mux_dbg_out, + msm_mux_gcc_plltest, + msm_mux_gcc_tlmm, + msm_mux_gpio, + msm_mux_lpass_aud, + msm_mux_lpass_aud0, + msm_mux_lpass_aud1, + msm_mux_lpass_aud2, + msm_mux_lpass_pcm, + msm_mux_lpass_pdm, + msm_mux_mac00, + msm_mux_mac01, + msm_mux_mac10, + msm_mux_mac11, + msm_mux_mac12, + msm_mux_mac13, + msm_mux_mac20, + msm_mux_mac21, + msm_mux_mdc, + msm_mux_mdio, + msm_mux_pcie0_clk, + msm_mux_pcie0_rst, + msm_mux_pcie0_wake, + msm_mux_prng_rosc, + msm_mux_pta1_0, + msm_mux_pta1_1, + msm_mux_pta1_2, + msm_mux_pta2_0, + msm_mux_pta2_1, + msm_mux_pta2_2, + msm_mux_pwm00, + msm_mux_pwm01, + msm_mux_pwm02, + msm_mux_pwm03, + msm_mux_pwm04, + msm_mux_pwm10, + msm_mux_pwm11, + msm_mux_pwm12, + msm_mux_pwm13, + msm_mux_pwm14, + msm_mux_pwm20, + msm_mux_pwm21, + msm_mux_pwm22, + msm_mux_pwm23, + msm_mux_pwm24, + msm_mux_pwm30, + msm_mux_pwm31, + msm_mux_pwm32, + msm_mux_pwm33, + msm_mux_qdss_cti_trig_in_a0, + msm_mux_qdss_cti_trig_in_a1, + msm_mux_qdss_cti_trig_out_a0, + msm_mux_qdss_cti_trig_out_a1, + msm_mux_qdss_cti_trig_in_b0, + msm_mux_qdss_cti_trig_in_b1, + msm_mux_qdss_cti_trig_out_b0, + msm_mux_qdss_cti_trig_out_b1, + msm_mux_qdss_traceclk_a, + msm_mux_qdss_tracectl_a, + msm_mux_qdss_tracedata_a, + msm_mux_qdss_traceclk_b, + msm_mux_qdss_tracectl_b, + msm_mux_qdss_tracedata_b, + msm_mux_qpic_pad, + msm_mux_rx0, + msm_mux_rx1, + msm_mux_rx_swrm, + msm_mux_rx_swrm0, + msm_mux_rx_swrm1, + msm_mux_sd_card, + msm_mux_sd_write, + msm_mux_tsens_max, + msm_mux_tx_swrm, + msm_mux_tx_swrm0, + msm_mux_tx_swrm1, + msm_mux_tx_swrm2, + msm_mux_wci20, + msm_mux_wci21, + msm_mux_wci22, + msm_mux_wci23, + msm_mux_wsa_swrm, + msm_mux__, +}; + +static const char * const blsp3_uart_groups[] = { + "gpio73", "gpio74", "gpio75", "gpio76", +}; + +static const char * const blsp3_i2c_groups[] = { + "gpio73", "gpio74", +}; + +static const char * const blsp3_spi_groups[] = { + "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", "gpio78", "gpio79", +}; + +static const char * const wci20_groups[] = { + "gpio0", "gpio2", +}; + +static const char * const qpic_pad_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio9", "gpio10", + "gpio11", "gpio17", +}; + +static const char * const burn0_groups[] = { + "gpio0", +}; + +static const char * const mac12_groups[] = { + "gpio1", "gpio11", +}; + +static const char * const qdss_tracectl_b_groups[] = { + "gpio1", +}; + +static const char * const burn1_groups[] = { + "gpio1", +}; + +static const char * const qdss_traceclk_b_groups[] = { + "gpio0", +}; + +static const char * const qdss_tracedata_b_groups[] = { + "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio8", "gpio9", + "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", "gpio15", "gpio16", + "gpio17", +}; + +static const char * const mac01_groups[] = { + "gpio3", "gpio4", +}; + +static const char * const mac21_groups[] = { + "gpio5", "gpio6", +}; + +static const char * const atest_char_groups[] = { + "gpio9", +}; + +static const char * const cxc0_groups[] = { + "gpio9", "gpio16", +}; + +static const char * const mac13_groups[] = { + "gpio9", "gpio16", +}; + +static const char * const dbg_out_groups[] = { + "gpio9", +}; + +static const char * const wci22_groups[] = { + "gpio11", "gpio17", +}; + +static const char * const pwm00_groups[] = { + "gpio18", +}; + +static const char * const atest_char0_groups[] = { + "gpio18", +}; + +static const char * const wci23_groups[] = { + "gpio18", "gpio19", +}; + +static const char * const mac11_groups[] = { + "gpio18", "gpio19", +}; + +static const char * const pwm10_groups[] = { + "gpio19", +}; + +static const char * const atest_char1_groups[] = { + "gpio19", +}; + +static const char * const pwm20_groups[] = { + "gpio20", +}; + +static const char * const atest_char2_groups[] = { + "gpio20", +}; + +static const char * const pwm30_groups[] = { + "gpio21", +}; + +static const char * const atest_char3_groups[] = { + "gpio21", +}; + +static const char * const audio_txmclk_groups[] = { + "gpio22", +}; + +static const char * const audio_txmclkin_groups[] = { + "gpio22", +}; + +static const char * const pwm02_groups[] = { + "gpio22", +}; + +static const char * const tx_swrm0_groups[] = { + "gpio22", +}; + +static const char * const qdss_cti_trig_out_b0_groups[] = { + "gpio22", +}; + +static const char * const audio_txbclk_groups[] = { + "gpio23", +}; + +static const char * const pwm12_groups[] = { + "gpio23", +}; + +static const char * const wsa_swrm_groups[] = { + "gpio23", "gpio24", +}; + +static const char * const tx_swrm1_groups[] = { + "gpio23", +}; + +static const char * const qdss_cti_trig_in_b0_groups[] = { + "gpio23", +}; + +static const char * const audio_txfsync_groups[] = { + "gpio24", +}; + +static const char * const pwm22_groups[] = { + "gpio24", +}; + +static const char * const tx_swrm2_groups[] = { + "gpio24", +}; + +static const char * const qdss_cti_trig_out_b1_groups[] = { + "gpio24", +}; + +static const char * const audio0_groups[] = { + "gpio25", "gpio32", +}; + +static const char * const pwm32_groups[] = { + "gpio25", +}; + +static const char * const tx_swrm_groups[] = { + "gpio25", +}; + +static const char * const qdss_cti_trig_in_b1_groups[] = { + "gpio25", +}; + +static const char * const audio1_groups[] = { + "gpio26", "gpio33", +}; + +static const char * const pwm04_groups[] = { + "gpio26", +}; + +static const char * const audio2_groups[] = { + "gpio27", +}; + +static const char * const pwm14_groups[] = { + "gpio27", +}; + +static const char * const audio3_groups[] = { + "gpio28", +}; + +static const char * const pwm24_groups[] = { + "gpio28", +}; + +static const char * const audio_rxmclk_groups[] = { + "gpio29", +}; + +static const char * const audio_rxmclkin_groups[] = { + "gpio29", +}; + +static const char * const pwm03_groups[] = { + "gpio29", +}; + +static const char * const lpass_pdm_groups[] = { + "gpio29", "gpio30", "gpio31", "gpio32", +}; + +static const char * const lpass_aud_groups[] = { + "gpio29", +}; + +static const char * const qdss_cti_trig_in_a1_groups[] = { + "gpio29", +}; + +static const char * const audio_rxbclk_groups[] = { + "gpio30", +}; + +static const char * const pwm13_groups[] = { + "gpio30", +}; + +static const char * const lpass_aud0_groups[] = { + "gpio30", +}; + +static const char * const rx_swrm_groups[] = { + "gpio30", +}; + +static const char * const qdss_cti_trig_out_a1_groups[] = { + "gpio30", +}; + +static const char * const audio_rxfsync_groups[] = { + "gpio31", +}; + +static const char * const pwm23_groups[] = { + "gpio31", +}; + +static const char * const lpass_aud1_groups[] = { + "gpio31", +}; + +static const char * const rx_swrm0_groups[] = { + "gpio31", +}; + +static const char * const qdss_cti_trig_in_a0_groups[] = { + "gpio31", +}; + +static const char * const pwm33_groups[] = { + "gpio32", +}; + +static const char * const lpass_aud2_groups[] = { + "gpio32", +}; + +static const char * const rx_swrm1_groups[] = { + "gpio32", +}; + +static const char * const qdss_cti_trig_out_a0_groups[] = { + "gpio32", +}; + +static const char * const lpass_pcm_groups[] = { + "gpio34", "gpio35", "gpio36", "gpio37", +}; + +static const char * const mac10_groups[] = { + "gpio34", "gpio35", +}; + +static const char * const mac00_groups[] = { + "gpio34", "gpio35", +}; + +static const char * const mac20_groups[] = { + "gpio36", "gpio37", +}; + +static const char * const blsp0_uart_groups[] = { + "gpio38", "gpio39", "gpio40", "gpio41", +}; + +static const char * const blsp0_i2c_groups[] = { + "gpio38", "gpio39", +}; + +static const char * const blsp0_spi_groups[] = { + "gpio38", "gpio39", "gpio40", "gpio41", +}; + +static const char * const blsp2_uart_groups[] = { + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const blsp2_i2c_groups[] = { + "gpio42", "gpio43", +}; + +static const char * const blsp2_spi_groups[] = { + "gpio42", "gpio43", "gpio44", "gpio45", +}; + +static const char * const blsp5_i2c_groups[] = { + "gpio46", "gpio47", +}; + +static const char * const blsp5_uart_groups[] = { + "gpio48", "gpio49", +}; + +static const char * const qdss_traceclk_a_groups[] = { + "gpio48", +}; + +static const char * const qdss_tracectl_a_groups[] = { + "gpio49", +}; + +static const char * const pwm01_groups[] = { + "gpio50", +}; + +static const char * const pta1_1_groups[] = { + "gpio51", +}; + +static const char * const pwm11_groups[] = { + "gpio51", +}; + +static const char * const rx1_groups[] = { + "gpio51", +}; + +static const char * const pta1_2_groups[] = { + "gpio52", +}; + +static const char * const pwm21_groups[] = { + "gpio52", +}; + +static const char * const pta1_0_groups[] = { + "gpio53", +}; + +static const char * const pwm31_groups[] = { + "gpio53", +}; + +static const char * const prng_rosc_groups[] = { + "gpio53", +}; + +static const char * const blsp4_uart_groups[] = { + "gpio55", "gpio56", "gpio57", "gpio58", +}; + +static const char * const blsp4_i2c_groups[] = { + "gpio55", "gpio56", +}; + +static const char * const blsp4_spi_groups[] = { + "gpio55", "gpio56", "gpio57", "gpio58", +}; + +static const char * const pcie0_clk_groups[] = { + "gpio59", +}; + +static const char * const cri_trng0_groups[] = { + "gpio59", +}; + +static const char * const pcie0_rst_groups[] = { + "gpio60", +}; + +static const char * const cri_trng1_groups[] = { + "gpio60", +}; + +static const char * const pcie0_wake_groups[] = { + "gpio61", +}; + +static const char * const cri_trng_groups[] = { + "gpio61", +}; + +static const char * const sd_card_groups[] = { + "gpio62", +}; + +static const char * const sd_write_groups[] = { + "gpio63", +}; + +static const char * const rx0_groups[] = { + "gpio63", +}; + +static const char * const tsens_max_groups[] = { + "gpio63", +}; + +static const char * const mdc_groups[] = { + "gpio64", +}; + +static const char * const qdss_tracedata_a_groups[] = { + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", +}; + +static const char * const mdio_groups[] = { + "gpio65", +}; + +static const char * const pta2_0_groups[] = { + "gpio66", +}; + +static const char * const wci21_groups[] = { + "gpio66", "gpio68", +}; + +static const char * const cxc1_groups[] = { + "gpio66", "gpio68", +}; + +static const char * const pta2_1_groups[] = { + "gpio67", +}; + +static const char * const pta2_2_groups[] = { + "gpio68", +}; + +static const char * const blsp1_uart_groups[] = { + "gpio69", "gpio70", "gpio71", "gpio72", +}; + +static const char * const blsp1_i2c_groups[] = { + "gpio69", "gpio70", +}; + +static const char * const blsp1_spi_groups[] = { + "gpio69", "gpio70", "gpio71", "gpio72", +}; + +static const char * const gcc_plltest_groups[] = { + "gpio69", "gpio71", +}; + +static const char * const gcc_tlmm_groups[] = { + "gpio70", +}; + +static const char * const gpio_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", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", +}; + +static const struct msm_function ipq6018_functions[] = { + FUNCTION(atest_char), + FUNCTION(atest_char0), + FUNCTION(atest_char1), + FUNCTION(atest_char2), + FUNCTION(atest_char3), + FUNCTION(audio0), + FUNCTION(audio1), + FUNCTION(audio2), + FUNCTION(audio3), + FUNCTION(audio_rxbclk), + FUNCTION(audio_rxfsync), + FUNCTION(audio_rxmclk), + FUNCTION(audio_rxmclkin), + FUNCTION(audio_txbclk), + FUNCTION(audio_txfsync), + FUNCTION(audio_txmclk), + FUNCTION(audio_txmclkin), + FUNCTION(blsp0_i2c), + FUNCTION(blsp0_spi), + FUNCTION(blsp0_uart), + FUNCTION(blsp1_i2c), + FUNCTION(blsp1_spi), + FUNCTION(blsp1_uart), + FUNCTION(blsp2_i2c), + FUNCTION(blsp2_spi), + FUNCTION(blsp2_uart), + FUNCTION(blsp3_i2c), + FUNCTION(blsp3_spi), + FUNCTION(blsp3_uart), + FUNCTION(blsp4_i2c), + FUNCTION(blsp4_spi), + FUNCTION(blsp4_uart), + FUNCTION(blsp5_i2c), + FUNCTION(blsp5_uart), + FUNCTION(burn0), + FUNCTION(burn1), + FUNCTION(cri_trng), + FUNCTION(cri_trng0), + FUNCTION(cri_trng1), + FUNCTION(cxc0), + FUNCTION(cxc1), + FUNCTION(dbg_out), + FUNCTION(gcc_plltest), + FUNCTION(gcc_tlmm), + FUNCTION(gpio), + FUNCTION(lpass_aud), + FUNCTION(lpass_aud0), + FUNCTION(lpass_aud1), + FUNCTION(lpass_aud2), + FUNCTION(lpass_pcm), + FUNCTION(lpass_pdm), + FUNCTION(mac00), + FUNCTION(mac01), + FUNCTION(mac10), + FUNCTION(mac11), + FUNCTION(mac12), + FUNCTION(mac13), + FUNCTION(mac20), + FUNCTION(mac21), + FUNCTION(mdc), + FUNCTION(mdio), + FUNCTION(pcie0_clk), + FUNCTION(pcie0_rst), + FUNCTION(pcie0_wake), + FUNCTION(prng_rosc), + FUNCTION(pta1_0), + FUNCTION(pta1_1), + FUNCTION(pta1_2), + FUNCTION(pta2_0), + FUNCTION(pta2_1), + FUNCTION(pta2_2), + FUNCTION(pwm00), + FUNCTION(pwm01), + FUNCTION(pwm02), + FUNCTION(pwm03), + FUNCTION(pwm04), + FUNCTION(pwm10), + FUNCTION(pwm11), + FUNCTION(pwm12), + FUNCTION(pwm13), + FUNCTION(pwm14), + FUNCTION(pwm20), + FUNCTION(pwm21), + FUNCTION(pwm22), + FUNCTION(pwm23), + FUNCTION(pwm24), + FUNCTION(pwm30), + FUNCTION(pwm31), + FUNCTION(pwm32), + FUNCTION(pwm33), + FUNCTION(qdss_cti_trig_in_a0), + FUNCTION(qdss_cti_trig_in_a1), + FUNCTION(qdss_cti_trig_out_a0), + FUNCTION(qdss_cti_trig_out_a1), + FUNCTION(qdss_cti_trig_in_b0), + FUNCTION(qdss_cti_trig_in_b1), + FUNCTION(qdss_cti_trig_out_b0), + FUNCTION(qdss_cti_trig_out_b1), + FUNCTION(qdss_traceclk_a), + FUNCTION(qdss_tracectl_a), + FUNCTION(qdss_tracedata_a), + FUNCTION(qdss_traceclk_b), + FUNCTION(qdss_tracectl_b), + FUNCTION(qdss_tracedata_b), + FUNCTION(qpic_pad), + FUNCTION(rx0), + FUNCTION(rx1), + FUNCTION(rx_swrm), + FUNCTION(rx_swrm0), + FUNCTION(rx_swrm1), + FUNCTION(sd_card), + FUNCTION(sd_write), + FUNCTION(tsens_max), + FUNCTION(tx_swrm), + FUNCTION(tx_swrm0), + FUNCTION(tx_swrm1), + FUNCTION(tx_swrm2), + FUNCTION(wci20), + FUNCTION(wci21), + FUNCTION(wci22), + FUNCTION(wci23), + FUNCTION(wsa_swrm), +}; + +static const struct msm_pingroup ipq6018_groups[] = { + PINGROUP(0, qpic_pad, wci20, qdss_traceclk_b, _, burn0, _, _, _, _), + PINGROUP(1, qpic_pad, mac12, qdss_tracectl_b, _, burn1, _, _, _, _), + PINGROUP(2, qpic_pad, wci20, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(3, qpic_pad, mac01, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(4, qpic_pad, mac01, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(5, qpic_pad, mac21, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(6, qpic_pad, mac21, qdss_tracedata_b, _, _, _, _, _, _), + PINGROUP(7, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(8, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(9, qpic_pad, atest_char, cxc0, mac13, dbg_out, qdss_tracedata_b, _, _, _), + PINGROUP(10, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(11, qpic_pad, wci22, mac12, qdss_tracedata_b, _, _, _, _, _), + PINGROUP(12, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(13, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(14, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(15, qpic_pad, qdss_tracedata_b, _, _, _, _, _, _, _), + PINGROUP(16, qpic_pad, cxc0, mac13, qdss_tracedata_b, _, _, _, _, _), + PINGROUP(17, qpic_pad, qdss_tracedata_b, wci22, _, _, _, _, _, _), + PINGROUP(18, pwm00, atest_char0, wci23, mac11, _, _, _, _, _), + PINGROUP(19, pwm10, atest_char1, wci23, mac11, _, _, _, _, _), + PINGROUP(20, pwm20, atest_char2, _, _, _, _, _, _, _), + PINGROUP(21, pwm30, atest_char3, _, _, _, _, _, _, _), + PINGROUP(22, audio_txmclk, audio_txmclkin, pwm02, tx_swrm0, _, qdss_cti_trig_out_b0, _, _, _), + PINGROUP(23, audio_txbclk, pwm12, wsa_swrm, tx_swrm1, _, qdss_cti_trig_in_b0, _, _, _), + PINGROUP(24, audio_txfsync, pwm22, wsa_swrm, tx_swrm2, _, qdss_cti_trig_out_b1, _, _, _), + PINGROUP(25, audio0, pwm32, tx_swrm, _, qdss_cti_trig_in_b1, _, _, _, _), + PINGROUP(26, audio1, pwm04, _, _, _, _, _, _, _), + PINGROUP(27, audio2, pwm14, _, _, _, _, _, _, _), + PINGROUP(28, audio3, pwm24, _, _, _, _, _, _, _), + PINGROUP(29, audio_rxmclk, audio_rxmclkin, pwm03, lpass_pdm, lpass_aud, qdss_cti_trig_in_a1, _, _, _), + PINGROUP(30, audio_rxbclk, pwm13, lpass_pdm, lpass_aud0, rx_swrm, _, qdss_cti_trig_out_a1, _, _), + PINGROUP(31, audio_rxfsync, pwm23, lpass_pdm, lpass_aud1, rx_swrm0, _, qdss_cti_trig_in_a0, _, _), + PINGROUP(32, audio0, pwm33, lpass_pdm, lpass_aud2, rx_swrm1, _, qdss_cti_trig_out_a0, _, _), + PINGROUP(33, audio1, _, _, _, _, _, _, _, _), + PINGROUP(34, lpass_pcm, mac10, mac00, _, _, _, _, _, _), + PINGROUP(35, lpass_pcm, mac10, mac00, _, _, _, _, _, _), + PINGROUP(36, lpass_pcm, mac20, _, _, _, _, _, _, _), + PINGROUP(37, lpass_pcm, mac20, _, _, _, _, _, _, _), + PINGROUP(38, blsp0_uart, blsp0_i2c, blsp0_spi, _, _, _, _, _, _), + PINGROUP(39, blsp0_uart, blsp0_i2c, blsp0_spi, _, _, _, _, _, _), + PINGROUP(40, blsp0_uart, blsp0_spi, _, _, _, _, _, _, _), + PINGROUP(41, blsp0_uart, blsp0_spi, _, _, _, _, _, _, _), + PINGROUP(42, blsp2_uart, blsp2_i2c, blsp2_spi, _, _, _, _, _, _), + PINGROUP(43, blsp2_uart, blsp2_i2c, blsp2_spi, _, _, _, _, _, _), + PINGROUP(44, blsp2_uart, blsp2_spi, _, _, _, _, _, _, _), + PINGROUP(45, blsp2_uart, blsp2_spi, _, _, _, _, _, _, _), + PINGROUP(46, blsp5_i2c, _, _, _, _, _, _, _, _), + PINGROUP(47, blsp5_i2c, _, _, _, _, _, _, _, _), + PINGROUP(48, blsp5_uart, _, qdss_traceclk_a, _, _, _, _, _, _), + PINGROUP(49, blsp5_uart, _, qdss_tracectl_a, _, _, _, _, _, _), + PINGROUP(50, pwm01, _, _, _, _, _, _, _, _), + PINGROUP(51, pta1_1, pwm11, _, rx1, _, _, _, _, _), + PINGROUP(52, pta1_2, pwm21, _, _, _, _, _, _, _), + PINGROUP(53, pta1_0, pwm31, prng_rosc, _, _, _, _, _, _), + PINGROUP(54, _, _, _, _, _, _, _, _, _), + PINGROUP(55, blsp4_uart, blsp4_i2c, blsp4_spi, _, _, _, _, _, _), + PINGROUP(56, blsp4_uart, blsp4_i2c, blsp4_spi, _, _, _, _, _, _), + PINGROUP(57, blsp4_uart, blsp4_spi, _, _, _, _, _, _, _), + PINGROUP(58, blsp4_uart, blsp4_spi, _, _, _, _, _, _, _), + PINGROUP(59, pcie0_clk, _, _, cri_trng0, _, _, _, _, _), + PINGROUP(60, pcie0_rst, _, _, cri_trng1, _, _, _, _, _), + PINGROUP(61, pcie0_wake, _, _, cri_trng, _, _, _, _, _), + PINGROUP(62, sd_card, _, _, _, _, _, _, _, _), + PINGROUP(63, sd_write, rx0, _, tsens_max, _, _, _, _, _), + PINGROUP(64, mdc, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(65, mdio, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(66, pta2_0, wci21, cxc1, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(67, pta2_1, qdss_tracedata_a, _, _, _, _, _, _, _), + PINGROUP(68, pta2_2, wci21, cxc1, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(69, blsp1_uart, blsp1_i2c, blsp1_spi, gcc_plltest, qdss_tracedata_a, _, _, _, _), + PINGROUP(70, blsp1_uart, blsp1_i2c, blsp1_spi, gcc_tlmm, qdss_tracedata_a, _, _, _, _), + PINGROUP(71, blsp1_uart, blsp1_spi, gcc_plltest, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(72, blsp1_uart, blsp1_spi, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(73, blsp3_uart, blsp3_i2c, blsp3_spi, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(74, blsp3_uart, blsp3_i2c, blsp3_spi, _, qdss_tracedata_a, _, _, _, _), + PINGROUP(75, blsp3_uart, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(76, blsp3_uart, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _), + PINGROUP(77, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(78, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _, _), + PINGROUP(79, blsp3_spi, _, qdss_tracedata_a, _, _, _, _, _, _), +}; + +static const struct msm_pinctrl_soc_data ipq6018_pinctrl = { + .pins = ipq6018_pins, + .npins = ARRAY_SIZE(ipq6018_pins), + .functions = ipq6018_functions, + .nfunctions = ARRAY_SIZE(ipq6018_functions), + .groups = ipq6018_groups, + .ngroups = ARRAY_SIZE(ipq6018_groups), + .ngpios = 80, +}; + +static int ipq6018_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &ipq6018_pinctrl); +} + +static const struct of_device_id ipq6018_pinctrl_of_match[] = { + { .compatible = "qcom,ipq6018-pinctrl", }, + { }, +}; + +static struct platform_driver ipq6018_pinctrl_driver = { + .driver = { + .name = "ipq6018-pinctrl", + .of_match_table = ipq6018_pinctrl_of_match, + }, + .probe = ipq6018_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init ipq6018_pinctrl_init(void) +{ + return platform_driver_register(&ipq6018_pinctrl_driver); +} +arch_initcall(ipq6018_pinctrl_init); + +static void __exit ipq6018_pinctrl_exit(void) +{ + platform_driver_unregister(&ipq6018_pinctrl_driver); +} +module_exit(ipq6018_pinctrl_exit); + +MODULE_DESCRIPTION("QTI ipq6018 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, ipq6018_pinctrl_of_match); diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c index c2fb1ddf2f22..ac717ee38416 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c @@ -299,7 +299,7 @@ static const char * const gpio_groups[] = { }; static const char * const mdio_groups[] = { - "gpio0", "gpio1", "gpio10", "gpio11", + "gpio0", "gpio1", "gpio2", "gpio10", "gpio11", "gpio66", }; static const char * const mi2s_groups[] = { @@ -403,8 +403,8 @@ static const char * const usb2_hsic_groups[] = { }; static const char * const rgmii2_groups[] = { - "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", - "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62", + "gpio2", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", + "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62", "gpio66", }; static const char * const sata_groups[] = { @@ -539,7 +539,7 @@ static const struct msm_function ipq8064_functions[] = { static const struct msm_pingroup ipq8064_groups[] = { PINGROUP(0, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(1, mdio, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(2, gsbi5_spi_cs3, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(2, gsbi5_spi_cs3, rgmii2, mdio, NA, NA, NA, NA, NA, NA, NA), PINGROUP(3, pcie1_rst, pcie1_prsnt, pdm, NA, NA, NA, NA, NA, NA, NA), PINGROUP(4, pcie1_pwren_n, pcie1_pwren, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(5, pcie1_clk_req, pcie1_pwrflt, NA, NA, NA, NA, NA, NA, NA, NA), @@ -603,7 +603,7 @@ static const struct msm_pingroup ipq8064_groups[] = { PINGROUP(63, pcie3_rst, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(65, pcie3_clk_req, NA, NA, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(66, rgmii2, mdio, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(67, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(68, usb2_hsic, NA, NA, NA, NA, NA, NA, NA, NA, NA), SDC_PINGROUP(sdc3_clk, 0x204a, 14, 6), diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 1a948c3f54b7..9a398a211d30 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -22,6 +22,8 @@ #include <linux/reboot.h> #include <linux/pm.h> #include <linux/log2.h> +#include <linux/qcom_scm.h> +#include <linux/io.h> #include <linux/soc/qcom/irq.h> @@ -60,6 +62,8 @@ struct msm_pinctrl { struct irq_chip irq_chip; int irq; + bool intr_target_use_scm; + raw_spinlock_t lock; DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO); @@ -68,6 +72,7 @@ struct msm_pinctrl { const struct msm_pinctrl_soc_data *soc; void __iomem *regs[MAX_NR_TILES]; + u32 phys_base[MAX_NR_TILES]; }; #define MSM_ACCESSOR(name) \ @@ -489,8 +494,8 @@ static int msm_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) val = msm_readl_ctl(pctrl, g); - /* 0 = output, 1 = input */ - return val & BIT(g->oe_bit) ? 0 : 1; + return val & BIT(g->oe_bit) ? GPIO_LINE_DIRECTION_OUT : + GPIO_LINE_DIRECTION_IN; } static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -882,11 +887,30 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) else clear_bit(d->hwirq, pctrl->dual_edge_irqs); - /* Route interrupts to application cpu */ - val = msm_readl_intr_target(pctrl, g); - val &= ~(7 << g->intr_target_bit); - val |= g->intr_target_kpss_val << g->intr_target_bit; - msm_writel_intr_target(val, pctrl, g); + /* Route interrupts to application cpu. + * With intr_target_use_scm interrupts are routed to + * application cpu using scm calls. + */ + if (pctrl->intr_target_use_scm) { + u32 addr = pctrl->phys_base[0] + g->intr_target_reg; + int ret; + + qcom_scm_io_readl(addr, &val); + + val &= ~(7 << g->intr_target_bit); + val |= g->intr_target_kpss_val << g->intr_target_bit; + + ret = qcom_scm_io_writel(addr, val); + if (ret) + dev_err(pctrl->dev, + "Failed routing %lu interrupt to Apps proc", + d->hwirq); + } else { + val = msm_readl_intr_target(pctrl, g); + val &= ~(7 << g->intr_target_bit); + val |= g->intr_target_kpss_val << g->intr_target_bit; + msm_writel_intr_target(val, pctrl, g); + } /* Update configuration for gpio. * RAW_STATUS_EN is left on for all gpio irqs. Due to the @@ -1240,6 +1264,9 @@ int msm_pinctrl_probe(struct platform_device *pdev, pctrl->dev = &pdev->dev; pctrl->soc = soc_data; pctrl->chip = msm_gpio_template; + pctrl->intr_target_use_scm = of_device_is_compatible( + pctrl->dev->of_node, + "qcom,ipq8064-pinctrl"); raw_spin_lock_init(&pctrl->lock); @@ -1252,9 +1279,12 @@ int msm_pinctrl_probe(struct platform_device *pdev, return PTR_ERR(pctrl->regs[i]); } } else { - pctrl->regs[0] = devm_platform_ioremap_resource(pdev, 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(pctrl->regs[0])) return PTR_ERR(pctrl->regs[0]); + + pctrl->phys_base[0] = res->start; } msm_pinctrl_setup_pm_reset(pctrl); diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig index cf0e0dc42b84..9552851b96f1 100644 --- a/drivers/pinctrl/sh-pfc/Kconfig +++ b/drivers/pinctrl/sh-pfc/Kconfig @@ -26,8 +26,8 @@ config PINCTRL_SH_PFC select PINCTRL_PFC_R8A7792 if ARCH_R8A7792 select PINCTRL_PFC_R8A7793 if ARCH_R8A7793 select PINCTRL_PFC_R8A7794 if ARCH_R8A7794 - select PINCTRL_PFC_R8A77950 if ARCH_R8A77950 || ARCH_R8A7795 - select PINCTRL_PFC_R8A77951 if ARCH_R8A77951 || ARCH_R8A7795 + select PINCTRL_PFC_R8A77950 if ARCH_R8A77950 + select PINCTRL_PFC_R8A77951 if ARCH_R8A77951 select PINCTRL_PFC_R8A77960 if ARCH_R8A77960 select PINCTRL_PFC_R8A77961 if ARCH_R8A77961 select PINCTRL_PFC_R8A77965 if ARCH_R8A77965 diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index 82209116955b..a2e19efa26e3 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -726,6 +726,27 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; } #endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */ #ifdef DEBUG +#define SH_PFC_MAX_REGS 300 +#define SH_PFC_MAX_ENUMS 3000 + +static unsigned int sh_pfc_errors __initdata = 0; +static unsigned int sh_pfc_warnings __initdata = 0; +static u32 *sh_pfc_regs __initdata = NULL; +static u32 sh_pfc_num_regs __initdata = 0; +static u16 *sh_pfc_enums __initdata = NULL; +static u32 sh_pfc_num_enums __initdata = 0; + +#define sh_pfc_err(fmt, ...) \ + do { \ + pr_err("%s: " fmt, drvname, ##__VA_ARGS__); \ + sh_pfc_errors++; \ + } while (0) +#define sh_pfc_warn(fmt, ...) \ + do { \ + pr_warn("%s: " fmt, drvname, ##__VA_ARGS__); \ + sh_pfc_warnings++; \ + } while (0) + static bool __init is0s(const u16 *enum_ids, unsigned int n) { unsigned int i; @@ -737,77 +758,181 @@ static bool __init is0s(const u16 *enum_ids, unsigned int n) return true; } -static unsigned int sh_pfc_errors __initdata = 0; -static unsigned int sh_pfc_warnings __initdata = 0; +static bool __init same_name(const char *a, const char *b) +{ + if (!a || !b) + return false; + + return !strcmp(a, b); +} + +static void __init sh_pfc_check_reg(const char *drvname, u32 reg) +{ + unsigned int i; + + for (i = 0; i < sh_pfc_num_regs; i++) + if (reg == sh_pfc_regs[i]) { + sh_pfc_err("reg 0x%x conflict\n", reg); + return; + } + + if (sh_pfc_num_regs == SH_PFC_MAX_REGS) { + pr_warn_once("%s: Please increase SH_PFC_MAX_REGS\n", drvname); + return; + } + + sh_pfc_regs[sh_pfc_num_regs++] = reg; +} + +static int __init sh_pfc_check_enum(const char *drvname, u16 enum_id) +{ + unsigned int i; + + for (i = 0; i < sh_pfc_num_enums; i++) { + if (enum_id == sh_pfc_enums[i]) + return -EINVAL; + } + + if (sh_pfc_num_enums == SH_PFC_MAX_ENUMS) { + pr_warn_once("%s: Please increase SH_PFC_MAX_ENUMS\n", drvname); + return 0; + } + + sh_pfc_enums[sh_pfc_num_enums++] = enum_id; + return 0; +} + +static void __init sh_pfc_check_reg_enums(const char *drvname, u32 reg, + const u16 *enums, unsigned int n) +{ + unsigned int i; + + for (i = 0; i < n; i++) { + if (enums[i] && sh_pfc_check_enum(drvname, enums[i])) + sh_pfc_err("reg 0x%x enum_id %u conflict\n", reg, + enums[i]); + } +} + +static void __init sh_pfc_check_pin(const struct sh_pfc_soc_info *info, + u32 reg, unsigned int pin) +{ + const char *drvname = info->name; + unsigned int i; + + if (pin == SH_PFC_PIN_NONE) + return; + + for (i = 0; i < info->nr_pins; i++) { + if (pin == info->pins[i].pin) + return; + } + + sh_pfc_err("reg 0x%x: pin %u not found\n", reg, pin); +} static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { unsigned int i, n, rw, fw; + sh_pfc_check_reg(drvname, cfg_reg->reg); + if (cfg_reg->field_width) { - /* Checked at build time */ - return; + n = cfg_reg->reg_width / cfg_reg->field_width; + /* Skip field checks (done at build time) */ + goto check_enum_ids; } for (i = 0, n = 0, rw = 0; (fw = cfg_reg->var_field_width[i]); i++) { - if (fw > 3 && is0s(&cfg_reg->enum_ids[n], 1 << fw)) { - pr_warn("%s: reg 0x%x: reserved field [%u:%u] can be split to reduce table size\n", - drvname, cfg_reg->reg, rw, rw + fw - 1); - sh_pfc_warnings++; - } + if (fw > 3 && is0s(&cfg_reg->enum_ids[n], 1 << fw)) + sh_pfc_warn("reg 0x%x: reserved field [%u:%u] can be split to reduce table size\n", + cfg_reg->reg, rw, rw + fw - 1); n += 1 << fw; rw += fw; } - if (rw != cfg_reg->reg_width) { - pr_err("%s: reg 0x%x: var_field_width declares %u instead of %u bits\n", - drvname, cfg_reg->reg, rw, cfg_reg->reg_width); - sh_pfc_errors++; - } + if (rw != cfg_reg->reg_width) + sh_pfc_err("reg 0x%x: var_field_width declares %u instead of %u bits\n", + cfg_reg->reg, rw, cfg_reg->reg_width); + + if (n != cfg_reg->nr_enum_ids) + sh_pfc_err("reg 0x%x: enum_ids[] has %u instead of %u values\n", + cfg_reg->reg, cfg_reg->nr_enum_ids, n); + +check_enum_ids: + sh_pfc_check_reg_enums(drvname, cfg_reg->reg, cfg_reg->enum_ids, n); +} + +static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info, + const struct pinmux_drive_reg *drive) +{ + const char *drvname = info->name; + unsigned long seen = 0, mask; + unsigned int i; + + sh_pfc_check_reg(info->name, drive->reg); + for (i = 0; i < ARRAY_SIZE(drive->fields); i++) { + const struct pinmux_drive_reg_field *field = &drive->fields[i]; + + if (!field->pin && !field->offset && !field->size) + continue; + + mask = GENMASK(field->offset + field->size, field->offset); + if (mask & seen) + sh_pfc_err("drive_reg 0x%x: field %u overlap\n", + drive->reg, i); + seen |= mask; - if (n != cfg_reg->nr_enum_ids) { - pr_err("%s: reg 0x%x: enum_ids[] has %u instead of %u values\n", - drvname, cfg_reg->reg, cfg_reg->nr_enum_ids, n); - sh_pfc_errors++; + sh_pfc_check_pin(info, drive->reg, field->pin); } } +static void __init sh_pfc_check_bias_reg(const struct sh_pfc_soc_info *info, + const struct pinmux_bias_reg *bias) +{ + unsigned int i; + + sh_pfc_check_reg(info->name, bias->puen); + if (bias->pud) + sh_pfc_check_reg(info->name, bias->pud); + for (i = 0; i < ARRAY_SIZE(bias->pins); i++) + sh_pfc_check_pin(info, bias->puen, bias->pins[i]); +} + static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) { - const struct sh_pfc_function *func; const char *drvname = info->name; unsigned int *refcnts; unsigned int i, j, k; pr_info("Checking %s\n", drvname); + sh_pfc_num_regs = 0; + sh_pfc_num_enums = 0; /* Check pins */ for (i = 0; i < info->nr_pins; i++) { + const struct sh_pfc_pin *pin = &info->pins[i]; + + if (!pin->name) { + sh_pfc_err("empty pin %u\n", i); + continue; + } for (j = 0; j < i; j++) { - if (!strcmp(info->pins[i].name, info->pins[j].name)) { - pr_err("%s: pin %s/%s: name conflict\n", - drvname, info->pins[i].name, - info->pins[j].name); - sh_pfc_errors++; - } + const struct sh_pfc_pin *pin2 = &info->pins[j]; - if (info->pins[i].pin != (u16)-1 && - info->pins[i].pin == info->pins[j].pin) { - pr_err("%s: pin %s/%s: pin %u conflict\n", - drvname, info->pins[i].name, - info->pins[j].name, info->pins[i].pin); - sh_pfc_errors++; - } + if (same_name(pin->name, pin2->name)) + sh_pfc_err("pin %s: name conflict\n", + pin->name); - if (info->pins[i].enum_id && - info->pins[i].enum_id == info->pins[j].enum_id) { - pr_err("%s: pin %s/%s: enum_id %u conflict\n", - drvname, info->pins[i].name, - info->pins[j].name, - info->pins[i].enum_id); - sh_pfc_errors++; - } + if (pin->pin != (u16)-1 && pin->pin == pin2->pin) + sh_pfc_err("pin %s/%s: pin %u conflict\n", + pin->name, pin2->name, pin->pin); + + if (pin->enum_id && pin->enum_id == pin2->enum_id) + sh_pfc_err("pin %s/%s: enum_id %u conflict\n", + pin->name, pin2->name, + pin->enum_id); } } @@ -817,45 +942,49 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) return; for (i = 0; i < info->nr_functions; i++) { - func = &info->functions[i]; + const struct sh_pfc_function *func = &info->functions[i]; + if (!func->name) { - pr_err("%s: empty function %u\n", drvname, i); - sh_pfc_errors++; + sh_pfc_err("empty function %u\n", i); continue; } + for (j = 0; j < i; j++) { + if (same_name(func->name, info->functions[j].name)) + sh_pfc_err("function %s: name conflict\n", + func->name); + } for (j = 0; j < func->nr_groups; j++) { for (k = 0; k < info->nr_groups; k++) { - if (info->groups[k].name && - !strcmp(func->groups[j], - info->groups[k].name)) { + if (same_name(func->groups[j], + info->groups[k].name)) { refcnts[k]++; break; } } - if (k == info->nr_groups) { - pr_err("%s: function %s: group %s not found\n", - drvname, func->name, func->groups[j]); - sh_pfc_errors++; - } + if (k == info->nr_groups) + sh_pfc_err("function %s: group %s not found\n", + func->name, func->groups[j]); } } for (i = 0; i < info->nr_groups; i++) { - if (!info->groups[i].name) { - pr_err("%s: empty group %u\n", drvname, i); - sh_pfc_errors++; + const struct sh_pfc_pin_group *group = &info->groups[i]; + + if (!group->name) { + sh_pfc_err("empty group %u\n", i); continue; } - if (!refcnts[i]) { - pr_err("%s: orphan group %s\n", drvname, - info->groups[i].name); - sh_pfc_errors++; - } else if (refcnts[i] > 1) { - pr_warn("%s: group %s referenced by %u functions\n", - drvname, info->groups[i].name, refcnts[i]); - sh_pfc_warnings++; + for (j = 0; j < i; j++) { + if (same_name(group->name, info->groups[j].name)) + sh_pfc_err("group %s: name conflict\n", + group->name); } + if (!refcnts[i]) + sh_pfc_err("orphan group %s\n", group->name); + else if (refcnts[i] > 1) + sh_pfc_warn("group %s referenced by %u functions\n", + group->name, refcnts[i]); } kfree(refcnts); @@ -863,12 +992,62 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) /* Check config register descriptions */ for (i = 0; info->cfg_regs && info->cfg_regs[i].reg; i++) sh_pfc_check_cfg_reg(drvname, &info->cfg_regs[i]); + + /* Check drive strength registers */ + for (i = 0; info->drive_regs && info->drive_regs[i].reg; i++) + sh_pfc_check_drive_reg(info, &info->drive_regs[i]); + + /* Check bias registers */ + for (i = 0; info->bias_regs && info->bias_regs[i].puen; i++) + sh_pfc_check_bias_reg(info, &info->bias_regs[i]); + + /* Check ioctrl registers */ + for (i = 0; info->ioctrl_regs && info->ioctrl_regs[i].reg; i++) + sh_pfc_check_reg(drvname, info->ioctrl_regs[i].reg); + + /* Check data registers */ + for (i = 0; info->data_regs && info->data_regs[i].reg; i++) { + sh_pfc_check_reg(drvname, info->data_regs[i].reg); + sh_pfc_check_reg_enums(drvname, info->data_regs[i].reg, + info->data_regs[i].enum_ids, + info->data_regs[i].reg_width); + } + +#ifdef CONFIG_PINCTRL_SH_FUNC_GPIO + /* Check function GPIOs */ + for (i = 0; i < info->nr_func_gpios; i++) { + const struct pinmux_func *func = &info->func_gpios[i]; + + if (!func->name) { + sh_pfc_err("empty function gpio %u\n", i); + continue; + } + for (j = 0; j < i; j++) { + if (same_name(func->name, info->func_gpios[j].name)) + sh_pfc_err("func_gpio %s: name conflict\n", + func->name); + } + if (sh_pfc_check_enum(drvname, func->enum_id)) + sh_pfc_err("%s enum_id %u conflict\n", func->name, + func->enum_id); + } +#endif } static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) { unsigned int i; + sh_pfc_regs = kcalloc(SH_PFC_MAX_REGS, sizeof(*sh_pfc_regs), + GFP_KERNEL); + if (!sh_pfc_regs) + return; + + sh_pfc_enums = kcalloc(SH_PFC_MAX_ENUMS, sizeof(*sh_pfc_enums), + GFP_KERNEL); + if (!sh_pfc_enums) + goto free_regs; + pr_warn("Checking builtin pinmux tables\n"); for (i = 0; pdrv->id_table[i].name[0]; i++) @@ -881,6 +1060,10 @@ static void __init sh_pfc_check_driver(const struct platform_driver *pdrv) pr_warn("Detected %u errors and %u warnings\n", sh_pfc_errors, sh_pfc_warnings); + + kfree(sh_pfc_enums); +free_regs: + kfree(sh_pfc_regs); } #else /* !DEBUG */ diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 8213e118aa40..9c6e931ae766 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -205,14 +205,11 @@ static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) for (k = 0; gpios[k] >= 0; k++) { if (gpios[k] == offset) - goto found; + return pfc->irqs[i]; } } return 0; - -found: - return pfc->irqs[i]; } static int gpio_pin_setup(struct sh_pfc_chip *chip) diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c index b1a9611f46b3..50df9e084414 100644 --- a/drivers/pinctrl/sirf/pinctrl-atlas7.c +++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c @@ -352,7 +352,7 @@ struct atlas7_gpio_chip { int nbank; raw_spinlock_t lock; struct gpio_chip chip; - struct atlas7_gpio_bank banks[0]; + struct atlas7_gpio_bank banks[]; }; /** diff --git a/drivers/pinctrl/sprd/Kconfig b/drivers/pinctrl/sprd/Kconfig index b6c5479b58fb..eef35d01b770 100644 --- a/drivers/pinctrl/sprd/Kconfig +++ b/drivers/pinctrl/sprd/Kconfig @@ -4,9 +4,7 @@ # config PINCTRL_SPRD - bool "Spreadtrum pinctrl driver" - depends on OF - depends on ARCH_SPRD || COMPILE_TEST + tristate select PINMUX select PINCONF select GENERIC_PINCONF @@ -15,7 +13,9 @@ config PINCTRL_SPRD Say Y here to enable Spreadtrum pinctrl driver config PINCTRL_SPRD_SC9860 - bool "Spreadtrum SC9860 pinctrl driver" - depends on PINCTRL_SPRD + tristate "Spreadtrum SC9860 pinctrl driver" + depends on OF + depends on ARCH_SPRD || COMPILE_TEST + select PINCTRL_SPRD help Say Y here to enable Spreadtrum SC9860 pinctrl driver diff --git a/drivers/pinctrl/sprd/pinctrl-sprd.c b/drivers/pinctrl/sprd/pinctrl-sprd.c index 157712ab05a8..48cbf2a2837f 100644 --- a/drivers/pinctrl/sprd/pinctrl-sprd.c +++ b/drivers/pinctrl/sprd/pinctrl-sprd.c @@ -464,9 +464,15 @@ static int sprd_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin_id, case PIN_CONFIG_INPUT_ENABLE: arg = (reg >> SLEEP_INPUT_SHIFT) & SLEEP_INPUT_MASK; break; - case PIN_CONFIG_OUTPUT: + case PIN_CONFIG_OUTPUT_ENABLE: arg = reg & SLEEP_OUTPUT_MASK; break; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + if ((reg & SLEEP_OUTPUT) || (reg & SLEEP_INPUT)) + return -EINVAL; + + arg = 1; + break; case PIN_CONFIG_DRIVE_STRENGTH: arg = (reg >> DRIVE_STRENGTH_SHIFT) & DRIVE_STRENGTH_MASK; @@ -635,13 +641,23 @@ static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, shift = SLEEP_INPUT_SHIFT; } break; - case PIN_CONFIG_OUTPUT: + case PIN_CONFIG_OUTPUT_ENABLE: if (is_sleep_config == true) { - val |= SLEEP_OUTPUT; + if (arg > 0) + val |= SLEEP_OUTPUT; + else + val &= ~SLEEP_OUTPUT; + mask = SLEEP_OUTPUT_MASK; shift = SLEEP_OUTPUT_SHIFT; } break; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + if (is_sleep_config == true) { + val = shift = 0; + mask = SLEEP_OUTPUT | SLEEP_INPUT; + } + break; case PIN_CONFIG_DRIVE_STRENGTH: if (arg < 2 || arg > 60) return -EINVAL; @@ -1090,6 +1106,7 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev, return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_core_probe); int sprd_pinctrl_remove(struct platform_device *pdev) { @@ -1098,6 +1115,7 @@ int sprd_pinctrl_remove(struct platform_device *pdev) pinctrl_unregister(sprd_pctl->pctl); return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_remove); void sprd_pinctrl_shutdown(struct platform_device *pdev) { @@ -1112,6 +1130,7 @@ void sprd_pinctrl_shutdown(struct platform_device *pdev) return; pinctrl_select_state(pinctl, state); } +EXPORT_SYMBOL_GPL(sprd_pinctrl_shutdown); MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver"); MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>"); diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index af3b24f26ff2..a657cd829ce6 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -284,9 +284,9 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) stm32_pmx_get_mode(bank, pin, &mode, &alt); if ((alt == 0) && (mode == 0)) - ret = 1; + ret = GPIO_LINE_DIRECTION_IN; else if ((alt == 0) && (mode == 1)) - ret = 0; + ret = GPIO_LINE_DIRECTION_OUT; else ret = -EINVAL; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index b35c3245ab3f..8e792f8e2dc9 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -13,6 +13,7 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/gpio/driver.h> +#include <linux/interrupt.h> #include <linux/irqdomain.h> #include <linux/irqchip/chained_irq.h> #include <linux/export.h> @@ -1058,6 +1059,14 @@ static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d) sunxi_pinctrl_irq_unmask(d); } +static int sunxi_pinctrl_irq_set_wake(struct irq_data *d, unsigned int on) +{ + struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); + u8 bank = d->hwirq / IRQ_PER_BANK; + + return irq_set_irq_wake(pctl->irq[bank], on); +} + static struct irq_chip sunxi_pinctrl_edge_irq_chip = { .name = "sunxi_pio_edge", .irq_ack = sunxi_pinctrl_irq_ack, @@ -1066,7 +1075,8 @@ static struct irq_chip sunxi_pinctrl_edge_irq_chip = { .irq_request_resources = sunxi_pinctrl_irq_request_resources, .irq_release_resources = sunxi_pinctrl_irq_release_resources, .irq_set_type = sunxi_pinctrl_irq_set_type, - .flags = IRQCHIP_SKIP_SET_WAKE, + .irq_set_wake = sunxi_pinctrl_irq_set_wake, + .flags = IRQCHIP_MASK_ON_SUSPEND, }; static struct irq_chip sunxi_pinctrl_level_irq_chip = { @@ -1081,7 +1091,9 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = { .irq_request_resources = sunxi_pinctrl_irq_request_resources, .irq_release_resources = sunxi_pinctrl_irq_release_resources, .irq_set_type = sunxi_pinctrl_irq_set_type, - .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED | + .irq_set_wake = sunxi_pinctrl_irq_set_wake, + .flags = IRQCHIP_EOI_THREADED | + IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_EOI_IF_HANDLED, }; diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index cefbbb8d1a68..21661f6490d6 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -275,11 +275,57 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, return 0; } +static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return 0; + + group = &pmx->soc->groups[offset]; + + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return -EINVAL; + + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); + value &= ~BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); + + return 0; +} + +static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *group; + u32 value; + + if (!pmx->soc->sfsel_in_mux) + return; + + group = &pmx->soc->groups[offset]; + + if (group->mux_reg < 0 || group->sfsel_bit < 0) + return; + + value = pmx_readl(pmx, group->mux_bank, group->mux_reg); + value |= BIT(group->sfsel_bit); + pmx_writel(pmx, value, group->mux_bank, group->mux_reg); +} + static const struct pinmux_ops tegra_pinmux_ops = { .get_functions_count = tegra_pinctrl_get_funcs_count, .get_function_name = tegra_pinctrl_get_func_name, .get_function_groups = tegra_pinctrl_get_func_groups, .set_mux = tegra_pinctrl_set_mux, + .gpio_request_enable = tegra_pinctrl_gpio_request_enable, + .gpio_disable_free = tegra_pinctrl_gpio_disable_free, }; static int tegra_pinconf_reg(struct tegra_pmx *pmx, @@ -689,12 +735,12 @@ const struct dev_pm_ops tegra_pinctrl_pm = { .resume = &tegra_pinctrl_resume }; -static bool gpio_node_has_range(const char *compatible) +static bool tegra_pinctrl_gpio_node_has_range(struct tegra_pmx *pmx) { struct device_node *np; bool has_prop = false; - np = of_find_compatible_node(NULL, NULL, compatible); + np = of_find_compatible_node(NULL, NULL, pmx->soc->gpio_compatible); if (!np) return has_prop; @@ -794,7 +840,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev, tegra_pinctrl_clear_parked_bits(pmx); - if (!gpio_node_has_range(pmx->soc->gpio_compatible)) + if (pmx->soc->ngpios > 0 && !tegra_pinctrl_gpio_node_has_range(pmx)) pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); platform_set_drvdata(pdev, pmx); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h index 0fc82eea9cf1..fcad7f74c5a2 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.h +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h @@ -107,7 +107,8 @@ struct tegra_function { * drvup, slwr, slwf, and drvtype parameters. * @drv_bank: Drive fields register bank. * @hsm_bit: High Speed Mode register bit. - * @schmitt_bit: Scmitt register bit. + * @sfsel_bit: GPIO/SFIO selection register bit. + * @schmitt_bit: Schmitt register bit. * @lpmd_bit: Low Power Mode register bit. * @drvdn_bit: Drive Down register bit. * @drvdn_width: Drive Down field width. @@ -153,6 +154,7 @@ struct tegra_pingroup { s32 ioreset_bit:6; s32 rcv_sel_bit:6; s32 hsm_bit:6; + s32 sfsel_bit:6; s32 schmitt_bit:6; s32 lpmd_bit:6; s32 drvdn_bit:6; @@ -192,6 +194,7 @@ struct tegra_pinctrl_soc_data { bool hsm_in_mux; bool schmitt_in_mux; bool drvtype_in_mux; + bool sfsel_in_mux; }; extern const struct dev_pm_ops tegra_pinctrl_pm; diff --git a/drivers/pinctrl/tegra/pinctrl-tegra194.c b/drivers/pinctrl/tegra/pinctrl-tegra194.c index daf44cf240c9..2e0b5f7bb095 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra194.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra194.c @@ -24,17 +24,14 @@ /* Define unique ID for each pins */ enum pin_id { - TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0 = 256, - TEGRA_PIN_PEX_L5_RST_N_PGG1 = 257, - TEGRA_PIN_NUM_GPIOS = 258, + TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0, + TEGRA_PIN_PEX_L5_RST_N_PGG1, }; /* Table for pin descriptor */ static const struct pinctrl_pin_desc tegra194_pins[] = { - PINCTRL_PIN(TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0, - "TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0"), - PINCTRL_PIN(TEGRA_PIN_PEX_L5_RST_N_PGG1, - "TEGRA_PIN_PEX_L5_RST_N_PGG1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L5_CLKREQ_N_PGG0, "PEX_L5_CLKREQ_N_PGG0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L5_RST_N_PGG1, "PEX_L5_RST_N_PGG1"), }; static const unsigned int pex_l5_clkreq_n_pgg0_pins[] = { @@ -59,6 +56,7 @@ enum tegra_mux_dt { { \ .name = #lid, \ } + static struct tegra_function tegra194_functions[] = { TEGRA_PIN_FUNCTION(rsvd0), TEGRA_PIN_FUNCTION(rsvd1), @@ -70,7 +68,7 @@ static struct tegra_function tegra194_functions[] = { #define DRV_PINGROUP_ENTRY_Y(r, drvdn_b, drvdn_w, drvup_b, \ drvup_w, slwr_b, slwr_w, slwf_b, \ slwf_w, bank) \ - .drv_reg = ((r)), \ + .drv_reg = ((r)), \ .drv_bank = bank, \ .drvdn_bit = drvdn_b, \ .drvdn_width = drvdn_w, \ @@ -89,7 +87,7 @@ static struct tegra_function tegra194_functions[] = { .hsm_bit = -1, \ .mux_bank = bank, \ .mux_bit = 0, \ - .pupd_reg = ((r)), \ + .pupd_reg = ((r)), \ .pupd_bank = bank, \ .pupd_bit = 2, \ .tri_reg = ((r)), \ @@ -97,6 +95,7 @@ static struct tegra_function tegra194_functions[] = { .tri_bit = 4, \ .einput_bit = e_input, \ .odrain_bit = e_od, \ + .sfsel_bit = 10, \ .schmitt_bit = schmitt_b, \ .drvtype_bit = 13, \ .drv_reg = -1, \ @@ -109,20 +108,20 @@ static struct tegra_function tegra194_functions[] = { #define PINGROUP(pg_name, f0, f1, f2, f3, r, bank, pupd, e_lpbk, \ e_input, e_lpdr, e_od, schmitt_b, drvtype, io_rail) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_lpbk, \ - e_input, e_od, \ - schmitt_b, drvtype), \ - drive_##pg_name, \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + PIN_PINGROUP_ENTRY_Y(r, bank, pupd, e_lpbk, \ + e_input, e_od, \ + schmitt_b, drvtype), \ + drive_##pg_name, \ } static const struct tegra_pingroup tegra194_groups[] = { @@ -133,7 +132,6 @@ static const struct tegra_pingroup tegra194_groups[] = { }; static const struct tegra_pinctrl_soc_data tegra194_pinctrl = { - .ngpios = TEGRA_PIN_NUM_GPIOS, .pins = tegra194_pins, .npins = ARRAY_SIZE(tegra194_pins), .functions = tegra194_functions, @@ -143,6 +141,7 @@ static const struct tegra_pinctrl_soc_data tegra194_pinctrl = { .hsm_in_mux = true, .schmitt_in_mux = true, .drvtype_in_mux = true, + .sfsel_in_mux = true, }; static int tegra194_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c index 57babf31e320..ade348b49b31 100644 --- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c +++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c @@ -29,7 +29,7 @@ struct uniphier_pinctrl_reg_region { struct list_head node; unsigned int base; unsigned int nregs; - u32 vals[0]; + u32 vals[]; }; struct uniphier_pinctrl_priv { diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index ea910a18b4d7..65b97e240196 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -486,8 +486,10 @@ static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset) u32 val; val = readl_relaxed(data->base + reg_dir); - /* Return 0 == output, 1 == input */ - return !(val & BIT(bit)); + if (val & BIT(bit)) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset) |