1*ce7a2f77SGeert Uytterhoeven.. SPDX-License-Identifier: GPL-2.0-only 2*ce7a2f77SGeert Uytterhoeven 3*ce7a2f77SGeert UytterhoevenGPIO Aggregator 4*ce7a2f77SGeert Uytterhoeven=============== 5*ce7a2f77SGeert Uytterhoeven 6*ce7a2f77SGeert UytterhoevenThe GPIO Aggregator provides a mechanism to aggregate GPIOs, and expose them as 7*ce7a2f77SGeert Uytterhoevena new gpio_chip. This supports the following use cases. 8*ce7a2f77SGeert Uytterhoeven 9*ce7a2f77SGeert Uytterhoeven 10*ce7a2f77SGeert UytterhoevenAggregating GPIOs using Sysfs 11*ce7a2f77SGeert Uytterhoeven----------------------------- 12*ce7a2f77SGeert Uytterhoeven 13*ce7a2f77SGeert UytterhoevenGPIO controllers are exported to userspace using /dev/gpiochip* character 14*ce7a2f77SGeert Uytterhoevendevices. Access control to these devices is provided by standard UNIX file 15*ce7a2f77SGeert Uytterhoevensystem permissions, on an all-or-nothing basis: either a GPIO controller is 16*ce7a2f77SGeert Uytterhoevenaccessible for a user, or it is not. 17*ce7a2f77SGeert Uytterhoeven 18*ce7a2f77SGeert UytterhoevenThe GPIO Aggregator provides access control for a set of one or more GPIOs, by 19*ce7a2f77SGeert Uytterhoevenaggregating them into a new gpio_chip, which can be assigned to a group or user 20*ce7a2f77SGeert Uytterhoevenusing standard UNIX file ownership and permissions. Furthermore, this 21*ce7a2f77SGeert Uytterhoevensimplifies and hardens exporting GPIOs to a virtual machine, as the VM can just 22*ce7a2f77SGeert Uytterhoevengrab the full GPIO controller, and no longer needs to care about which GPIOs to 23*ce7a2f77SGeert Uytterhoevengrab and which not, reducing the attack surface. 24*ce7a2f77SGeert Uytterhoeven 25*ce7a2f77SGeert UytterhoevenAggregated GPIO controllers are instantiated and destroyed by writing to 26*ce7a2f77SGeert Uytterhoevenwrite-only attribute files in sysfs. 27*ce7a2f77SGeert Uytterhoeven 28*ce7a2f77SGeert Uytterhoeven /sys/bus/platform/drivers/gpio-aggregator/ 29*ce7a2f77SGeert Uytterhoeven 30*ce7a2f77SGeert Uytterhoeven "new_device" ... 31*ce7a2f77SGeert Uytterhoeven Userspace may ask the kernel to instantiate an aggregated GPIO 32*ce7a2f77SGeert Uytterhoeven controller by writing a string describing the GPIOs to 33*ce7a2f77SGeert Uytterhoeven aggregate to the "new_device" file, using the format 34*ce7a2f77SGeert Uytterhoeven 35*ce7a2f77SGeert Uytterhoeven .. code-block:: none 36*ce7a2f77SGeert Uytterhoeven 37*ce7a2f77SGeert Uytterhoeven [<gpioA>] [<gpiochipB> <offsets>] ... 38*ce7a2f77SGeert Uytterhoeven 39*ce7a2f77SGeert Uytterhoeven Where: 40*ce7a2f77SGeert Uytterhoeven 41*ce7a2f77SGeert Uytterhoeven "<gpioA>" ... 42*ce7a2f77SGeert Uytterhoeven is a GPIO line name, 43*ce7a2f77SGeert Uytterhoeven 44*ce7a2f77SGeert Uytterhoeven "<gpiochipB>" ... 45*ce7a2f77SGeert Uytterhoeven is a GPIO chip label, and 46*ce7a2f77SGeert Uytterhoeven 47*ce7a2f77SGeert Uytterhoeven "<offsets>" ... 48*ce7a2f77SGeert Uytterhoeven is a comma-separated list of GPIO offsets and/or 49*ce7a2f77SGeert Uytterhoeven GPIO offset ranges denoted by dashes. 50*ce7a2f77SGeert Uytterhoeven 51*ce7a2f77SGeert Uytterhoeven Example: Instantiate a new GPIO aggregator by aggregating GPIO 52*ce7a2f77SGeert Uytterhoeven line 19 of "e6052000.gpio" and GPIO lines 20-21 of 53*ce7a2f77SGeert Uytterhoeven "e6050000.gpio" into a new gpio_chip: 54*ce7a2f77SGeert Uytterhoeven 55*ce7a2f77SGeert Uytterhoeven .. code-block:: sh 56*ce7a2f77SGeert Uytterhoeven 57*ce7a2f77SGeert Uytterhoeven $ echo 'e6052000.gpio 19 e6050000.gpio 20-21' > new_device 58*ce7a2f77SGeert Uytterhoeven 59*ce7a2f77SGeert Uytterhoeven "delete_device" ... 60*ce7a2f77SGeert Uytterhoeven Userspace may ask the kernel to destroy an aggregated GPIO 61*ce7a2f77SGeert Uytterhoeven controller after use by writing its device name to the 62*ce7a2f77SGeert Uytterhoeven "delete_device" file. 63*ce7a2f77SGeert Uytterhoeven 64*ce7a2f77SGeert Uytterhoeven Example: Destroy the previously-created aggregated GPIO 65*ce7a2f77SGeert Uytterhoeven controller, assumed to be "gpio-aggregator.0": 66*ce7a2f77SGeert Uytterhoeven 67*ce7a2f77SGeert Uytterhoeven .. code-block:: sh 68*ce7a2f77SGeert Uytterhoeven 69*ce7a2f77SGeert Uytterhoeven $ echo gpio-aggregator.0 > delete_device 70*ce7a2f77SGeert Uytterhoeven 71*ce7a2f77SGeert Uytterhoeven 72*ce7a2f77SGeert UytterhoevenGeneric GPIO Driver 73*ce7a2f77SGeert Uytterhoeven------------------- 74*ce7a2f77SGeert Uytterhoeven 75*ce7a2f77SGeert UytterhoevenThe GPIO Aggregator can also be used as a generic driver for a simple 76*ce7a2f77SGeert UytterhoevenGPIO-operated device described in DT, without a dedicated in-kernel driver. 77*ce7a2f77SGeert UytterhoevenThis is useful in industrial control, and is not unlike e.g. spidev, which 78*ce7a2f77SGeert Uytterhoevenallows the user to communicate with an SPI device from userspace. 79*ce7a2f77SGeert Uytterhoeven 80*ce7a2f77SGeert UytterhoevenBinding a device to the GPIO Aggregator is performed either by modifying the 81*ce7a2f77SGeert Uytterhoevengpio-aggregator driver, or by writing to the "driver_override" file in Sysfs. 82*ce7a2f77SGeert Uytterhoeven 83*ce7a2f77SGeert UytterhoevenExample: If "door" is a GPIO-operated device described in DT, using its own 84*ce7a2f77SGeert Uytterhoevencompatible value:: 85*ce7a2f77SGeert Uytterhoeven 86*ce7a2f77SGeert Uytterhoeven door { 87*ce7a2f77SGeert Uytterhoeven compatible = "myvendor,mydoor"; 88*ce7a2f77SGeert Uytterhoeven 89*ce7a2f77SGeert Uytterhoeven gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>, 90*ce7a2f77SGeert Uytterhoeven <&gpio2 20 GPIO_ACTIVE_LOW>; 91*ce7a2f77SGeert Uytterhoeven gpio-line-names = "open", "lock"; 92*ce7a2f77SGeert Uytterhoeven }; 93*ce7a2f77SGeert Uytterhoeven 94*ce7a2f77SGeert Uytterhoevenit can be bound to the GPIO Aggregator by either: 95*ce7a2f77SGeert Uytterhoeven 96*ce7a2f77SGeert Uytterhoeven1. Adding its compatible value to ``gpio_aggregator_dt_ids[]``, 97*ce7a2f77SGeert Uytterhoeven2. Binding manually using "driver_override": 98*ce7a2f77SGeert Uytterhoeven 99*ce7a2f77SGeert Uytterhoeven.. code-block:: sh 100*ce7a2f77SGeert Uytterhoeven 101*ce7a2f77SGeert Uytterhoeven $ echo gpio-aggregator > /sys/bus/platform/devices/door/driver_override 102*ce7a2f77SGeert Uytterhoeven $ echo door > /sys/bus/platform/drivers/gpio-aggregator/bind 103*ce7a2f77SGeert Uytterhoeven 104*ce7a2f77SGeert UytterhoevenAfter that, a new gpiochip "door" has been created: 105*ce7a2f77SGeert Uytterhoeven 106*ce7a2f77SGeert Uytterhoeven.. code-block:: sh 107*ce7a2f77SGeert Uytterhoeven 108*ce7a2f77SGeert Uytterhoeven $ gpioinfo door 109*ce7a2f77SGeert Uytterhoeven gpiochip12 - 2 lines: 110*ce7a2f77SGeert Uytterhoeven line 0: "open" unused input active-high 111*ce7a2f77SGeert Uytterhoeven line 1: "lock" unused input active-high 112