1*8fb49b4cSBin Meng /* SPDX-License-Identifier: GPL-2.0+ */
2*8fb49b4cSBin Meng /*
3*8fb49b4cSBin Meng * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4*8fb49b4cSBin Meng * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5*8fb49b4cSBin Meng *
6*8fb49b4cSBin Meng * VirtIO is a virtualization standard for network and disk device drivers
7*8fb49b4cSBin Meng * where just the guest's device driver "knows" it is running in a virtual
8*8fb49b4cSBin Meng * environment, and cooperates with the hypervisor. This enables guests to
9*8fb49b4cSBin Meng * get high performance network and disk operations, and gives most of the
10*8fb49b4cSBin Meng * performance benefits of paravirtualization. In the U-Boot case, the guest
11*8fb49b4cSBin Meng * is U-Boot itself, while the virtual environment are normally QEMU targets
12*8fb49b4cSBin Meng * like ARM, RISC-V and x86.
13*8fb49b4cSBin Meng *
14*8fb49b4cSBin Meng * See http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf for
15*8fb49b4cSBin Meng * the VirtIO specification v1.0.
16*8fb49b4cSBin Meng *
17*8fb49b4cSBin Meng * This file is largely based on Linux kernel virtio_*.h files
18*8fb49b4cSBin Meng */
19*8fb49b4cSBin Meng
20*8fb49b4cSBin Meng #ifndef __VIRTIO_H__
21*8fb49b4cSBin Meng #define __VIRTIO_H__
22*8fb49b4cSBin Meng
23*8fb49b4cSBin Meng #define VIRTIO_ID_NET 1 /* virtio net */
24*8fb49b4cSBin Meng #define VIRTIO_ID_BLOCK 2 /* virtio block */
25*8fb49b4cSBin Meng #define VIRTIO_ID_MAX_NUM 3
26*8fb49b4cSBin Meng
27*8fb49b4cSBin Meng #define VIRTIO_NET_DRV_NAME "virtio-net"
28*8fb49b4cSBin Meng #define VIRTIO_BLK_DRV_NAME "virtio-blk"
29*8fb49b4cSBin Meng
30*8fb49b4cSBin Meng /* Status byte for guest to report progress, and synchronize features */
31*8fb49b4cSBin Meng
32*8fb49b4cSBin Meng /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
33*8fb49b4cSBin Meng #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
34*8fb49b4cSBin Meng /* We have found a driver for the device */
35*8fb49b4cSBin Meng #define VIRTIO_CONFIG_S_DRIVER 2
36*8fb49b4cSBin Meng /* Driver has used its parts of the config, and is happy */
37*8fb49b4cSBin Meng #define VIRTIO_CONFIG_S_DRIVER_OK 4
38*8fb49b4cSBin Meng /* Driver has finished configuring features */
39*8fb49b4cSBin Meng #define VIRTIO_CONFIG_S_FEATURES_OK 8
40*8fb49b4cSBin Meng /* Device entered invalid state, driver must reset it */
41*8fb49b4cSBin Meng #define VIRTIO_CONFIG_S_NEEDS_RESET 0x40
42*8fb49b4cSBin Meng /* We've given up on this device */
43*8fb49b4cSBin Meng #define VIRTIO_CONFIG_S_FAILED 0x80
44*8fb49b4cSBin Meng
45*8fb49b4cSBin Meng /*
46*8fb49b4cSBin Meng * Virtio feature bits VIRTIO_TRANSPORT_F_START through VIRTIO_TRANSPORT_F_END
47*8fb49b4cSBin Meng * are reserved for the transport being used (eg: virtio_ring, virtio_pci etc.),
48*8fb49b4cSBin Meng * the rest are per-device feature bits.
49*8fb49b4cSBin Meng */
50*8fb49b4cSBin Meng #define VIRTIO_TRANSPORT_F_START 28
51*8fb49b4cSBin Meng #define VIRTIO_TRANSPORT_F_END 38
52*8fb49b4cSBin Meng
53*8fb49b4cSBin Meng #ifndef VIRTIO_CONFIG_NO_LEGACY
54*8fb49b4cSBin Meng /*
55*8fb49b4cSBin Meng * Do we get callbacks when the ring is completely used,
56*8fb49b4cSBin Meng * even if we've suppressed them?
57*8fb49b4cSBin Meng */
58*8fb49b4cSBin Meng #define VIRTIO_F_NOTIFY_ON_EMPTY 24
59*8fb49b4cSBin Meng
60*8fb49b4cSBin Meng /* Can the device handle any descriptor layout? */
61*8fb49b4cSBin Meng #define VIRTIO_F_ANY_LAYOUT 27
62*8fb49b4cSBin Meng #endif /* VIRTIO_CONFIG_NO_LEGACY */
63*8fb49b4cSBin Meng
64*8fb49b4cSBin Meng /* v1.0 compliant */
65*8fb49b4cSBin Meng #define VIRTIO_F_VERSION_1 32
66*8fb49b4cSBin Meng
67*8fb49b4cSBin Meng /*
68*8fb49b4cSBin Meng * If clear - device has the IOMMU bypass quirk feature.
69*8fb49b4cSBin Meng * If set - use platform tools to detect the IOMMU.
70*8fb49b4cSBin Meng *
71*8fb49b4cSBin Meng * Note the reverse polarity (compared to most other features),
72*8fb49b4cSBin Meng * this is for compatibility with legacy systems.
73*8fb49b4cSBin Meng */
74*8fb49b4cSBin Meng #define VIRTIO_F_IOMMU_PLATFORM 33
75*8fb49b4cSBin Meng
76*8fb49b4cSBin Meng /* Does the device support Single Root I/O Virtualization? */
77*8fb49b4cSBin Meng #define VIRTIO_F_SR_IOV 37
78*8fb49b4cSBin Meng
79*8fb49b4cSBin Meng /**
80*8fb49b4cSBin Meng * virtio scatter-gather struct
81*8fb49b4cSBin Meng *
82*8fb49b4cSBin Meng * @addr: sg buffer address
83*8fb49b4cSBin Meng * @lengh: sg buffer length
84*8fb49b4cSBin Meng */
85*8fb49b4cSBin Meng struct virtio_sg {
86*8fb49b4cSBin Meng void *addr;
87*8fb49b4cSBin Meng size_t length;
88*8fb49b4cSBin Meng };
89*8fb49b4cSBin Meng
90*8fb49b4cSBin Meng struct virtqueue;
91*8fb49b4cSBin Meng
92*8fb49b4cSBin Meng /* virtio bus operations */
93*8fb49b4cSBin Meng struct dm_virtio_ops {
94*8fb49b4cSBin Meng /**
95*8fb49b4cSBin Meng * get_config() - read the value of a configuration field
96*8fb49b4cSBin Meng *
97*8fb49b4cSBin Meng * @vdev: the real virtio device
98*8fb49b4cSBin Meng * @offset: the offset of the configuration field
99*8fb49b4cSBin Meng * @buf: the buffer to write the field value into
100*8fb49b4cSBin Meng * @len: the length of the buffer
101*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
102*8fb49b4cSBin Meng */
103*8fb49b4cSBin Meng int (*get_config)(struct udevice *vdev, unsigned int offset,
104*8fb49b4cSBin Meng void *buf, unsigned int len);
105*8fb49b4cSBin Meng /**
106*8fb49b4cSBin Meng * set_config() - write the value of a configuration field
107*8fb49b4cSBin Meng *
108*8fb49b4cSBin Meng * @vdev: the real virtio device
109*8fb49b4cSBin Meng * @offset: the offset of the configuration field
110*8fb49b4cSBin Meng * @buf: the buffer to read the field value from
111*8fb49b4cSBin Meng * @len: the length of the buffer
112*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
113*8fb49b4cSBin Meng */
114*8fb49b4cSBin Meng int (*set_config)(struct udevice *vdev, unsigned int offset,
115*8fb49b4cSBin Meng const void *buf, unsigned int len);
116*8fb49b4cSBin Meng /**
117*8fb49b4cSBin Meng * generation() - config generation counter
118*8fb49b4cSBin Meng *
119*8fb49b4cSBin Meng * @vdev: the real virtio device
120*8fb49b4cSBin Meng * @counter: the returned config generation counter
121*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
122*8fb49b4cSBin Meng */
123*8fb49b4cSBin Meng int (*generation)(struct udevice *vdev, u32 *counter);
124*8fb49b4cSBin Meng /**
125*8fb49b4cSBin Meng * get_status() - read the status byte
126*8fb49b4cSBin Meng *
127*8fb49b4cSBin Meng * @vdev: the real virtio device
128*8fb49b4cSBin Meng * @status: the returned status byte
129*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
130*8fb49b4cSBin Meng */
131*8fb49b4cSBin Meng int (*get_status)(struct udevice *vdev, u8 *status);
132*8fb49b4cSBin Meng /**
133*8fb49b4cSBin Meng * set_status() - write the status byte
134*8fb49b4cSBin Meng *
135*8fb49b4cSBin Meng * @vdev: the real virtio device
136*8fb49b4cSBin Meng * @status: the new status byte
137*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
138*8fb49b4cSBin Meng */
139*8fb49b4cSBin Meng int (*set_status)(struct udevice *vdev, u8 status);
140*8fb49b4cSBin Meng /**
141*8fb49b4cSBin Meng * reset() - reset the device
142*8fb49b4cSBin Meng *
143*8fb49b4cSBin Meng * @vdev: the real virtio device
144*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
145*8fb49b4cSBin Meng */
146*8fb49b4cSBin Meng int (*reset)(struct udevice *vdev);
147*8fb49b4cSBin Meng /**
148*8fb49b4cSBin Meng * get_features() - get the array of feature bits for this device
149*8fb49b4cSBin Meng *
150*8fb49b4cSBin Meng * @vdev: the real virtio device
151*8fb49b4cSBin Meng * @features: the first 32 feature bits (all we currently need)
152*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
153*8fb49b4cSBin Meng */
154*8fb49b4cSBin Meng int (*get_features)(struct udevice *vdev, u64 *features);
155*8fb49b4cSBin Meng /**
156*8fb49b4cSBin Meng * set_features() - confirm what device features we'll be using
157*8fb49b4cSBin Meng *
158*8fb49b4cSBin Meng * @vdev: the real virtio device
159*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
160*8fb49b4cSBin Meng */
161*8fb49b4cSBin Meng int (*set_features)(struct udevice *vdev);
162*8fb49b4cSBin Meng /**
163*8fb49b4cSBin Meng * find_vqs() - find virtqueues and instantiate them
164*8fb49b4cSBin Meng *
165*8fb49b4cSBin Meng * @vdev: the real virtio device
166*8fb49b4cSBin Meng * @nvqs: the number of virtqueues to find
167*8fb49b4cSBin Meng * @vqs: on success, includes new virtqueues
168*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
169*8fb49b4cSBin Meng */
170*8fb49b4cSBin Meng int (*find_vqs)(struct udevice *vdev, unsigned int nvqs,
171*8fb49b4cSBin Meng struct virtqueue *vqs[]);
172*8fb49b4cSBin Meng /**
173*8fb49b4cSBin Meng * del_vqs() - free virtqueues found by find_vqs()
174*8fb49b4cSBin Meng *
175*8fb49b4cSBin Meng * @vdev: the real virtio device
176*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
177*8fb49b4cSBin Meng */
178*8fb49b4cSBin Meng int (*del_vqs)(struct udevice *vdev);
179*8fb49b4cSBin Meng /**
180*8fb49b4cSBin Meng * notify() - notify the device to process the queue
181*8fb49b4cSBin Meng *
182*8fb49b4cSBin Meng * @vdev: the real virtio device
183*8fb49b4cSBin Meng * @vq: virtqueue to process
184*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
185*8fb49b4cSBin Meng */
186*8fb49b4cSBin Meng int (*notify)(struct udevice *vdev, struct virtqueue *vq);
187*8fb49b4cSBin Meng };
188*8fb49b4cSBin Meng
189*8fb49b4cSBin Meng /* Get access to a virtio bus' operations */
190*8fb49b4cSBin Meng #define virtio_get_ops(dev) ((struct dm_virtio_ops *)(dev)->driver->ops)
191*8fb49b4cSBin Meng
192*8fb49b4cSBin Meng /**
193*8fb49b4cSBin Meng * virtio uclass per device private data
194*8fb49b4cSBin Meng *
195*8fb49b4cSBin Meng * @vqs: virtualqueue for the virtio device
196*8fb49b4cSBin Meng * @vdev: the real virtio device underneath
197*8fb49b4cSBin Meng * @legacy: is it a legacy device?
198*8fb49b4cSBin Meng * @device: virtio device ID
199*8fb49b4cSBin Meng * @vendor: virtio vendor ID
200*8fb49b4cSBin Meng * @features: negotiated supported features
201*8fb49b4cSBin Meng * @feature_table: an array of feature supported by the driver
202*8fb49b4cSBin Meng * @feature_table_size: number of entries in the feature table array
203*8fb49b4cSBin Meng * @feature_table_legacy: same as feature_table but working in legacy mode
204*8fb49b4cSBin Meng * @feature_table_size_legacy: number of entries in feature table legacy array
205*8fb49b4cSBin Meng */
206*8fb49b4cSBin Meng struct virtio_dev_priv {
207*8fb49b4cSBin Meng struct list_head vqs;
208*8fb49b4cSBin Meng struct udevice *vdev;
209*8fb49b4cSBin Meng bool legacy;
210*8fb49b4cSBin Meng u32 device;
211*8fb49b4cSBin Meng u32 vendor;
212*8fb49b4cSBin Meng u64 features;
213*8fb49b4cSBin Meng const u32 *feature_table;
214*8fb49b4cSBin Meng u32 feature_table_size;
215*8fb49b4cSBin Meng const u32 *feature_table_legacy;
216*8fb49b4cSBin Meng u32 feature_table_size_legacy;
217*8fb49b4cSBin Meng };
218*8fb49b4cSBin Meng
219*8fb49b4cSBin Meng /**
220*8fb49b4cSBin Meng * virtio_get_config() - read the value of a configuration field
221*8fb49b4cSBin Meng *
222*8fb49b4cSBin Meng * @vdev: the real virtio device
223*8fb49b4cSBin Meng * @offset: the offset of the configuration field
224*8fb49b4cSBin Meng * @buf: the buffer to write the field value into
225*8fb49b4cSBin Meng * @len: the length of the buffer
226*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
227*8fb49b4cSBin Meng */
228*8fb49b4cSBin Meng int virtio_get_config(struct udevice *vdev, unsigned int offset,
229*8fb49b4cSBin Meng void *buf, unsigned int len);
230*8fb49b4cSBin Meng
231*8fb49b4cSBin Meng /**
232*8fb49b4cSBin Meng * virtio_set_config() - write the value of a configuration field
233*8fb49b4cSBin Meng *
234*8fb49b4cSBin Meng * @vdev: the real virtio device
235*8fb49b4cSBin Meng * @offset: the offset of the configuration field
236*8fb49b4cSBin Meng * @buf: the buffer to read the field value from
237*8fb49b4cSBin Meng * @len: the length of the buffer
238*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
239*8fb49b4cSBin Meng */
240*8fb49b4cSBin Meng int virtio_set_config(struct udevice *vdev, unsigned int offset,
241*8fb49b4cSBin Meng void *buf, unsigned int len);
242*8fb49b4cSBin Meng
243*8fb49b4cSBin Meng /**
244*8fb49b4cSBin Meng * virtio_generation() - config generation counter
245*8fb49b4cSBin Meng *
246*8fb49b4cSBin Meng * @vdev: the real virtio device
247*8fb49b4cSBin Meng * @counter: the returned config generation counter
248*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
249*8fb49b4cSBin Meng */
250*8fb49b4cSBin Meng int virtio_generation(struct udevice *vdev, u32 *counter);
251*8fb49b4cSBin Meng
252*8fb49b4cSBin Meng /**
253*8fb49b4cSBin Meng * virtio_get_status() - read the status byte
254*8fb49b4cSBin Meng *
255*8fb49b4cSBin Meng * @vdev: the real virtio device
256*8fb49b4cSBin Meng * @status: the returned status byte
257*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
258*8fb49b4cSBin Meng */
259*8fb49b4cSBin Meng int virtio_get_status(struct udevice *vdev, u8 *status);
260*8fb49b4cSBin Meng
261*8fb49b4cSBin Meng /**
262*8fb49b4cSBin Meng * virtio_set_status() - write the status byte
263*8fb49b4cSBin Meng *
264*8fb49b4cSBin Meng * @vdev: the real virtio device
265*8fb49b4cSBin Meng * @status: the new status byte
266*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
267*8fb49b4cSBin Meng */
268*8fb49b4cSBin Meng int virtio_set_status(struct udevice *vdev, u8 status);
269*8fb49b4cSBin Meng
270*8fb49b4cSBin Meng /**
271*8fb49b4cSBin Meng * virtio_reset() - reset the device
272*8fb49b4cSBin Meng *
273*8fb49b4cSBin Meng * @vdev: the real virtio device
274*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
275*8fb49b4cSBin Meng */
276*8fb49b4cSBin Meng int virtio_reset(struct udevice *vdev);
277*8fb49b4cSBin Meng
278*8fb49b4cSBin Meng /**
279*8fb49b4cSBin Meng * virtio_get_features() - get the array of feature bits for this device
280*8fb49b4cSBin Meng *
281*8fb49b4cSBin Meng * @vdev: the real virtio device
282*8fb49b4cSBin Meng * @features: the first 32 feature bits (all we currently need)
283*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
284*8fb49b4cSBin Meng */
285*8fb49b4cSBin Meng int virtio_get_features(struct udevice *vdev, u64 *features);
286*8fb49b4cSBin Meng
287*8fb49b4cSBin Meng /**
288*8fb49b4cSBin Meng * virtio_set_features() - confirm what device features we'll be using
289*8fb49b4cSBin Meng *
290*8fb49b4cSBin Meng * @vdev: the real virtio device
291*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
292*8fb49b4cSBin Meng */
293*8fb49b4cSBin Meng int virtio_set_features(struct udevice *vdev);
294*8fb49b4cSBin Meng
295*8fb49b4cSBin Meng /**
296*8fb49b4cSBin Meng * virtio_find_vqs() - find virtqueues and instantiate them
297*8fb49b4cSBin Meng *
298*8fb49b4cSBin Meng * @vdev: the real virtio device
299*8fb49b4cSBin Meng * @nvqs: the number of virtqueues to find
300*8fb49b4cSBin Meng * @vqs: on success, includes new virtqueues
301*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
302*8fb49b4cSBin Meng */
303*8fb49b4cSBin Meng int virtio_find_vqs(struct udevice *vdev, unsigned int nvqs,
304*8fb49b4cSBin Meng struct virtqueue *vqs[]);
305*8fb49b4cSBin Meng
306*8fb49b4cSBin Meng /**
307*8fb49b4cSBin Meng * virtio_del_vqs() - free virtqueues found by find_vqs()
308*8fb49b4cSBin Meng *
309*8fb49b4cSBin Meng * @vdev: the real virtio device
310*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
311*8fb49b4cSBin Meng */
312*8fb49b4cSBin Meng int virtio_del_vqs(struct udevice *vdev);
313*8fb49b4cSBin Meng
314*8fb49b4cSBin Meng /**
315*8fb49b4cSBin Meng * virtio_notify() - notify the device to process the queue
316*8fb49b4cSBin Meng *
317*8fb49b4cSBin Meng * @vdev: the real virtio device
318*8fb49b4cSBin Meng * @vq: virtqueue to process
319*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
320*8fb49b4cSBin Meng */
321*8fb49b4cSBin Meng int virtio_notify(struct udevice *vdev, struct virtqueue *vq);
322*8fb49b4cSBin Meng
323*8fb49b4cSBin Meng /**
324*8fb49b4cSBin Meng * virtio_add_status() - helper to set a new status code to the device
325*8fb49b4cSBin Meng *
326*8fb49b4cSBin Meng * @vdev: the real virtio device
327*8fb49b4cSBin Meng * @status: new status code to be added
328*8fb49b4cSBin Meng */
329*8fb49b4cSBin Meng void virtio_add_status(struct udevice *vdev, u8 status);
330*8fb49b4cSBin Meng
331*8fb49b4cSBin Meng /**
332*8fb49b4cSBin Meng * virtio_finalize_features() - helper to finalize features
333*8fb49b4cSBin Meng *
334*8fb49b4cSBin Meng * @vdev: the real virtio device
335*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
336*8fb49b4cSBin Meng */
337*8fb49b4cSBin Meng int virtio_finalize_features(struct udevice *vdev);
338*8fb49b4cSBin Meng
339*8fb49b4cSBin Meng /**
340*8fb49b4cSBin Meng * virtio_driver_features_init() - initialize driver supported features
341*8fb49b4cSBin Meng *
342*8fb49b4cSBin Meng * This fills in the virtio device parent per child private data with the given
343*8fb49b4cSBin Meng * information, which contains driver supported features and legacy features.
344*8fb49b4cSBin Meng *
345*8fb49b4cSBin Meng * This API should be called in the virtio device driver's bind method, so that
346*8fb49b4cSBin Meng * later virtio transport uclass driver can utilize the driver supplied features
347*8fb49b4cSBin Meng * to negotiate with the device on the final supported features.
348*8fb49b4cSBin Meng *
349*8fb49b4cSBin Meng * @priv: virtio uclass per device private data
350*8fb49b4cSBin Meng * @feature: an array of feature supported by the driver
351*8fb49b4cSBin Meng * @feature_size: number of entries in the feature table array
352*8fb49b4cSBin Meng * @feature_legacy: same as feature_table but working in legacy mode
353*8fb49b4cSBin Meng * @feature_legacy_size:number of entries in feature table legacy array
354*8fb49b4cSBin Meng */
355*8fb49b4cSBin Meng void virtio_driver_features_init(struct virtio_dev_priv *priv,
356*8fb49b4cSBin Meng const u32 *feature,
357*8fb49b4cSBin Meng u32 feature_size,
358*8fb49b4cSBin Meng const u32 *feature_legacy,
359*8fb49b4cSBin Meng u32 feature_legacy_size);
360*8fb49b4cSBin Meng
361*8fb49b4cSBin Meng /**
362*8fb49b4cSBin Meng * virtio_init() - helper to enumerate all known virtio devices
363*8fb49b4cSBin Meng *
364*8fb49b4cSBin Meng * @return 0 if OK, -ve on error
365*8fb49b4cSBin Meng */
366*8fb49b4cSBin Meng int virtio_init(void);
367*8fb49b4cSBin Meng
__virtio16_to_cpu(bool little_endian,__virtio16 val)368*8fb49b4cSBin Meng static inline u16 __virtio16_to_cpu(bool little_endian, __virtio16 val)
369*8fb49b4cSBin Meng {
370*8fb49b4cSBin Meng if (little_endian)
371*8fb49b4cSBin Meng return le16_to_cpu((__force __le16)val);
372*8fb49b4cSBin Meng else
373*8fb49b4cSBin Meng return be16_to_cpu((__force __be16)val);
374*8fb49b4cSBin Meng }
375*8fb49b4cSBin Meng
__cpu_to_virtio16(bool little_endian,u16 val)376*8fb49b4cSBin Meng static inline __virtio16 __cpu_to_virtio16(bool little_endian, u16 val)
377*8fb49b4cSBin Meng {
378*8fb49b4cSBin Meng if (little_endian)
379*8fb49b4cSBin Meng return (__force __virtio16)cpu_to_le16(val);
380*8fb49b4cSBin Meng else
381*8fb49b4cSBin Meng return (__force __virtio16)cpu_to_be16(val);
382*8fb49b4cSBin Meng }
383*8fb49b4cSBin Meng
__virtio32_to_cpu(bool little_endian,__virtio32 val)384*8fb49b4cSBin Meng static inline u32 __virtio32_to_cpu(bool little_endian, __virtio32 val)
385*8fb49b4cSBin Meng {
386*8fb49b4cSBin Meng if (little_endian)
387*8fb49b4cSBin Meng return le32_to_cpu((__force __le32)val);
388*8fb49b4cSBin Meng else
389*8fb49b4cSBin Meng return be32_to_cpu((__force __be32)val);
390*8fb49b4cSBin Meng }
391*8fb49b4cSBin Meng
__cpu_to_virtio32(bool little_endian,u32 val)392*8fb49b4cSBin Meng static inline __virtio32 __cpu_to_virtio32(bool little_endian, u32 val)
393*8fb49b4cSBin Meng {
394*8fb49b4cSBin Meng if (little_endian)
395*8fb49b4cSBin Meng return (__force __virtio32)cpu_to_le32(val);
396*8fb49b4cSBin Meng else
397*8fb49b4cSBin Meng return (__force __virtio32)cpu_to_be32(val);
398*8fb49b4cSBin Meng }
399*8fb49b4cSBin Meng
__virtio64_to_cpu(bool little_endian,__virtio64 val)400*8fb49b4cSBin Meng static inline u64 __virtio64_to_cpu(bool little_endian, __virtio64 val)
401*8fb49b4cSBin Meng {
402*8fb49b4cSBin Meng if (little_endian)
403*8fb49b4cSBin Meng return le64_to_cpu((__force __le64)val);
404*8fb49b4cSBin Meng else
405*8fb49b4cSBin Meng return be64_to_cpu((__force __be64)val);
406*8fb49b4cSBin Meng }
407*8fb49b4cSBin Meng
__cpu_to_virtio64(bool little_endian,u64 val)408*8fb49b4cSBin Meng static inline __virtio64 __cpu_to_virtio64(bool little_endian, u64 val)
409*8fb49b4cSBin Meng {
410*8fb49b4cSBin Meng if (little_endian)
411*8fb49b4cSBin Meng return (__force __virtio64)cpu_to_le64(val);
412*8fb49b4cSBin Meng else
413*8fb49b4cSBin Meng return (__force __virtio64)cpu_to_be64(val);
414*8fb49b4cSBin Meng }
415*8fb49b4cSBin Meng
416*8fb49b4cSBin Meng /**
417*8fb49b4cSBin Meng * __virtio_test_bit - helper to test feature bits
418*8fb49b4cSBin Meng *
419*8fb49b4cSBin Meng * For use by transports. Devices should normally use virtio_has_feature,
420*8fb49b4cSBin Meng * which includes more checks.
421*8fb49b4cSBin Meng *
422*8fb49b4cSBin Meng * @udev: the transport device
423*8fb49b4cSBin Meng * @fbit: the feature bit
424*8fb49b4cSBin Meng */
__virtio_test_bit(struct udevice * udev,unsigned int fbit)425*8fb49b4cSBin Meng static inline bool __virtio_test_bit(struct udevice *udev, unsigned int fbit)
426*8fb49b4cSBin Meng {
427*8fb49b4cSBin Meng struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
428*8fb49b4cSBin Meng
429*8fb49b4cSBin Meng /* Did you forget to fix assumptions on max features? */
430*8fb49b4cSBin Meng if (__builtin_constant_p(fbit))
431*8fb49b4cSBin Meng BUILD_BUG_ON(fbit >= 64);
432*8fb49b4cSBin Meng else
433*8fb49b4cSBin Meng WARN_ON(fbit >= 64);
434*8fb49b4cSBin Meng
435*8fb49b4cSBin Meng return uc_priv->features & BIT_ULL(fbit);
436*8fb49b4cSBin Meng }
437*8fb49b4cSBin Meng
438*8fb49b4cSBin Meng /**
439*8fb49b4cSBin Meng * __virtio_set_bit - helper to set feature bits
440*8fb49b4cSBin Meng *
441*8fb49b4cSBin Meng * For use by transports.
442*8fb49b4cSBin Meng *
443*8fb49b4cSBin Meng * @udev: the transport device
444*8fb49b4cSBin Meng * @fbit: the feature bit
445*8fb49b4cSBin Meng */
__virtio_set_bit(struct udevice * udev,unsigned int fbit)446*8fb49b4cSBin Meng static inline void __virtio_set_bit(struct udevice *udev, unsigned int fbit)
447*8fb49b4cSBin Meng {
448*8fb49b4cSBin Meng struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
449*8fb49b4cSBin Meng
450*8fb49b4cSBin Meng /* Did you forget to fix assumptions on max features? */
451*8fb49b4cSBin Meng if (__builtin_constant_p(fbit))
452*8fb49b4cSBin Meng BUILD_BUG_ON(fbit >= 64);
453*8fb49b4cSBin Meng else
454*8fb49b4cSBin Meng WARN_ON(fbit >= 64);
455*8fb49b4cSBin Meng
456*8fb49b4cSBin Meng uc_priv->features |= BIT_ULL(fbit);
457*8fb49b4cSBin Meng }
458*8fb49b4cSBin Meng
459*8fb49b4cSBin Meng /**
460*8fb49b4cSBin Meng * __virtio_clear_bit - helper to clear feature bits
461*8fb49b4cSBin Meng *
462*8fb49b4cSBin Meng * For use by transports.
463*8fb49b4cSBin Meng *
464*8fb49b4cSBin Meng * @vdev: the transport device
465*8fb49b4cSBin Meng * @fbit: the feature bit
466*8fb49b4cSBin Meng */
__virtio_clear_bit(struct udevice * udev,unsigned int fbit)467*8fb49b4cSBin Meng static inline void __virtio_clear_bit(struct udevice *udev, unsigned int fbit)
468*8fb49b4cSBin Meng {
469*8fb49b4cSBin Meng struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
470*8fb49b4cSBin Meng
471*8fb49b4cSBin Meng /* Did you forget to fix assumptions on max features? */
472*8fb49b4cSBin Meng if (__builtin_constant_p(fbit))
473*8fb49b4cSBin Meng BUILD_BUG_ON(fbit >= 64);
474*8fb49b4cSBin Meng else
475*8fb49b4cSBin Meng WARN_ON(fbit >= 64);
476*8fb49b4cSBin Meng
477*8fb49b4cSBin Meng uc_priv->features &= ~BIT_ULL(fbit);
478*8fb49b4cSBin Meng }
479*8fb49b4cSBin Meng
480*8fb49b4cSBin Meng /**
481*8fb49b4cSBin Meng * virtio_has_feature - helper to determine if this device has this feature
482*8fb49b4cSBin Meng *
483*8fb49b4cSBin Meng * Note this API is only usable after the virtio device driver's bind phase,
484*8fb49b4cSBin Meng * as the feature has been negotiated between the device and the driver.
485*8fb49b4cSBin Meng *
486*8fb49b4cSBin Meng * @vdev: the virtio device
487*8fb49b4cSBin Meng * @fbit: the feature bit
488*8fb49b4cSBin Meng */
virtio_has_feature(struct udevice * vdev,unsigned int fbit)489*8fb49b4cSBin Meng static inline bool virtio_has_feature(struct udevice *vdev, unsigned int fbit)
490*8fb49b4cSBin Meng {
491*8fb49b4cSBin Meng if (!(vdev->flags & DM_FLAG_BOUND))
492*8fb49b4cSBin Meng WARN_ON(true);
493*8fb49b4cSBin Meng
494*8fb49b4cSBin Meng return __virtio_test_bit(vdev->parent, fbit);
495*8fb49b4cSBin Meng }
496*8fb49b4cSBin Meng
virtio_legacy_is_little_endian(void)497*8fb49b4cSBin Meng static inline bool virtio_legacy_is_little_endian(void)
498*8fb49b4cSBin Meng {
499*8fb49b4cSBin Meng #ifdef __LITTLE_ENDIAN
500*8fb49b4cSBin Meng return true;
501*8fb49b4cSBin Meng #else
502*8fb49b4cSBin Meng return false;
503*8fb49b4cSBin Meng #endif
504*8fb49b4cSBin Meng }
505*8fb49b4cSBin Meng
virtio_is_little_endian(struct udevice * vdev)506*8fb49b4cSBin Meng static inline bool virtio_is_little_endian(struct udevice *vdev)
507*8fb49b4cSBin Meng {
508*8fb49b4cSBin Meng struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(vdev->parent);
509*8fb49b4cSBin Meng
510*8fb49b4cSBin Meng return !uc_priv->legacy || virtio_legacy_is_little_endian();
511*8fb49b4cSBin Meng }
512*8fb49b4cSBin Meng
513*8fb49b4cSBin Meng /* Memory accessors */
virtio16_to_cpu(struct udevice * vdev,__virtio16 val)514*8fb49b4cSBin Meng static inline u16 virtio16_to_cpu(struct udevice *vdev, __virtio16 val)
515*8fb49b4cSBin Meng {
516*8fb49b4cSBin Meng return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
517*8fb49b4cSBin Meng }
518*8fb49b4cSBin Meng
cpu_to_virtio16(struct udevice * vdev,u16 val)519*8fb49b4cSBin Meng static inline __virtio16 cpu_to_virtio16(struct udevice *vdev, u16 val)
520*8fb49b4cSBin Meng {
521*8fb49b4cSBin Meng return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
522*8fb49b4cSBin Meng }
523*8fb49b4cSBin Meng
virtio32_to_cpu(struct udevice * vdev,__virtio32 val)524*8fb49b4cSBin Meng static inline u32 virtio32_to_cpu(struct udevice *vdev, __virtio32 val)
525*8fb49b4cSBin Meng {
526*8fb49b4cSBin Meng return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
527*8fb49b4cSBin Meng }
528*8fb49b4cSBin Meng
cpu_to_virtio32(struct udevice * vdev,u32 val)529*8fb49b4cSBin Meng static inline __virtio32 cpu_to_virtio32(struct udevice *vdev, u32 val)
530*8fb49b4cSBin Meng {
531*8fb49b4cSBin Meng return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
532*8fb49b4cSBin Meng }
533*8fb49b4cSBin Meng
virtio64_to_cpu(struct udevice * vdev,__virtio64 val)534*8fb49b4cSBin Meng static inline u64 virtio64_to_cpu(struct udevice *vdev, __virtio64 val)
535*8fb49b4cSBin Meng {
536*8fb49b4cSBin Meng return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
537*8fb49b4cSBin Meng }
538*8fb49b4cSBin Meng
cpu_to_virtio64(struct udevice * vdev,u64 val)539*8fb49b4cSBin Meng static inline __virtio64 cpu_to_virtio64(struct udevice *vdev, u64 val)
540*8fb49b4cSBin Meng {
541*8fb49b4cSBin Meng return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
542*8fb49b4cSBin Meng }
543*8fb49b4cSBin Meng
544*8fb49b4cSBin Meng /* Read @count fields, @bytes each */
__virtio_cread_many(struct udevice * vdev,unsigned int offset,void * buf,size_t count,size_t bytes)545*8fb49b4cSBin Meng static inline void __virtio_cread_many(struct udevice *vdev,
546*8fb49b4cSBin Meng unsigned int offset,
547*8fb49b4cSBin Meng void *buf, size_t count, size_t bytes)
548*8fb49b4cSBin Meng {
549*8fb49b4cSBin Meng u32 old, gen;
550*8fb49b4cSBin Meng int i;
551*8fb49b4cSBin Meng
552*8fb49b4cSBin Meng /* no need to check return value as generation can be optional */
553*8fb49b4cSBin Meng virtio_generation(vdev, &gen);
554*8fb49b4cSBin Meng do {
555*8fb49b4cSBin Meng old = gen;
556*8fb49b4cSBin Meng
557*8fb49b4cSBin Meng for (i = 0; i < count; i++)
558*8fb49b4cSBin Meng virtio_get_config(vdev, offset + bytes * i,
559*8fb49b4cSBin Meng buf + i * bytes, bytes);
560*8fb49b4cSBin Meng
561*8fb49b4cSBin Meng virtio_generation(vdev, &gen);
562*8fb49b4cSBin Meng } while (gen != old);
563*8fb49b4cSBin Meng }
564*8fb49b4cSBin Meng
virtio_cread_bytes(struct udevice * vdev,unsigned int offset,void * buf,size_t len)565*8fb49b4cSBin Meng static inline void virtio_cread_bytes(struct udevice *vdev,
566*8fb49b4cSBin Meng unsigned int offset,
567*8fb49b4cSBin Meng void *buf, size_t len)
568*8fb49b4cSBin Meng {
569*8fb49b4cSBin Meng __virtio_cread_many(vdev, offset, buf, len, 1);
570*8fb49b4cSBin Meng }
571*8fb49b4cSBin Meng
virtio_cread8(struct udevice * vdev,unsigned int offset)572*8fb49b4cSBin Meng static inline u8 virtio_cread8(struct udevice *vdev, unsigned int offset)
573*8fb49b4cSBin Meng {
574*8fb49b4cSBin Meng u8 ret;
575*8fb49b4cSBin Meng
576*8fb49b4cSBin Meng virtio_get_config(vdev, offset, &ret, sizeof(ret));
577*8fb49b4cSBin Meng return ret;
578*8fb49b4cSBin Meng }
579*8fb49b4cSBin Meng
virtio_cwrite8(struct udevice * vdev,unsigned int offset,u8 val)580*8fb49b4cSBin Meng static inline void virtio_cwrite8(struct udevice *vdev,
581*8fb49b4cSBin Meng unsigned int offset, u8 val)
582*8fb49b4cSBin Meng {
583*8fb49b4cSBin Meng virtio_set_config(vdev, offset, &val, sizeof(val));
584*8fb49b4cSBin Meng }
585*8fb49b4cSBin Meng
virtio_cread16(struct udevice * vdev,unsigned int offset)586*8fb49b4cSBin Meng static inline u16 virtio_cread16(struct udevice *vdev,
587*8fb49b4cSBin Meng unsigned int offset)
588*8fb49b4cSBin Meng {
589*8fb49b4cSBin Meng u16 ret;
590*8fb49b4cSBin Meng
591*8fb49b4cSBin Meng virtio_get_config(vdev, offset, &ret, sizeof(ret));
592*8fb49b4cSBin Meng return virtio16_to_cpu(vdev, (__force __virtio16)ret);
593*8fb49b4cSBin Meng }
594*8fb49b4cSBin Meng
virtio_cwrite16(struct udevice * vdev,unsigned int offset,u16 val)595*8fb49b4cSBin Meng static inline void virtio_cwrite16(struct udevice *vdev,
596*8fb49b4cSBin Meng unsigned int offset, u16 val)
597*8fb49b4cSBin Meng {
598*8fb49b4cSBin Meng val = (__force u16)cpu_to_virtio16(vdev, val);
599*8fb49b4cSBin Meng virtio_set_config(vdev, offset, &val, sizeof(val));
600*8fb49b4cSBin Meng }
601*8fb49b4cSBin Meng
virtio_cread32(struct udevice * vdev,unsigned int offset)602*8fb49b4cSBin Meng static inline u32 virtio_cread32(struct udevice *vdev,
603*8fb49b4cSBin Meng unsigned int offset)
604*8fb49b4cSBin Meng {
605*8fb49b4cSBin Meng u32 ret;
606*8fb49b4cSBin Meng
607*8fb49b4cSBin Meng virtio_get_config(vdev, offset, &ret, sizeof(ret));
608*8fb49b4cSBin Meng return virtio32_to_cpu(vdev, (__force __virtio32)ret);
609*8fb49b4cSBin Meng }
610*8fb49b4cSBin Meng
virtio_cwrite32(struct udevice * vdev,unsigned int offset,u32 val)611*8fb49b4cSBin Meng static inline void virtio_cwrite32(struct udevice *vdev,
612*8fb49b4cSBin Meng unsigned int offset, u32 val)
613*8fb49b4cSBin Meng {
614*8fb49b4cSBin Meng val = (__force u32)cpu_to_virtio32(vdev, val);
615*8fb49b4cSBin Meng virtio_set_config(vdev, offset, &val, sizeof(val));
616*8fb49b4cSBin Meng }
617*8fb49b4cSBin Meng
virtio_cread64(struct udevice * vdev,unsigned int offset)618*8fb49b4cSBin Meng static inline u64 virtio_cread64(struct udevice *vdev,
619*8fb49b4cSBin Meng unsigned int offset)
620*8fb49b4cSBin Meng {
621*8fb49b4cSBin Meng u64 ret;
622*8fb49b4cSBin Meng
623*8fb49b4cSBin Meng __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
624*8fb49b4cSBin Meng return virtio64_to_cpu(vdev, (__force __virtio64)ret);
625*8fb49b4cSBin Meng }
626*8fb49b4cSBin Meng
virtio_cwrite64(struct udevice * vdev,unsigned int offset,u64 val)627*8fb49b4cSBin Meng static inline void virtio_cwrite64(struct udevice *vdev,
628*8fb49b4cSBin Meng unsigned int offset, u64 val)
629*8fb49b4cSBin Meng {
630*8fb49b4cSBin Meng val = (__force u64)cpu_to_virtio64(vdev, val);
631*8fb49b4cSBin Meng virtio_set_config(vdev, offset, &val, sizeof(val));
632*8fb49b4cSBin Meng }
633*8fb49b4cSBin Meng
634*8fb49b4cSBin Meng /* Config space read accessor */
635*8fb49b4cSBin Meng #define virtio_cread(vdev, structname, member, ptr) \
636*8fb49b4cSBin Meng do { \
637*8fb49b4cSBin Meng /* Must match the member's type, and be integer */ \
638*8fb49b4cSBin Meng if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
639*8fb49b4cSBin Meng (*ptr) = 1; \
640*8fb49b4cSBin Meng \
641*8fb49b4cSBin Meng switch (sizeof(*ptr)) { \
642*8fb49b4cSBin Meng case 1: \
643*8fb49b4cSBin Meng *(ptr) = virtio_cread8(vdev, \
644*8fb49b4cSBin Meng offsetof(structname, member)); \
645*8fb49b4cSBin Meng break; \
646*8fb49b4cSBin Meng case 2: \
647*8fb49b4cSBin Meng *(ptr) = virtio_cread16(vdev, \
648*8fb49b4cSBin Meng offsetof(structname, member)); \
649*8fb49b4cSBin Meng break; \
650*8fb49b4cSBin Meng case 4: \
651*8fb49b4cSBin Meng *(ptr) = virtio_cread32(vdev, \
652*8fb49b4cSBin Meng offsetof(structname, member)); \
653*8fb49b4cSBin Meng break; \
654*8fb49b4cSBin Meng case 8: \
655*8fb49b4cSBin Meng *(ptr) = virtio_cread64(vdev, \
656*8fb49b4cSBin Meng offsetof(structname, member)); \
657*8fb49b4cSBin Meng break; \
658*8fb49b4cSBin Meng default: \
659*8fb49b4cSBin Meng WARN_ON(true); \
660*8fb49b4cSBin Meng } \
661*8fb49b4cSBin Meng } while (0)
662*8fb49b4cSBin Meng
663*8fb49b4cSBin Meng /* Config space write accessor */
664*8fb49b4cSBin Meng #define virtio_cwrite(vdev, structname, member, ptr) \
665*8fb49b4cSBin Meng do { \
666*8fb49b4cSBin Meng /* Must match the member's type, and be integer */ \
667*8fb49b4cSBin Meng if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
668*8fb49b4cSBin Meng WARN_ON((*ptr) == 1); \
669*8fb49b4cSBin Meng \
670*8fb49b4cSBin Meng switch (sizeof(*ptr)) { \
671*8fb49b4cSBin Meng case 1: \
672*8fb49b4cSBin Meng virtio_cwrite8(vdev, \
673*8fb49b4cSBin Meng offsetof(structname, member), \
674*8fb49b4cSBin Meng *(ptr)); \
675*8fb49b4cSBin Meng break; \
676*8fb49b4cSBin Meng case 2: \
677*8fb49b4cSBin Meng virtio_cwrite16(vdev, \
678*8fb49b4cSBin Meng offsetof(structname, member), \
679*8fb49b4cSBin Meng *(ptr)); \
680*8fb49b4cSBin Meng break; \
681*8fb49b4cSBin Meng case 4: \
682*8fb49b4cSBin Meng virtio_cwrite32(vdev, \
683*8fb49b4cSBin Meng offsetof(structname, member), \
684*8fb49b4cSBin Meng *(ptr)); \
685*8fb49b4cSBin Meng break; \
686*8fb49b4cSBin Meng case 8: \
687*8fb49b4cSBin Meng virtio_cwrite64(vdev, \
688*8fb49b4cSBin Meng offsetof(structname, member), \
689*8fb49b4cSBin Meng *(ptr)); \
690*8fb49b4cSBin Meng break; \
691*8fb49b4cSBin Meng default: \
692*8fb49b4cSBin Meng WARN_ON(true); \
693*8fb49b4cSBin Meng } \
694*8fb49b4cSBin Meng } while (0)
695*8fb49b4cSBin Meng
696*8fb49b4cSBin Meng /* Conditional config space accessors */
697*8fb49b4cSBin Meng #define virtio_cread_feature(vdev, fbit, structname, member, ptr) \
698*8fb49b4cSBin Meng ({ \
699*8fb49b4cSBin Meng int _r = 0; \
700*8fb49b4cSBin Meng if (!virtio_has_feature(vdev, fbit)) \
701*8fb49b4cSBin Meng _r = -ENOENT; \
702*8fb49b4cSBin Meng else \
703*8fb49b4cSBin Meng virtio_cread(vdev, structname, member, ptr); \
704*8fb49b4cSBin Meng _r; \
705*8fb49b4cSBin Meng })
706*8fb49b4cSBin Meng
707*8fb49b4cSBin Meng #endif /* __VIRTIO_H__ */
708