162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci
362306a36Sopenharmony_ciGPIO Aggregator
462306a36Sopenharmony_ci===============
562306a36Sopenharmony_ci
662306a36Sopenharmony_ciThe GPIO Aggregator provides a mechanism to aggregate GPIOs, and expose them as
762306a36Sopenharmony_cia new gpio_chip.  This supports the following use cases.
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ciAggregating GPIOs using Sysfs
1162306a36Sopenharmony_ci-----------------------------
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ciGPIO controllers are exported to userspace using /dev/gpiochip* character
1462306a36Sopenharmony_cidevices.  Access control to these devices is provided by standard UNIX file
1562306a36Sopenharmony_cisystem permissions, on an all-or-nothing basis: either a GPIO controller is
1662306a36Sopenharmony_ciaccessible for a user, or it is not.
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciThe GPIO Aggregator provides access control for a set of one or more GPIOs, by
1962306a36Sopenharmony_ciaggregating them into a new gpio_chip, which can be assigned to a group or user
2062306a36Sopenharmony_ciusing standard UNIX file ownership and permissions.  Furthermore, this
2162306a36Sopenharmony_cisimplifies and hardens exporting GPIOs to a virtual machine, as the VM can just
2262306a36Sopenharmony_cigrab the full GPIO controller, and no longer needs to care about which GPIOs to
2362306a36Sopenharmony_cigrab and which not, reducing the attack surface.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciAggregated GPIO controllers are instantiated and destroyed by writing to
2662306a36Sopenharmony_ciwrite-only attribute files in sysfs.
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci    /sys/bus/platform/drivers/gpio-aggregator/
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	"new_device" ...
3162306a36Sopenharmony_ci		Userspace may ask the kernel to instantiate an aggregated GPIO
3262306a36Sopenharmony_ci		controller by writing a string describing the GPIOs to
3362306a36Sopenharmony_ci		aggregate to the "new_device" file, using the format
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci		.. code-block:: none
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci		    [<gpioA>] [<gpiochipB> <offsets>] ...
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci		Where:
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci		    "<gpioA>" ...
4262306a36Sopenharmony_ci			    is a GPIO line name,
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		    "<gpiochipB>" ...
4562306a36Sopenharmony_ci			    is a GPIO chip label, and
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci		    "<offsets>" ...
4862306a36Sopenharmony_ci			    is a comma-separated list of GPIO offsets and/or
4962306a36Sopenharmony_ci			    GPIO offset ranges denoted by dashes.
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci		Example: Instantiate a new GPIO aggregator by aggregating GPIO
5262306a36Sopenharmony_ci		line 19 of "e6052000.gpio" and GPIO lines 20-21 of
5362306a36Sopenharmony_ci		"e6050000.gpio" into a new gpio_chip:
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci		.. code-block:: sh
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci		    $ echo 'e6052000.gpio 19 e6050000.gpio 20-21' > new_device
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	"delete_device" ...
6062306a36Sopenharmony_ci		Userspace may ask the kernel to destroy an aggregated GPIO
6162306a36Sopenharmony_ci		controller after use by writing its device name to the
6262306a36Sopenharmony_ci		"delete_device" file.
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci		Example: Destroy the previously-created aggregated GPIO
6562306a36Sopenharmony_ci		controller, assumed to be "gpio-aggregator.0":
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci		.. code-block:: sh
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci		    $ echo gpio-aggregator.0 > delete_device
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ciGeneric GPIO Driver
7362306a36Sopenharmony_ci-------------------
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciThe GPIO Aggregator can also be used as a generic driver for a simple
7662306a36Sopenharmony_ciGPIO-operated device described in DT, without a dedicated in-kernel driver.
7762306a36Sopenharmony_ciThis is useful in industrial control, and is not unlike e.g. spidev, which
7862306a36Sopenharmony_ciallows the user to communicate with an SPI device from userspace.
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ciBinding a device to the GPIO Aggregator is performed either by modifying the
8162306a36Sopenharmony_cigpio-aggregator driver, or by writing to the "driver_override" file in Sysfs.
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciExample: If "door" is a GPIO-operated device described in DT, using its own
8462306a36Sopenharmony_cicompatible value::
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	door {
8762306a36Sopenharmony_ci		compatible = "myvendor,mydoor";
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci		gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>,
9062306a36Sopenharmony_ci			<&gpio2 20 GPIO_ACTIVE_LOW>;
9162306a36Sopenharmony_ci		gpio-line-names = "open", "lock";
9262306a36Sopenharmony_ci	};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ciit can be bound to the GPIO Aggregator by either:
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci1. Adding its compatible value to ``gpio_aggregator_dt_ids[]``,
9762306a36Sopenharmony_ci2. Binding manually using "driver_override":
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci.. code-block:: sh
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci    $ echo gpio-aggregator > /sys/bus/platform/devices/door/driver_override
10262306a36Sopenharmony_ci    $ echo door > /sys/bus/platform/drivers/gpio-aggregator/bind
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciAfter that, a new gpiochip "door" has been created:
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci.. code-block:: sh
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci    $ gpioinfo door
10962306a36Sopenharmony_ci    gpiochip12 - 2 lines:
11062306a36Sopenharmony_ci	    line   0:       "open"       unused   input  active-high
11162306a36Sopenharmony_ci	    line   1:       "lock"       unused   input  active-high
112