1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
6 * VirtIO memory-maped I/O transport driver
7 * Ported from Linux drivers/virtio/virtio_mmio.c
12 #include <virtio_types.h>
14 #include <virtio_ring.h>
15 #include <linux/compat.h>
16 #include <linux/err.h>
18 #include "virtio_mmio.h"
20 static int virtio_mmio_get_config(struct udevice *udev, unsigned int offset,
21 void *buf, unsigned int len)
23 struct virtio_mmio_priv *priv = dev_get_priv(udev);
24 void __iomem *base = priv->base + VIRTIO_MMIO_CONFIG;
29 if (priv->version == 1) {
33 for (i = 0; i < len; i++)
34 ptr[i] = readb(base + offset + i);
41 b = readb(base + offset);
42 memcpy(buf, &b, sizeof(b));
45 w = cpu_to_le16(readw(base + offset));
46 memcpy(buf, &w, sizeof(w));
49 l = cpu_to_le32(readl(base + offset));
50 memcpy(buf, &l, sizeof(l));
53 l = cpu_to_le32(readl(base + offset));
54 memcpy(buf, &l, sizeof(l));
55 l = cpu_to_le32(readl(base + offset + sizeof(l)));
56 memcpy(buf + sizeof(l), &l, sizeof(l));
65 static int virtio_mmio_set_config(struct udevice *udev, unsigned int offset,
66 const void *buf, unsigned int len)
68 struct virtio_mmio_priv *priv = dev_get_priv(udev);
69 void __iomem *base = priv->base + VIRTIO_MMIO_CONFIG;
74 if (priv->version == 1) {
78 for (i = 0; i < len; i++)
79 writeb(ptr[i], base + offset + i);
86 memcpy(&b, buf, sizeof(b));
87 writeb(b, base + offset);
90 memcpy(&w, buf, sizeof(w));
91 writew(le16_to_cpu(w), base + offset);
94 memcpy(&l, buf, sizeof(l));
95 writel(le32_to_cpu(l), base + offset);
98 memcpy(&l, buf, sizeof(l));
99 writel(le32_to_cpu(l), base + offset);
100 memcpy(&l, buf + sizeof(l), sizeof(l));
101 writel(le32_to_cpu(l), base + offset + sizeof(l));
110 static int virtio_mmio_generation(struct udevice *udev, u32 *counter)
112 struct virtio_mmio_priv *priv = dev_get_priv(udev);
114 if (priv->version == 1)
117 *counter = readl(priv->base + VIRTIO_MMIO_CONFIG_GENERATION);
122 static int virtio_mmio_get_status(struct udevice *udev, u8 *status)
124 struct virtio_mmio_priv *priv = dev_get_priv(udev);
126 *status = readl(priv->base + VIRTIO_MMIO_STATUS) & 0xff;
131 static int virtio_mmio_set_status(struct udevice *udev, u8 status)
133 struct virtio_mmio_priv *priv = dev_get_priv(udev);
135 /* We should never be setting status to 0 */
136 WARN_ON(status == 0);
138 writel(status, priv->base + VIRTIO_MMIO_STATUS);
143 static int virtio_mmio_reset(struct udevice *udev)
145 struct virtio_mmio_priv *priv = dev_get_priv(udev);
147 /* 0 status means a reset */
148 writel(0, priv->base + VIRTIO_MMIO_STATUS);
153 static int virtio_mmio_get_features(struct udevice *udev, u64 *features)
155 struct virtio_mmio_priv *priv = dev_get_priv(udev);
157 writel(1, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
158 *features = readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
161 writel(0, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
162 *features |= readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
167 static int virtio_mmio_set_features(struct udevice *udev)
169 struct virtio_mmio_priv *priv = dev_get_priv(udev);
170 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
172 /* Make sure there is are no mixed devices */
173 if (priv->version == 2 && uc_priv->legacy) {
174 debug("New virtio-mmio devices (version 2) must provide VIRTIO_F_VERSION_1 feature!\n");
178 writel(1, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
179 writel((u32)(uc_priv->features >> 32),
180 priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
182 writel(0, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
183 writel((u32)uc_priv->features,
184 priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
189 static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
192 struct virtio_mmio_priv *priv = dev_get_priv(udev);
193 struct virtqueue *vq;
197 /* Select the queue we're interested in */
198 writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
200 /* Queue shouldn't already be set up */
201 if (readl(priv->base + (priv->version == 1 ?
202 VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
204 goto error_available;
207 num = readl(priv->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
210 goto error_new_virtqueue;
213 /* Create the vring */
214 vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, udev);
217 goto error_new_virtqueue;
220 /* Activate the queue */
221 writel(virtqueue_get_vring_size(vq),
222 priv->base + VIRTIO_MMIO_QUEUE_NUM);
223 if (priv->version == 1) {
224 u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
227 * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something
228 * that doesn't fit in 32bit, fail the setup rather than
229 * pretending to be successful.
232 debug("platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
233 0x1ULL << (32 + PAGE_SHIFT - 30));
238 writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_QUEUE_ALIGN);
239 writel(q_pfn, priv->base + VIRTIO_MMIO_QUEUE_PFN);
243 addr = virtqueue_get_desc_addr(vq);
244 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
245 writel((u32)(addr >> 32),
246 priv->base + VIRTIO_MMIO_QUEUE_DESC_HIGH);
248 addr = virtqueue_get_avail_addr(vq);
249 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
250 writel((u32)(addr >> 32),
251 priv->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH);
253 addr = virtqueue_get_used_addr(vq);
254 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_USED_LOW);
255 writel((u32)(addr >> 32),
256 priv->base + VIRTIO_MMIO_QUEUE_USED_HIGH);
258 writel(1, priv->base + VIRTIO_MMIO_QUEUE_READY);
264 vring_del_virtqueue(vq);
267 if (priv->version == 1) {
268 writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
270 writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
271 WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
278 static void virtio_mmio_del_vq(struct virtqueue *vq)
280 struct virtio_mmio_priv *priv = dev_get_priv(vq->vdev);
281 unsigned int index = vq->index;
283 /* Select and deactivate the queue */
284 writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
285 if (priv->version == 1) {
286 writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
288 writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
289 WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
292 vring_del_virtqueue(vq);
295 static int virtio_mmio_del_vqs(struct udevice *udev)
297 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
298 struct virtqueue *vq, *n;
300 list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
301 virtio_mmio_del_vq(vq);
306 static int virtio_mmio_find_vqs(struct udevice *udev, unsigned int nvqs,
307 struct virtqueue *vqs[])
311 for (i = 0; i < nvqs; ++i) {
312 vqs[i] = virtio_mmio_setup_vq(udev, i);
313 if (IS_ERR(vqs[i])) {
314 virtio_mmio_del_vqs(udev);
315 return PTR_ERR(vqs[i]);
322 static int virtio_mmio_notify(struct udevice *udev, struct virtqueue *vq)
324 struct virtio_mmio_priv *priv = dev_get_priv(udev);
327 * We write the queue's selector into the notification register
328 * to signal the other end
330 writel(vq->index, priv->base + VIRTIO_MMIO_QUEUE_NOTIFY);
335 static int virtio_mmio_ofdata_to_platdata(struct udevice *udev)
337 struct virtio_mmio_priv *priv = dev_get_priv(udev);
339 priv->base = (void __iomem *)(ulong)dev_read_addr(udev);
340 if (priv->base == (void __iomem *)FDT_ADDR_T_NONE)
346 static int virtio_mmio_probe(struct udevice *udev)
348 struct virtio_mmio_priv *priv = dev_get_priv(udev);
349 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
352 /* Check magic value */
353 magic = readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
354 if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
355 debug("(%s): wrong magic value 0x%08x!\n", udev->name, magic);
359 /* Check device version */
360 priv->version = readl(priv->base + VIRTIO_MMIO_VERSION);
361 if (priv->version < 1 || priv->version > 2) {
362 debug("(%s): version %d not supported!\n",
363 udev->name, priv->version);
367 /* Check device ID */
368 uc_priv->device = readl(priv->base + VIRTIO_MMIO_DEVICE_ID);
369 if (uc_priv->device == 0) {
371 * virtio-mmio device with an ID 0 is a (dummy) placeholder
372 * with no function. End probing now with no error reported.
376 uc_priv->vendor = readl(priv->base + VIRTIO_MMIO_VENDOR_ID);
378 if (priv->version == 1)
379 writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
381 debug("(%s): device (%d) vendor (%08x) version (%d)\n", udev->name,
382 uc_priv->device, uc_priv->vendor, priv->version);
387 static const struct dm_virtio_ops virtio_mmio_ops = {
388 .get_config = virtio_mmio_get_config,
389 .set_config = virtio_mmio_set_config,
390 .generation = virtio_mmio_generation,
391 .get_status = virtio_mmio_get_status,
392 .set_status = virtio_mmio_set_status,
393 .reset = virtio_mmio_reset,
394 .get_features = virtio_mmio_get_features,
395 .set_features = virtio_mmio_set_features,
396 .find_vqs = virtio_mmio_find_vqs,
397 .del_vqs = virtio_mmio_del_vqs,
398 .notify = virtio_mmio_notify,
401 static const struct udevice_id virtio_mmio_ids[] = {
402 { .compatible = "virtio,mmio" },
406 U_BOOT_DRIVER(virtio_mmio) = {
407 .name = "virtio-mmio",
409 .of_match = virtio_mmio_ids,
410 .ops = &virtio_mmio_ops,
411 .probe = virtio_mmio_probe,
412 .ofdata_to_platdata = virtio_mmio_ofdata_to_platdata,
413 .priv_auto_alloc_size = sizeof(struct virtio_mmio_priv),