virtio: Add a virtio RTC driver
v6 cover virtio: Add a virtio RTC driver
QEMU v11.1.0 added a virtio RTC device (virtio-rtc-pci and virtio-rtc-device), but U-Boot has no driver for it. This series adds one, so that "date" and anything else using dm_rtc_get() work on any virtio-capable QEMU target.
Patch 1 adds the driver, patch 2 updates the virtio documentation and patch 3 adds a MAINTAINERS entry. Patch 4 lets sandbox tests answer virtqueue requests as the device would, which patch 5 uses to test the driver. Patch 6 documents how to reach the virtio RTC.
Changes in v6:
- Add patch 6, the documentation follow-up Simon suggested on v5, which I first sent on its own. Following Simon's review of it, the virtio RTC now has its own section, which also takes the QEMU version note from patch 2, and x86 is described like ARM and RISC-V: with DM_RTC enabled, the MC146818 CMOS RTC gets sequence 0. The Status section already lists the RTC since patch 2.
- Rebase onto main. Patches 1-5 are otherwise unchanged.
Tested with qemu-riscv64_smode_defconfig and RTC_GOLDFISH disabled, on QEMU v11.1.2, which reports a UTC clock, and on QEMU master, which reports a smeared UTC clock:
- With -device virtio-rtc-pci and with -device virtio-rtc-device, "date" reads the host time and advances between reads.
- Setting the time fails, as the clocks are read-only.
- With no virtio RTC device, "date" fails cleanly with err=-19.
With qemu-x86_64_defconfig plus DM_RTC on QEMU v11.1.2, "dm uclass rtc" shows the CMOS RTC at sequence 0 and the virtio RTC at 1; with RTC_MC146818 disabled, the virtio RTC is sequence 0 and "date" reads it.
On sandbox, "ut dm virtio_rtc*" passes.
Hung-Chun Tseng (6):
virtio: rtc: Add virtio RTC driver
doc: virtio: List the supported device types
MAINTAINERS: Add entry for virtio RTC
virtio: sandbox: Let tests emulate the device side of a virtqueue
test: dm: Add tests for the virtio RTC driver
doc: virtio: Explain how to reach the virtio RTC
MAINTAINERS | 6 + arch/sandbox/dts/test.dts | 5 + arch/sandbox/include/asm/test.h | 25 +++ doc/develop/driver-model/virtio.rst | 26 ++- drivers/virtio/Kconfig | 11 + drivers/virtio/Makefile | 1 + drivers/virtio/virtio-uclass.c | 1 + drivers/virtio/virtio_rtc.c | 244 ++++++++++++++++++++++ drivers/virtio/virtio_sandbox.c | 15 ++ include/virtio.h | 4 +- test/dm/Makefile | 1 + test/dm/virtio_rtc.c | 306 ++++++++++++++++++++++++++++ 12 files changed, 640 insertions(+), 5 deletions(-) create mode 100644 drivers/virtio/virtio_rtc.c create mode 100644 test/dm/virtio_rtc.c
Signature · 1 line
2.43.0
PATCH v6 1/6 virtio: rtc: Add virtio RTC driver
QEMU provides a virtio RTC device (virtio-rtc-pci, virtio-rtc-device) since v11.1.0, but U-Boot has no driver for it.
The virtqueue must not be used before the virtio uclass sets DRIVER_OK, which happens after probe(), so the clock is looked up on the first read.
Like Linux, the driver prefers a VIRTIO_RTC_CLOCK_UTC_SMEARED clock, as it never steps on leap seconds. QEMU master reports such a clock since "virtio-rtc: Report smeared UTC clock type", but v11.1 reports VIRTIO_RTC_CLOCK_UTC, so the driver falls back to another UTC clock rather than leave U-Boot without an RTC there.
The set of clocks never changes, so if none of them is UTC, the driver remembers it and fails later reads at once.
--- drivers/virtio/Kconfig | 11 ++ drivers/virtio/Makefile | 1 + drivers/virtio/virtio-uclass.c | 1 + drivers/virtio/virtio_rtc.c | 244 +++++++++++++++++++++++++++++++++ include/virtio.h | 4 +- 5 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 drivers/virtio/virtio_rtc.c
drivers/virtio/Kconfig +11 -0
@@ -84,4 +84,15 @@ config VIRTIO_9P help This enables the 9P transport driver over virtio. It can be used with QEMU based targets. + +config VIRTIO_RTC + bool "virtio RTC driver" + depends on DM_RTC + depends on VIRTIO + default y + help + This enables the virtio RTC driver, which reads the UTC clock + exposed by a virtio RTC device. QEMU v11.1.0 or later provides + it as virtio-rtc-pci and virtio-rtc-device. The clocks are + read-only, so the time cannot be set. endmenu
drivers/virtio/Makefile +1 -0
@@ -12,3 +12,4 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o obj-$(CONFIG_VIRTIO_RNG) += virtio_rng.o obj-$(CONFIG_VIRTIO_9P) += virtio_9p.o +obj-$(CONFIG_VIRTIO_RTC) += virtio_rtc.o
drivers/virtio/virtio-uclass.c +1 -0
@@ -32,6 +32,7 @@ static const char *const virtio_drv_name[VIRTIO_ID_MAX_NUM] = { [VIRTIO_ID_BLOCK] = VIRTIO_BLK_DRV_NAME, [VIRTIO_ID_RNG] = VIRTIO_RNG_DRV_NAME, [VIRTIO_ID_9P] = VIRTIO_9P_DRV_NAME, + [VIRTIO_ID_CLOCK] = VIRTIO_RTC_DRV_NAME, }; int virtio_get_config(struct udevice *vdev, unsigned int offset,
drivers/virtio/virtio_rtc.c new file +244 -0
244 lines not on this page · raw message
include/virtio.h +3 -1
@@ -32,12 +32,14 @@#define VIRTIO_ID_BLOCK 2/* virtio block */ #define VIRTIO_ID_RNG 4/* virtio rng */ #define VIRTIO_ID_9P 9/* virtio 9p */ -#define VIRTIO_ID_MAX_NUM 10 +#define VIRTIO_ID_CLOCK 17/* virtio clock/timer (rtc) */ +#define VIRTIO_ID_MAX_NUM 18#define VIRTIO_NET_DRV_NAME "virtio-net"#define VIRTIO_BLK_DRV_NAME "virtio-blk"#define VIRTIO_RNG_DRV_NAME "virtio-rng"#define VIRTIO_9P_DRV_NAME "virtio-9p" +#define VIRTIO_RTC_DRV_NAME "virtio-rtc"/* Feature bits for virtio 9P */ #define VIRTIO_9P_MOUNT_TAG 0
Signature · 1 line
2.43.0
PATCH v6 2/6 doc: virtio: List the supported device types
In reply to Hung-Chun TsengThe list of supported device types still only named network and block devices. Turn it into a bulleted list, which is easier to extend, and add the entropy, 9P and RTC devices. Also note that the virtio RTC device needs QEMU v11.1.0 or later.
The Development Flow section repeated the old list; point it to the one at the top instead.
--- doc/develop/driver-model/virtio.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
doc/develop/driver-model/virtio.rst +11 -4
@@ -28,7 +28,13 @@ queues configuration and buffer transfers are nearly identical. Both MMIO and PCI transport options are supported in U-Boot. The VirtIO spec defines a lots of VirtIO device types, however at present only -network and block device, the most two commonly used devices, are supported. +the following devices are supported. + + - network + - block + - entropy (rng) + - 9P transport + - RTC The following QEMU targets are supported.
@@ -72,6 +78,8 @@ Requirements ------------ It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V. +The VirtIO RTC device (``-device virtio-rtc-pci`` or +``-device virtio-rtc-device``) requires QEMU v11.1.0+. Testing -------
@@ -246,9 +254,8 @@ So it's easy to tell which device these functions are operating on. Development Flow ---------------- -At present only VirtIO network card (device ID 1) and block device (device -ID 2) are supported. If you want to develop new driver for new devices, -please follow the guideline below. +The supported devices are listed at the top of this document. If you want +to develop new driver for new devices, please follow the guideline below. 1. add new device ID in virtio.h
Signature · 1 line
2.43.0
PATCH v6 3/6 MAINTAINERS: Add entry for virtio RTC
In reply to Hung-Chun TsengAdd myself as the maintainer of the virtio RTC driver.
--- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+)
MAINTAINERS +5 -0
@@ -1887,6 +1887,11 @@ F: include/virtio*.h F: test/dm/virtio*.c F: doc/develop/driver-model/virtio.rst +VIRTIO RTC +M: Hung-Chun Tseng <[email protected]> +S: Maintained +F: drivers/virtio/virtio_rtc.c + WATCHDOG M: Stefan Roese <[email protected]> S: Maintained
Signature · 1 line
2.43.0
PATCH v6 4/6 virtio: sandbox: Let tests emulate the device side of a virtqueue
In reply to Hung-Chun TsengThe sandbox virtio transport ignores notifications, so a driver that waits for the device to answer a request cannot be tested beyond its probe. The virtio-rng test works around this by writing to the used ring of the driver's virtqueue before reading.
Add sandbox_virtio_set_notify() so that a test can install a handler which is called when the driver kicks a virtqueue. The handler can then process the available ring and fill in the used ring, as a real device would. Without a handler, notifications are still ignored.
--- arch/sandbox/include/asm/test.h | 25 +++++++++++++++++++++++++ drivers/virtio/virtio_sandbox.c | 15 +++++++++++++++ 2 files changed, 40 insertions(+)
arch/sandbox/include/asm/test.h +25 -0
@@ -11,6 +11,8 @@#include <pci_ids.h> struct unit_test_state ; +struct udevice ; +struct virtqueue ;/* The sandbox driver always permits an I2C device with this address */ #define SANDBOX_I2C_TEST_ADDR 0x59
@@ -369,4 +371,27 @@ bool sandbox_sf_bootdev_enabled(void);*/ void sandbox_sf_set_enable_bootdevs (bool enable); +/** +* typedef sandbox_virtio_notify_t - Emulate the device side of a virtqueue +* +* @dev: sandbox virtio transport device +* @vq: virtqueue that was kicked +* Returns: 0 on success, or -ve error code +*/ +typedef int (*sandbox_virtio_notify_t )(struct udevice *dev, +struct virtqueue *vq); + +/** +* sandbox_virtio_set_notify() - Set a handler for virtqueue notifications +* +* The sandbox virtio transport ignores notifications by default. A test can +* set a handler here to process the buffers the driver adds, like a real +* device would. +* +* @dev: sandbox virtio transport device +* @notify: handler to call, or NULL to ignore notifications again +*/ +void sandbox_virtio_set_notify (struct udevice *dev, +sandbox_virtio_notify_t notify); +#endif
drivers/virtio/virtio_sandbox.c +15 -0
@@ -13,6 +13,7 @@#include <linux/compat.h> #include <linux/err.h> #include <linux/io.h> +#include <asm/test.h> struct virtio_sandbox_priv {u8 id;
@@ -22,6 +23,7 @@ struct virtio_sandbox_priv {ulong queue_desc;ulong queue_available;ulong queue_used; +sandbox_virtio_notify_t notify; }; static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
@@ -150,9 +152,22 @@ static int virtio_sandbox_find_vqs(struct udevice *udev, unsigned int nvqs,static int virtio_sandbox_notify (struct udevice *udev,struct virtqueue *vq) { +struct virtio_sandbox_priv *priv =dev_get_priv (udev); + +if (priv->notify) +return priv->notify (udev, vq); +return 0 ; } +void sandbox_virtio_set_notify (struct udevice *udev, +sandbox_virtio_notify_t notify) +{ +struct virtio_sandbox_priv *priv =dev_get_priv (udev); + + priv->notify = notify; +} +static int virtio_sandbox_probe (struct udevice *udev) {struct virtio_sandbox_priv *priv =dev_get_priv (udev);
Signature · 1 line
2.43.0
PATCH v6 5/6 test: dm: Add tests for the virtio RTC driver
In reply to Hung-Chun TsengAdd a virtio RTC device to the sandbox test device tree and emulate it through the sandbox virtio transport. The emulated device answers the VIRTIO_RTC_REQ_CFG, VIRTIO_RTC_REQ_CLOCK_CAP and VIRTIO_RTC_REQ_READ requests from a configurable list of clocks.
The tests check that the driver:
- does not use the virtqueue in probe()
- reads the time from the first UTC clock and looks it up only once
- remembers that there is no UTC clock and does not ask again
- reports a failed request and looks for the clock again next time
- gives up with -ETIMEDOUT when the device does not answer
--- MAINTAINERS | 1 + arch/sandbox/dts/test.dts | 5 + test/dm/Makefile | 1 + test/dm/virtio_rtc.c | 306 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 313 insertions(+) create mode 100644 test/dm/virtio_rtc.c
MAINTAINERS +1 -0
@@ -1891,6 +1891,7 @@ VIRTIO RTC M: Hung-Chun Tseng <[email protected]> S: Maintained F: drivers/virtio/virtio_rtc.c +F: test/dm/virtio_rtc.c WATCHDOG M: Stefan Roese <[email protected]>
arch/sandbox/dts/test.dts +5 -0
@@ -1996,6 +1996,11 @@ virtio-type = <2>; /* block */ }; + sandbox-virtio-rtc { + compatible = "sandbox,virtio1"; + virtio-type = <17>; /* clock */ + }; + sandbox_scmi { compatible = "sandbox,scmi-devices"; power-domains = <&pwrdom_scmi 2>;
test/dm/Makefile +1 -0
@@ -155,6 +155,7 @@ ifeq ($(CONFIG_VIRTIO_SANDBOX),y) obj-y += virtio.o obj-$(CONFIG_VIRTIO_RNG) += virtio_device.o obj-$(CONFIG_VIRTIO_RNG) += virtio_rng.o +obj-$(CONFIG_VIRTIO_RTC) += virtio_rtc.o endif ifeq ($(CONFIG_WDT_GPIO)$(CONFIG_WDT_SANDBOX),yy) obj-y += wdt.o
test/dm/virtio_rtc.c new file +306 -0
306 lines not on this page · raw message
Signature · 1 line
2.43.0
PATCH v6 6/6 doc: virtio: Explain how to reach the virtio RTC
In reply to Hung-Chun TsengThe date command only uses RTC sequence 0. On the QEMU ARM, RISC-V and x86 machines that is the PL031, Goldfish or MC146818 RTC, so date never reads the virtio RTC unless that driver is disabled. rtc dev does not help, as rtc read reads raw registers, which the virtio RTC does not have.
Give the virtio RTC its own section and say this there, along with the QEMU version it needs and that x86 needs DM_RTC.
--- doc/develop/driver-model/virtio.rst | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
doc/develop/driver-model/virtio.rst +12 -1
@@ -78,8 +78,19 @@ Requirements ------------ It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V. + +VirtIO RTC +---------- The VirtIO RTC device (``-device virtio-rtc-pci`` or -``-device virtio-rtc-device``) requires QEMU v11.1.0+. +``-device virtio-rtc-device``) requires QEMU v11.1.0+. The driver needs +``CONFIG_DM_RTC``, which QEMU x86 does not enable by default. + +The ``date`` command only uses RTC sequence 0. The QEMU ARM, RISC-V and x86 +machines also have a PL031, Goldfish or MC146818 RTC, which gets sequence 0, +so ``date`` reads the VirtIO RTC only if ``CONFIG_RTC_PL031``, +``CONFIG_RTC_GOLDFISH`` or ``CONFIG_RTC_MC146818`` is disabled. +``dm uclass rtc`` shows the sequence numbers. ``rtc dev`` does not help, as +``rtc read`` reads raw registers, which the VirtIO RTC does not have. Testing -------
Signature · 1 line
2.43.0
Re: [PATCH v6 6/6] doc: virtio: Explain how to reach the virtio RTC
Hi Hung-Chun,
Quoted 10 lines · Hung-Chun Tseng
doc: virtio: Explain how to reach the virtio RTC
The date command only uses RTC sequence 0. On the QEMU ARM, RISC-V and x86 machines that is the PL031, Goldfish or MC146818 RTC, so date never reads the virtio RTC unless that driver is disabled. rtc dev does not help, as rtc read reads raw registers, which the virtio RTC does not have.
Give the virtio RTC its own section and say this there, along with the QEMU version it needs and that x86 needs
DM_RTC.
Please can you drop the DM_RTC part here too, once the doc is updated (see below).
doc/develop/driver-model/virtio.rst Requirements · line 79
Quoted 11 lines
Suggested-by Simon Glass <[email protected]>Signed-off-by Hung-Chun Tseng <[email protected]>doc/develop/driver-model/virtio.rst | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)doc/develop/driver-model/virtio.rst +2
-0@@ -78,8 +78,19 @@ Requirements +``-device virtio-rtc-device``) requires QEMU v11.1.0+. The driver needs +``CONFIG_DM_RTC``, which QEMU x86 does not enable by default.
Just to check, how did you find this? The config X86 entry in arch/Kconfig has 'imply DM_RTC', and both qemu-x86_defconfig and qemu-x86_64_defconfig give me CONFIG_DM_RTC=y and CONFIG_VIRTIO_RTC=y, so the driver looks to be already enabled on QEMU x86. Please can you drop the sentence, unless there is a case I am missing.
Regards,
Simon
Re: [PATCH v6 6/6] doc: virtio: Explain how to reach the virtio RTC
Hi Simon,
Quoted 5 lines · Simon Glass
Just to check, how did you find this? The config X86 entry in
arch/Kconfighas 'implyDM_RTC', and both qemu-x86_defconfig and qemu-x86_64_defconfig give meCONFIG_DM_RTC=yandCONFIG_VIRTIO_RTC=y, so the driver looks to be already enabled on QEMU x86. Please can you drop the sentence, unless there is a case I am missing.
You're right, there is no such case. I carried the claim over from the v5 discussion and didn't check it against the defconfigs. Both give me CONFIG_DM_RTC=y and CONFIG_VIRTIO_RTC=y as well.
I'll drop the sentence and the DM_RTC part of the commit message in v7.
Regards,
Hung-Chun