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. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAl6FlRoACgkQQRCzN7AZ XXPiAxAAuAvY07H739YF4ANvtLpfbtz0KBK4M2XGiD41VMcp5MhZtT9TdXAIRisb W4QMHbMxhwO4gdxmhVOetXeQNQnHch4oPsFyd1UdyuwNEtvlm8qst99VcdQPz7Jv zyL4cat1fTrwdcnLQl5eaJR7a9bKLqAd4rlb/suQZsaVf+URUWJyZBuU41GEx9A+ w+EPv8doxTWRaE0NpafIwNCLxTR3i2Vt59fkRT4pSi8fTu9/Zv5yW8yWvbYZdlaO 2bUaFjN65oyiikjPTgyQxb95A8yDJHkNnkgfTw4ghCY/k8u3GvMfKS7V1tO+nq6B bkv9E3jR1u7Ktkq1rLshS2eycl02uSJ3OmzyfL8S/GQxVdUPi3+X3hmyv2ctbEvC qy+7F6zx/Pt/WdPnAisdsVai9T3/YGoSN1C3n7Ufltjcrt0w5xP7/AgEVR4nHHMP NMWNoauGWsBDKtYPG7beX3thjkm3mUpezcEOxho7+r5tOtBaU623pWr+NHEPZu48 8oKOCILaUkacUmmMjjOzraAeOxV7Ut+xumu0mgMj0EjZfJZDrgQsqkmfMbGcU5Fa y4S5+tAd+cELXveLVJB3Ml9u1R037x8VtAv+Z2a7qVnf1gSgf0bpAJ+SnfC/XbLX fBpSCsIMXSpioVNuS9gbkpnfsRPcTOrOXyxinP5onI8AHlIj1Rg= =1ZKq -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
Коммит
bc3b3f4bfb
|
@ -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
|
||||
|
|
|
@ -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
|
||||
>;
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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
|
||||
>;
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
>;
|
||||
};
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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;
|
||||
};
|
||||
};
|
37
MAINTAINERS
37
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
c++;
|
||||
} else if (start == end)
|
||||
break;
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
} else {
|
||||
return -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;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
|
||||
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;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val || !val2)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (hw->soc->drive_get) {
|
||||
err = hw->soc->drive_get(hw, desc, &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 {
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
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, &ret);
|
||||
if (err)
|
||||
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, &ret);
|
||||
if (err)
|
||||
goto out;
|
||||
/* return error when in output mode
|
||||
* because schmitt trigger only work in input mode
|
||||
*/
|
||||
if (ret) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (hw->soc->drive_get)
|
||||
err = hw->soc->drive_get(hw, desc, &ret);
|
||||
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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
|
@ -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;
|
||||
|
||||
return !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR);
|
||||
if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
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++;
|
||||
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;
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче