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