178 lines
7.0 KiB
ReStructuredText
178 lines
7.0 KiB
ReStructuredText
|
.. SPDX-License-Identifier: GPL-2.0-only
|
||
|
|
||
|
Virtual GPIO Consumer
|
||
|
=====================
|
||
|
|
||
|
The virtual GPIO Consumer module allows users to instantiate virtual devices
|
||
|
that request GPIOs and then control their behavior over debugfs. Virtual
|
||
|
consumer devices can be instantiated from device-tree or over configfs.
|
||
|
|
||
|
A virtual consumer uses the driver-facing GPIO APIs and allows to cover it with
|
||
|
automated tests driven by user-space. The GPIOs are requested using
|
||
|
``gpiod_get_array()`` and so we support multiple GPIOs per connector ID.
|
||
|
|
||
|
Creating GPIO consumers
|
||
|
-----------------------
|
||
|
|
||
|
The gpio-consumer module registers a configfs subsystem called
|
||
|
``'gpio-virtuser'``. For details of the configfs filesystem, please refer to
|
||
|
the configfs documentation.
|
||
|
|
||
|
The user can create a hierarchy of configfs groups and items as well as modify
|
||
|
values of exposed attributes. Once the consumer is instantiated, this hierarchy
|
||
|
will be translated to appropriate device properties. The general structure is:
|
||
|
|
||
|
**Group:** ``/config/gpio-virtuser``
|
||
|
|
||
|
This is the top directory of the gpio-consumer configfs tree.
|
||
|
|
||
|
**Group:** ``/config/gpio-consumer/example-name``
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/live``
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/dev_name``
|
||
|
|
||
|
This is a directory representing a GPIO consumer device.
|
||
|
|
||
|
The read-only ``dev_name`` attribute exposes the name of the device as it will
|
||
|
appear in the system on the platform bus. This is useful for locating the
|
||
|
associated debugfs directory under
|
||
|
``/sys/kernel/debug/gpio-virtuser/$dev_name``.
|
||
|
|
||
|
The ``'live'`` attribute allows to trigger the actual creation of the device
|
||
|
once it's fully configured. The accepted values are: ``'1'`` to enable the
|
||
|
virtual device and ``'0'`` to disable and tear it down.
|
||
|
|
||
|
Creating GPIO lookup tables
|
||
|
---------------------------
|
||
|
|
||
|
Users can create a number of configfs groups under the device group:
|
||
|
|
||
|
**Group:** ``/config/gpio-consumer/example-name/con_id``
|
||
|
|
||
|
The ``'con_id'`` directory represents a single GPIO lookup and its value maps
|
||
|
to the ``'con_id'`` argument of the ``gpiod_get()`` function. For example:
|
||
|
``con_id`` == ``'reset'`` maps to the ``reset-gpios`` device property.
|
||
|
|
||
|
Users can assign a number of GPIOs to each lookup. Each GPIO is a sub-directory
|
||
|
with a user-defined name under the ``'con_id'`` group.
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/key``
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/offset``
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/drive``
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/pull``
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/active_low``
|
||
|
|
||
|
**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/transitory``
|
||
|
|
||
|
This is a group describing a single GPIO in the ``con_id-gpios`` property.
|
||
|
|
||
|
For virtual consumers created using configfs we use machine lookup tables so
|
||
|
this group can be considered as a mapping between the filesystem and the fields
|
||
|
of a single entry in ``'struct gpiod_lookup'``.
|
||
|
|
||
|
The ``'key'`` attribute represents either the name of the chip this GPIO
|
||
|
belongs to or the GPIO line name. This depends on the value of the ``'offset'``
|
||
|
attribute: if its value is >= 0, then ``'key'`` represents the label of the
|
||
|
chip to lookup while ``'offset'`` represents the offset of the line in that
|
||
|
chip. If ``'offset'`` is < 0, then ``'key'`` represents the name of the line.
|
||
|
|
||
|
The remaining attributes map to the ``'flags'`` field of the GPIO lookup
|
||
|
struct. The first two take string values as arguments:
|
||
|
|
||
|
**``'drive'``:** ``'push-pull'``, ``'open-drain'``, ``'open-source'``
|
||
|
**``'pull'``:** ``'pull-up'``, ``'pull-down'``, ``'pull-disabled'``, ``'as-is'``
|
||
|
|
||
|
``'active_low'`` and ``'transitory'`` are boolean attributes.
|
||
|
|
||
|
Activating GPIO consumers
|
||
|
-------------------------
|
||
|
|
||
|
Once the confiuration is complete, the ``'live'`` attribute must be set to 1 in
|
||
|
order to instantiate the consumer. It can be set back to 0 to destroy the
|
||
|
virtual device. The module will synchronously wait for the new simulated device
|
||
|
to be successfully probed and if this doesn't happen, writing to ``'live'`` will
|
||
|
result in an error.
|
||
|
|
||
|
Device-tree
|
||
|
-----------
|
||
|
|
||
|
Virtual GPIO consumers can also be defined in device-tree. The compatible string
|
||
|
must be: ``"gpio-virtuser"`` with at least one property following the
|
||
|
standardized GPIO pattern.
|
||
|
|
||
|
An example device-tree code defining a virtual GPIO consumer:
|
||
|
|
||
|
.. code-block :: none
|
||
|
|
||
|
gpio-virt-consumer {
|
||
|
compatible = "gpio-virtuser";
|
||
|
|
||
|
foo-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>, <&gpio1 2 0>;
|
||
|
bar-gpios = <&gpio0 6 0>;
|
||
|
};
|
||
|
|
||
|
Controlling virtual GPIO consumers
|
||
|
----------------------------------
|
||
|
|
||
|
Once active, the device will export debugfs attributes for controlling GPIO
|
||
|
arrays as well as each requested GPIO line separately. Let's consider the
|
||
|
following device property: ``foo-gpios = <&gpio0 0 0>, <&gpio0 4 0>;``.
|
||
|
|
||
|
The following debugfs attribute groups will be created:
|
||
|
|
||
|
**Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/``
|
||
|
|
||
|
This is the group that will contain the attributes for the entire GPIO array.
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values``
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values_atomic``
|
||
|
|
||
|
Both attributes allow to read and set arrays of GPIO values. User must pass
|
||
|
exactly the number of values that the array contains in the form of a string
|
||
|
containing zeroes and ones representing inactive and active GPIO states
|
||
|
respectively. In this example: ``echo 11 > values``.
|
||
|
|
||
|
The ``values_atomic`` attribute works the same as ``values`` but the kernel
|
||
|
will execute the GPIO driver callbacks in interrupt context.
|
||
|
|
||
|
**Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/``
|
||
|
|
||
|
This is a group that represents a single GPIO with ``$index`` being its offset
|
||
|
in the array.
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/consumer``
|
||
|
|
||
|
Allows to set and read the consumer label of the GPIO line.
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/debounce``
|
||
|
|
||
|
Allows to set and read the debounce period of the GPIO line.
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction``
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction_atomic``
|
||
|
|
||
|
These two attributes allow to set the direction of the GPIO line. They accept
|
||
|
"input" and "output" as values. The atomic variant executes the driver callback
|
||
|
in interrupt context.
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/interrupts``
|
||
|
|
||
|
If the line is requested in input mode, writing ``1`` to this attribute will
|
||
|
make the module listen for edge interrupts on the GPIO. Writing ``0`` disables
|
||
|
the monitoring. Reading this attribute returns the current number of registered
|
||
|
interrupts (both edges).
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value``
|
||
|
|
||
|
**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value_atomic``
|
||
|
|
||
|
Both attributes allow to read and set values of individual requested GPIO lines.
|
||
|
They accept the following values: ``1`` and ``0``.
|