|
| 1 | +.. SPDX-License-Identifier: GPL-2.0-only |
| 2 | +
|
| 3 | +Virtual GPIO Consumer |
| 4 | +===================== |
| 5 | + |
| 6 | +The virtual GPIO Consumer module allows users to instantiate virtual devices |
| 7 | +that request GPIOs and then control their behavior over debugfs. Virtual |
| 8 | +consumer devices can be instantiated from device-tree or over configfs. |
| 9 | + |
| 10 | +A virtual consumer uses the driver-facing GPIO APIs and allows to cover it with |
| 11 | +automated tests driven by user-space. The GPIOs are requested using |
| 12 | +``gpiod_get_array()`` and so we support multiple GPIOs per connector ID. |
| 13 | + |
| 14 | +Creating GPIO consumers |
| 15 | +----------------------- |
| 16 | + |
| 17 | +The gpio-consumer module registers a configfs subsystem called |
| 18 | +``'gpio-virtuser'``. For details of the configfs filesystem, please refer to |
| 19 | +the configfs documentation. |
| 20 | + |
| 21 | +The user can create a hierarchy of configfs groups and items as well as modify |
| 22 | +values of exposed attributes. Once the consumer is instantiated, this hierarchy |
| 23 | +will be translated to appropriate device properties. The general structure is: |
| 24 | + |
| 25 | +**Group:** ``/config/gpio-virtuser`` |
| 26 | + |
| 27 | +This is the top directory of the gpio-consumer configfs tree. |
| 28 | + |
| 29 | +**Group:** ``/config/gpio-consumer/example-name`` |
| 30 | + |
| 31 | +**Attribute:** ``/config/gpio-consumer/example-name/live`` |
| 32 | + |
| 33 | +**Attribute:** ``/config/gpio-consumer/example-name/dev_name`` |
| 34 | + |
| 35 | +This is a directory representing a GPIO consumer device. |
| 36 | + |
| 37 | +The read-only ``dev_name`` attribute exposes the name of the device as it will |
| 38 | +appear in the system on the platform bus. This is useful for locating the |
| 39 | +associated debugfs directory under |
| 40 | +``/sys/kernel/debug/gpio-virtuser/$dev_name``. |
| 41 | + |
| 42 | +The ``'live'`` attribute allows to trigger the actual creation of the device |
| 43 | +once it's fully configured. The accepted values are: ``'1'`` to enable the |
| 44 | +virtual device and ``'0'`` to disable and tear it down. |
| 45 | + |
| 46 | +Creating GPIO lookup tables |
| 47 | +--------------------------- |
| 48 | + |
| 49 | +Users can create a number of configfs groups under the device group: |
| 50 | + |
| 51 | +**Group:** ``/config/gpio-consumer/example-name/con_id`` |
| 52 | + |
| 53 | +The ``'con_id'`` directory represents a single GPIO lookup and its value maps |
| 54 | +to the ``'con_id'`` argument of the ``gpiod_get()`` function. For example: |
| 55 | +``con_id`` == ``'reset'`` maps to the ``reset-gpios`` device property. |
| 56 | + |
| 57 | +Users can assign a number of GPIOs to each lookup. Each GPIO is a sub-directory |
| 58 | +with a user-defined name under the ``'con_id'`` group. |
| 59 | + |
| 60 | +**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/key`` |
| 61 | + |
| 62 | +**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/offset`` |
| 63 | + |
| 64 | +**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/drive`` |
| 65 | + |
| 66 | +**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/pull`` |
| 67 | + |
| 68 | +**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/active_low`` |
| 69 | + |
| 70 | +**Attribute:** ``/config/gpio-consumer/example-name/con_id/0/transitory`` |
| 71 | + |
| 72 | +This is a group describing a single GPIO in the ``con_id-gpios`` property. |
| 73 | + |
| 74 | +For virtual consumers created using configfs we use machine lookup tables so |
| 75 | +this group can be considered as a mapping between the filesystem and the fields |
| 76 | +of a single entry in ``'struct gpiod_lookup'``. |
| 77 | + |
| 78 | +The ``'key'`` attribute represents either the name of the chip this GPIO |
| 79 | +belongs to or the GPIO line name. This depends on the value of the ``'offset'`` |
| 80 | +attribute: if its value is >= 0, then ``'key'`` represents the label of the |
| 81 | +chip to lookup while ``'offset'`` represents the offset of the line in that |
| 82 | +chip. If ``'offset'`` is < 0, then ``'key'`` represents the name of the line. |
| 83 | + |
| 84 | +The remaining attributes map to the ``'flags'`` field of the GPIO lookup |
| 85 | +struct. The first two take string values as arguments: |
| 86 | + |
| 87 | +**``'drive'``:** ``'push-pull'``, ``'open-drain'``, ``'open-source'`` |
| 88 | +**``'pull'``:** ``'pull-up'``, ``'pull-down'``, ``'pull-disabled'``, ``'as-is'`` |
| 89 | + |
| 90 | +``'active_low'`` and ``'transitory'`` are boolean attributes. |
| 91 | + |
| 92 | +Activating GPIO consumers |
| 93 | +------------------------- |
| 94 | + |
| 95 | +Once the confiuration is complete, the ``'live'`` attribute must be set to 1 in |
| 96 | +order to instantiate the consumer. It can be set back to 0 to destroy the |
| 97 | +virtual device. The module will synchronously wait for the new simulated device |
| 98 | +to be successfully probed and if this doesn't happen, writing to ``'live'`` will |
| 99 | +result in an error. |
| 100 | + |
| 101 | +Device-tree |
| 102 | +----------- |
| 103 | + |
| 104 | +Virtual GPIO consumers can also be defined in device-tree. The compatible string |
| 105 | +must be: ``"gpio-virtuser"`` with at least one property following the |
| 106 | +standardized GPIO pattern. |
| 107 | + |
| 108 | +An example device-tree code defining a virtual GPIO consumer: |
| 109 | + |
| 110 | +.. code-block :: none |
| 111 | +
|
| 112 | + gpio-virt-consumer { |
| 113 | + compatible = "gpio-virtuser"; |
| 114 | +
|
| 115 | + foo-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>, <&gpio1 2 0>; |
| 116 | + bar-gpios = <&gpio0 6 0>; |
| 117 | + }; |
| 118 | +
|
| 119 | +Controlling virtual GPIO consumers |
| 120 | +---------------------------------- |
| 121 | + |
| 122 | +Once active, the device will export debugfs attributes for controlling GPIO |
| 123 | +arrays as well as each requested GPIO line separately. Let's consider the |
| 124 | +following device property: ``foo-gpios = <&gpio0 0 0>, <&gpio0 4 0>;``. |
| 125 | + |
| 126 | +The following debugfs attribute groups will be created: |
| 127 | + |
| 128 | +**Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/`` |
| 129 | + |
| 130 | +This is the group that will contain the attributes for the entire GPIO array. |
| 131 | + |
| 132 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values`` |
| 133 | + |
| 134 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values_atomic`` |
| 135 | + |
| 136 | +Both attributes allow to read and set arrays of GPIO values. User must pass |
| 137 | +exactly the number of values that the array contains in the form of a string |
| 138 | +containing zeroes and ones representing inactive and active GPIO states |
| 139 | +respectively. In this example: ``echo 11 > values``. |
| 140 | + |
| 141 | +The ``values_atomic`` attribute works the same as ``values`` but the kernel |
| 142 | +will execute the GPIO driver callbacks in interrupt context. |
| 143 | + |
| 144 | +**Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/`` |
| 145 | + |
| 146 | +This is a group that represents a single GPIO with ``$index`` being its offset |
| 147 | +in the array. |
| 148 | + |
| 149 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/consumer`` |
| 150 | + |
| 151 | +Allows to set and read the consumer label of the GPIO line. |
| 152 | + |
| 153 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/debounce`` |
| 154 | + |
| 155 | +Allows to set and read the debounce period of the GPIO line. |
| 156 | + |
| 157 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction`` |
| 158 | + |
| 159 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction_atomic`` |
| 160 | + |
| 161 | +These two attributes allow to set the direction of the GPIO line. They accept |
| 162 | +"input" and "output" as values. The atomic variant executes the driver callback |
| 163 | +in interrupt context. |
| 164 | + |
| 165 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/interrupts`` |
| 166 | + |
| 167 | +If the line is requested in input mode, writing ``1`` to this attribute will |
| 168 | +make the module listen for edge interrupts on the GPIO. Writing ``0`` disables |
| 169 | +the monitoring. Reading this attribute returns the current number of registered |
| 170 | +interrupts (both edges). |
| 171 | + |
| 172 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value`` |
| 173 | + |
| 174 | +**Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value_atomic`` |
| 175 | + |
| 176 | +Both attributes allow to read and set values of individual requested GPIO lines. |
| 177 | +They accept the following values: ``1`` and ``0``. |
0 commit comments