Hello,
This patchset adds virtio specification for GPIO devices. It supports basic GPIO line operations, along with optional interrupts on them (in a separate patch).
This is an *alternative implementation* of the virtio-gpio specification, a different version of it was earlier posted by Enrico [1].
I took back V4 of the specification I posted earlier (on June 17th), to allow Enrico to come up with something that is robust and works for everyone (as he started this thing last year), but it didn't go as expected. I couldn't see any of my review comments being incorporated (or any intentions of them getting in ever) in the two versions Enrico posted and a month passed since then.
And so I am trying to present an alternative approach here to solve the problem, which I believe is more clear and robust. I am open to suggestions to improve it further.
I will let the virtio/gpio maintainers decide on its fate.
Key differences from Enrico's approach [1]:
- config structure is rearranged to remove everything apart from number of gpios and size of the gpio_names_field.
- Supports freeing of a GPIO line after use, we call them activate/deactivate now, which suits their purpose better.
- Interrupt implementation handled with feature bit 0. Either the interrupts are fully supported or not at all.
- All non-interrupt traffic happens on a single virtqueue, requestq. Interrupt traffic goes over eventq.
- Doesn't add any ordering restrictions on the device, it can respond earlier to the second request, while still processing the first one.
- Clearly state that two requests can't be initiated for the same line by device or driver.
Version history of the specification I sent:
V5 -> V6: - All non-interrupt traffic happens on a single virtqueue, requestq. Interrupt traffic goes over eventq now. - Many fields dropped from the config structure. - Separate message type to get gpio-names, added more description about how the names should be. - Much clearer message flows, both non-irq messages and irq-messages. - Parallelism supported for all type of messages, for different GPIO pins. - All references to POSIX errors dropped, just reply pass or fail. - request/free renamed to activate/deactivate, as that's what we will end up doing there, activate or deactivate a GPIO line. - General purpose IO as I/O or Input/Output instead. - Hopefully I didn't miss any review comments.
V4 -> V5: - Split into two patches, irq stuff in patch 2. - Use separate virtqueue for sending data from device/driver. - Allow parallel processing of requests for different GPIOs, only one request at a time for the same GPIO line. - Same goes for interrupt side, only one interrupt request per GPIO line. - Improved formatting in general. - Add new sections explaining message flow sequence.
V3 -> V4: - The GPIO line names must be unique within a device. - The gpio_names[0] field is dropped and gpio_names_offset field is added in place of the 2 bytes of padding. - New interrupts must not be initiated by the device, without a response for the previous one.
V2 -> V3: - Unused char in name string should be marked 0 now. - s/host/device/ and s/guest/driver/ - Added a new feature for IRQ mode, VIRTIO_GPIO_F_IRQ. - A new feature should be added for Version information if required later on.
V1 -> V2: - gpio_names_size is 32 bit. - gpio field is 16 bit. - padding added 16 bit. - Added packed attribute to few structures - Add the missing 'type' field to the request - Dropped to _nodata request/responses to simplify a bit, updated related text.
-- Viresh
[1] https://lists.oasis-open.org/archives/virtio-dev/202106/msg00030.html
Viresh Kumar (2): virtio-gpio: Add the device specification virtio-gpio: Add support for interrupts
conformance.tex | 30 ++- content.tex | 1 + virtio-gpio.tex | 608 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 635 insertions(+), 4 deletions(-) create mode 100644 virtio-gpio.tex
virtio-gpio is a virtual GPIO controller. It provides a way to flexibly communicate with the host GPIO controllers from the guest.
This patch adds the specification for it.
Based on the initial work posted by: "Enrico Weigelt, metux IT consult" lkml@metux.net.
Fixes: https://github.com/oasis-tcs/virtio-spec/issues/110 Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- conformance.tex | 28 +++- content.tex | 1 + virtio-gpio.tex | 369 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 394 insertions(+), 4 deletions(-) create mode 100644 virtio-gpio.tex
diff --git a/conformance.tex b/conformance.tex index 94d7a06db899..c52f1a40be2d 100644 --- a/conformance.tex +++ b/conformance.tex @@ -30,8 +30,9 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets} \ref{sec:Conformance / Driver Conformance / IOMMU Driver Conformance}, \ref{sec:Conformance / Driver Conformance / Sound Driver Conformance}, \ref{sec:Conformance / Driver Conformance / Memory Driver Conformance}, -\ref{sec:Conformance / Driver Conformance / I2C Adapter Driver Conformance} or -\ref{sec:Conformance / Driver Conformance / SCMI Driver Conformance}. +\ref{sec:Conformance / Driver Conformance / I2C Adapter Driver Conformance}, +\ref{sec:Conformance / Driver Conformance / SCMI Driver Conformance} or +\ref{sec:Conformance / Driver Conformance / GPIO Driver Conformance}.
\item Clause \ref{sec:Conformance / Legacy Interface: Transitional Device and Transitional Driver Conformance}. \end{itemize} @@ -54,8 +55,9 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets} \ref{sec:Conformance / Device Conformance / IOMMU Device Conformance}, \ref{sec:Conformance / Device Conformance / Sound Device Conformance}, \ref{sec:Conformance / Device Conformance / Memory Device Conformance}, -\ref{sec:Conformance / Device Conformance / I2C Adapter Device Conformance} or -\ref{sec:Conformance / Device Conformance / SCMI Device Conformance}. +\ref{sec:Conformance / Device Conformance / I2C Adapter Device Conformance}, +\ref{sec:Conformance / Device Conformance / SCMI Device Conformance} or +\ref{sec:Conformance / Device Conformance / GPIO Device Conformance}.
\item Clause \ref{sec:Conformance / Legacy Interface: Transitional Device and Transitional Driver Conformance}. \end{itemize} @@ -301,6 +303,15 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets} \item \ref{drivernormative:Device Types / SCMI Device / Device Operation / Setting Up eventq Buffers} \end{itemize}
+\conformance{\subsection}{GPIO Driver Conformance}\label{sec:Conformance / Driver Conformance / GPIO Driver Conformance} + +A General Purpose Input/Output (GPIO) driver MUST conform to the following +normative statements: + +\begin{itemize} +\item \ref{drivernormative:Device Types / GPIO Device / requestq Operation} +\end{itemize} + \conformance{\section}{Device Conformance}\label{sec:Conformance / Device Conformance}
A device MUST conform to the following normative statements: @@ -550,6 +561,15 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets} \item \ref{devicenormative:Device Types / SCMI Device / Device Operation / Shared Memory Operation} \end{itemize}
+\conformance{\subsection}{GPIO Device Conformance}\label{sec:Conformance / Device Conformance / GPIO Device Conformance} + +A General Purpose Input/Output (GPIO) device MUST conform to the following +normative statements: + +\begin{itemize} +\item \ref{devicenormative:Device Types / GPIO Device / requestq Operation} +\end{itemize} + \conformance{\section}{Legacy Interface: Transitional Device and Transitional Driver Conformance}\label{sec:Conformance / Legacy Interface: Transitional Device and Transitional Driver Conformance} A conformant implementation MUST be either transitional or non-transitional, see \ref{intro:Legacy diff --git a/content.tex b/content.tex index 5c70a3c415a3..511f2071959d 100644 --- a/content.tex +++ b/content.tex @@ -6583,6 +6583,7 @@ \subsubsection{Legacy Interface: Framing Requirements}\label{sec:Device \input{virtio-mem.tex} \input{virtio-i2c.tex} \input{virtio-scmi.tex} +\input{virtio-gpio.tex}
\chapter{Reserved Feature Bits}\label{sec:Reserved Feature Bits}
diff --git a/virtio-gpio.tex b/virtio-gpio.tex new file mode 100644 index 000000000000..fa48780a29db --- /dev/null +++ b/virtio-gpio.tex @@ -0,0 +1,369 @@ +\section{GPIO Device}\label{sec:Device Types / GPIO Device} + +The Virtio GPIO device is a virtual General Purpose Input/Output device that +supports a variable number of named I/O lines, which can be configured in input +mode or in output mode with logical level low (0) or high (1). + +\subsection{Device ID}\label{sec:Device Types / GPIO Device / Device ID} +41 + +\subsection{Virtqueues}\label{sec:Device Types / GPIO Device / Virtqueues} + +\begin{description} +\item[0] requestq +\end{description} + +\subsection{Feature bits}\label{sec:Device Types / GPIO Device / Feature bits} + +None currently defined. + +\subsection{Device configuration layout}\label{sec:Device Types / GPIO Device / Device configuration layout} + +GPIO device uses the following configuration structure layout: + +\begin{lstlisting} +struct virtio_gpio_config { + le16 ngpio; + u8 padding[2]; + le32 gpio_names_size; +}; +\end{lstlisting} + +\begin{description} +\item[\field{ngpio}] is the total number of GPIO lines supported by the device. + +\item[\field{padding}] has no meaning and is reserved for future use. This + MUST be set to zero by the device. + +\item[\field{gpio_names_size}] is the size of the gpio-names memory block in + bytes, which can be fetched by the driver using the + \field{VIRTIO_GPIO_MSG_GET_NAMES} message. The device MUST set this to 0 if + it doesn't support names for the GPIO lines. +\end{description} + + +\subsection{Device Initialization}\label{sec:Device Types / GPIO Device / Device Initialization} + +\begin{itemize} +\item The driver MUST configure and initialize the \field{requestq} virtqueue. +\end{itemize} + +\subsection{Device Operation: requestq}\label{sec:Device Types / GPIO Device / requestq Operation} + +The driver uses the \field{requestq} virtqueue to send messages to the device. +The driver sends a pair of buffers, request (filled by driver) and response (to +be filled by device later), to the device. The device in turn fills the response +buffer and sends it back to the driver. + +\begin{lstlisting} +struct virtio_gpio_request { + le16 type; + le16 gpio; + le32 value; +}; +\end{lstlisting} + +All the fields of this structure are set by the driver and read by the device. + +\begin{description} +\item[\field{type}] is the GPIO message type, i.e. one of + \field{VIRTIO_GPIO_MSG_*} values. + +\item[\field{gpio}] is the GPIO line number, i.e. 0 <= \field{gpio} < + \field{ngpio}. + +\item[\field{value}] is a message specific value. +\end{description} + +\begin{lstlisting} +struct virtio_gpio_response { + u8 status; + u8 value[N]; +}; + +/* Possible values of the status field */ +#define VIRTIO_GPIO_STATUS_OK 0x0 +#define VIRTIO_GPIO_STATUS_ERR 0x1 +\end{lstlisting} + +All the fields of this structure are set by the device and read by the driver. + +\begin{description} +\item[\field{status}] of the GPIO message, + \field{VIRTIO_GPIO_STATUS_OK} on success and \field{VIRTIO_GPIO_STATUS_ERR} + on failure. + +\item[\field{value}] is a message specific defined value. The value of N (i.e. + size of the \field{value} buffer in bytes) is 1 for most of the messages, + except \field{VIRTIO_GPIO_MSG_GET_NAMES}, where it is set to the value of + \field{gpio_names_size} field. +\end{description} + +Following is the list of messages supported by the virtio gpio specification. + +\begin{lstlisting} +/* GPIO message types */ +#define VIRTIO_GPIO_MSG_GET_NAMES 0x0001 +#define VIRTIO_GPIO_MSG_ACTIVATE 0x0002 +#define VIRTIO_GPIO_MSG_DEACTIVATE 0x0003 +#define VIRTIO_GPIO_MSG_GET_DIRECTION 0x0004 +#define VIRTIO_GPIO_MSG_SET_DIRECTION_IN 0x0005 +#define VIRTIO_GPIO_MSG_SET_DIRECTION_OUT 0x0006 +#define VIRTIO_GPIO_MSG_GET_VALUE 0x0007 +#define VIRTIO_GPIO_MSG_SET_VALUE 0x0008 +\end{lstlisting} + +\subsubsection{requestq Operation: Get Names}\label{sec:Device Types / GPIO Device / requestq Operation / Get Names} + +The driver sends this message to receive a stream of zero-terminated strings, +where each string represents the name of a GPIO line, present in increasing +order of the GPIO line numbers. The GPIO line names must be unique within a GPIO +Device and must not be an empty string. + +These names of the GPIO lines should be most meaningful producer names for the +system, such as name indicating the usage. For example "MMC-CD", "Red LED Vdd" +and "ethernet reset" are reasonable line names as they describe what the line is +used for, while "GPIO0" is not a good name to give to a GPIO line. + +The device MUST set the \field{gpio_names_size} to a non-zero value if this +message is supported by the device, else it must be set to zero. + +The driver must allocate the \field{value[N]} buffer in the \field{struct +virtio_gpio_response} for N bytes, where N = \field{gpio_names_size}. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_GET_NAMES} & 0 & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & gpio-names & \field{gpio_names_size} \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Activate}\label{sec:Device Types / GPIO Device / requestq Operation / Activate} + +The driver sends this message to notify the device that one of its lines has +been assigned for use. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_ACTIVATE} & line number & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Deactivate}\label{sec:Device Types / GPIO Device / requestq Operation / Deactivate} + +The driver sends this message to notify the device that a previously requested +line has been unassigned and can be deactivated. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_DEACTIVATE} & line number & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Get Direction}\label{sec:Device Types / GPIO Device / requestq Operation / Get Direction} + +The driver sends this message to request the device to return a line's +configured direction. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_GET_DIRECTION} & line number & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 = output, 1 = input & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Set Direction In}\label{sec:Device Types / GPIO Device / requestq Operation / Set Direction In} + +The driver sends this message to request the device to configure a line for +input. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_SET_DIRECTION_IN} & line number & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Set Direction Out}\label{sec:Device Types / GPIO Device / requestq Operation / Set Direction Out} + +The driver sends this message to request the device to configure a line for +output, and set its initial output value. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_SET_DIRECTION_OUT} & line number & 0 = low, 1 = high \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Get Value}\label{sec:Device Types / GPIO Device / requestq Operation / Get Value} + +The driver sends this message to request the device to return current value +sensed on a line configured for input. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_GET_VALUE} & line number & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 = low, 1 = high & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Set Value}\label{sec:Device Types / GPIO Device / requestq Operation / Set Value} + +The driver sends this message to request the device to set the value of a line +configured for output. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_SET_VALUE} & line number & 0 = low, 1 = high \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO Device / requestq Operation / Message Flow} + +\begin{itemize} +\item The driver queues \field{struct virtio_gpio_request} and + \field{virtio_gpio_response} buffers to the \field{requestq} virtqueue, + after filling all fields of the \field{struct virtio_gpio_request} buffer as + defined by the specific message type. + +\item The driver notifies the device of the presence of buffers on the + \field{requestq} virtqueue. + +\item The device, after receiving the message from the driver, processes it and + fills all the fields of the \field{struct virtio_gpio_response} buffer + (received from the driver). The \field{status} must be set to + \field{VIRTIO_GPIO_STATUS_OK} on success and \field{VIRTIO_GPIO_STATUS_ERR} + on failure. + +\item The device puts the buffers back on the \field{requestq} virtqueue and + notifies the driver of the same. + +\item The driver fetches the buffers and processes the response received in the + \field{virtio_gpio_response} buffer. + +\item The driver can now send another message for the same GPIO line. +\end{itemize} + +\drivernormative{\subsubsection}{requestq Operation}{Device Types / GPIO Device / requestq Operation} + +\begin{itemize} +\item The driver MUST send messages on the \field{requestq} virtqueue. + +\item The driver MUST queue both \field{struct virtio_gpio_request} and + \field{virtio_gpio_response} for every message sent to the device. + +\item The \field{struct virtio_gpio_request} buffer MUST be filled by the driver + and MUST be read-only for the device. + +\item The \field{struct virtio_gpio_response} buffer MUST be filled by the + device and MUST be writable by the device. + +\item The driver MUST NOT set value of a GPIO line configured for input. + +\item The driver MUST NOT get value of a GPIO line configured for output. + +\item The driver MAY send messages for different GPIO lines in parallel. + +\item The driver MUST NOT send another message, of any type, for a GPIO line + before receiving a response from the device for the previously sent message + for the same GPIO line. +\end{itemize} + +\devicenormative{\subsubsection}{requestq Operation}{Device Types / GPIO Device / requestq Operation} + +\begin{itemize} +\item The device MUST set all the fields of the \field{struct + virtio_gpio_response} before sending it back to the driver. + +\item The device MUST set all the fields of the \field{struct + virtio_gpio_config} on receiving a configuration request from the driver. + +\item The device MUST set the \field{gpio_names_size} field as zero in the + \field{struct virtio_gpio_config}, if it doesn't implement names for + individual GPIO lines. + +\item The device MUST set the \field{gpio_names_size} field, in the + \field{struct virtio_gpio_config}, with the size of gpio-names memory block + in bytes, if the device implements names for individual GPIO lines. The + strings MUST be zero-terminated and an unique and a valid string MUST be + added for each supported GPIO line. + +\item The device MAY process messages out of order and in parallel and MAY send + message's response to the driver out of order. +\end{itemize}
This patch adds support for interrupts to the virtio-gpio specification. This uses the feature bit 0 for the same.
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- conformance.tex | 2 + virtio-gpio.tex | 241 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 242 insertions(+), 1 deletion(-)
diff --git a/conformance.tex b/conformance.tex index c52f1a40be2d..64bcc12d1199 100644 --- a/conformance.tex +++ b/conformance.tex @@ -310,6 +310,7 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets}
\begin{itemize} \item \ref{drivernormative:Device Types / GPIO Device / requestq Operation} +\item \ref{drivernormative:Device Types / GPIO Device / eventq Operation} \end{itemize}
\conformance{\section}{Device Conformance}\label{sec:Conformance / Device Conformance} @@ -568,6 +569,7 @@ \section{Conformance Targets}\label{sec:Conformance / Conformance Targets}
\begin{itemize} \item \ref{devicenormative:Device Types / GPIO Device / requestq Operation} +\item \ref{devicenormative:Device Types / GPIO Device / eventq Operation} \end{itemize}
\conformance{\section}{Legacy Interface: Transitional Device and Transitional Driver Conformance}\label{sec:Conformance / Legacy Interface: Transitional Device and Transitional Driver Conformance} diff --git a/virtio-gpio.tex b/virtio-gpio.tex index fa48780a29db..f432a3f3ad0d 100644 --- a/virtio-gpio.tex +++ b/virtio-gpio.tex @@ -11,11 +11,17 @@ \subsection{Virtqueues}\label{sec:Device Types / GPIO Device / Virtqueues}
\begin{description} \item[0] requestq +\item[1] eventq \end{description}
+The \field{eventq} virtqueue is available only if the \field{VIRTIO_GPIO_F_IRQ} +feature is enabled by the device. + \subsection{Feature bits}\label{sec:Device Types / GPIO Device / Feature bits}
-None currently defined. +\begin{description} +\item[VIRTIO_GPIO_F_IRQ (0)] The device supports interrupts on GPIO lines. +\end{description}
\subsection{Device configuration layout}\label{sec:Device Types / GPIO Device / Device configuration layout}
@@ -46,6 +52,15 @@ \subsection{Device Initialization}\label{sec:Device Types / GPIO Device / Device
\begin{itemize} \item The driver MUST configure and initialize the \field{requestq} virtqueue. + +\item The driver MUST check the presence of \field{VIRTIO_GPIO_F_IRQ} feature + before initiating any IRQ messages. + +\item The driver MUST configure and initialize the \field{eventq} virtqueue if + the \field{VIRTIO_GPIO_F_IRQ} feature is enabled by the device. + +\item The device MUST have interrupts on all the GPIO lines masked, if the + \field{VIRTIO_GPIO_F_IRQ} feature is supported. \end{itemize}
\subsection{Device Operation: requestq}\label{sec:Device Types / GPIO Device / requestq Operation} @@ -111,6 +126,19 @@ \subsection{Device Operation: requestq}\label{sec:Device Types / GPIO Device / r #define VIRTIO_GPIO_MSG_SET_DIRECTION_OUT 0x0006 #define VIRTIO_GPIO_MSG_GET_VALUE 0x0007 #define VIRTIO_GPIO_MSG_SET_VALUE 0x0008 +#define VIRTIO_GPIO_MSG_IRQ_TYPE 0x0009 +#define VIRTIO_GPIO_MSG_IRQ_MASK 0x000a +#define VIRTIO_GPIO_MSG_IRQ_UNMASK 0x000b +\end{lstlisting} + +\begin{lstlisting} +/* GPIO interrupt types */ +#define VIRTIO_GPIO_IRQ_TYPE_NONE 0x00 +#define VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING 0x01 +#define VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING 0x02 +#define VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH 0x03 +#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04 +#define VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW 0x08 \end{lstlisting}
\subsubsection{requestq Operation: Get Names}\label{sec:Device Types / GPIO Device / requestq Operation / Get Names} @@ -294,6 +322,79 @@ \subsubsection{requestq Operation: Set Value}\label{sec:Device Types / GPIO Devi \hline \end{tabularx}
+\subsubsection{requestq Operation: IRQ Type}\label{sec:Device Types / GPIO Device / requestq Operation / IRQ Type} + +The driver initiates this message to request the device to set the IRQ trigger +type, to one of the \field{VIRTIO_GPIO_IRQ_TYPE_*} values, for a line configured +for input. + +This request is only allowed if the \field{VIRTIO_GPIO_F_IRQ} feature is +enabled by the device. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_IRQ_TYPE} & line number & one of \field{VIRTIO_GPIO_IRQ_TYPE_*} \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: IRQ Mask}\label{sec:Device Types / GPIO Device / requestq Operation / IRQ Mask} + +The driver initiates this message to request the device to mask IRQ on a GPIO +line configured for input. + +This request is only allowed if the \field{VIRTIO_GPIO_F_IRQ} feature is +enabled by the device. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_IRQ_MASK} & line number & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + +\subsubsection{requestq Operation: IRQ Unmask}\label{sec:Device Types / GPIO Device / requestq Operation / IRQ Unmask} + +The driver initiates this message to request the device to unmask IRQ on a GPIO +line configured for input. + +This request is only allowed if the \field{VIRTIO_GPIO_F_IRQ} feature is +enabled by the device. + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Request} & \field{type} & \field{gpio} & \field{value} \ +\hline +& \field{VIRTIO_GPIO_MSG_IRQ_UNMASK} & line number & 0 \ +\hline +\end{tabularx} + +\begin{tabularx}{\textwidth}{ |l||X|X|X| } +\hline +\textbf{Response} & \field{status} & \field{value[N]} & \field{Where N is} \ +\hline +& \field{VIRTIO_GPIO_STATUS_*} & 0 & 1 \ +\hline +\end{tabularx} + \subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO Device / requestq Operation / Message Flow}
\begin{itemize} @@ -343,6 +444,17 @@ \subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO D \item The driver MUST NOT send another message, of any type, for a GPIO line before receiving a response from the device for the previously sent message for the same GPIO line. + +\item The driver MUST NOT send IRQ messages for a GPIO line configured for + output. + +\item The driver MUST NOT initiate IRQ messages if the \field{VIRTIO_GPIO_F_IRQ} + feature is not enabled by the device. + +\item If the driver has sent the \field{VIRTIO_GPIO_MSG_IRQ_UNMASK} message + earlier for a GPIO line, then it MUST send the + \field{VIRTIO_GPIO_MSG_IRQ_MASK} message over the \field{requestq} + virtqueue, if it no longer wants to receive interrupts from the device. \end{itemize}
\devicenormative{\subsubsection}{requestq Operation}{Device Types / GPIO Device / requestq Operation} @@ -367,3 +479,130 @@ \subsubsection{requestq Operation: Message Flow}\label{sec:Device Types / GPIO D \item The device MAY process messages out of order and in parallel and MAY send message's response to the driver out of order. \end{itemize} + +\subsection{Device Operation: eventq}\label{sec:Device Types / GPIO Device / eventq Operation} + +The \field{eventq} virtqueue is used for sending interrupt events from the +device to the driver. The driver queues a separate pair of buffers, +interrupt-request (filled by driver) and interrupt-response (to be filled by +device later), to the \field{eventq} virtqueue for each GPIO line. The device, +on sensing an interrupt, returns the pair of buffers of the respective GPIO line +for which the interrupt is sensed. + +\begin{lstlisting} +struct virtio_gpio_irq_request { + le16 gpio; +}; +\end{lstlisting} + +This structure is filled by the driver and read by the device. + +\begin{description} +\item[\field{gpio}] is the GPIO line number, i.e. 0 <= \field{gpio} < + \field{ngpio}. +\end{description} + +\begin{lstlisting} +struct virtio_gpio_irq_response { + u8 status; +}; + +/* Possible values of the interrupt status field */ +#define VIRTIO_GPIO_IRQ_INVALID 0x0 +#define VIRTIO_GPIO_IRQ_VALID 0x1 +\end{lstlisting} + +This structure is filled by the device and read by the driver. + +\begin{description} +\item[\field{status}] of the interrupt event, \field{VIRTIO_GPIO_IRQ_VALID} on + valid interrupt and \field{VIRTIO_GPIO_IRQ_INVALID} otherwise on returning + the buffer back to the driver without an interrupt. +\end{description} + +\subsubsection{eventq Operation: Message Flow}\label{sec:Device Types / GPIO Device / eventq Operation / Message Flow} + +\begin{itemize} +\item The driver is requested by a user to enable interrupt for a GPIO and + configure it to a particular type. + +\item The driver sends the \field{VIRTIO_GPIO_MSG_IRQ_TYPE} message over the + \field{requestq} virtqueue and the device configures the GPIO line for the + same and responds. + +\item The driver queues a pair of buffers, interrupt-request and + interrupt-response, to the \field{eventq} virtqueue for the GPIO line. + +\item The driver notifies the device of the presence of new buffers on the + \field{eventq} virtqueue. + +\item The driver sends the \field{VIRTIO_GPIO_MSG_IRQ_UNMASK} message over the + \field{requestq} virtqueue and the device configures the GPIO line for the + same and responds. + +\item The interrupt is fully configured at this point. + +\item The device, on sensing an interrupt on a GPIO line, finds the matching + buffers (based on GPIO line number) from the \field{eventq} virtqueue and + fills its \field{struct virtio_gpio_irq_response} buffer's \field{status} + with \field{VIRTIO_GPIO_IRQ_VALID} and returns the pair of buffers to the + device. + +\item The device notifies the driver of the presence of new buffers on the + \field{eventq} virtqueue. + +\item If the GPIO line is configured for Level interrupts, the device MUST + ignore any further interrupts for the line, until the time the buffers are + made available again by the driver. + +\item If the GPIO line is configured for Edge interrupts, the device MUST latch + the latest interrupt received for the line, until the time the buffers are + made available again by the driver. At that point, the device can again + return the buffers for the line if an interrupt was received while the + device was waiting for the buffers to be made available by the driver. + +\item The driver on receiving the notification from the device, processes the + interrupt. The driver may try to mask/unmask the interrupts for the GPIO + line over the \field{requestq} virtqueue. + +\item The driver may again queue, same or new, pair of buffers for that GPIO + line and notify the device. + +\item The driver may send the \field{VIRTIO_GPIO_MSG_IRQ_MASK} message over the + \field{requestq} virtqueue, once it no longer wants to receive the + interrupts for a GPIO line. + +\item The device must return the unused pair of buffers for that GPIO line, over + the \field{eventq} virtqueue, by setting the \field{status} field with + \field{VIRTIO_GPIO_IRQ_INVALID}. + +\item The driver can then free the associated buffer and remove it from the + \field{eventq} virtqueue. +\end{itemize} + +\drivernormative{\subsubsection}{eventq Operation}{Device Types / GPIO Device / eventq Operation} + +\begin{itemize} +\item The driver MUST queue a separate pair of buffers, interrupt-request and + interrupt-response, to the \field{eventq} virtqueue for each GPIO line for + which it is expecting an interrupt from the device. + +\item The driver MUST not queue a pair of buffers for a GPIO line which it is + not going to use as interrupt source, otherwise the buffer may never be + freed by the device (as no unmask request will follow from the driver). + +\item The driver MUST NOT add multiple pairs of buffers for the same GPIO line + on the \field{eventq} virtqueue. And so there can only be one interrupt + event for each GPIO line at any point of time. + +\item The pair of buffers for any GPIO line can either be owned by the device or + the driver at any particular point of time, but not both. +\end{itemize} + +\devicenormative{\subsubsection}{eventq Operation}{Device Types / GPIO Device / eventq Operation} + +\begin{itemize} +\item The device can send an interrupt event for a GPIO line to the driver, only + if a buffer for that GPIO line is provided by the driver in the first place + on the \field{eventq} virtqueue. +\end{itemize}
stratos-dev@op-lists.linaro.org