1.. SPDX-License-Identifier: GPL-2.0-only 2 3GPIO Aggregator 4=============== 5 6The GPIO Aggregator provides a mechanism to aggregate GPIOs, and expose them as 7a new gpio_chip. This supports the following use cases. 8 9 10Aggregating GPIOs using Sysfs 11----------------------------- 12 13GPIO controllers are exported to userspace using /dev/gpiochip* character 14devices. Access control to these devices is provided by standard UNIX file 15system permissions, on an all-or-nothing basis: either a GPIO controller is 16accessible for a user, or it is not. 17 18The GPIO Aggregator provides access control for a set of one or more GPIOs, by 19aggregating them into a new gpio_chip, which can be assigned to a group or user 20using standard UNIX file ownership and permissions. Furthermore, this 21simplifies and hardens exporting GPIOs to a virtual machine, as the VM can just 22grab the full GPIO controller, and no longer needs to care about which GPIOs to 23grab and which not, reducing the attack surface. 24 25Aggregated GPIO controllers are instantiated and destroyed by writing to 26write-only attribute files in sysfs. 27 28 /sys/bus/platform/drivers/gpio-aggregator/ 29 30 "new_device" ... 31 Userspace may ask the kernel to instantiate an aggregated GPIO 32 controller by writing a string describing the GPIOs to 33 aggregate to the "new_device" file, using the format 34 35 .. code-block:: none 36 37 [<gpioA>] [<gpiochipB> <offsets>] ... 38 39 Where: 40 41 "<gpioA>" ... 42 is a GPIO line name, 43 44 "<gpiochipB>" ... 45 is a GPIO chip label, and 46 47 "<offsets>" ... 48 is a comma-separated list of GPIO offsets and/or 49 GPIO offset ranges denoted by dashes. 50 51 Example: Instantiate a new GPIO aggregator by aggregating GPIO 52 line 19 of "e6052000.gpio" and GPIO lines 20-21 of 53 "e6050000.gpio" into a new gpio_chip: 54 55 .. code-block:: sh 56 57 $ echo 'e6052000.gpio 19 e6050000.gpio 20-21' > new_device 58 59 "delete_device" ... 60 Userspace may ask the kernel to destroy an aggregated GPIO 61 controller after use by writing its device name to the 62 "delete_device" file. 63 64 Example: Destroy the previously-created aggregated GPIO 65 controller, assumed to be "gpio-aggregator.0": 66 67 .. code-block:: sh 68 69 $ echo gpio-aggregator.0 > delete_device 70 71 72Aggregating GPIOs using Configfs 73-------------------------------- 74 75**Group:** ``/config/gpio-aggregator`` 76 77 This is the root directory of the gpio-aggregator configfs tree. 78 79**Group:** ``/config/gpio-aggregator/<example-name>`` 80 81 This directory represents a GPIO aggregator device. You can assign any 82 name to ``<example-name>`` (e.g. ``agg0``), except names starting with 83 ``_sysfs`` prefix, which are reserved for auto-generated configfs 84 entries corresponding to devices created via Sysfs. 85 86**Attribute:** ``/config/gpio-aggregator/<example-name>/live`` 87 88 The ``live`` attribute allows to trigger the actual creation of the device 89 once it's fully configured. Accepted values are: 90 91 * ``1``, ``yes``, ``true`` : enable the virtual device 92 * ``0``, ``no``, ``false`` : disable the virtual device 93 94**Attribute:** ``/config/gpio-aggregator/<example-name>/dev_name`` 95 96 The read-only ``dev_name`` attribute exposes the name of the device as it 97 will appear in the system on the platform bus (e.g. ``gpio-aggregator.0``). 98 This is useful for identifying a character device for the newly created 99 aggregator. If it's ``gpio-aggregator.0``, 100 ``/sys/devices/platform/gpio-aggregator.0/gpiochipX`` path tells you that the 101 GPIO device id is ``X``. 102 103You must create subdirectories for each virtual line you want to 104instantiate, named exactly as ``line0``, ``line1``, ..., ``lineY``, when 105you want to instantiate ``Y+1`` (Y >= 0) lines. Configure all lines before 106activating the device by setting ``live`` to 1. 107 108**Group:** ``/config/gpio-aggregator/<example-name>/<lineY>/`` 109 110 This directory represents a GPIO line to include in the aggregator. 111 112**Attribute:** ``/config/gpio-aggregator/<example-name>/<lineY>/key`` 113 114**Attribute:** ``/config/gpio-aggregator/<example-name>/<lineY>/offset`` 115 116 The default values after creating the ``<lineY>`` directory are: 117 118 * ``key`` : <empty> 119 * ``offset`` : -1 120 121 ``key`` must always be explicitly configured, while ``offset`` depends. 122 Two configuration patterns exist for each ``<lineY>``: 123 124 (a). For lookup by GPIO line name: 125 126 * Set ``key`` to the line name. 127 * Ensure ``offset`` remains -1 (the default). 128 129 (b). For lookup by GPIO chip name and the line offset within the chip: 130 131 * Set ``key`` to the chip name. 132 * Set ``offset`` to the line offset (0 <= ``offset`` < 65535). 133 134**Attribute:** ``/config/gpio-aggregator/<example-name>/<lineY>/name`` 135 136 The ``name`` attribute sets a custom name for lineY. If left unset, the 137 line will remain unnamed. 138 139Once the configuration is done, the ``'live'`` attribute must be set to 1 140in order to instantiate the aggregator device. It can be set back to 0 to 141destroy the virtual device. The module will synchronously wait for the new 142aggregator device to be successfully probed and if this doesn't happen, writing 143to ``'live'`` will result in an error. This is a different behaviour from the 144case when you create it using sysfs ``new_device`` interface. 145 146.. note:: 147 148 For aggregators created via Sysfs, the configfs entries are 149 auto-generated and appear as ``/config/gpio-aggregator/_sysfs.<N>/``. You 150 cannot add or remove line directories with mkdir(2)/rmdir(2). To modify 151 lines, you must use the "delete_device" interface to tear down the 152 existing device and reconfigure it from scratch. However, you can still 153 toggle the aggregator with the ``live`` attribute and adjust the 154 ``key``, ``offset``, and ``name`` attributes for each line when ``live`` 155 is set to 0 by hand (i.e. it's not waiting for deferred probe). 156 157Sample configuration commands 158~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 159 160.. code-block:: sh 161 162 # Create a directory for an aggregator device 163 $ mkdir /sys/kernel/config/gpio-aggregator/agg0 164 165 # Configure each line 166 $ mkdir /sys/kernel/config/gpio-aggregator/agg0/line0 167 $ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line0/key 168 $ echo 6 > /sys/kernel/config/gpio-aggregator/agg0/line0/offset 169 $ echo test0 > /sys/kernel/config/gpio-aggregator/agg0/line0/name 170 $ mkdir /sys/kernel/config/gpio-aggregator/agg0/line1 171 $ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line1/key 172 $ echo 7 > /sys/kernel/config/gpio-aggregator/agg0/line1/offset 173 $ echo test1 > /sys/kernel/config/gpio-aggregator/agg0/line1/name 174 175 # Activate the aggregator device 176 $ echo 1 > /sys/kernel/config/gpio-aggregator/agg0/live 177 178 179Generic GPIO Driver 180------------------- 181 182The GPIO Aggregator can also be used as a generic driver for a simple 183GPIO-operated device described in DT, without a dedicated in-kernel driver. 184This is useful in industrial control, and is not unlike e.g. spidev, which 185allows the user to communicate with an SPI device from userspace. 186 187Binding a device to the GPIO Aggregator is performed either by modifying the 188gpio-aggregator driver, or by writing to the "driver_override" file in Sysfs. 189 190Example: If "door" is a GPIO-operated device described in DT, using its own 191compatible value:: 192 193 door { 194 compatible = "myvendor,mydoor"; 195 196 gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>, 197 <&gpio2 20 GPIO_ACTIVE_LOW>; 198 gpio-line-names = "open", "lock"; 199 }; 200 201it can be bound to the GPIO Aggregator by either: 202 2031. Adding its compatible value to ``gpio_aggregator_dt_ids[]``, 2042. Binding manually using "driver_override": 205 206.. code-block:: sh 207 208 $ echo gpio-aggregator > /sys/bus/platform/devices/door/driver_override 209 $ echo door > /sys/bus/platform/drivers/gpio-aggregator/bind 210 211After that, a new gpiochip "door" has been created: 212 213.. code-block:: sh 214 215 $ gpioinfo door 216 gpiochip12 - 2 lines: 217 line 0: "open" unused input active-high 218 line 1: "lock" unused input active-high 219