Merge tag 'efi-2020-01-rc2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
[oweals/u-boot.git] / drivers / virtio / virtio_mmio.c
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 memory-maped I/O transport driver
7  * Ported from Linux drivers/virtio/virtio_mmio.c
8  */
9
10 #include <common.h>
11 #include <dm.h>
12 #include <virtio_types.h>
13 #include <virtio.h>
14 #include <virtio_ring.h>
15 #include <linux/compat.h>
16 #include <linux/io.h>
17 #include "virtio_mmio.h"
18
19 static int virtio_mmio_get_config(struct udevice *udev, unsigned int offset,
20                                   void *buf, unsigned int len)
21 {
22         struct virtio_mmio_priv *priv = dev_get_priv(udev);
23         void __iomem *base = priv->base + VIRTIO_MMIO_CONFIG;
24         u8 b;
25         __le16 w;
26         __le32 l;
27
28         if (priv->version == 1) {
29                 u8 *ptr = buf;
30                 int i;
31
32                 for (i = 0; i < len; i++)
33                         ptr[i] = readb(base + offset + i);
34
35                 return 0;
36         }
37
38         switch (len) {
39         case 1:
40                 b = readb(base + offset);
41                 memcpy(buf, &b, sizeof(b));
42                 break;
43         case 2:
44                 w = cpu_to_le16(readw(base + offset));
45                 memcpy(buf, &w, sizeof(w));
46                 break;
47         case 4:
48                 l = cpu_to_le32(readl(base + offset));
49                 memcpy(buf, &l, sizeof(l));
50                 break;
51         case 8:
52                 l = cpu_to_le32(readl(base + offset));
53                 memcpy(buf, &l, sizeof(l));
54                 l = cpu_to_le32(readl(base + offset + sizeof(l)));
55                 memcpy(buf + sizeof(l), &l, sizeof(l));
56                 break;
57         default:
58                 WARN_ON(true);
59         }
60
61         return 0;
62 }
63
64 static int virtio_mmio_set_config(struct udevice *udev, unsigned int offset,
65                                   const void *buf, unsigned int len)
66 {
67         struct virtio_mmio_priv *priv = dev_get_priv(udev);
68         void __iomem *base = priv->base + VIRTIO_MMIO_CONFIG;
69         u8 b;
70         __le16 w;
71         __le32 l;
72
73         if (priv->version == 1) {
74                 const u8 *ptr = buf;
75                 int i;
76
77                 for (i = 0; i < len; i++)
78                         writeb(ptr[i], base + offset + i);
79
80                 return 0;
81         }
82
83         switch (len) {
84         case 1:
85                 memcpy(&b, buf, sizeof(b));
86                 writeb(b, base + offset);
87                 break;
88         case 2:
89                 memcpy(&w, buf, sizeof(w));
90                 writew(le16_to_cpu(w), base + offset);
91                 break;
92         case 4:
93                 memcpy(&l, buf, sizeof(l));
94                 writel(le32_to_cpu(l), base + offset);
95                 break;
96         case 8:
97                 memcpy(&l, buf, sizeof(l));
98                 writel(le32_to_cpu(l), base + offset);
99                 memcpy(&l, buf + sizeof(l), sizeof(l));
100                 writel(le32_to_cpu(l), base + offset + sizeof(l));
101                 break;
102         default:
103                 WARN_ON(true);
104         }
105
106         return 0;
107 }
108
109 static int virtio_mmio_generation(struct udevice *udev, u32 *counter)
110 {
111         struct virtio_mmio_priv *priv = dev_get_priv(udev);
112
113         if (priv->version == 1)
114                 *counter = 0;
115         else
116                 *counter = readl(priv->base + VIRTIO_MMIO_CONFIG_GENERATION);
117
118         return 0;
119 }
120
121 static int virtio_mmio_get_status(struct udevice *udev, u8 *status)
122 {
123         struct virtio_mmio_priv *priv = dev_get_priv(udev);
124
125         *status = readl(priv->base + VIRTIO_MMIO_STATUS) & 0xff;
126
127         return 0;
128 }
129
130 static int virtio_mmio_set_status(struct udevice *udev, u8 status)
131 {
132         struct virtio_mmio_priv *priv = dev_get_priv(udev);
133
134         /* We should never be setting status to 0 */
135         WARN_ON(status == 0);
136
137         writel(status, priv->base + VIRTIO_MMIO_STATUS);
138
139         return 0;
140 }
141
142 static int virtio_mmio_reset(struct udevice *udev)
143 {
144         struct virtio_mmio_priv *priv = dev_get_priv(udev);
145
146         /* 0 status means a reset */
147         writel(0, priv->base + VIRTIO_MMIO_STATUS);
148
149         return 0;
150 }
151
152 static int virtio_mmio_get_features(struct udevice *udev, u64 *features)
153 {
154         struct virtio_mmio_priv *priv = dev_get_priv(udev);
155
156         writel(1, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
157         *features = readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
158         *features <<= 32;
159
160         writel(0, priv->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
161         *features |= readl(priv->base + VIRTIO_MMIO_DEVICE_FEATURES);
162
163         return 0;
164 }
165
166 static int virtio_mmio_set_features(struct udevice *udev)
167 {
168         struct virtio_mmio_priv *priv = dev_get_priv(udev);
169         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
170
171         /* Make sure there is are no mixed devices */
172         if (priv->version == 2 && uc_priv->legacy) {
173                 debug("New virtio-mmio devices (version 2) must provide VIRTIO_F_VERSION_1 feature!\n");
174                 return -EINVAL;
175         }
176
177         writel(1, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
178         writel((u32)(uc_priv->features >> 32),
179                priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
180
181         writel(0, priv->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
182         writel((u32)uc_priv->features,
183                priv->base + VIRTIO_MMIO_DRIVER_FEATURES);
184
185         return 0;
186 }
187
188 static struct virtqueue *virtio_mmio_setup_vq(struct udevice *udev,
189                                               unsigned int index)
190 {
191         struct virtio_mmio_priv *priv = dev_get_priv(udev);
192         struct virtqueue *vq;
193         unsigned int num;
194         int err;
195
196         /* Select the queue we're interested in */
197         writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
198
199         /* Queue shouldn't already be set up */
200         if (readl(priv->base + (priv->version == 1 ?
201             VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
202                 err = -ENOENT;
203                 goto error_available;
204         }
205
206         num = readl(priv->base + VIRTIO_MMIO_QUEUE_NUM_MAX);
207         if (num == 0) {
208                 err = -ENOENT;
209                 goto error_new_virtqueue;
210         }
211
212         /* Create the vring */
213         vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, udev);
214         if (!vq) {
215                 err = -ENOMEM;
216                 goto error_new_virtqueue;
217         }
218
219         /* Activate the queue */
220         writel(virtqueue_get_vring_size(vq),
221                priv->base + VIRTIO_MMIO_QUEUE_NUM);
222         if (priv->version == 1) {
223                 u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
224
225                 /*
226                  * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something
227                  * that doesn't fit in 32bit, fail the setup rather than
228                  * pretending to be successful.
229                  */
230                 if (q_pfn >> 32) {
231                         debug("platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
232                               0x1ULL << (32 + PAGE_SHIFT - 30));
233                         err = -E2BIG;
234                         goto error_bad_pfn;
235                 }
236
237                 writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_QUEUE_ALIGN);
238                 writel(q_pfn, priv->base + VIRTIO_MMIO_QUEUE_PFN);
239         } else {
240                 u64 addr;
241
242                 addr = virtqueue_get_desc_addr(vq);
243                 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
244                 writel((u32)(addr >> 32),
245                        priv->base + VIRTIO_MMIO_QUEUE_DESC_HIGH);
246
247                 addr = virtqueue_get_avail_addr(vq);
248                 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
249                 writel((u32)(addr >> 32),
250                        priv->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH);
251
252                 addr = virtqueue_get_used_addr(vq);
253                 writel((u32)addr, priv->base + VIRTIO_MMIO_QUEUE_USED_LOW);
254                 writel((u32)(addr >> 32),
255                        priv->base + VIRTIO_MMIO_QUEUE_USED_HIGH);
256
257                 writel(1, priv->base + VIRTIO_MMIO_QUEUE_READY);
258         }
259
260         return vq;
261
262 error_bad_pfn:
263         vring_del_virtqueue(vq);
264
265 error_new_virtqueue:
266         if (priv->version == 1) {
267                 writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
268         } else {
269                 writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
270                 WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
271         }
272
273 error_available:
274         return ERR_PTR(err);
275 }
276
277 static void virtio_mmio_del_vq(struct virtqueue *vq)
278 {
279         struct virtio_mmio_priv *priv = dev_get_priv(vq->vdev);
280         unsigned int index = vq->index;
281
282         /* Select and deactivate the queue */
283         writel(index, priv->base + VIRTIO_MMIO_QUEUE_SEL);
284         if (priv->version == 1) {
285                 writel(0, priv->base + VIRTIO_MMIO_QUEUE_PFN);
286         } else {
287                 writel(0, priv->base + VIRTIO_MMIO_QUEUE_READY);
288                 WARN_ON(readl(priv->base + VIRTIO_MMIO_QUEUE_READY));
289         }
290
291         vring_del_virtqueue(vq);
292 }
293
294 static int virtio_mmio_del_vqs(struct udevice *udev)
295 {
296         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
297         struct virtqueue *vq, *n;
298
299         list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
300                 virtio_mmio_del_vq(vq);
301
302         return 0;
303 }
304
305 static int virtio_mmio_find_vqs(struct udevice *udev, unsigned int nvqs,
306                                 struct virtqueue *vqs[])
307 {
308         int i;
309
310         for (i = 0; i < nvqs; ++i) {
311                 vqs[i] = virtio_mmio_setup_vq(udev, i);
312                 if (IS_ERR(vqs[i])) {
313                         virtio_mmio_del_vqs(udev);
314                         return PTR_ERR(vqs[i]);
315                 }
316         }
317
318         return 0;
319 }
320
321 static int virtio_mmio_notify(struct udevice *udev, struct virtqueue *vq)
322 {
323         struct virtio_mmio_priv *priv = dev_get_priv(udev);
324
325         /*
326          * We write the queue's selector into the notification register
327          * to signal the other end
328          */
329         writel(vq->index, priv->base + VIRTIO_MMIO_QUEUE_NOTIFY);
330
331         return 0;
332 }
333
334 static int virtio_mmio_ofdata_to_platdata(struct udevice *udev)
335 {
336         struct virtio_mmio_priv *priv = dev_get_priv(udev);
337
338         priv->base = (void __iomem *)(ulong)dev_read_addr(udev);
339         if (priv->base == (void __iomem *)FDT_ADDR_T_NONE)
340                 return -EINVAL;
341
342         return 0;
343 }
344
345 static int virtio_mmio_probe(struct udevice *udev)
346 {
347         struct virtio_mmio_priv *priv = dev_get_priv(udev);
348         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
349         u32 magic;
350
351         /* Check magic value */
352         magic = readl(priv->base + VIRTIO_MMIO_MAGIC_VALUE);
353         if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
354                 debug("(%s): wrong magic value 0x%08x!\n", udev->name, magic);
355                 return 0;
356         }
357
358         /* Check device version */
359         priv->version = readl(priv->base + VIRTIO_MMIO_VERSION);
360         if (priv->version < 1 || priv->version > 2) {
361                 debug("(%s): version %d not supported!\n",
362                       udev->name, priv->version);
363                 return 0;
364         }
365
366         /* Check devicd ID */
367         uc_priv->device = readl(priv->base + VIRTIO_MMIO_DEVICE_ID);
368         if (uc_priv->device == 0) {
369                 /*
370                  * virtio-mmio device with an ID 0 is a (dummy) placeholder
371                  * with no function. End probing now with no error reported.
372                  */
373                 return 0;
374         }
375         uc_priv->vendor = readl(priv->base + VIRTIO_MMIO_VENDOR_ID);
376
377         if (priv->version == 1)
378                 writel(PAGE_SIZE, priv->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
379
380         debug("(%s): device (%d) vendor (%08x) version (%d)\n", udev->name,
381               uc_priv->device, uc_priv->vendor, priv->version);
382
383         return 0;
384 }
385
386 static const struct dm_virtio_ops virtio_mmio_ops = {
387         .get_config     = virtio_mmio_get_config,
388         .set_config     = virtio_mmio_set_config,
389         .generation     = virtio_mmio_generation,
390         .get_status     = virtio_mmio_get_status,
391         .set_status     = virtio_mmio_set_status,
392         .reset          = virtio_mmio_reset,
393         .get_features   = virtio_mmio_get_features,
394         .set_features   = virtio_mmio_set_features,
395         .find_vqs       = virtio_mmio_find_vqs,
396         .del_vqs        = virtio_mmio_del_vqs,
397         .notify         = virtio_mmio_notify,
398 };
399
400 static const struct udevice_id virtio_mmio_ids[] = {
401         { .compatible = "virtio,mmio" },
402         { }
403 };
404
405 U_BOOT_DRIVER(virtio_mmio) = {
406         .name   = "virtio-mmio",
407         .id     = UCLASS_VIRTIO,
408         .of_match = virtio_mmio_ids,
409         .ops    = &virtio_mmio_ops,
410         .probe  = virtio_mmio_probe,
411         .ofdata_to_platdata = virtio_mmio_ofdata_to_platdata,
412         .priv_auto_alloc_size = sizeof(struct virtio_mmio_priv),
413 };