| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- .. 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
|