Skip to content
Permalink
Browse files
drivers: gpio: add virtio-gpio guest driver
Introduce new GPIO driver for virtual GPIO devices via virtio.

The driver implements the virtio-gpio protocol (ID 41), which can be
used by either VM guests (e.g. bridging virtual gpios from the guest
to real gpios in the host or attaching simulators for automatic
application testing), as well as virtio-gpio hardware devices.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
  • Loading branch information
metux authored and intel-lab-lkp committed Jun 16, 2021
1 parent 6b00bc6 commit 8df8c3f8af32ee316ad10d20fc9d75f6e5afae9c
Show file tree
Hide file tree
Showing 7 changed files with 633 additions and 0 deletions.
@@ -0,0 +1,195 @@
===================
Virtio-GPIO protocol specification
===================
...........
Specification for virtio-based GPIO devices
...........

+------------
+Version_ 1.0
+------------

General
===================

The virtio-gpio protocol provides access to general purpose IO devices via
virtio interfaces, used by many virtual machine monitors as well as hardware
fabrics. In VM setups, these GPIOs could be either provided by some simulator
(e.g. virtual HIL), routed to some external device or routed to real GPIOs on
the host (e.g. virtualized embedded applications).

Instead of simulating some existing real GPIO chip within an VMM, this
protocol provides a hardware independent interface between CPU and device
that solely relies on an active virtio connection (no matter which transport
actually used), no other buses or additional platform driver logic required.

At the same time, this protocol be implemented directly in virtio attached
hardware, FPGAs or tiny MCUs.

Protocol layout
===================

Configuration space
----------------------

+--------+----------+-------------------------------+
| Offset | Type | Description |
+========+==========+===============================+
| 0x00 | u8 | version |
+--------+----------+-------------------------------+
| 0x02 | u16 | number of GPIO lines |
+--------+----------+-------------------------------+
| 0x04 | u32 | size of gpio name block |
+--------+----------+-------------------------------+
| 0x20 | char[32] | device name (0-terminated) |
+--------+----------+-------------------------------+
| 0x40 | char[] | line names block |
+--------+----------+-------------------------------+

- for version field currently only value 1 supported.
- the line names block holds a stream of zero-terminated strings,
containing the individual line names in ASCII. line names must unique.
- unspecified fields are reserved for future use and should be zero.

Virtqueues and messages:
------------------------

- Queue #0: transmission from device to CPU
- Queue #1: transmission from CPU to device

The queues transport messages of the struct virtio_gpio_msg:

Message format:
~~~~~~~~~~~~~~~

+--------+----------+---------------+
| Offset | Type | Description |
+========+==========+===============+
| 0x00 | uint16 | message type |
+--------+----------+---------------+
| 0x02 | uint16 | line id |
+--------+----------+---------------+
| 0x04 | uint32 | value |
+--------+----------+---------------+

Message types:
~~~~~~~~~~~~~~

+---------+----------------------------------------+-----------------------------+
| Code | Symbol | |
+=========+========================================+=============================+
| 0x0001 | VIRTIO_GPIO_MSG_CPU_REQUEST | request gpio line |
+---------+----------------------------------------+-----------------------------+
| 0x0002 | VIRTIO_GPIO_MSG_CPU_DIRECTION_INPUT | set direction to input |
+---------+----------------------------------------+-----------------------------+
| 0x0003 | VIRTIO_GPIO_MSG_CPU_DIRECTION_OUTPUT | set direction to output |
+---------+----------------------------------------+-----------------------------+
| 0x0004 | VIRTIO_GPIO_MSG_CPU_GET_DIRECTION | read current direction |
+---------+----------------------------------------+-----------------------------+
| 0x0005 | VIRTIO_GPIO_MSG_CPU_GET_LEVEL | read current level |
+---------+----------------------------------------+-----------------------------+
| 0x0006 | VIRTIO_GPIO_MSG_CPU_SET_LEVEL | set current (out) level |
+---------+----------------------------------------+-----------------------------+
| 0x0011 | VIRTIO_GPIO_MSG_DEVICE_LEVEL | state changed (device->CPU) |
+---------+----------------------------------------+-----------------------------+
| 0x8000 | VIRTIO_GPIO_MSG_REPLY | device reply mask |
+---------+----------------------------------------+-----------------------------+

Data flow:
----------------------

- all operations, except ``VIRTIO_GPIO_MSG_DEVICE_LEVEL``, are initiated by CPU
- device replies with the orinal ``type`` value OR'ed with ``VIRTIO_GPIO_MSG_REPLY``
- ``VIRTIO_GPIO_MSG_DEVICE_LEVEL`` is only sent asynchronously from device to CPU
- in replies, a negative ``value`` field denotes an Unix-style / POSIX errno code
- valid direction values are:
* 0 = output
* 1 = input
- valid line state values are:
* 0 = inactive
* 1 = active

VIRTIO_GPIO_MSG_CPU_REQUEST
~~~~~~~~~~~~~~~~~~~~~~~~~~~

- notify the device that given line# is going to be used
- request:
* ``line`` field: line number
* ``value`` field: unused
- reply:
* ``value`` field: errno code (0 = success)

VIRTIO_GPIO_MSG_CPU_DIRECTION_INPUT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- set line line direction to input
- request:
* ``line`` field: line number
* ``value`` field: unused
- reply: value field holds errno
* ``value`` field: errno code (0 = success)

VIRTIO_GPIO_MSG_CPU_DIRECTION_OUTPUT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- set line direction to output and given line state
- request:
* ``line`` field: line number
* ``value`` field: output state (0=inactive, 1=active)
- reply:
* ``value`` field: holds errno

VIRTIO_GPIO_MSG_CPU_GET_DIRECTION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- retrieve line direction
- request:
* ``line`` field: line number
* ``value`` field: unused
- reply:
* ``value`` field: direction (0=output, 1=input) or errno code

VIRTIO_GPIO_MSG_CPU_GET_LEVEL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- retrieve line state value
- request:
* ``line`` field: line number
* ``value`` field: unused
- reply:
* ``value`` field: line state (0=inactive, 1=active) or errno code

VIRTIO_GPIO_MSG_CPU_SET_LEVEL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- set line state value (output only)
- request:
* ``line`` field: line number
* ``value`` field: line state (0=inactive, 1=active)
- reply:
* ``value`` field: new line state or errno code

VIRTIO_GPIO_MSG_DEVICE_LEVEL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- async notification from device to CPU: line state changed
- ``line`` field: line number
- ``value`` field: new line state (0=inactive, 1=active)

Request concurrency
===================

- CPU may send multiple request in serial, as long as the virtio queue
is not exceeded
- device replies must be sent in the same order than the CPU requests
- CPU should process asynchronous messages from device as soon as possible,
in order to avoid missing messages due to queue overrun

Future versions
===================

- future versions must increment the ``version`` value
- the basic data structures (config space, message format) should remain
backwards compatible, but may increased in size or use reserved fields
- device needs to support commands in older versions
- CPU should not send commands of newer versions that the device doesn't support
@@ -19397,6 +19397,12 @@ F: Documentation/filesystems/virtiofs.rst
F: fs/fuse/virtio_fs.c
F: include/uapi/linux/virtio_fs.h

VIRTIO GPIO DRIVER
M: Enrico Weigelt, metux IT consult <info@metux.net>
S: Maintained
F: drivers/gpio/gpio-virtio.c
F: include/uapi/linux/virtio_gpio.h

VIRTIO GPU DRIVER
M: David Airlie <airlied@linux.ie>
M: Gerd Hoffmann <kraxel@redhat.com>
@@ -1655,6 +1655,13 @@ config GPIO_MOCKUP
tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
it.

config GPIO_VIRTIO
tristate "VirtIO GPIO support"
select VIRTIO
select GPIOLIB_IRQCHIP
help
Say Y here to enable guest support for virtio-based GPIOs.

endmenu

endif
@@ -162,6 +162,7 @@ obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o
obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o

0 comments on commit 8df8c3f

Please sign in to comment.