blob: 0f1ebef22e58692154881c4ff68fd6208d965fba [file] [log] [blame]
Bin Meng51a2e0e2018-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
Bin Meng51a2e0e2018-10-15 02:21:25 -07008#include <dm.h>
9#include <virtio_types.h>
10#include <virtio.h>
11#include <virtio_ring.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060012#include <linux/bug.h>
Bin Meng51a2e0e2018-10-15 02:21:25 -070013#include <linux/compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070014#include <linux/err.h>
Bin Meng51a2e0e2018-10-15 02:21:25 -070015#include <linux/io.h>
16
17struct 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
27static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
28 void *buf, unsigned int len)
29{
30 return 0;
31}
32
33static int virtio_sandbox_set_config(struct udevice *udev, unsigned int offset,
34 const void *buf, unsigned int len)
35{
36 return 0;
37}
38
39static 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
48static 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
60static 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
70static 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
79static 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
89static 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
115error_new_virtqueue:
116 return ERR_PTR(err);
117}
118
119static void virtio_sandbox_del_vq(struct virtqueue *vq)
120{
121 vring_del_virtqueue(vq);
122}
123
124static 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
135static 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
151static int virtio_sandbox_notify(struct udevice *udev, struct virtqueue *vq)
152{
153 return 0;
154}
155
156static 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 */
Andrew Scull506ba0d2022-05-16 10:41:34 +0000162 priv->device_features = BIT_ULL(VIRTIO_F_VERSION_1);
Simon Glass8de5a542023-01-17 10:47:51 -0700163 uc_priv->device = dev_read_u32_default(udev, "virtio-type",
164 VIRTIO_ID_RNG);
Bin Meng51a2e0e2018-10-15 02:21:25 -0700165 uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';
166
167 return 0;
168}
169
Bin Meng51a2e0e2018-10-15 02:21:25 -0700170static const struct dm_virtio_ops virtio_sandbox1_ops = {
171 .get_config = virtio_sandbox_get_config,
172 .set_config = virtio_sandbox_set_config,
173 .get_status = virtio_sandbox_get_status,
174 .set_status = virtio_sandbox_set_status,
175 .reset = virtio_sandbox_reset,
176 .get_features = virtio_sandbox_get_features,
177 .set_features = virtio_sandbox_set_features,
178 .find_vqs = virtio_sandbox_find_vqs,
179 .del_vqs = virtio_sandbox_del_vqs,
180 .notify = virtio_sandbox_notify,
181};
182
183static const struct udevice_id virtio_sandbox1_ids[] = {
184 { .compatible = "sandbox,virtio1" },
185 { }
186};
187
188U_BOOT_DRIVER(virtio_sandbox1) = {
189 .name = "virtio-sandbox1",
190 .id = UCLASS_VIRTIO,
191 .of_match = virtio_sandbox1_ids,
192 .ops = &virtio_sandbox1_ops,
193 .probe = virtio_sandbox_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700194 .priv_auto = sizeof(struct virtio_sandbox_priv),
Bin Meng51a2e0e2018-10-15 02:21:25 -0700195};
196
197/* this one without notify op */
198static const struct dm_virtio_ops virtio_sandbox2_ops = {
199 .get_config = virtio_sandbox_get_config,
200 .set_config = virtio_sandbox_set_config,
201 .get_status = virtio_sandbox_get_status,
202 .set_status = virtio_sandbox_set_status,
203 .reset = virtio_sandbox_reset,
204 .get_features = virtio_sandbox_get_features,
205 .set_features = virtio_sandbox_set_features,
206 .find_vqs = virtio_sandbox_find_vqs,
207 .del_vqs = virtio_sandbox_del_vqs,
208};
209
210static const struct udevice_id virtio_sandbox2_ids[] = {
211 { .compatible = "sandbox,virtio2" },
212 { }
213};
214
215U_BOOT_DRIVER(virtio_sandbox2) = {
216 .name = "virtio-sandbox2",
217 .id = UCLASS_VIRTIO,
218 .of_match = virtio_sandbox2_ids,
219 .ops = &virtio_sandbox2_ops,
220 .probe = virtio_sandbox_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700221 .priv_auto = sizeof(struct virtio_sandbox_priv),
Bin Meng51a2e0e2018-10-15 02:21:25 -0700222};