blob: b34f1d60455e554cb3b2ddf0b7fd0bd357c9b163 [file] [log] [blame]
Bin Meng640aae02018-10-15 02:21:25 -07001// 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>
Simon Glasseb41d8a2020-05-10 11:40:08 -060013#include <linux/bug.h>
Bin Meng640aae02018-10-15 02:21:25 -070014#include <linux/compat.h>
Simon Glass61b29b82020-02-03 07:36:15 -070015#include <linux/err.h>
Bin Meng640aae02018-10-15 02:21:25 -070016#include <linux/io.h>
17
18struct virtio_sandbox_priv {
19 u8 id;
20 u8 status;
21 u64 device_features;
22 u64 driver_features;
23 ulong queue_desc;
24 ulong queue_available;
25 ulong queue_used;
26};
27
28static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
29 void *buf, unsigned int len)
30{
31 return 0;
32}
33
34static int virtio_sandbox_set_config(struct udevice *udev, unsigned int offset,
35 const void *buf, unsigned int len)
36{
37 return 0;
38}
39
40static int virtio_sandbox_get_status(struct udevice *udev, u8 *status)
41{
42 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
43
44 *status = priv->status;
45
46 return 0;
47}
48
49static int virtio_sandbox_set_status(struct udevice *udev, u8 status)
50{
51 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
52
53 /* We should never be setting status to 0 */
54 WARN_ON(status == 0);
55
56 priv->status = status;
57
58 return 0;
59}
60
61static int virtio_sandbox_reset(struct udevice *udev)
62{
63 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
64
65 /* 0 status means a reset */
66 priv->status = 0;
67
68 return 0;
69}
70
71static int virtio_sandbox_get_features(struct udevice *udev, u64 *features)
72{
73 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
74
75 *features = priv->device_features;
76
77 return 0;
78}
79
80static int virtio_sandbox_set_features(struct udevice *udev)
81{
82 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
83 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
84
85 priv->driver_features = uc_priv->features;
86
87 return 0;
88}
89
90static struct virtqueue *virtio_sandbox_setup_vq(struct udevice *udev,
91 unsigned int index)
92{
93 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
94 struct virtqueue *vq;
95 ulong addr;
96 int err;
97
98 /* Create the vring */
99 vq = vring_create_virtqueue(index, 4, 4096, udev);
100 if (!vq) {
101 err = -ENOMEM;
102 goto error_new_virtqueue;
103 }
104
105 addr = virtqueue_get_desc_addr(vq);
106 priv->queue_desc = addr;
107
108 addr = virtqueue_get_avail_addr(vq);
109 priv->queue_available = addr;
110
111 addr = virtqueue_get_used_addr(vq);
112 priv->queue_used = addr;
113
114 return vq;
115
116error_new_virtqueue:
117 return ERR_PTR(err);
118}
119
120static void virtio_sandbox_del_vq(struct virtqueue *vq)
121{
122 vring_del_virtqueue(vq);
123}
124
125static int virtio_sandbox_del_vqs(struct udevice *udev)
126{
127 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
128 struct virtqueue *vq, *n;
129
130 list_for_each_entry_safe(vq, n, &uc_priv->vqs, list)
131 virtio_sandbox_del_vq(vq);
132
133 return 0;
134}
135
136static int virtio_sandbox_find_vqs(struct udevice *udev, unsigned int nvqs,
137 struct virtqueue *vqs[])
138{
139 int i;
140
141 for (i = 0; i < nvqs; ++i) {
142 vqs[i] = virtio_sandbox_setup_vq(udev, i);
143 if (IS_ERR(vqs[i])) {
144 virtio_sandbox_del_vqs(udev);
145 return PTR_ERR(vqs[i]);
146 }
147 }
148
149 return 0;
150}
151
152static int virtio_sandbox_notify(struct udevice *udev, struct virtqueue *vq)
153{
154 return 0;
155}
156
157static int virtio_sandbox_probe(struct udevice *udev)
158{
159 struct virtio_sandbox_priv *priv = dev_get_priv(udev);
160 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
161
162 /* fake some information for testing */
Andrew Scull1674b6c2022-05-16 10:41:34 +0000163 priv->device_features = BIT_ULL(VIRTIO_F_VERSION_1);
Simon Glass00fc8ca2023-01-17 10:47:51 -0700164 uc_priv->device = dev_read_u32_default(udev, "virtio-type",
165 VIRTIO_ID_RNG);
Bin Meng640aae02018-10-15 02:21:25 -0700166 uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';
167
168 return 0;
169}
170
Bin Meng640aae02018-10-15 02:21:25 -0700171static const struct dm_virtio_ops virtio_sandbox1_ops = {
172 .get_config = virtio_sandbox_get_config,
173 .set_config = virtio_sandbox_set_config,
174 .get_status = virtio_sandbox_get_status,
175 .set_status = virtio_sandbox_set_status,
176 .reset = virtio_sandbox_reset,
177 .get_features = virtio_sandbox_get_features,
178 .set_features = virtio_sandbox_set_features,
179 .find_vqs = virtio_sandbox_find_vqs,
180 .del_vqs = virtio_sandbox_del_vqs,
181 .notify = virtio_sandbox_notify,
182};
183
184static const struct udevice_id virtio_sandbox1_ids[] = {
185 { .compatible = "sandbox,virtio1" },
186 { }
187};
188
189U_BOOT_DRIVER(virtio_sandbox1) = {
190 .name = "virtio-sandbox1",
191 .id = UCLASS_VIRTIO,
192 .of_match = virtio_sandbox1_ids,
193 .ops = &virtio_sandbox1_ops,
194 .probe = virtio_sandbox_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700195 .priv_auto = sizeof(struct virtio_sandbox_priv),
Bin Meng640aae02018-10-15 02:21:25 -0700196};
197
198/* this one without notify op */
199static const struct dm_virtio_ops virtio_sandbox2_ops = {
200 .get_config = virtio_sandbox_get_config,
201 .set_config = virtio_sandbox_set_config,
202 .get_status = virtio_sandbox_get_status,
203 .set_status = virtio_sandbox_set_status,
204 .reset = virtio_sandbox_reset,
205 .get_features = virtio_sandbox_get_features,
206 .set_features = virtio_sandbox_set_features,
207 .find_vqs = virtio_sandbox_find_vqs,
208 .del_vqs = virtio_sandbox_del_vqs,
209};
210
211static const struct udevice_id virtio_sandbox2_ids[] = {
212 { .compatible = "sandbox,virtio2" },
213 { }
214};
215
216U_BOOT_DRIVER(virtio_sandbox2) = {
217 .name = "virtio-sandbox2",
218 .id = UCLASS_VIRTIO,
219 .of_match = virtio_sandbox2_ids,
220 .ops = &virtio_sandbox2_ops,
221 .probe = virtio_sandbox_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700222 .priv_auto = sizeof(struct virtio_sandbox_priv),
Bin Meng640aae02018-10-15 02:21:25 -0700223};