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/bug.h>
16 #include <linux/compat.h>
17 #include <linux/err.h>
19 #include "virtio_mmio.h"
21 static int virtio_mmio_get_config(struct udevice *udev, unsigned int offset,
22 void *buf, unsigned int len)
24 struct virtio_mmio_priv *priv = dev_get_priv(udev);
25 void __iomem *base = priv->base + VIRTIO_MMIO_CONFIG;
30 if (priv->version == 1) {
34 for (i = 0; i < len; i++)
35 ptr[i] = readb(base + offset + i);
42 b = readb(base + offset);
43 memcpy(buf, &b, sizeof(b));
46 w = cpu_to_le16(readw(base + offset));
47 memcpy(buf, &w, sizeof(w));
50 l = cpu_to_le32(readl(base + offset));
51 memcpy(buf, &l, sizeof(l));
54 l = cpu_to_le32(readl(base + offset));
55 memcpy(buf, &l, sizeof(l));
56 l = cpu_to_le32(readl(base + offset + sizeof(l)));
57 memcpy(buf + sizeof(l), &l, sizeof(l));
66 static int virtio_mmio_set_config(struct udevice *udev, unsigned int offset,
67 const void *buf, unsigned int len)
69 struct virtio_mmio_priv *priv = dev_get_priv(udev);
70 void __iomem *base = priv->base + VIRTIO_MMIO_CONFIG;
75 if (priv->version == 1) {
79 for (i = 0; i < len; i++)
80 writeb(ptr[i], base + offset + i);
87 memcpy(&b, buf, sizeof(b));
88 writeb(b, base + offset);
91 memcpy(&w, buf, sizeof(w));
92 writew(le16_to_cpu(w), base + offset);
95 memcpy(&l, buf, sizeof(l));
96 writel(le32_to_cpu(l), base + offset);
99 memcpy(&l, buf, sizeof(l));
100 writel(le32_to_cpu(l), base + offset);
101 memcpy(&l, buf + sizeof(l), sizeof(l));
102 writel(le32_to_cpu(l), base + offset + sizeof(l));
111 static int virtio_mmio_generation(struct udevice *udev, u32 *counter)
113 struct virtio_mmio_priv *priv = dev_get_priv(udev);
115 if (priv->version == 1)
118 *counter = readl(priv->base + VIRTIO_MMIO_CONFIG_GENERATION);
123 static int virtio_mmio_get_status(struct udevice *udev, u8 *status)
125 struct virtio_mmio_priv *priv = dev_get_priv(udev);
127 *status = readl(priv->base + VIRTIO_MMIO_STATUS) & 0xff;
132 static int virtio_mmio_set_status(struct udevice *udev, u8 status)
134 struct virtio_mmio_priv *priv = dev_get_priv(udev);
136 /* We should never be setting status to 0 */
137 WARN_ON(status == 0);
139 writel(status, priv->base + VIRTIO_MMIO_STATUS);
144 static int virtio_mmio_reset(struct udevice *udev)
146 struct virtio_mmio_priv *priv = dev_get_priv(udev);
148 /* 0 status means a reset */
149 writel(0, priv->base + VIRTIO_MMIO_STATUS);
154 static int virtio_mmio_get_features(struct udevice *udev, u64 *features)
156 struct virtio_mmio_priv *priv = dev_get_priv(udev);
158 writel(1, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
159 *features = readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
162 writel(0, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
163 *features |= readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
168 static int virtio_mmio_set_features(struct udevice *udev)
170 struct virtio_mmio_priv *priv = dev_get_priv(udev);
171 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
173 /* Make sure there is are no mixed devices */
174 if (priv->version == 2 && uc_priv->legacy) {
175 debug("New virtio-mmio devices (version 2) must provide VIRTIO_F_VERSION_1 feature!\n");
179 writel(1, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
180 writel((u32)(uc_priv->features >> 32),
181 priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
183 writel(0, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
184 writel((u32)uc_priv->features,
185 priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
190 static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
193 struct virtio_mmio_priv *priv = dev_get_priv(udev);
194 struct virtqueue *vq;
198 /* Select the queue we're interested in */
199 writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
201 /* Queue shouldn't already be set up */
202 if (readl(priv->base + (priv->version == 1 ?
203 VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
205 goto error_available;
208 num = readl(priv->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
211 goto error_new_virtqueue;
214 /* Create the vring */
215 vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, udev);
218 goto error_new_virtqueue;
221 /* Activate the queue */
222 writel(virtqueue_get_vring_size(vq),
223 priv->base + VIRTIO_MMIO_QUEUE_NUM);
224 if (priv->version == 1) {
225 u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
228 * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something
229 * that doesn't fit in 32bit, fail the setup rather than
230 * pretending to be successful.
233 debug("platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
234 0x1ULL << (32 + PAGE_SHIFT - 30));
239 writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_QUEUE_ALIGN);
240 writel(q_pfn, priv->base + VIRTIO_MMIO_QUEUE_PFN);
244 addr = virtqueue_get_desc_addr(vq);
245 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
246 writel((u32)(addr >> 32),
247 priv->base + VIRTIO_MMIO_QUEUE_DESC_HIGH);
249 addr = virtqueue_get_avail_addr(vq);
250 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
251 writel((u32)(addr >> 32),
252 priv->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH);
254 addr = virtqueue_get_used_addr(vq);
255 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_USED_LOW);
256 writel((u32)(addr >> 32),
257 priv->base + VIRTIO_MMIO_QUEUE_USED_HIGH);
259 writel(1, priv->base + VIRTIO_MMIO_QUEUE_READY);
265 vring_del_virtqueue(vq);
268 if (priv->version == 1) {
269 writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
271 writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
272 WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
279 static void virtio_mmio_del_vq(struct virtqueue *vq)
281 struct virtio_mmio_priv *priv = dev_get_priv(vq->vdev);
282 unsigned int index = vq->index;
284 /* Select and deactivate the queue */
285 writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
286 if (priv->version == 1) {
287 writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
289 writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
290 WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
293 vring_del_virtqueue(vq);
296 static int virtio_mmio_del_vqs(struct udevice *udev)
298 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
299 struct virtqueue *vq, *n;
301 list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
302 virtio_mmio_del_vq(vq);
307 static int virtio_mmio_find_vqs(struct udevice *udev, unsigned int nvqs,
308 struct virtqueue *vqs[])
312 for (i = 0; i < nvqs; ++i) {
313 vqs[i] = virtio_mmio_setup_vq(udev, i);
314 if (IS_ERR(vqs[i])) {
315 virtio_mmio_del_vqs(udev);
316 return PTR_ERR(vqs[i]);
323 static int virtio_mmio_notify(struct udevice *udev, struct virtqueue *vq)
325 struct virtio_mmio_priv *priv = dev_get_priv(udev);
328 * We write the queue's selector into the notification register
329 * to signal the other end
331 writel(vq->index, priv->base + VIRTIO_MMIO_QUEUE_NOTIFY);
336 static int virtio_mmio_of_to_plat(struct udevice *udev)
338 struct virtio_mmio_priv *priv = dev_get_priv(udev);
340 priv->base = (void __iomem *)(ulong)dev_read_addr(udev);
341 if (priv->base == (void __iomem *)FDT_ADDR_T_NONE)
347 static int virtio_mmio_probe(struct udevice *udev)
349 struct virtio_mmio_priv *priv = dev_get_priv(udev);
350 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
353 /* Check magic value */
354 magic = readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
355 if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
356 debug("(%s): wrong magic value 0x%08x!\n", udev->name, magic);
360 /* Check device version */
361 priv->version = readl(priv->base + VIRTIO_MMIO_VERSION);
362 if (priv->version < 1 || priv->version > 2) {
363 debug("(%s): version %d not supported!\n",
364 udev->name, priv->version);
368 /* Check device ID */
369 uc_priv->device = readl(priv->base + VIRTIO_MMIO_DEVICE_ID);
370 if (uc_priv->device == 0) {
372 * virtio-mmio device with an ID 0 is a (dummy) placeholder
373 * with no function. End probing now with no error reported.
377 uc_priv->vendor = readl(priv->base + VIRTIO_MMIO_VENDOR_ID);
379 if (priv->version == 1)
380 writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
382 debug("(%s): device (%d) vendor (%08x) version (%d)\n", udev->name,
383 uc_priv->device, uc_priv->vendor, priv->version);
388 static const struct dm_virtio_ops virtio_mmio_ops = {
389 .get_config = virtio_mmio_get_config,
390 .set_config = virtio_mmio_set_config,
391 .generation = virtio_mmio_generation,
392 .get_status = virtio_mmio_get_status,
393 .set_status = virtio_mmio_set_status,
394 .reset = virtio_mmio_reset,
395 .get_features = virtio_mmio_get_features,
396 .set_features = virtio_mmio_set_features,
397 .find_vqs = virtio_mmio_find_vqs,
398 .del_vqs = virtio_mmio_del_vqs,
399 .notify = virtio_mmio_notify,
402 static const struct udevice_id virtio_mmio_ids[] = {
403 { .compatible = "virtio,mmio" },
407 U_BOOT_DRIVER(virtio_mmio) = {
408 .name = "virtio-mmio",
410 .of_match = virtio_mmio_ids,
411 .ops = &virtio_mmio_ops,
412 .probe = virtio_mmio_probe,
413 .of_to_plat = virtio_mmio_of_to_plat,
414 .priv_auto = sizeof(struct virtio_mmio_priv),