aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBin Meng2018-10-15 04:21:00 -0500
committerSimon Glass2018-11-14 11:16:27 -0600
commit8fb49b4c7a820461db7c11dce767f36fd6395cac (patch)
tree3289c27071a293689680da11b1d9614531d7cce9
parentb1893a9e0def4052e56513bfcee0a0eb95841f7f (diff)
downloadu-boot-8fb49b4c7a820461db7c11dce767f36fd6395cac.tar.gz
u-boot-8fb49b4c7a820461db7c11dce767f36fd6395cac.tar.xz
u-boot-8fb49b4c7a820461db7c11dce767f36fd6395cac.zip
dm: Add a new uclass driver for VirtIO transport devices
This adds a new virtio uclass driver for “virtio” [1] family of devices that are are found in virtual environments like QEMU, yet by design they look like physical devices to the guest. The uclass driver provides child_pre_probe() and child_post_probe() methods to do some common operations for virtio device drivers like device and driver supported feature negotiation, etc. [1] http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf Signed-off-by: Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi> Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/virtio/Kconfig25
-rw-r--r--drivers/virtio/Makefile6
-rw-r--r--drivers/virtio/virtio-uclass.c369
-rw-r--r--include/dm/uclass-id.h1
-rw-r--r--include/virtio.h707
-rw-r--r--include/virtio_types.h24
8 files changed, 1135 insertions, 0 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 927a2b87f6..4ac823d962 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -112,6 +112,8 @@ source "drivers/usb/Kconfig"
112 112
113source "drivers/video/Kconfig" 113source "drivers/video/Kconfig"
114 114
115source "drivers/virtio/Kconfig"
116
115source "drivers/w1/Kconfig" 117source "drivers/w1/Kconfig"
116 118
117source "drivers/w1-eeprom/Kconfig" 119source "drivers/w1-eeprom/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index fb38b67541..4453c62ad3 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/
14obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/ 14obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/
15obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/ 15obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/
16obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/ 16obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/
17obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/
17obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/ 18obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/
18obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/ 19obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/
19 20
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
new file mode 100644
index 0000000000..82fc536831
--- /dev/null
+++ b/drivers/virtio/Kconfig
@@ -0,0 +1,25 @@
1# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5#
6# VirtIO is a virtualization standard for network and disk device drivers
7# where just the guest's device driver "knows" it is running in a virtual
8# environment, and cooperates with the hypervisor. This enables guests to
9# get high performance network and disk operations, and gives most of the
10# performance benefits of paravirtualization. In the U-Boot case, the guest
11# is U-Boot itself, while the virtual environment are normally QEMU targets
12# like ARM, RISC-V and x86.
13#
14# See http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf for
15# the VirtIO specification v1.0.
16
17menu "VirtIO Drivers"
18
19config VIRTIO
20 bool
21 help
22 This option is selected by any driver which implements the virtio
23 transport, such as CONFIG_VIRTIO_MMIO or CONFIG_VIRTIO_PCI.
24
25endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
new file mode 100644
index 0000000000..23e7be7165
--- /dev/null
+++ b/drivers/virtio/Makefile
@@ -0,0 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0+
2#
3# Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5
6obj-y += virtio-uclass.o
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
new file mode 100644
index 0000000000..34397d7dbb
--- /dev/null
+++ b/drivers/virtio/virtio-uclass.c
@@ -0,0 +1,369 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 *
6 * VirtIO is a virtualization standard for network and disk device drivers
7 * where just the guest's device driver "knows" it is running in a virtual
8 * environment, and cooperates with the hypervisor. This enables guests to
9 * get high performance network and disk operations, and gives most of the
10 * performance benefits of paravirtualization. In the U-Boot case, the guest
11 * is U-Boot itself, while the virtual environment are normally QEMU targets
12 * like ARM, RISC-V and x86.
13 *
14 * See http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf for
15 * the VirtIO specification v1.0.
16 */
17
18#include <common.h>
19#include <dm.h>
20#include <virtio_types.h>
21#include <virtio.h>
22#include <dm/lists.h>
23
24static const char *const virtio_drv_name[VIRTIO_ID_MAX_NUM] = {
25 [VIRTIO_ID_NET] = VIRTIO_NET_DRV_NAME,
26 [VIRTIO_ID_BLOCK] = VIRTIO_BLK_DRV_NAME,
27};
28
29int virtio_get_config(struct udevice *vdev, unsigned int offset,
30 void *buf, unsigned int len)
31{
32 struct dm_virtio_ops *ops;
33
34 ops = virtio_get_ops(vdev->parent);
35
36 return ops->get_config(vdev->parent, offset, buf, len);
37}
38
39int virtio_set_config(struct udevice *vdev, unsigned int offset,
40 void *buf, unsigned int len)
41{
42 struct dm_virtio_ops *ops;
43
44 ops = virtio_get_ops(vdev->parent);
45
46 return ops->set_config(vdev->parent, offset, buf, len);
47}
48
49int virtio_generation(struct udevice *vdev, u32 *counter)
50{
51 struct dm_virtio_ops *ops;
52
53 ops = virtio_get_ops(vdev->parent);
54 if (!ops->generation)
55 return -ENOSYS;
56
57 return ops->generation(vdev->parent, counter);
58}
59
60int virtio_get_status(struct udevice *vdev, u8 *status)
61{
62 struct dm_virtio_ops *ops;
63
64 ops = virtio_get_ops(vdev->parent);
65
66 return ops->get_status(vdev->parent, status);
67}
68
69int virtio_set_status(struct udevice *vdev, u8 status)
70{
71 struct dm_virtio_ops *ops;
72
73 ops = virtio_get_ops(vdev->parent);
74
75 return ops->set_status(vdev->parent, status);
76}
77
78int virtio_reset(struct udevice *vdev)
79{
80 struct dm_virtio_ops *ops;
81
82 ops = virtio_get_ops(vdev->parent);
83
84 return ops->reset(vdev->parent);
85}
86
87int virtio_get_features(struct udevice *vdev, u64 *features)
88{
89 struct dm_virtio_ops *ops;
90
91 ops = virtio_get_ops(vdev->parent);
92
93 return ops->get_features(vdev->parent, features);
94}
95
96int virtio_set_features(struct udevice *vdev)
97{
98 struct dm_virtio_ops *ops;
99
100 ops = virtio_get_ops(vdev->parent);
101
102 return ops->set_features(vdev->parent);
103}
104
105int virtio_find_vqs(struct udevice *vdev, unsigned int nvqs,
106 struct virtqueue *vqs[])
107{
108 struct dm_virtio_ops *ops;
109
110 ops = virtio_get_ops(vdev->parent);
111
112 return ops->find_vqs(vdev->parent, nvqs, vqs);
113}
114
115int virtio_del_vqs(struct udevice *vdev)
116{
117 struct dm_virtio_ops *ops;
118
119 ops = virtio_get_ops(vdev->parent);
120
121 return ops->del_vqs(vdev->parent);
122}
123
124int virtio_notify(struct udevice *vdev, struct virtqueue *vq)
125{
126 struct dm_virtio_ops *ops;
127
128 ops = virtio_get_ops(vdev->parent);
129
130 return ops->notify(vdev->parent, vq);
131}
132
133void virtio_add_status(struct udevice *vdev, u8 status)
134{
135 u8 old;
136
137 if (!virtio_get_status(vdev, &old))
138 virtio_set_status(vdev, old | status);
139}
140
141int virtio_finalize_features(struct udevice *vdev)
142{
143 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev->parent);
144 u8 status;
145 int ret;
146
147 ret = virtio_set_features(vdev);
148 if (ret)
149 return ret;
150
151 if (uc_priv->legacy)
152 return 0;
153
154 virtio_add_status(vdev, VIRTIO_CONFIG_S_FEATURES_OK);
155 ret = virtio_get_status(vdev, &status);
156 if (ret)
157 return ret;
158 if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) {
159 debug("(%s): device refuses features %x\n", vdev->name, status);
160 return -ENODEV;
161 }
162
163 return 0;
164}
165
166void virtio_driver_features_init(struct virtio_dev_priv *priv,
167 const u32 *feature,
168 u32 feature_size,
169 const u32 *feature_legacy,
170 u32 feature_legacy_size)
171{
172 priv->feature_table = feature;
173 priv->feature_table_size = feature_size;
174 priv->feature_table_legacy = feature_legacy;
175 priv->feature_table_size_legacy = feature_legacy_size;
176}
177
178int virtio_init(void)
179{
180 struct udevice *bus;
181 int ret;
182
183 /* Enumerate all known virtio devices */
184 ret = uclass_first_device(UCLASS_VIRTIO, &bus);
185 if (ret)
186 return ret;
187
188 while (bus) {
189 ret = uclass_next_device(&bus);
190 if (ret)
191 break;
192 }
193
194 return ret;
195}
196
197static int virtio_uclass_pre_probe(struct udevice *udev)
198{
199 struct dm_virtio_ops *ops;
200
201 ops = (struct dm_virtio_ops *)(udev->driver->ops);
202
203 /*
204 * Check virtio transport driver ops here so that we don't need
205 * check these ops each time when the virtio_xxx APIs are called.
206 *
207 * Only generation op is optional. All other ops are must-have.
208 */
209 if (!ops->get_config || !ops->set_config ||
210 !ops->get_status || !ops->set_status ||
211 !ops->get_features || !ops->set_features ||
212 !ops->find_vqs || !ops->del_vqs ||
213 !ops->reset || !ops->notify)
214 return -ENOENT;
215
216 return 0;
217}
218
219static int virtio_uclass_post_probe(struct udevice *udev)
220{
221 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
222 char dev_name[30], *str;
223 struct udevice *vdev;
224 int ret;
225
226 if (uc_priv->device > VIRTIO_ID_MAX_NUM) {
227 debug("(%s): virtio device ID %d exceeds maximum num\n",
228 udev->name, uc_priv->device);
229 return 0;
230 }
231
232 if (!virtio_drv_name[uc_priv->device]) {
233 debug("(%s): underlying virtio device driver unavailable\n",
234 udev->name);
235 return 0;
236 }
237
238 snprintf(dev_name, sizeof(dev_name), "%s#%d",
239 virtio_drv_name[uc_priv->device], udev->seq);
240 str = strdup(dev_name);
241 if (!str)
242 return -ENOMEM;
243
244 ret = device_bind_driver(udev, virtio_drv_name[uc_priv->device],
245 str, &vdev);
246 if (ret == -ENOENT) {
247 debug("(%s): no driver configured\n", udev->name);
248 return 0;
249 }
250 if (ret) {
251 free(str);
252 return ret;
253 }
254 device_set_name_alloced(vdev);
255
256 INIT_LIST_HEAD(&uc_priv->vqs);
257
258 return 0;
259}
260
261static int virtio_uclass_child_post_bind(struct udevice *vdev)
262{
263 /* Acknowledge that we've seen the device */
264 virtio_add_status(vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
265
266 return 0;
267}
268
269static int virtio_uclass_child_pre_probe(struct udevice *vdev)
270{
271 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev->parent);
272 u64 device_features;
273 u64 driver_features;
274 u64 driver_features_legacy;
275 int i;
276 int ret;
277
278 /*
279 * Save the real virtio device (eg: virtio-net, virtio-blk) to
280 * the transport (parent) device's uclass priv for future use.
281 */
282 uc_priv->vdev = vdev;
283
284 /*
285 * We always start by resetting the device, in case a previous driver
286 * messed it up. This also tests that code path a little.
287 */
288 ret = virtio_reset(vdev);
289 if (ret)
290 goto err;
291
292 /* We have a driver! */
293 virtio_add_status(vdev, VIRTIO_CONFIG_S_DRIVER);
294
295 /* Figure out what features the device supports */
296 virtio_get_features(vdev, &device_features);
297 debug("(%s) plain device features supported %016llx\n",
298 vdev->name, device_features);
299 if (!(device_features & (1ULL << VIRTIO_F_VERSION_1)))
300 uc_priv->legacy = true;
301
302 /* Figure out what features the driver supports */
303 driver_features = 0;
304 for (i = 0; i < uc_priv->feature_table_size; i++) {
305 unsigned int f = uc_priv->feature_table[i];
306
307 WARN_ON(f >= 64);
308 driver_features |= (1ULL << f);
309 }
310
311 /* Some drivers have a separate feature table for virtio v1.0 */
312 if (uc_priv->feature_table_legacy) {
313 driver_features_legacy = 0;
314 for (i = 0; i < uc_priv->feature_table_size_legacy; i++) {
315 unsigned int f = uc_priv->feature_table_legacy[i];
316
317 WARN_ON(f >= 64);
318 driver_features_legacy |= (1ULL << f);
319 }
320 } else {
321 driver_features_legacy = driver_features;
322 }
323
324 if (uc_priv->legacy) {
325 debug("(%s): legacy virtio device\n", vdev->name);
326 uc_priv->features = driver_features_legacy & device_features;
327 } else {
328 debug("(%s): v1.0 complaint virtio device\n", vdev->name);
329 uc_priv->features = driver_features & device_features;
330 }
331
332 /* Transport features always preserved to pass to finalize_features */
333 for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
334 if ((device_features & (1ULL << i)) &&
335 (i == VIRTIO_F_VERSION_1))
336 __virtio_set_bit(vdev->parent, i);
337
338 debug("(%s) final negotiated features supported %016llx\n",
339 vdev->name, uc_priv->features);
340 ret = virtio_finalize_features(vdev);
341 if (ret)
342 goto err;
343
344 return 0;
345
346err:
347 virtio_add_status(vdev, VIRTIO_CONFIG_S_FAILED);
348 return ret;
349}
350
351static int virtio_uclass_child_post_probe(struct udevice *vdev)
352{
353 /* Indicates that the driver is set up and ready to drive the device */
354 virtio_add_status(vdev, VIRTIO_CONFIG_S_DRIVER_OK);
355
356 return 0;
357}
358
359UCLASS_DRIVER(virtio) = {
360 .name = "virtio",
361 .id = UCLASS_VIRTIO,
362 .flags = DM_UC_FLAG_SEQ_ALIAS,
363 .pre_probe = virtio_uclass_pre_probe,
364 .post_probe = virtio_uclass_post_probe,
365 .child_post_bind = virtio_uclass_child_post_bind,
366 .child_pre_probe = virtio_uclass_child_pre_probe,
367 .child_post_probe = virtio_uclass_child_post_probe,
368 .per_device_auto_alloc_size = sizeof(struct virtio_dev_priv),
369};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 269a2c6e72..c91dca1f82 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -96,6 +96,7 @@ enum uclass_id {
96 UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */ 96 UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */
97 UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */ 97 UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */
98 UCLASS_VIDEO_OSD, /* On-screen display */ 98 UCLASS_VIDEO_OSD, /* On-screen display */
99 UCLASS_VIRTIO, /* VirtIO transport device */
99 UCLASS_W1, /* Dallas 1-Wire bus */ 100 UCLASS_W1, /* Dallas 1-Wire bus */
100 UCLASS_W1_EEPROM, /* one-wire EEPROMs */ 101 UCLASS_W1_EEPROM, /* one-wire EEPROMs */
101 UCLASS_WDT, /* Watchdot Timer driver */ 102 UCLASS_WDT, /* Watchdot Timer driver */
diff --git a/include/virtio.h b/include/virtio.h
new file mode 100644
index 0000000000..654fdf154b
--- /dev/null
+++ b/include/virtio.h
@@ -0,0 +1,707 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 *
6 * VirtIO is a virtualization standard for network and disk device drivers
7 * where just the guest's device driver "knows" it is running in a virtual
8 * environment, and cooperates with the hypervisor. This enables guests to
9 * get high performance network and disk operations, and gives most of the
10 * performance benefits of paravirtualization. In the U-Boot case, the guest
11 * is U-Boot itself, while the virtual environment are normally QEMU targets
12 * like ARM, RISC-V and x86.
13 *
14 * See http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf for
15 * the VirtIO specification v1.0.
16 *
17 * This file is largely based on Linux kernel virtio_*.h files
18 */
19
20#ifndef __VIRTIO_H__
21#define __VIRTIO_H__
22
23#define VIRTIO_ID_NET 1 /* virtio net */
24#define VIRTIO_ID_BLOCK 2 /* virtio block */
25#define VIRTIO_ID_MAX_NUM 3
26
27#define VIRTIO_NET_DRV_NAME "virtio-net"
28#define VIRTIO_BLK_DRV_NAME "virtio-blk"
29
30/* Status byte for guest to report progress, and synchronize features */
31
32/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
33#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
34/* We have found a driver for the device */
35#define VIRTIO_CONFIG_S_DRIVER 2
36/* Driver has used its parts of the config, and is happy */
37#define VIRTIO_CONFIG_S_DRIVER_OK 4
38/* Driver has finished configuring features */
39#define VIRTIO_CONFIG_S_FEATURES_OK 8
40/* Device entered invalid state, driver must reset it */
41#define VIRTIO_CONFIG_S_NEEDS_RESET 0x40
42/* We've given up on this device */
43#define VIRTIO_CONFIG_S_FAILED 0x80
44
45/*
46 * Virtio feature bits VIRTIO_TRANSPORT_F_START through VIRTIO_TRANSPORT_F_END
47 * are reserved for the transport being used (eg: virtio_ring, virtio_pci etc.),
48 * the rest are per-device feature bits.
49 */
50#define VIRTIO_TRANSPORT_F_START 28
51#define VIRTIO_TRANSPORT_F_END 38
52
53#ifndef VIRTIO_CONFIG_NO_LEGACY
54/*
55 * Do we get callbacks when the ring is completely used,
56 * even if we've suppressed them?
57 */
58#define VIRTIO_F_NOTIFY_ON_EMPTY 24
59
60/* Can the device handle any descriptor layout? */
61#define VIRTIO_F_ANY_LAYOUT 27
62#endif /* VIRTIO_CONFIG_NO_LEGACY */
63
64/* v1.0 compliant */
65#define VIRTIO_F_VERSION_1 32
66
67/*
68 * If clear - device has the IOMMU bypass quirk feature.
69 * If set - use platform tools to detect the IOMMU.
70 *
71 * Note the reverse polarity (compared to most other features),
72 * this is for compatibility with legacy systems.
73 */
74#define VIRTIO_F_IOMMU_PLATFORM 33
75
76/* Does the device support Single Root I/O Virtualization? */
77#define VIRTIO_F_SR_IOV 37
78
79/**
80 * virtio scatter-gather struct
81 *
82 * @addr: sg buffer address
83 * @lengh: sg buffer length
84 */
85struct virtio_sg {
86 void *addr;
87 size_t length;
88};
89
90struct virtqueue;
91
92/* virtio bus operations */
93struct dm_virtio_ops {
94 /**
95 * get_config() - read the value of a configuration field
96 *
97 * @vdev: the real virtio device
98 * @offset: the offset of the configuration field
99 * @buf: the buffer to write the field value into
100 * @len: the length of the buffer
101 * @return 0 if OK, -ve on error
102 */
103 int (*get_config)(struct udevice *vdev, unsigned int offset,
104 void *buf, unsigned int len);
105 /**
106 * set_config() - write the value of a configuration field
107 *
108 * @vdev: the real virtio device
109 * @offset: the offset of the configuration field
110 * @buf: the buffer to read the field value from
111 * @len: the length of the buffer
112 * @return 0 if OK, -ve on error
113 */
114 int (*set_config)(struct udevice *vdev, unsigned int offset,
115 const void *buf, unsigned int len);
116 /**
117 * generation() - config generation counter
118 *
119 * @vdev: the real virtio device
120 * @counter: the returned config generation counter
121 * @return 0 if OK, -ve on error
122 */
123 int (*generation)(struct udevice *vdev, u32 *counter);
124 /**
125 * get_status() - read the status byte
126 *
127 * @vdev: the real virtio device
128 * @status: the returned status byte
129 * @return 0 if OK, -ve on error
130 */
131 int (*get_status)(struct udevice *vdev, u8 *status);
132 /**
133 * set_status() - write the status byte
134 *
135 * @vdev: the real virtio device
136 * @status: the new status byte
137 * @return 0 if OK, -ve on error
138 */
139 int (*set_status)(struct udevice *vdev, u8 status);
140 /**
141 * reset() - reset the device
142 *
143 * @vdev: the real virtio device
144 * @return 0 if OK, -ve on error
145 */
146 int (*reset)(struct udevice *vdev);
147 /**
148 * get_features() - get the array of feature bits for this device
149 *
150 * @vdev: the real virtio device
151 * @features: the first 32 feature bits (all we currently need)
152 * @return 0 if OK, -ve on error
153 */
154 int (*get_features)(struct udevice *vdev, u64 *features);
155 /**
156 * set_features() - confirm what device features we'll be using
157 *
158 * @vdev: the real virtio device
159 * @return 0 if OK, -ve on error
160 */
161 int (*set_features)(struct udevice *vdev);
162 /**
163 * find_vqs() - find virtqueues and instantiate them
164 *
165 * @vdev: the real virtio device
166 * @nvqs: the number of virtqueues to find
167 * @vqs: on success, includes new virtqueues
168 * @return 0 if OK, -ve on error
169 */
170 int (*find_vqs)(struct udevice *vdev, unsigned int nvqs,
171 struct virtqueue *vqs[]);
172 /**
173 * del_vqs() - free virtqueues found by find_vqs()
174 *
175 * @vdev: the real virtio device
176 * @return 0 if OK, -ve on error
177 */
178 int (*del_vqs)(struct udevice *vdev);
179 /**
180 * notify() - notify the device to process the queue
181 *
182 * @vdev: the real virtio device
183 * @vq: virtqueue to process
184 * @return 0 if OK, -ve on error
185 */
186 int (*notify)(struct udevice *vdev, struct virtqueue *vq);
187};
188
189/* Get access to a virtio bus' operations */
190#define virtio_get_ops(dev) ((struct dm_virtio_ops *)(dev)->driver->ops)
191
192/**
193 * virtio uclass per device private data
194 *
195 * @vqs: virtualqueue for the virtio device
196 * @vdev: the real virtio device underneath
197 * @legacy: is it a legacy device?
198 * @device: virtio device ID
199 * @vendor: virtio vendor ID
200 * @features: negotiated supported features
201 * @feature_table: an array of feature supported by the driver
202 * @feature_table_size: number of entries in the feature table array
203 * @feature_table_legacy: same as feature_table but working in legacy mode
204 * @feature_table_size_legacy: number of entries in feature table legacy array
205 */
206struct virtio_dev_priv {
207 struct list_head vqs;
208 struct udevice *vdev;
209 bool legacy;
210 u32 device;
211 u32 vendor;
212 u64 features;
213 const u32 *feature_table;
214 u32 feature_table_size;
215 const u32 *feature_table_legacy;
216 u32 feature_table_size_legacy;
217};
218
219/**
220 * virtio_get_config() - read the value of a configuration field
221 *
222 * @vdev: the real virtio device
223 * @offset: the offset of the configuration field
224 * @buf: the buffer to write the field value into
225 * @len: the length of the buffer
226 * @return 0 if OK, -ve on error
227 */
228int virtio_get_config(struct udevice *vdev, unsigned int offset,
229 void *buf, unsigned int len);
230
231/**
232 * virtio_set_config() - write the value of a configuration field
233 *
234 * @vdev: the real virtio device
235 * @offset: the offset of the configuration field
236 * @buf: the buffer to read the field value from
237 * @len: the length of the buffer
238 * @return 0 if OK, -ve on error
239 */
240int virtio_set_config(struct udevice *vdev, unsigned int offset,
241 void *buf, unsigned int len);
242
243/**
244 * virtio_generation() - config generation counter
245 *
246 * @vdev: the real virtio device
247 * @counter: the returned config generation counter
248 * @return 0 if OK, -ve on error
249 */
250int virtio_generation(struct udevice *vdev, u32 *counter);
251
252/**
253 * virtio_get_status() - read the status byte
254 *
255 * @vdev: the real virtio device
256 * @status: the returned status byte
257 * @return 0 if OK, -ve on error
258 */
259int virtio_get_status(struct udevice *vdev, u8 *status);
260
261/**
262 * virtio_set_status() - write the status byte
263 *
264 * @vdev: the real virtio device
265 * @status: the new status byte
266 * @return 0 if OK, -ve on error
267 */
268int virtio_set_status(struct udevice *vdev, u8 status);
269
270/**
271 * virtio_reset() - reset the device
272 *
273 * @vdev: the real virtio device
274 * @return 0 if OK, -ve on error
275 */
276int virtio_reset(struct udevice *vdev);
277
278/**
279 * virtio_get_features() - get the array of feature bits for this device
280 *
281 * @vdev: the real virtio device
282 * @features: the first 32 feature bits (all we currently need)
283 * @return 0 if OK, -ve on error
284 */
285int virtio_get_features(struct udevice *vdev, u64 *features);
286
287/**
288 * virtio_set_features() - confirm what device features we'll be using
289 *
290 * @vdev: the real virtio device
291 * @return 0 if OK, -ve on error
292 */
293int virtio_set_features(struct udevice *vdev);
294
295/**
296 * virtio_find_vqs() - find virtqueues and instantiate them
297 *
298 * @vdev: the real virtio device
299 * @nvqs: the number of virtqueues to find
300 * @vqs: on success, includes new virtqueues
301 * @return 0 if OK, -ve on error
302 */
303int virtio_find_vqs(struct udevice *vdev, unsigned int nvqs,
304 struct virtqueue *vqs[]);
305
306/**
307 * virtio_del_vqs() - free virtqueues found by find_vqs()
308 *
309 * @vdev: the real virtio device
310 * @return 0 if OK, -ve on error
311 */
312int virtio_del_vqs(struct udevice *vdev);
313
314/**
315 * virtio_notify() - notify the device to process the queue
316 *
317 * @vdev: the real virtio device
318 * @vq: virtqueue to process
319 * @return 0 if OK, -ve on error
320 */
321int virtio_notify(struct udevice *vdev, struct virtqueue *vq);
322
323/**
324 * virtio_add_status() - helper to set a new status code to the device
325 *
326 * @vdev: the real virtio device
327 * @status: new status code to be added
328 */
329void virtio_add_status(struct udevice *vdev, u8 status);
330
331/**
332 * virtio_finalize_features() - helper to finalize features
333 *
334 * @vdev: the real virtio device
335 * @return 0 if OK, -ve on error
336 */
337int virtio_finalize_features(struct udevice *vdev);
338
339/**
340 * virtio_driver_features_init() - initialize driver supported features
341 *
342 * This fills in the virtio device parent per child private data with the given
343 * information, which contains driver supported features and legacy features.
344 *
345 * This API should be called in the virtio device driver's bind method, so that
346 * later virtio transport uclass driver can utilize the driver supplied features
347 * to negotiate with the device on the final supported features.
348 *
349 * @priv: virtio uclass per device private data
350 * @feature: an array of feature supported by the driver
351 * @feature_size: number of entries in the feature table array
352 * @feature_legacy: same as feature_table but working in legacy mode
353 * @feature_legacy_size:number of entries in feature table legacy array
354 */
355void virtio_driver_features_init(struct virtio_dev_priv *priv,
356 const u32 *feature,
357 u32 feature_size,
358 const u32 *feature_legacy,
359 u32 feature_legacy_size);
360
361/**
362 * virtio_init() - helper to enumerate all known virtio devices
363 *
364 * @return 0 if OK, -ve on error
365 */
366int virtio_init(void);
367
368static inline u16 __virtio16_to_cpu(bool little_endian, __virtio16 val)
369{
370 if (little_endian)
371 return le16_to_cpu((__force __le16)val);
372 else
373 return be16_to_cpu((__force __be16)val);
374}
375
376static inline __virtio16 __cpu_to_virtio16(bool little_endian, u16 val)
377{
378 if (little_endian)
379 return (__force __virtio16)cpu_to_le16(val);
380 else
381 return (__force __virtio16)cpu_to_be16(val);
382}
383
384static inline u32 __virtio32_to_cpu(bool little_endian, __virtio32 val)
385{
386 if (little_endian)
387 return le32_to_cpu((__force __le32)val);
388 else
389 return be32_to_cpu((__force __be32)val);
390}
391
392static inline __virtio32 __cpu_to_virtio32(bool little_endian, u32 val)
393{
394 if (little_endian)
395 return (__force __virtio32)cpu_to_le32(val);
396 else
397 return (__force __virtio32)cpu_to_be32(val);
398}
399
400static inline u64 __virtio64_to_cpu(bool little_endian, __virtio64 val)
401{
402 if (little_endian)
403 return le64_to_cpu((__force __le64)val);
404 else
405 return be64_to_cpu((__force __be64)val);
406}
407
408static inline __virtio64 __cpu_to_virtio64(bool little_endian, u64 val)
409{
410 if (little_endian)
411 return (__force __virtio64)cpu_to_le64(val);
412 else
413 return (__force __virtio64)cpu_to_be64(val);
414}
415
416/**
417 * __virtio_test_bit - helper to test feature bits
418 *
419 * For use by transports. Devices should normally use virtio_has_feature,
420 * which includes more checks.
421 *
422 * @udev: the transport device
423 * @fbit: the feature bit
424 */
425static inline bool __virtio_test_bit(struct udevice *udev, unsigned int fbit)
426{
427 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
428
429 /* Did you forget to fix assumptions on max features? */
430 if (__builtin_constant_p(fbit))
431 BUILD_BUG_ON(fbit >= 64);
432 else
433 WARN_ON(fbit >= 64);
434
435 return uc_priv->features & BIT_ULL(fbit);
436}
437
438/**
439 * __virtio_set_bit - helper to set feature bits
440 *
441 * For use by transports.
442 *
443 * @udev: the transport device
444 * @fbit: the feature bit
445 */
446static inline void __virtio_set_bit(struct udevice *udev, unsigned int fbit)
447{
448 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
449
450 /* Did you forget to fix assumptions on max features? */
451 if (__builtin_constant_p(fbit))
452 BUILD_BUG_ON(fbit >= 64);
453 else
454 WARN_ON(fbit >= 64);
455
456 uc_priv->features |= BIT_ULL(fbit);
457}
458
459/**
460 * __virtio_clear_bit - helper to clear feature bits
461 *
462 * For use by transports.
463 *
464 * @vdev: the transport device
465 * @fbit: the feature bit
466 */
467static inline void __virtio_clear_bit(struct udevice *udev, unsigned int fbit)
468{
469 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
470
471 /* Did you forget to fix assumptions on max features? */
472 if (__builtin_constant_p(fbit))
473 BUILD_BUG_ON(fbit >= 64);
474 else
475 WARN_ON(fbit >= 64);
476
477 uc_priv->features &= ~BIT_ULL(fbit);
478}
479
480/**
481 * virtio_has_feature - helper to determine if this device has this feature
482 *
483 * Note this API is only usable after the virtio device driver's bind phase,
484 * as the feature has been negotiated between the device and the driver.
485 *
486 * @vdev: the virtio device
487 * @fbit: the feature bit
488 */
489static inline bool virtio_has_feature(struct udevice *vdev, unsigned int fbit)
490{
491 if (!(vdev->flags & DM_FLAG_BOUND))
492 WARN_ON(true);
493
494 return __virtio_test_bit(vdev->parent, fbit);
495}
496
497static inline bool virtio_legacy_is_little_endian(void)
498{
499#ifdef __LITTLE_ENDIAN
500 return true;
501#else
502 return false;
503#endif
504}
505
506static inline bool virtio_is_little_endian(struct udevice *vdev)
507{
508 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev->parent);
509
510 return !uc_priv->legacy || virtio_legacy_is_little_endian();
511}
512
513/* Memory accessors */
514static inline u16 virtio16_to_cpu(struct udevice *vdev, __virtio16 val)
515{
516 return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
517}
518
519static inline __virtio16 cpu_to_virtio16(struct udevice *vdev, u16 val)
520{
521 return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
522}
523
524static inline u32 virtio32_to_cpu(struct udevice *vdev, __virtio32 val)
525{
526 return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
527}
528
529static inline __virtio32 cpu_to_virtio32(struct udevice *vdev, u32 val)
530{
531 return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
532}
533
534static inline u64 virtio64_to_cpu(struct udevice *vdev, __virtio64 val)
535{
536 return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
537}
538
539static inline __virtio64 cpu_to_virtio64(struct udevice *vdev, u64 val)
540{
541 return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
542}
543
544/* Read @count fields, @bytes each */
545static inline void __virtio_cread_many(struct udevice *vdev,
546 unsigned int offset,
547 void *buf, size_t count, size_t bytes)
548{
549 u32 old, gen;
550 int i;
551
552 /* no need to check return value as generation can be optional */
553 virtio_generation(vdev, &gen);
554 do {
555 old = gen;
556
557 for (i = 0; i < count; i++)
558 virtio_get_config(vdev, offset + bytes * i,
559 buf + i * bytes, bytes);
560
561 virtio_generation(vdev, &gen);
562 } while (gen != old);
563}
564
565static inline void virtio_cread_bytes(struct udevice *vdev,
566 unsigned int offset,
567 void *buf, size_t len)
568{
569 __virtio_cread_many(vdev, offset, buf, len, 1);
570}
571
572static inline u8 virtio_cread8(struct udevice *vdev, unsigned int offset)
573{
574 u8 ret;
575
576 virtio_get_config(vdev, offset, &ret, sizeof(ret));
577 return ret;
578}
579
580static inline void virtio_cwrite8(struct udevice *vdev,
581 unsigned int offset, u8 val)
582{
583 virtio_set_config(vdev, offset, &val, sizeof(val));
584}
585
586static inline u16 virtio_cread16(struct udevice *vdev,
587 unsigned int offset)
588{
589 u16 ret;
590
591 virtio_get_config(vdev, offset, &ret, sizeof(ret));
592 return virtio16_to_cpu(vdev, (__force __virtio16)ret);
593}
594
595static inline void virtio_cwrite16(struct udevice *vdev,
596 unsigned int offset, u16 val)
597{
598 val = (__force u16)cpu_to_virtio16(vdev, val);
599 virtio_set_config(vdev, offset, &val, sizeof(val));
600}
601
602static inline u32 virtio_cread32(struct udevice *vdev,
603 unsigned int offset)
604{
605 u32 ret;
606
607 virtio_get_config(vdev, offset, &ret, sizeof(ret));
608 return virtio32_to_cpu(vdev, (__force __virtio32)ret);
609}
610
611static inline void virtio_cwrite32(struct udevice *vdev,
612 unsigned int offset, u32 val)
613{
614 val = (__force u32)cpu_to_virtio32(vdev, val);
615 virtio_set_config(vdev, offset, &val, sizeof(val));
616}
617
618static inline u64 virtio_cread64(struct udevice *vdev,
619 unsigned int offset)
620{
621 u64 ret;
622
623 __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
624 return virtio64_to_cpu(vdev, (__force __virtio64)ret);
625}
626
627static inline void virtio_cwrite64(struct udevice *vdev,
628 unsigned int offset, u64 val)
629{
630 val = (__force u64)cpu_to_virtio64(vdev, val);
631 virtio_set_config(vdev, offset, &val, sizeof(val));
632}
633
634/* Config space read accessor */
635#define virtio_cread(vdev, structname, member, ptr) \
636 do { \
637 /* Must match the member's type, and be integer */ \
638 if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
639 (*ptr) = 1; \
640 \
641 switch (sizeof(*ptr)) { \
642 case 1: \
643 *(ptr) = virtio_cread8(vdev, \
644 offsetof(structname, member)); \
645 break; \
646 case 2: \
647 *(ptr) = virtio_cread16(vdev, \
648 offsetof(structname, member)); \
649 break; \
650 case 4: \
651 *(ptr) = virtio_cread32(vdev, \
652 offsetof(structname, member)); \
653 break; \
654 case 8: \
655 *(ptr) = virtio_cread64(vdev, \
656 offsetof(structname, member)); \
657 break; \
658 default: \
659 WARN_ON(true); \
660 } \
661 } while (0)
662
663/* Config space write accessor */
664#define virtio_cwrite(vdev, structname, member, ptr) \
665 do { \
666 /* Must match the member's type, and be integer */ \
667 if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
668 WARN_ON((*ptr) == 1); \
669 \
670 switch (sizeof(*ptr)) { \
671 case 1: \
672 virtio_cwrite8(vdev, \
673 offsetof(structname, member), \
674 *(ptr)); \
675 break; \
676 case 2: \
677 virtio_cwrite16(vdev, \
678 offsetof(structname, member), \
679 *(ptr)); \
680 break; \
681 case 4: \
682 virtio_cwrite32(vdev, \
683 offsetof(structname, member), \
684 *(ptr)); \
685 break; \
686 case 8: \
687 virtio_cwrite64(vdev, \
688 offsetof(structname, member), \
689 *(ptr)); \
690 break; \
691 default: \
692 WARN_ON(true); \
693 } \
694 } while (0)
695
696/* Conditional config space accessors */
697#define virtio_cread_feature(vdev, fbit, structname, member, ptr) \
698 ({ \
699 int _r = 0; \
700 if (!virtio_has_feature(vdev, fbit)) \
701 _r = -ENOENT; \
702 else \
703 virtio_cread(vdev, structname, member, ptr); \
704 _r; \
705 })
706
707#endif /* __VIRTIO_H__ */
diff --git a/include/virtio_types.h b/include/virtio_types.h
new file mode 100644
index 0000000000..d700d1936d
--- /dev/null
+++ b/include/virtio_types.h
@@ -0,0 +1,24 @@
1/* SPDX-License-Identifier: BSD-3-Clause */
2/*
3 * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 *
6 * From Linux kernel include/uapi/linux/virtio_types.h
7 */
8
9#ifndef _LINUX_VIRTIO_TYPES_H
10#define _LINUX_VIRTIO_TYPES_H
11
12#include <linux/types.h>
13
14/*
15 * __virtio{16,32,64} have the following meaning:
16 * - __u{16,32,64} for virtio devices in legacy mode, accessed in native endian
17 * - __le{16,32,64} for standard-compliant virtio devices
18 */
19
20typedef __u16 __bitwise __virtio16;
21typedef __u32 __bitwise __virtio32;
22typedef __u64 __bitwise __virtio64;
23
24#endif /* _LINUX_VIRTIO_TYPES_H */