Skip to content

Commit a450add

Browse files
conghuic23acrnsi
authored andcommitted
DM: virtio-i2c: add support for virtio i2c adapter
Add virtio i2c adapter BE driver. Tracked-On: #3357 Signed-off-by: Conghui Chen <conghui.chen@intel.com> Reviewed-by: Yuan Liu <yuan1.liu@intel.com> Reviewed-by: Shuo A Liu <shuo.a.liu@intel.com> Acked-by: Wang Yu <yu1.wang@intel.com>
1 parent 2751f13 commit a450add

File tree

3 files changed

+200
-0
lines changed

3 files changed

+200
-0
lines changed

devicemodel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ SRCS += hw/pci/core.c
105105
SRCS += hw/pci/virtio/virtio_console.c
106106
SRCS += hw/pci/virtio/virtio_block.c
107107
SRCS += hw/pci/virtio/virtio_input.c
108+
SRCS += hw/pci/virtio/virtio_i2c.c
108109
SRCS += hw/pci/ahci.c
109110
SRCS += hw/pci/hostbridge.c
110111
SRCS += hw/pci/platform_gsi_info.c
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*
6+
*/
7+
8+
#include <sys/param.h>
9+
#include <sys/uio.h>
10+
#include <errno.h>
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <string.h>
14+
#include <pthread.h>
15+
#include <openssl/md5.h>
16+
#include <linux/i2c.h>
17+
#include <linux/i2c-dev.h>
18+
#include <sys/ioctl.h>
19+
20+
#include "dm.h"
21+
#include "pci_core.h"
22+
#include "virtio.h"
23+
24+
/* I2c adapter virtualization architecture
25+
*
26+
* +-----------------------------+
27+
* | ACRN DM |
28+
* | +----------------------+ | virtqueue
29+
* | | |<--+-----------+
30+
* | | virtio i2c mediator | | |
31+
* | | | | |
32+
* | +--+-----+-----+-------+ | |
33+
* +-----+-----+-----+-----------+ |
34+
* User space +-------+ | +-----------+ |
35+
* v v v |
36+
* +---------+----+ +-----+--------+ +-----+------+ | +-----------+
37+
* ---+ /dev/i2c-0 +--+ /dev/i2c-1 +--+ /dev/i2c-n +----+--+UOS: |
38+
* | | | | | | |/dev/i2c-n |
39+
* +----------+---+ +-------+------+ +-----+------+ | +-----+-----+
40+
* Kernel space v v v | v
41+
* +-----+-------+ +----+--------+ +----+--------+ | +-----+------------+
42+
* |i2c adapter 0| |i2c adapter 1| |i2c adapter n| +->|UOS: |
43+
* | | | | | |virtio i2c adapter|
44+
* +-----+-------+ +-------------+ +-------------+ +------------------+
45+
* --------------+-----------------------------------------
46+
* Hardware +----------+
47+
* | |
48+
* bus 0v v ....
49+
* +-----+---+ +----+----+
50+
* |i2c slave| |i2c slave| ....
51+
* +---------+ +---------+
52+
*/
53+
54+
static int virtio_i2c_debug=0;
55+
#define VIRTIO_I2C_PREF "virtio_i2c: "
56+
#define DPRINTF(fmt, args...) \
57+
do { if (virtio_i2c_debug) printf(VIRTIO_I2C_PREF fmt, ##args); } while (0)
58+
#define WPRINTF(fmt, args...) printf(VIRTIO_I2C_PREF fmt, ##args)
59+
60+
/*
61+
* Per-device struct
62+
*/
63+
struct virtio_i2c {
64+
struct virtio_base base;
65+
pthread_mutex_t mtx;
66+
struct virtio_vq_info vq;
67+
char ident[256];
68+
};
69+
70+
static void virtio_i2c_reset(void *);
71+
static void virtio_i2c_notify(void *, struct virtio_vq_info *);
72+
73+
static struct virtio_ops virtio_i2c_ops = {
74+
"virtio_i2c", /* our name */
75+
1, /* we support 1 virtqueue */
76+
0, /* config reg size */
77+
virtio_i2c_reset, /* reset */
78+
virtio_i2c_notify, /* device-wide qnotify */
79+
NULL, /* read PCI config */
80+
NULL, /* write PCI config */
81+
NULL, /* apply negotiated features */
82+
NULL, /* called on guest set status */
83+
};
84+
85+
static void
86+
virtio_i2c_reset(void *vdev)
87+
{
88+
struct virtio_i2c *vi2c = vdev;
89+
90+
DPRINTF("device reset requested !\n");
91+
virtio_reset_dev(&vi2c->base);
92+
}
93+
94+
static void
95+
virtio_i2c_notify(void *vdev, struct virtio_vq_info *vq)
96+
{
97+
/* TODO: Add notify logic */
98+
}
99+
100+
static int
101+
virtio_i2c_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
102+
{
103+
MD5_CTX mdctx;
104+
u_char digest[16];
105+
struct virtio_i2c *vi2c;
106+
pthread_mutexattr_t attr;
107+
int rc;
108+
109+
vi2c = calloc(1, sizeof(struct virtio_i2c));
110+
if (!vi2c) {
111+
WPRINTF("calloc returns NULL\n");
112+
return -ENOMEM;
113+
}
114+
115+
/* init mutex attribute properly to avoid deadlock */
116+
rc = pthread_mutexattr_init(&attr);
117+
if (rc) {
118+
WPRINTF("mutexattr init failed with erro %d!\n", rc);
119+
goto mtx_fail;
120+
}
121+
rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
122+
if (rc) {
123+
WPRINTF("mutexattr_settype failed with "
124+
"error %d!\n", rc);
125+
goto mtx_fail;
126+
}
127+
128+
rc = pthread_mutex_init(&vi2c->mtx, &attr);
129+
if (rc) {
130+
WPRINTF("pthread_mutex_init failed with "
131+
"error %d!\n", rc);
132+
goto mtx_fail;
133+
}
134+
135+
/* init virtio struct and virtqueues */
136+
virtio_linkup(&vi2c->base, &virtio_i2c_ops, vi2c, dev, &vi2c->vq, BACKEND_VBSU);
137+
vi2c->base.mtx = &vi2c->mtx;
138+
vi2c->vq.qsize = 64;
139+
140+
MD5_Init(&mdctx);
141+
MD5_Update(&mdctx, "vi2c", strlen("vi2c"));
142+
MD5_Final(digest, &mdctx);
143+
rc = snprintf(vi2c->ident, sizeof(vi2c->ident),
144+
"ACRN--%02X%02X-%02X%02X-%02X%02X", digest[0],
145+
digest[1], digest[2], digest[3], digest[4],
146+
digest[5]);
147+
if (rc < 0) {
148+
WPRINTF("create ident failed");
149+
goto fail;
150+
}
151+
if (rc >= sizeof(vi2c->ident)) {
152+
WPRINTF("ident too long\n");
153+
}
154+
155+
pci_set_cfgdata16(dev, PCIR_DEVICE, VIRTIO_DEV_I2C);
156+
pci_set_cfgdata16(dev, PCIR_VENDOR, INTEL_VENDOR_ID);
157+
pci_set_cfgdata8(dev, PCIR_CLASS, PCIC_SERIALBUS);
158+
pci_set_cfgdata16(dev, PCIR_SUBDEV_0, VIRTIO_TYPE_I2C);
159+
pci_set_cfgdata16(dev, PCIR_SUBVEND_0, INTEL_VENDOR_ID);
160+
161+
if (virtio_interrupt_init(&vi2c->base, virtio_uses_msix())) {
162+
WPRINTF("failed to init interrupt");
163+
rc = -1;
164+
goto fail;
165+
}
166+
virtio_set_io_bar(&vi2c->base, 0);
167+
return 0;
168+
169+
fail:
170+
pthread_mutex_destroy(&vi2c->mtx);
171+
mtx_fail:
172+
free(vi2c);
173+
return rc;
174+
}
175+
176+
static void
177+
virtio_i2c_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
178+
{
179+
struct virtio_i2c *vi2c;
180+
181+
if (dev->arg) {
182+
DPRINTF("deinit\n");
183+
vi2c = (struct virtio_i2c *) dev->arg;
184+
pthread_mutex_destroy(&vi2c->mtx);
185+
free(vi2c);
186+
dev->arg = NULL;
187+
}
188+
}
189+
190+
struct pci_vdev_ops pci_ops_virtio_i2c = {
191+
.class_name = "virtio-i2c",
192+
.vdev_init = virtio_i2c_init,
193+
.vdev_deinit = virtio_i2c_deinit,
194+
.vdev_barwrite = virtio_pci_write,
195+
.vdev_barread = virtio_pci_read,
196+
};
197+
DEFINE_PCI_DEVTYPE(pci_ops_virtio_i2c);

devicemodel/include/virtio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ enum {
207207
#define VIRTIO_TYPE_HDCP 0xFFF9
208208
#define VIRTIO_TYPE_COREU 0xFFF8
209209
#define VIRTIO_TYPE_GPIO 0xFFF7
210+
#define VIRTIO_TYPE_I2C 0xFFF6
210211

211212
/*
212213
* PCI vendor/device IDs
@@ -230,6 +231,7 @@ enum {
230231
#define VIRTIO_DEV_HDCP 0x8607
231232
#define VIRTIO_DEV_COREU 0x8608
232233
#define VIRTIO_DEV_GPIO 0x8609
234+
#define VIRTIO_DEV_I2C 0x860a
233235

234236
/*
235237
* VIRTIO_CONFIG_S_NEEDS_RESET is not defined

0 commit comments

Comments
 (0)