treewide: Remove unused FSL QSPI config options for IMX platforms
[oweals/u-boot.git] / drivers / virtio / virtio_sandbox.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
4  *
5  * VirtIO Sandbox transport driver, for testing purpose only
6  */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <virtio_types.h>
11 #include <virtio.h>
12 #include <virtio_ring.h>
13 #include <linux/compat.h>
14 #include <linux/err.h>
15 #include <linux/io.h>
16
17 struct virtio_sandbox_priv {
18         u8 id;
19         u8 status;
20         u64 device_features;
21         u64 driver_features;
22         ulong queue_desc;
23         ulong queue_available;
24         ulong queue_used;
25 };
26
27 static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
28                                      void *buf, unsigned int len)
29 {
30         return 0;
31 }
32
33 static int virtio_sandbox_set_config(struct udevice *udev, unsigned int offset,
34                                      const void *buf, unsigned int len)
35 {
36         return 0;
37 }
38
39 static int virtio_sandbox_get_status(struct udevice *udev, u8 *status)
40 {
41         struct virtio_sandbox_priv *priv = dev_get_priv(udev);
42
43         *status = priv->status;
44
45         return 0;
46 }
47
48 static int virtio_sandbox_set_status(struct udevice *udev, u8 status)
49 {
50         struct virtio_sandbox_priv *priv = dev_get_priv(udev);
51
52         /* We should never be setting status to 0 */
53         WARN_ON(status == 0);
54
55         priv->status = status;
56
57         return 0;
58 }
59
60 static int virtio_sandbox_reset(struct udevice *udev)
61 {
62         struct virtio_sandbox_priv *priv = dev_get_priv(udev);
63
64         /* 0 status means a reset */
65         priv->status = 0;
66
67         return 0;
68 }
69
70 static int virtio_sandbox_get_features(struct udevice *udev, u64 *features)
71 {
72         struct virtio_sandbox_priv *priv = dev_get_priv(udev);
73
74         *features = priv->device_features;
75
76         return 0;
77 }
78
79 static int virtio_sandbox_set_features(struct udevice *udev)
80 {
81         struct virtio_sandbox_priv *priv = dev_get_priv(udev);
82         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
83
84         priv->driver_features = uc_priv->features;
85
86         return 0;
87 }
88
89 static struct virtqueue *virtio_sandbox_setup_vq(struct udevice *udev,
90                                                  unsigned int index)
91 {
92         struct virtio_sandbox_priv *priv = dev_get_priv(udev);
93         struct virtqueue *vq;
94         ulong addr;
95         int err;
96
97         /* Create the vring */
98         vq = vring_create_virtqueue(index, 4, 4096, udev);
99         if (!vq) {
100                 err = -ENOMEM;
101                 goto error_new_virtqueue;
102         }
103
104         addr = virtqueue_get_desc_addr(vq);
105         priv->queue_desc = addr;
106
107         addr = virtqueue_get_avail_addr(vq);
108         priv->queue_available = addr;
109
110         addr = virtqueue_get_used_addr(vq);
111         priv->queue_used = addr;
112
113         return vq;
114
115 error_new_virtqueue:
116         return ERR_PTR(err);
117 }
118
119 static void virtio_sandbox_del_vq(struct virtqueue *vq)
120 {
121         vring_del_virtqueue(vq);
122 }
123
124 static int virtio_sandbox_del_vqs(struct udevice *udev)
125 {
126         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
127         struct virtqueue *vq, *n;
128
129         list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
130                 virtio_sandbox_del_vq(vq);
131
132         return 0;
133 }
134
135 static int virtio_sandbox_find_vqs(struct udevice *udev, unsigned int nvqs,
136                                    struct virtqueue *vqs[])
137 {
138         int i;
139
140         for (i = 0; i < nvqs; ++i) {
141                 vqs[i] = virtio_sandbox_setup_vq(udev, i);
142                 if (IS_ERR(vqs[i])) {
143                         virtio_sandbox_del_vqs(udev);
144                         return PTR_ERR(vqs[i]);
145                 }
146         }
147
148         return 0;
149 }
150
151 static int virtio_sandbox_notify(struct udevice *udev, struct virtqueue *vq)
152 {
153         return 0;
154 }
155
156 static int virtio_sandbox_probe(struct udevice *udev)
157 {
158         struct virtio_sandbox_priv *priv = dev_get_priv(udev);
159         struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
160
161         /* fake some information for testing */
162         priv->device_features = VIRTIO_F_VERSION_1;
163         uc_priv->device = VIRTIO_ID_BLOCK;
164         uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';
165
166         return 0;
167 }
168
169 /* check virtio device driver's remove routine was called to reset the device */
170 static int virtio_sandbox_child_post_remove(struct udevice *vdev)
171 {
172         u8 status;
173
174         virtio_get_status(vdev, &status);
175         if (status)
176                 panic("virtio device was not reset\n");
177
178         return 0;
179 }
180
181 static const struct dm_virtio_ops virtio_sandbox1_ops = {
182         .get_config     = virtio_sandbox_get_config,
183         .set_config     = virtio_sandbox_set_config,
184         .get_status     = virtio_sandbox_get_status,
185         .set_status     = virtio_sandbox_set_status,
186         .reset          = virtio_sandbox_reset,
187         .get_features   = virtio_sandbox_get_features,
188         .set_features   = virtio_sandbox_set_features,
189         .find_vqs       = virtio_sandbox_find_vqs,
190         .del_vqs        = virtio_sandbox_del_vqs,
191         .notify         = virtio_sandbox_notify,
192 };
193
194 static const struct udevice_id virtio_sandbox1_ids[] = {
195         { .compatible = "sandbox,virtio1" },
196         { }
197 };
198
199 U_BOOT_DRIVER(virtio_sandbox1) = {
200         .name   = "virtio-sandbox1",
201         .id     = UCLASS_VIRTIO,
202         .of_match = virtio_sandbox1_ids,
203         .ops    = &virtio_sandbox1_ops,
204         .probe  = virtio_sandbox_probe,
205         .child_post_remove = virtio_sandbox_child_post_remove,
206         .priv_auto_alloc_size = sizeof(struct virtio_sandbox_priv),
207 };
208
209 /* this one without notify op */
210 static const struct dm_virtio_ops virtio_sandbox2_ops = {
211         .get_config     = virtio_sandbox_get_config,
212         .set_config     = virtio_sandbox_set_config,
213         .get_status     = virtio_sandbox_get_status,
214         .set_status     = virtio_sandbox_set_status,
215         .reset          = virtio_sandbox_reset,
216         .get_features   = virtio_sandbox_get_features,
217         .set_features   = virtio_sandbox_set_features,
218         .find_vqs       = virtio_sandbox_find_vqs,
219         .del_vqs        = virtio_sandbox_del_vqs,
220 };
221
222 static const struct udevice_id virtio_sandbox2_ids[] = {
223         { .compatible = "sandbox,virtio2" },
224         { }
225 };
226
227 U_BOOT_DRIVER(virtio_sandbox2) = {
228         .name   = "virtio-sandbox2",
229         .id     = UCLASS_VIRTIO,
230         .of_match = virtio_sandbox2_ids,
231         .ops    = &virtio_sandbox2_ops,
232         .probe  = virtio_sandbox_probe,
233         .priv_auto_alloc_size = sizeof(struct virtio_sandbox_priv),
234 };