diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-01 11:34:12 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-01 11:34:12 -0700 |
| commit | d5f74114114cb2cdbed75b91ca2fa4482c1d5611 (patch) | |
| tree | 9a1332d112b666963a61d08fc28bbfb4bc579ae1 /Documentation | |
| parent | Merge tag 'pwm/for-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git... (diff) | |
| parent | gpio: mpfs: fix setting gpio direction to output (diff) | |
| download | linux-d5f74114114cb2cdbed75b91ca2fa4482c1d5611.tar.gz linux-d5f74114114cb2cdbed75b91ca2fa4482c1d5611.zip | |
Merge tag 'gpio-updates-for-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio updates from Bartosz Golaszewski:
"There are two new drivers and support for more models in existing
ones.
The generic GPIO API has been reworked and all users converted
which allowed us to move the fields specific to the generic GPIO
implementation out of the high-level struct gpio_chip into its own
structure that wraps the gpio_chip.
Other than that, there's nothing too exciting. Mostly minor tweaks and
fixes all over the place, some refactoring and some small new features
in helper modules.
GPIO core:
- add support for sparse pin ranges to the glue between GPIO and
pinctrl
- use a common prefix across all GPIO descriptor flags for improved
namespacing
New drivers:
- add new GPIO driver for the Nuvoton NCT6694
- add new GPIO driver for MAX7360
Driver improvements:
- add support for Tegra 256 to the gpio-tegra186 driver
- add support for Loongson-2K0300 to the gpio-loongson-64bit driver
- refactor the gpio-aggregator module to expose its GPIO forwarder
API to other in-kernel users (to enable merging of a new pinctrl
driver that uses it)
- convert all remaining drivers to using the modernized generic GPIO
chip API and remove the old interface
- stop displaying global GPIO numbers in debugfs output of controller
drivers
- extend the gpio-regmap helper with a new config option and improve
its support for GPIO interrupts
- remove redundant fast_io parameter from regmap configs in GPIO
drivers that already use MMIO regmaps which imply it
- add support for a new model in gpio-mmio: ixp4xx expansion bus
- order includes alphabetically in a few drivers for better
readability
- use generic device properties where applicable
- use devm_mutex_init() where applicable
- extend build coverage of drivers by enabling more to be compiled
with COMPILE_TEST enabled
- allow building gpio-stmpe as a module
- use dev_err_probe() where it makes sense in drivers
Late driver fixes:
- fix setting GPIO direction to output in gpio-mpfs
Documentation:
- document the usage of software nodes with GPIO chips
Device-tree bindings:
- Add DT bindings documents for new hardware: Tegra256, MAX7360
- Document a new model in Loongson bindings: LS2K0300
- Document a new model using the generic GPIO binding: IXP4xx
- Convert the DT binding for fsl,mxs-pinctrl to YAML
- fix the schema ID in the "trivial" GPIO schema
- describe GPIO hogs in the generic GPIO binding"
* tag 'gpio-updates-for-v6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (122 commits)
gpio: mpfs: fix setting gpio direction to output
gpio: generic: move GPIO_GENERIC_ flags to the correct header
gpio: generic: rename BGPIOF_ flags to GPIO_GENERIC_
gpio: nomadik: fix the debugfs helper stub
MAINTAINERS: Add entry on MAX7360 driver
input: misc: Add support for MAX7360 rotary
input: keyboard: Add support for MAX7360 keypad
gpio: max7360: Add MAX7360 gpio support
gpio: regmap: Allow to provide init_valid_mask callback
gpio: regmap: Allow to allocate regmap-irq device
pwm: max7360: Add MAX7360 PWM support
pinctrl: Add MAX7360 pinctrl driver
mfd: Add max7360 support
dt-bindings: mfd: gpio: Add MAX7360
rtc: Add Nuvoton NCT6694 RTC support
hwmon: Add Nuvoton NCT6694 HWMON support
watchdog: Add Nuvoton NCT6694 WDT support
can: Add Nuvoton NCT6694 CANFD support
i2c: Add Nuvoton NCT6694 I2C support
gpio: Add Nuvoton NCT6694 GPIO support
...
Diffstat (limited to 'Documentation')
13 files changed, 782 insertions, 139 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml index 87e986386f32..b4d55bf6a285 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-mmio.yaml @@ -22,6 +22,7 @@ properties: - brcm,bcm6345-gpio - ni,169445-nand-gpio - wd,mbl-gpio # Western Digital MyBook Live memory-mapped GPIO controller + - intel,ixp4xx-expansion-bus-mmio-gpio big-endian: true @@ -89,6 +90,20 @@ properties: description: If this property is present, the controller cannot drive the GPIO lines. +if: + properties: + compatible: + contains: + const: intel,ixp4xx-expansion-bus-mmio-gpio +then: + $ref: /schemas/memory-controllers/intel,ixp4xx-expansion-peripheral-props.yaml# + +patternProperties: + "^.+-hog(-[0-9]+)?$": + type: object + required: + - gpio-hog + required: - compatible - reg @@ -96,7 +111,7 @@ required: - '#gpio-cells' - gpio-controller -additionalProperties: false +unevaluatedProperties: false examples: - | @@ -126,3 +141,22 @@ examples: gpio-controller; #gpio-cells = <2>; }; + + bus@c4000000 { + compatible = "intel,ixp42x-expansion-bus-controller", "syscon"; + reg = <0xc4000000 0x30>; + native-endian; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0x0 0x50000000 0x01000000>; + dma-ranges = <0 0x0 0x50000000 0x01000000>; + gpio@1,0 { + compatible = "intel,ixp4xx-expansion-bus-mmio-gpio"; + gpio-controller; + #gpio-cells = <2>; + big-endian; + reg = <1 0x00000000 0x2>; + reg-names = "dat"; + intel,ixp4xx-eb-write-enable = <1>; + }; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml b/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml index b58e08c8ecd8..aaf97124803f 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-mxs.yaml @@ -18,9 +18,13 @@ description: | properties: compatible: - enum: - - fsl,imx23-pinctrl - - fsl,imx28-pinctrl + items: + - enum: + - fsl,imx23-pinctrl + - fsl,imx28-pinctrl + # Over 10 years old devices, driver use simple-bus to probe child gpio + # Devices. Keep it as it to be compatible existed dts files. + - const: simple-bus '#address-cells': const: 1 @@ -31,7 +35,65 @@ properties: maxItems: 1 patternProperties: - "gpio@[0-9]+$": + "^(?!gpio@)[^@]+@[0-9]+$": + type: object + properties: + fsl,pinmux-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + An integer array. Each integer in the array specify a pin + with given mux function, with bank, pin and mux packed as below. + + [15..12] : bank number + [11..4] : pin number + [3..0] : mux selection + + This integer with mux selection packed is used as an entity by both group + and config nodes to identify a pin. The mux selection in the integer takes + effects only on group node, and will get ignored by driver with config node, + since config node is only meant to set up pin configurations. + + Valid values for these integers are listed below. + + reg: + items: + - description: | + pin group index. NOTE: it is supposed wrong use reg property + here. But it is over 10 years devices. Just keep it as it. + + fsl,drive-strength: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + 0: MXS_DRIVE_4mA + 1: MXS_DRIVE_8mA + 2: MXS_DRIVE_12mA + 3: MXS_DRIVE_16mA + + fsl,voltage: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: | + 0: MXS_VOLTAGE_LOW - 1.8 V + 1: MXS_VOLTAGE_HIGH - 3.3 V + + fsl,pull-up: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: | + 0: MXS_PULL_DISABLE - Disable the internal pull-up + 1: MXS_PULL_ENABLE - Enable the internal pull-up + + Note that when enabling the pull-up, the internal pad keeper gets disabled. + Also, some pins doesn't have a pull up, in that case, setting the fsl,pull-up + will only disable the internal pad keeper. + + required: + - fsl,pinmux-ids + + additionalProperties: false + + "^gpio@[0-9]+$": type: object properties: compatible: @@ -80,7 +142,7 @@ examples: pinctrl@80018000 { #address-cells = <1>; #size-cells = <0>; - compatible = "fsl,imx28-pinctrl"; + compatible = "fsl,imx28-pinctrl", "simple-bus"; reg = <0x80018000 0x2000>; gpio@0 { @@ -132,4 +194,12 @@ examples: interrupt-controller; #interrupt-cells = <2>; }; + + lcdif-apx4@5 { + reg = <5>; + fsl,pinmux-ids = <0x1181 0x1191>; + fsl,drive-strength = <0>; + fsl,voltage = <0>; + fsl,pull-up = <0>; + }; }; diff --git a/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml index b68159600e2b..69852444df23 100644 --- a/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml @@ -14,6 +14,7 @@ properties: oneOf: - enum: - loongson,ls2k-gpio + - loongson,ls2k0300-gpio - loongson,ls2k0500-gpio0 - loongson,ls2k0500-gpio1 - loongson,ls2k2000-gpio0 @@ -36,7 +37,7 @@ properties: ngpios: minimum: 1 - maximum: 64 + maximum: 128 "#gpio-cells": const: 2 @@ -49,6 +50,14 @@ properties: minItems: 1 maxItems: 64 + "#interrupt-cells": + const: 2 + + interrupt-controller: true + + resets: + maxItems: 1 + required: - compatible - reg @@ -58,6 +67,23 @@ required: - gpio-ranges - interrupts +allOf: + - if: + properties: + compatible: + contains: + const: loongson,ls2k0300-gpio + then: + required: + - "#interrupt-cells" + - interrupt-controller + - resets + else: + properties: + "#interrupts-cells": false + interrupt-controller: false + resets: false + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/gpio/maxim,max31910.yaml b/Documentation/devicetree/bindings/gpio/maxim,max31910.yaml index 82a190a715f9..4d200f9dffd5 100644 --- a/Documentation/devicetree/bindings/gpio/maxim,max31910.yaml +++ b/Documentation/devicetree/bindings/gpio/maxim,max31910.yaml @@ -95,9 +95,9 @@ examples: #gpio-cells = <2>; maxim,modesel-gpios = <&gpio2 23>; - maxim,fault-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>; - maxim,db0-gpios = <&gpio2 25>; - maxim,db1-gpios = <&gpio2 26>; + maxim,fault-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>; + maxim,db0-gpios = <&gpio2 25>; + maxim,db1-gpios = <&gpio2 26>; spi-max-frequency = <25000000>; }; diff --git a/Documentation/devicetree/bindings/gpio/maxim,max7360-gpio.yaml b/Documentation/devicetree/bindings/gpio/maxim,max7360-gpio.yaml new file mode 100644 index 000000000000..c5c3fc4c816f --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/maxim,max7360-gpio.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/maxim,max7360-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX7360 GPIO controller + +maintainers: + - Kamel Bouhara <kamel.bouhara@bootlin.com> + - Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com> + +description: | + Maxim MAX7360 GPIO controller, in MAX7360 chipset + https://www.analog.com/en/products/max7360.html + + The device provides two series of GPIOs, referred here as GPIOs and GPOs. + + PORT0 to PORT7 pins can be used as GPIOs, with support for interrupts and + constant-current mode. These pins will also be used by the rotary encoder and + PWM functionalities. + + COL2 to COL7 pins can be used as GPOs, there is no input capability. COL pins + will be partitioned, with the first pins being affected to the keypad + functionality and the last ones as GPOs. + +properties: + compatible: + enum: + - maxim,max7360-gpio + - maxim,max7360-gpo + + gpio-controller: true + + "#gpio-cells": + const: 2 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + maxim,constant-current-disable: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Bit field, each bit disables constant-current output of the associated + GPIO, starting from the least significant bit for the first GPIO. + maximum: 0xff + +required: + - compatible + - gpio-controller + +allOf: + - if: + properties: + compatible: + contains: + enum: + - maxim,max7360-gpio + ngpios: false + then: + required: + - interrupt-controller + else: + properties: + interrupt-controller: false + maxim,constant-current-disable: false + +additionalProperties: false + +examples: + - | + gpio { + compatible = "maxim,max7360-gpio"; + + gpio-controller; + #gpio-cells = <2>; + maxim,constant-current-disable = <0x06>; + + interrupt-controller; + #interrupt-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.yaml b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.yaml index 065f5761a93f..2bd620a1099b 100644 --- a/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.yaml @@ -85,6 +85,7 @@ properties: - nvidia,tegra194-gpio-aon - nvidia,tegra234-gpio - nvidia,tegra234-gpio-aon + - nvidia,tegra256-gpio reg-names: items: @@ -155,6 +156,7 @@ allOf: - nvidia,tegra186-gpio - nvidia,tegra194-gpio - nvidia,tegra234-gpio + - nvidia,tegra256-gpio then: properties: interrupts: diff --git a/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml index ec0232e72c71..83e0b2d14c9f 100644 --- a/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml @@ -80,7 +80,7 @@ examples: gpio@d4019000 { compatible = "spacemit,k1-gpio"; reg = <0xd4019000 0x800>; - clocks =<&ccu 9>, <&ccu 61>; + clocks = <&ccu 9>, <&ccu 61>; clock-names = "core", "bus"; gpio-controller; #gpio-cells = <3>; diff --git a/Documentation/devicetree/bindings/gpio/trivial-gpio.yaml b/Documentation/devicetree/bindings/gpio/trivial-gpio.yaml index 0299d4a25086..c994177de940 100644 --- a/Documentation/devicetree/bindings/gpio/trivial-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/trivial-gpio.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/trivial-gpio.yaml# +$id: http://devicetree.org/schemas/gpio/trivial-gpio.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Trivial 2-cell GPIO controllers diff --git a/Documentation/devicetree/bindings/mfd/maxim,max7360.yaml b/Documentation/devicetree/bindings/mfd/maxim,max7360.yaml new file mode 100644 index 000000000000..3fc920c8639d --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/maxim,max7360.yaml @@ -0,0 +1,191 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/maxim,max7360.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX7360 Keypad, Rotary encoder, PWM and GPIO controller + +maintainers: + - Kamel Bouhara <kamel.bouhara@bootlin.com> + - Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com> + +description: | + Maxim MAX7360 device, with following functions: + - keypad controller + - rotary controller + - GPIO and GPO controller + - PWM controller + + https://www.analog.com/en/products/max7360.html + +allOf: + - $ref: /schemas/input/matrix-keymap.yaml# + - $ref: /schemas/input/input.yaml# + +properties: + compatible: + enum: + - maxim,max7360 + + reg: + maxItems: 1 + + interrupts: + maxItems: 2 + + interrupt-names: + items: + - const: inti + - const: intk + + keypad-debounce-delay-ms: + description: Keypad debounce delay in ms + minimum: 9 + maximum: 40 + default: 9 + + rotary-debounce-delay-ms: + description: Rotary encoder debounce delay in ms + minimum: 0 + maximum: 15 + default: 0 + + linux,axis: + $ref: /schemas/input/rotary-encoder.yaml#/properties/linux,axis + + rotary-encoder,relative-axis: + $ref: /schemas/types.yaml#/definitions/flag + description: + Register a relative axis rather than an absolute one. + + rotary-encoder,steps: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 24 + description: + Number of steps in a full turnaround of the + encoder. Only relevant for absolute axis. Defaults to 24 which is a + typical value for such devices. + + rotary-encoder,rollover: + $ref: /schemas/types.yaml#/definitions/flag + description: + Automatic rollover when the rotary value becomes + greater than the specified steps or smaller than 0. For absolute axis only. + + "#pwm-cells": + const: 3 + + gpio: + $ref: /schemas/gpio/maxim,max7360-gpio.yaml# + description: + PORT0 to PORT7 general purpose input/output pins configuration. + + gpo: + $ref: /schemas/gpio/maxim,max7360-gpio.yaml# + description: > + COL2 to COL7 general purpose output pins configuration. Allows to use + unused keypad columns as outputs. + + The MAX7360 has 8 column lines and 6 of them can be used as GPOs. GPIOs + numbers used for this gpio-controller node do correspond to the column + numbers: values 0 and 1 are never valid, values from 2 to 7 might be valid + depending on the value of the keypad,num-column property. + +patternProperties: + '-pins$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: /schemas/pinctrl/pincfg-node.yaml + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + pattern: '^(PORT[0-7]|ROTARY)$' + minItems: 1 + maxItems: 8 + + function: + description: + Specify the alternative function to be configured for the specified + pins. + enum: [gpio, pwm, rotary] + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - interrupt-names + - linux,keymap + - linux,axis + - "#pwm-cells" + - gpio + - gpo + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/input/input.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + io-expander@38 { + compatible = "maxim,max7360"; + reg = <0x38>; + + interrupt-parent = <&gpio1>; + interrupts = <23 IRQ_TYPE_LEVEL_LOW>, + <24 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "inti", "intk"; + + keypad,num-rows = <8>; + keypad,num-columns = <4>; + linux,keymap = < + MATRIX_KEY(0x00, 0x00, KEY_F5) + MATRIX_KEY(0x01, 0x00, KEY_F4) + MATRIX_KEY(0x02, 0x01, KEY_F6) + >; + keypad-debounce-delay-ms = <10>; + autorepeat; + + rotary-debounce-delay-ms = <2>; + linux,axis = <0>; /* REL_X */ + rotary-encoder,relative-axis; + + #pwm-cells = <3>; + + max7360_gpio: gpio { + compatible = "maxim,max7360-gpio"; + + gpio-controller; + #gpio-cells = <2>; + maxim,constant-current-disable = <0x06>; + + interrupt-controller; + #interrupt-cells = <0x2>; + }; + + max7360_gpo: gpo { + compatible = "maxim,max7360-gpo"; + + gpio-controller; + #gpio-cells = <2>; + }; + + backlight_pins: backlight-pins { + pins = "PORT2"; + function = "pwm"; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt deleted file mode 100644 index 1e70a8aff260..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt +++ /dev/null @@ -1,127 +0,0 @@ -* Freescale MXS Pin Controller - -The pins controlled by mxs pin controller are organized in banks, each bank -has 32 pins. Each pin has 4 multiplexing functions, and generally, the 4th -function is GPIO. The configuration on the pins includes drive strength, -voltage and pull-up. - -Required properties: -- compatible: "fsl,imx23-pinctrl" or "fsl,imx28-pinctrl" -- reg: Should contain the register physical address and length for the - pin controller. - -Please refer to pinctrl-bindings.txt in this directory for details of the -common pinctrl bindings used by client devices. - -The node of mxs pin controller acts as a container for an arbitrary number of -subnodes. Each of these subnodes represents some desired configuration for -a group of pins, and only affects those parameters that are explicitly listed. -In other words, a subnode that describes a drive strength parameter implies no -information about pull-up. For this reason, even seemingly boolean values are -actually tristates in this binding: unspecified, off, or on. Unspecified is -represented as an absent property, and off/on are represented as integer -values 0 and 1. - -Those subnodes under mxs pin controller node will fall into two categories. -One is to set up a group of pins for a function, both mux selection and pin -configurations, and it's called group node in the binding document. The other -one is to adjust the pin configuration for some particular pins that need a -different configuration than what is defined in group node. The binding -document calls this type of node config node. - -On mxs, there is no hardware pin group. The pin group in this binding only -means a group of pins put together for particular peripheral to work in -particular function, like SSP0 functioning as mmc0-8bit. That said, the -group node should include all the pins needed for one function rather than -having these pins defined in several group nodes. It also means each of -"pinctrl-*" phandle in client device node should only have one group node -pointed in there, while the phandle can have multiple config node referenced -there to adjust configurations for some pins in the group. - -Required subnode-properties: -- fsl,pinmux-ids: An integer array. Each integer in the array specify a pin - with given mux function, with bank, pin and mux packed as below. - - [15..12] : bank number - [11..4] : pin number - [3..0] : mux selection - - This integer with mux selection packed is used as an entity by both group - and config nodes to identify a pin. The mux selection in the integer takes - effects only on group node, and will get ignored by driver with config node, - since config node is only meant to set up pin configurations. - - Valid values for these integers are listed below. - -- reg: Should be the index of the group nodes for same function. This property - is required only for group nodes, and should not be present in any config - nodes. - -Optional subnode-properties: -- fsl,drive-strength: Integer. - 0: MXS_DRIVE_4mA - 1: MXS_DRIVE_8mA - 2: MXS_DRIVE_12mA - 3: MXS_DRIVE_16mA -- fsl,voltage: Integer. - 0: MXS_VOLTAGE_LOW - 1.8 V - 1: MXS_VOLTAGE_HIGH - 3.3 V -- fsl,pull-up: Integer. - 0: MXS_PULL_DISABLE - Disable the internal pull-up - 1: MXS_PULL_ENABLE - Enable the internal pull-up - -Note that when enabling the pull-up, the internal pad keeper gets disabled. -Also, some pins doesn't have a pull up, in that case, setting the fsl,pull-up -will only disable the internal pad keeper. - -Examples: - -pinctrl@80018000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,imx28-pinctrl"; - reg = <0x80018000 2000>; - - mmc0_8bit_pins_a: mmc0-8bit@0 { - reg = <0>; - fsl,pinmux-ids = < - MX28_PAD_SSP0_DATA0__SSP0_D0 - MX28_PAD_SSP0_DATA1__SSP0_D1 - MX28_PAD_SSP0_DATA2__SSP0_D2 - MX28_PAD_SSP0_DATA3__SSP0_D3 - MX28_PAD_SSP0_DATA4__SSP0_D4 - MX28_PAD_SSP0_DATA5__SSP0_D5 - MX28_PAD_SSP0_DATA6__SSP0_D6 - MX28_PAD_SSP0_DATA7__SSP0_D7 - MX28_PAD_SSP0_CMD__SSP0_CMD - MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT - MX28_PAD_SSP0_SCK__SSP0_SCK - >; - fsl,drive-strength = <MXS_DRIVE_4mA>; - fsl,voltage = <MXS_VOLTAGE_HIGH>; - fsl,pull-up = <MXS_PULL_ENABLE>; - }; - - mmc_cd_cfg: mmc-cd-cfg { - fsl,pinmux-ids = <MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT>; - fsl,pull-up = <MXS_PULL_DISABLE>; - }; - - mmc_sck_cfg: mmc-sck-cfg { - fsl,pinmux-ids = <MX28_PAD_SSP0_SCK__SSP0_SCK>; - fsl,drive-strength = <MXS_DRIVE_12mA>; - fsl,pull-up = <MXS_PULL_DISABLE>; - }; -}; - -In this example, group node mmc0-8bit defines a group of pins for mxs SSP0 -to function as a 8-bit mmc device, with 8mA, 3.3V and pull-up configurations -applied on all these pins. And config nodes mmc-cd-cfg and mmc-sck-cfg are -adjusting the configuration for pins card-detection and clock from what group -node mmc0-8bit defines. Only the configuration properties to be adjusted need -to be listed in the config nodes. - -Valid values for i.MX28/i.MX23 pinmux-id are defined in -arch/arm/boot/dts/imx28-pinfunc.h and arch/arm/boot/dts/imx23-pinfunc.h. -The definitions for the padconfig properties can be found in -arch/arm/boot/dts/mxs-pinfunc.h. diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst index 4fd1cbd8296e..069b54d8591b 100644 --- a/Documentation/driver-api/gpio/board.rst +++ b/Documentation/driver-api/gpio/board.rst @@ -94,6 +94,71 @@ with the help of _DSD (Device Specific Data), introduced in ACPI 5.1:: For more information about the ACPI GPIO bindings see Documentation/firmware-guide/acpi/gpio-properties.rst. +Software Nodes +-------------- + +Software nodes allow board-specific code to construct an in-memory, +device-tree-like structure using struct software_node and struct +property_entry. This structure can then be associated with a platform device, +allowing drivers to use the standard device properties API to query +configuration, just as they would on an ACPI or device tree system. + +Software-node-backed GPIOs are described using the ``PROPERTY_ENTRY_GPIO()`` +macro, which ties a software node representing the GPIO controller with +consumer device. It allows consumers to use regular gpiolib APIs, such as +gpiod_get(), gpiod_get_optional(). + +The software node representing a GPIO controller need not be attached to the +GPIO controller device. The only requirement is that the node must be +registered and its name must match the GPIO controller's label. + +For example, here is how to describe a single GPIO-connected LED. This is an +alternative to using platform_data on legacy systems. + +.. code-block:: c + + #include <linux/property.h> + #include <linux/gpio/machine.h> + #include <linux/gpio/property.h> + + /* + * 1. Define a node for the GPIO controller. Its .name must match the + * controller's label. + */ + static const struct software_node gpio_controller_node = { + .name = "gpio-foo", + }; + + /* 2. Define the properties for the LED device. */ + static const struct property_entry led_device_props[] = { + PROPERTY_ENTRY_STRING("label", "myboard:green:status"), + PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"), + PROPERTY_ENTRY_GPIO("gpios", &gpio_controller_node, 42, GPIO_ACTIVE_HIGH), + { } + }; + + /* 3. Define the software node for the LED device. */ + static const struct software_node led_device_swnode = { + .name = "status-led", + .properties = led_device_props, + }; + + /* + * 4. Register the software nodes and the platform device. + */ + const struct software_node *swnodes[] = { + &gpio_controller_node, + &led_device_swnode, + NULL + }; + software_node_register_node_group(swnodes); + + // Then register a platform_device for "leds-gpio" and associate + // it with &led_device_swnode via .fwnode. + +For a complete guide on converting board files to use software nodes, see +Documentation/driver-api/gpio/legacy-boards.rst. + Platform Data ------------- Finally, GPIOs can be bound to devices and functions using platform data. Board diff --git a/Documentation/driver-api/gpio/index.rst b/Documentation/driver-api/gpio/index.rst index 43f6a3afe10b..87929840e85a 100644 --- a/Documentation/driver-api/gpio/index.rst +++ b/Documentation/driver-api/gpio/index.rst @@ -12,6 +12,7 @@ Contents: driver consumer board + legacy-boards drivers-on-gpio bt8xxgpio diff --git a/Documentation/driver-api/gpio/legacy-boards.rst b/Documentation/driver-api/gpio/legacy-boards.rst new file mode 100644 index 000000000000..46e3a26dba77 --- /dev/null +++ b/Documentation/driver-api/gpio/legacy-boards.rst @@ -0,0 +1,298 @@ +Supporting Legacy Boards +======================== + +Many drivers in the kernel, such as ``leds-gpio`` and ``gpio-keys``, are +migrating away from using board-specific ``platform_data`` to a unified device +properties interface. This interface allows drivers to be simpler and more +generic, as they can query properties in a standardized way. + +On modern systems, these properties are provided via device tree. However, some +older platforms have not been converted to device tree and instead rely on +board files to describe their hardware configuration. To bridge this gap and +allow these legacy boards to work with modern, generic drivers, the kernel +provides a mechanism called **software nodes**. + +This document provides a guide on how to convert a legacy board file from using +``platform_data`` and ``gpiod_lookup_table`` to the modern software node +approach for describing GPIO-connected devices. + +The Core Idea: Software Nodes +----------------------------- + +Software nodes allow board-specific code to construct an in-memory, +device-tree-like structure using struct software_node and struct +property_entry. This structure can then be associated with a platform device, +allowing drivers to use the standard device properties API (e.g., +device_property_read_u32(), device_property_read_string()) to query +configuration, just as they would on an ACPI or device tree system. + +The gpiolib code has support for handling software nodes, so that if GPIO is +described properly, as detailed in the section below, then regular gpiolib APIs, +such as gpiod_get(), gpiod_get_optional(), and others will work. + +Requirements for GPIO Properties +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using software nodes to describe GPIO connections, the following +requirements must be met for the GPIO core to correctly resolve the reference: + +1. **The GPIO controller's software node "name" must match the controller's + "label".** The gpiolib core uses this name to find the corresponding + struct gpio_chip at runtime. + This software node has to be registered, but need not be attached to the + device representing the GPIO controller that is providing the GPIO in + question. It may be left as a "free floating" node. + +2. **The GPIO property must be a reference.** The ``PROPERTY_ENTRY_GPIO()`` + macro handles this as it is an alias for ``PROPERTY_ENTRY_REF()``. + +3. **The reference must have exactly two arguments:** + + - The first argument is the GPIO offset within the controller. + - The second argument is the flags for the GPIO line (e.g., + GPIO_ACTIVE_HIGH, GPIO_ACTIVE_LOW). + +The ``PROPERTY_ENTRY_GPIO()`` macro is the preferred way of defining GPIO +properties in software nodes. + +Conversion Example +------------------ + +Let's walk through an example of converting a board file that defines a GPIO- +connected LED and a button. + +Before: Using Platform Data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A typical legacy board file might look like this: + +.. code-block:: c + + #include <linux/platform_device.h> + #include <linux/leds.h> + #include <linux/gpio_keys.h> + #include <linux/gpio/machine.h> + + #define MYBOARD_GPIO_CONTROLLER "gpio-foo" + + /* LED setup */ + static const struct gpio_led myboard_leds[] = { + { + .name = "myboard:green:status", + .default_trigger = "heartbeat", + }, + }; + + static const struct gpio_led_platform_data myboard_leds_pdata = { + .num_leds = ARRAY_SIZE(myboard_leds), + .leds = myboard_leds, + }; + + static struct gpiod_lookup_table myboard_leds_gpios = { + .dev_id = "leds-gpio", + .table = { + GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 42, NULL, 0, GPIO_ACTIVE_HIGH), + { }, + }, + }; + + /* Button setup */ + static struct gpio_keys_button myboard_buttons[] = { + { + .code = KEY_WPS_BUTTON, + .desc = "WPS Button", + .active_low = 1, + }, + }; + + static const struct gpio_keys_platform_data myboard_buttons_pdata = { + .buttons = myboard_buttons, + .nbuttons = ARRAY_SIZE(myboard_buttons), + }; + + static struct gpiod_lookup_table myboard_buttons_gpios = { + .dev_id = "gpio-keys", + .table = { + GPIO_LOOKUP_IDX(MYBOARD_GPIO_CONTROLLER, 15, NULL, 0, GPIO_ACTIVE_LOW), + { }, + }, + }; + + /* Device registration */ + static int __init myboard_init(void) + { + gpiod_add_lookup_table(&myboard_leds_gpios); + gpiod_add_lookup_table(&myboard_buttons_gpios); + + platform_device_register_data(NULL, "leds-gpio", -1, + &myboard_leds_pdata, sizeof(myboard_leds_pdata)); + platform_device_register_data(NULL, "gpio-keys", -1, + &myboard_buttons_pdata, sizeof(myboard_buttons_pdata)); + + return 0; + } + +After: Using Software Nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here is how the same configuration can be expressed using software nodes. + +Step 1: Define the GPIO Controller Node +*************************************** + +First, define a software node that represents the GPIO controller that the +LEDs and buttons are connected to. The ``name`` of this node must match the +name of the driver for the GPIO controller (e.g., "gpio-foo"). + +.. code-block:: c + + #include <linux/property.h> + #include <linux/gpio/property.h> + + #define MYBOARD_GPIO_CONTROLLER "gpio-foo" + + static const struct software_node myboard_gpio_controller_node = { + .name = MYBOARD_GPIO_CONTROLLER, + }; + +Step 2: Define Consumer Device Nodes and Properties +*************************************************** + +Next, define the software nodes for the consumer devices (the LEDs and buttons). +This involves creating a parent node for each device type and child nodes for +each individual LED or button. + +.. code-block:: c + + /* LED setup */ + static const struct software_node myboard_leds_node = { + .name = "myboard-leds", + }; + + static const struct property_entry myboard_status_led_props[] = { + PROPERTY_ENTRY_STRING("label", "myboard:green:status"), + PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"), + PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 42, GPIO_ACTIVE_HIGH), + { } + }; + + static const struct software_node myboard_status_led_swnode = { + .name = "status-led", + .parent = &myboard_leds_node, + .properties = myboard_status_led_props, + }; + + /* Button setup */ + static const struct software_node myboard_keys_node = { + .name = "myboard-keys", + }; + + static const struct property_entry myboard_wps_button_props[] = { + PROPERTY_ENTRY_STRING("label", "WPS Button"), + PROPERTY_ENTRY_U32("linux,code", KEY_WPS_BUTTON), + PROPERTY_ENTRY_GPIO("gpios", &myboard_gpio_controller_node, 15, GPIO_ACTIVE_LOW), + { } + }; + + static const struct software_node myboard_wps_button_swnode = { + .name = "wps-button", + .parent = &myboard_keys_node, + .properties = myboard_wps_button_props, + }; + + + +Step 3: Group and Register the Nodes +************************************ + +For maintainability, it is often beneficial to group all software nodes into a +single array and register them with one call. + +.. code-block:: c + + static const struct software_node * const myboard_swnodes[] = { + &myboard_gpio_controller_node, + &myboard_leds_node, + &myboard_status_led_swnode, + &myboard_keys_node, + &myboard_wps_button_swnode, + NULL + }; + + static int __init myboard_init(void) + { + int error; + + error = software_node_register_node_group(myboard_swnodes); + if (error) { + pr_err("Failed to register software nodes: %d\n", error); + return error; + } + + // ... platform device registration follows + } + +.. note:: + When splitting registration of nodes by devices that they represent, it is + essential that the software node representing the GPIO controller itself + is registered first, before any of the nodes that reference it. + +Step 4: Register Platform Devices with Software Nodes +***************************************************** + +Finally, register the platform devices and associate them with their respective +software nodes using the ``fwnode`` field in struct platform_device_info. + +.. code-block:: c + + static struct platform_device *leds_pdev; + static struct platform_device *keys_pdev; + + static int __init myboard_init(void) + { + struct platform_device_info pdev_info; + int error; + + error = software_node_register_node_group(myboard_swnodes); + if (error) + return error; + + memset(&pdev_info, 0, sizeof(pdev_info)); + pdev_info.name = "leds-gpio"; + pdev_info.id = PLATFORM_DEVID_NONE; + pdev_info.fwnode = software_node_fwnode(&myboard_leds_node); + leds_pdev = platform_device_register_full(&pdev_info); + if (IS_ERR(leds_pdev)) { + error = PTR_ERR(leds_pdev); + goto err_unregister_nodes; + } + + memset(&pdev_info, 0, sizeof(pdev_info)); + pdev_info.name = "gpio-keys"; + pdev_info.id = PLATFORM_DEVID_NONE; + pdev_info.fwnode = software_node_fwnode(&myboard_keys_node); + keys_pdev = platform_device_register_full(&pdev_info); + if (IS_ERR(keys_pdev)) { + error = PTR_ERR(keys_pdev); + platform_device_unregister(leds_pdev); + goto err_unregister_nodes; + } + + return 0; + + err_unregister_nodes: + software_node_unregister_node_group(myboard_swnodes); + return error; + } + + static void __exit myboard_exit(void) + { + platform_device_unregister(keys_pdev); + platform_device_unregister(leds_pdev); + software_node_unregister_node_group(myboard_swnodes); + } + +With these changes, the generic ``leds-gpio`` and ``gpio-keys`` drivers will +be able to probe successfully and get their configuration from the properties +defined in the software nodes, removing the need for board-specific platform +data. |
