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