xref: /linux/Documentation/admin-guide/gpio/gpio-aggregator.rst (revision aacc73ceeb8bf664426f0e53db2778a59325bd9f)
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