mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Add documentation for the newly added configfs-based interface for GPIO aggregator. Signed-off-by: Koichiro Den <koichiro.den@canonical.com> Link: https://lore.kernel.org/r/20250407043019.4105613-9-koichiro.den@canonical.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
218 lines
7.8 KiB
ReStructuredText
218 lines
7.8 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
GPIO Aggregator
|
|
===============
|
|
|
|
The GPIO Aggregator provides a mechanism to aggregate GPIOs, and expose them as
|
|
a new gpio_chip. This supports the following use cases.
|
|
|
|
|
|
Aggregating GPIOs using Sysfs
|
|
-----------------------------
|
|
|
|
GPIO controllers are exported to userspace using /dev/gpiochip* character
|
|
devices. Access control to these devices is provided by standard UNIX file
|
|
system permissions, on an all-or-nothing basis: either a GPIO controller is
|
|
accessible for a user, or it is not.
|
|
|
|
The GPIO Aggregator provides access control for a set of one or more GPIOs, by
|
|
aggregating them into a new gpio_chip, which can be assigned to a group or user
|
|
using standard UNIX file ownership and permissions. Furthermore, this
|
|
simplifies and hardens exporting GPIOs to a virtual machine, as the VM can just
|
|
grab the full GPIO controller, and no longer needs to care about which GPIOs to
|
|
grab and which not, reducing the attack surface.
|
|
|
|
Aggregated GPIO controllers are instantiated and destroyed by writing to
|
|
write-only attribute files in sysfs.
|
|
|
|
/sys/bus/platform/drivers/gpio-aggregator/
|
|
|
|
"new_device" ...
|
|
Userspace may ask the kernel to instantiate an aggregated GPIO
|
|
controller by writing a string describing the GPIOs to
|
|
aggregate to the "new_device" file, using the format
|
|
|
|
.. code-block:: none
|
|
|
|
[<gpioA>] [<gpiochipB> <offsets>] ...
|
|
|
|
Where:
|
|
|
|
"<gpioA>" ...
|
|
is a GPIO line name,
|
|
|
|
"<gpiochipB>" ...
|
|
is a GPIO chip label, and
|
|
|
|
"<offsets>" ...
|
|
is a comma-separated list of GPIO offsets and/or
|
|
GPIO offset ranges denoted by dashes.
|
|
|
|
Example: Instantiate a new GPIO aggregator by aggregating GPIO
|
|
line 19 of "e6052000.gpio" and GPIO lines 20-21 of
|
|
"e6050000.gpio" into a new gpio_chip:
|
|
|
|
.. code-block:: sh
|
|
|
|
$ echo 'e6052000.gpio 19 e6050000.gpio 20-21' > new_device
|
|
|
|
"delete_device" ...
|
|
Userspace may ask the kernel to destroy an aggregated GPIO
|
|
controller after use by writing its device name to the
|
|
"delete_device" file.
|
|
|
|
Example: Destroy the previously-created aggregated GPIO
|
|
controller, assumed to be "gpio-aggregator.0":
|
|
|
|
.. code-block:: sh
|
|
|
|
$ echo gpio-aggregator.0 > delete_device
|
|
|
|
|
|
Aggregating GPIOs using Configfs
|
|
--------------------------------
|
|
|
|
**Group:** ``/config/gpio-aggregator``
|
|
|
|
This is the root directory of the gpio-aggregator configfs tree.
|
|
|
|
**Group:** ``/config/gpio-aggregator/<example-name>``
|
|
|
|
This directory represents a GPIO aggregator device. You can assign any
|
|
name to ``<example-name>`` (e.g. ``agg0``), except names starting with
|
|
``_sysfs`` prefix, which are reserved for auto-generated configfs
|
|
entries corresponding to devices created via Sysfs.
|
|
|
|
**Attribute:** ``/config/gpio-aggregator/<example-name>/live``
|
|
|
|
The ``live`` attribute allows to trigger the actual creation of the device
|
|
once it's fully configured. Accepted values are:
|
|
|
|
* ``1``, ``yes``, ``true`` : enable the virtual device
|
|
* ``0``, ``no``, ``false`` : disable the virtual device
|
|
|
|
**Attribute:** ``/config/gpio-aggregator/<example-name>/dev_name``
|
|
|
|
The read-only ``dev_name`` attribute exposes the name of the device as it
|
|
will appear in the system on the platform bus (e.g. ``gpio-aggregator.0``).
|
|
This is useful for identifying a character device for the newly created
|
|
aggregator. If it's ``gpio-aggregator.0``,
|
|
``/sys/devices/platform/gpio-aggregator.0/gpiochipX`` path tells you that the
|
|
GPIO device id is ``X``.
|
|
|
|
You must create subdirectories for each virtual line you want to
|
|
instantiate, named exactly as ``line0``, ``line1``, ..., ``lineY``, when
|
|
you want to instantiate ``Y+1`` (Y >= 0) lines. Configure all lines before
|
|
activating the device by setting ``live`` to 1.
|
|
|
|
**Group:** ``/config/gpio-aggregator/<example-name>/<lineY>/``
|
|
|
|
This directory represents a GPIO line to include in the aggregator.
|
|
|
|
**Attribute:** ``/config/gpio-aggregator/<example-name>/<lineY>/key``
|
|
|
|
**Attribute:** ``/config/gpio-aggregator/<example-name>/<lineY>/offset``
|
|
|
|
The default values after creating the ``<lineY>`` directory are:
|
|
|
|
* ``key`` : <empty>
|
|
* ``offset`` : -1
|
|
|
|
``key`` must always be explicitly configured, while ``offset`` depends.
|
|
Two configuration patterns exist for each ``<lineY>``:
|
|
|
|
(a). For lookup by GPIO line name:
|
|
|
|
* Set ``key`` to the line name.
|
|
* Ensure ``offset`` remains -1 (the default).
|
|
|
|
(b). For lookup by GPIO chip name and the line offset within the chip:
|
|
|
|
* Set ``key`` to the chip name.
|
|
* Set ``offset`` to the line offset (0 <= ``offset`` < 65535).
|
|
|
|
**Attribute:** ``/config/gpio-aggregator/<example-name>/<lineY>/name``
|
|
|
|
The ``name`` attribute sets a custom name for lineY. If left unset, the
|
|
line will remain unnamed.
|
|
|
|
Once the configuration is done, the ``'live'`` attribute must be set to 1
|
|
in order to instantiate the aggregator device. It can be set back to 0 to
|
|
destroy the virtual device. The module will synchronously wait for the new
|
|
aggregator device to be successfully probed and if this doesn't happen, writing
|
|
to ``'live'`` will result in an error. This is a different behaviour from the
|
|
case when you create it using sysfs ``new_device`` interface.
|
|
|
|
.. note::
|
|
|
|
For aggregators created via Sysfs, the configfs entries are
|
|
auto-generated and appear as ``/config/gpio-aggregator/_sysfs.<N>/``. You
|
|
cannot add or remove line directories with mkdir(2)/rmdir(2). To modify
|
|
lines, you must use the "delete_device" interface to tear down the
|
|
existing device and reconfigure it from scratch. However, you can still
|
|
toggle the aggregator with the ``live`` attribute and adjust the
|
|
``key``, ``offset``, and ``name`` attributes for each line when ``live``
|
|
is set to 0 by hand (i.e. it's not waiting for deferred probe).
|
|
|
|
Sample configuration commands
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: sh
|
|
|
|
# Create a directory for an aggregator device
|
|
$ mkdir /sys/kernel/config/gpio-aggregator/agg0
|
|
|
|
# Configure each line
|
|
$ mkdir /sys/kernel/config/gpio-aggregator/agg0/line0
|
|
$ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line0/key
|
|
$ echo 6 > /sys/kernel/config/gpio-aggregator/agg0/line0/offset
|
|
$ echo test0 > /sys/kernel/config/gpio-aggregator/agg0/line0/name
|
|
$ mkdir /sys/kernel/config/gpio-aggregator/agg0/line1
|
|
$ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line1/key
|
|
$ echo 7 > /sys/kernel/config/gpio-aggregator/agg0/line1/offset
|
|
$ echo test1 > /sys/kernel/config/gpio-aggregator/agg0/line1/name
|
|
|
|
# Activate the aggregator device
|
|
$ echo 1 > /sys/kernel/config/gpio-aggregator/agg0/live
|
|
|
|
|
|
Generic GPIO Driver
|
|
-------------------
|
|
|
|
The GPIO Aggregator can also be used as a generic driver for a simple
|
|
GPIO-operated device described in DT, without a dedicated in-kernel driver.
|
|
This is useful in industrial control, and is not unlike e.g. spidev, which
|
|
allows the user to communicate with an SPI device from userspace.
|
|
|
|
Binding a device to the GPIO Aggregator is performed either by modifying the
|
|
gpio-aggregator driver, or by writing to the "driver_override" file in Sysfs.
|
|
|
|
Example: If "door" is a GPIO-operated device described in DT, using its own
|
|
compatible value::
|
|
|
|
door {
|
|
compatible = "myvendor,mydoor";
|
|
|
|
gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>,
|
|
<&gpio2 20 GPIO_ACTIVE_LOW>;
|
|
gpio-line-names = "open", "lock";
|
|
};
|
|
|
|
it can be bound to the GPIO Aggregator by either:
|
|
|
|
1. Adding its compatible value to ``gpio_aggregator_dt_ids[]``,
|
|
2. Binding manually using "driver_override":
|
|
|
|
.. code-block:: sh
|
|
|
|
$ echo gpio-aggregator > /sys/bus/platform/devices/door/driver_override
|
|
$ echo door > /sys/bus/platform/drivers/gpio-aggregator/bind
|
|
|
|
After that, a new gpiochip "door" has been created:
|
|
|
|
.. code-block:: sh
|
|
|
|
$ gpioinfo door
|
|
gpiochip12 - 2 lines:
|
|
line 0: "open" unused input active-high
|
|
line 1: "lock" unused input active-high
|