Skip to content

Commit e720dda

Browse files
conghuic23acrnsi
authored andcommitted
DM: virtio-i2c: add dsdt info
Add dsdt information for i2c adapter and i2c slave devices. Currently, only support 'cam1', 'cam2' and 'hdac' for MRB board. To add other specific i2c device, please extend acpi_node_table[]. Usage: virtio-i2c,<bus>[:<slave_addr>[@<node>]][:<slave_addr>[@<node>]] [,<bus>[:<slave_addr>[@<node>]][:<slave_addr>][@<node>]] e.g. virtio-i2c,0:70@cam1:2F This will add slave devices 0x70, 0x74 to virtio i2c adapter. And for 0x70, it has '@cam1', so, will also add acpi info for it. For 0x74, it has no '@<node>', will not add any acpi info for it. Note, there is slave address in acpi node info, please use '@<node>' according to real hardware. 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 b6f9ed3 commit e720dda

File tree

1 file changed

+309
-4
lines changed

1 file changed

+309
-4
lines changed

devicemodel/hw/pci/virtio/virtio_i2c.c

Lines changed: 309 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "dm.h"
2626
#include "pci_core.h"
2727
#include "virtio.h"
28+
#include "acpi.h"
2829

2930
/* I2c adapter virtualization architecture
3031
*
@@ -62,12 +63,33 @@ static int virtio_i2c_debug=0;
6263
do { if (virtio_i2c_debug) printf(VIRTIO_I2C_PREF fmt, ##args); } while (0)
6364
#define WPRINTF(fmt, args...) printf(VIRTIO_I2C_PREF fmt, ##args)
6465

66+
#define MAX_NODE_NAME_LEN 20
6567
#define MAX_I2C_VDEV 128
6668
#define MAX_NATIVE_I2C_ADAPTER 16
6769
#define I2C_MSG_OK 0
6870
#define I2C_MSG_ERR 1
6971
#define I2C_NO_DEV 2
7072

73+
static int acpi_i2c_adapter_num = 0;
74+
static void acpi_add_i2c_adapter(struct pci_vdev *dev, int i2c_bus);
75+
static void acpi_add_cam1(struct pci_vdev *dev, int i2c_bus);
76+
static void acpi_add_cam2(struct pci_vdev *dev, int i2c_bus);
77+
static void acpi_add_hdac(struct pci_vdev *dev, int i2c_bus);
78+
static void acpi_add_default(struct pci_vdev *dev, int i2c_bus);
79+
80+
struct acpi_node {
81+
char node_name[MAX_NODE_NAME_LEN];
82+
void (*add_node_fn)(struct pci_vdev *, int);
83+
};
84+
85+
static struct acpi_node acpi_node_table[] = {
86+
/* cam1, cam2 and hdac is dump from MRB board */
87+
{"cam1", acpi_add_cam1},
88+
{"cam2", acpi_add_cam2},
89+
{"hdac", acpi_add_hdac},
90+
{"default", acpi_add_default},
91+
};
92+
7193
struct virtio_i2c_hdr {
7294
uint16_t addr; /* slave address */
7395
uint16_t flags;
@@ -89,6 +111,7 @@ struct virtio_i2c {
89111
struct native_i2c_adapter *native_adapter[MAX_NATIVE_I2C_ADAPTER];
90112
int native_adapter_num;
91113
uint16_t adapter_map[MAX_I2C_VDEV];
114+
char acpi_nodes[MAX_I2C_VDEV][MAX_NODE_NAME_LEN];
92115
struct virtio_vq_info vq;
93116
char ident[256];
94117
pthread_t req_tid;
@@ -113,6 +136,235 @@ static struct virtio_ops virtio_i2c_ops = {
113136
NULL, /* called on guest set status */
114137
};
115138

139+
static void
140+
acpi_add_i2c_adapter(struct pci_vdev *dev, int i2c_bus)
141+
{
142+
dsdt_line("Device (I2C%d)", i2c_bus);
143+
dsdt_line("{");
144+
dsdt_line(" Name (_ADR, 0x%04X%04X)", dev->slot, dev->func);
145+
dsdt_line(" Name (_DDN, \"Intel(R) I2C Controller #%d\")", i2c_bus);
146+
dsdt_line(" Name (_UID, One)");
147+
dsdt_line(" Name (LINK, \"\\\\_SB.PCI%d.I2C%d\")", dev->bus, i2c_bus);
148+
dsdt_line(" Name (RBUF, ResourceTemplate ()");
149+
dsdt_line(" {");
150+
dsdt_line(" })");
151+
dsdt_line(" Name (IC0S, 0x00061A80)");
152+
dsdt_line(" Name (_DSD, Package (0x02)");
153+
dsdt_line(" {");
154+
dsdt_line(" ToUUID (\"daffd814-6eba-4d8c-8a91-bc9bbf4aa301\")"
155+
" ,");
156+
dsdt_line(" Package (0x01)");
157+
dsdt_line(" {");
158+
dsdt_line(" Package (0x02)");
159+
dsdt_line(" {");
160+
dsdt_line(" \"clock-frequency\", ");
161+
dsdt_line(" IC0S");
162+
dsdt_line(" }");
163+
dsdt_line(" }");
164+
dsdt_line(" })");
165+
dsdt_line("");
166+
dsdt_line("}");
167+
}
168+
169+
static void
170+
acpi_add_cam1(struct pci_vdev *dev, int i2c_bus)
171+
{
172+
dsdt_line("Scope(I2C%d)", i2c_bus);
173+
dsdt_line("{");
174+
dsdt_line(" Device (CAM1)");
175+
dsdt_line(" {");
176+
dsdt_line(" Name (_ADR, Zero) // _ADR: Address");
177+
dsdt_line(" Name (_HID, \"ADV7481A\") // _HID: Hardware ID");
178+
dsdt_line(" Name (_CID, \"ADV7481A\") // _CID: Compatible ID");
179+
dsdt_line(" Name (_UID, One) // _UID: Unique ID");
180+
dsdt_line(" Method (_CRS, 0, Serialized)");
181+
dsdt_line(" {");
182+
dsdt_line(" Name (SBUF, ResourceTemplate ()");
183+
dsdt_line(" {");
184+
dsdt_line(" GpioIo (Exclusive, PullDefault, 0x0000, "
185+
"0x0000, IoRestrictionInputOnly,");
186+
dsdt_line(" \"\\\\_SB.GPO0\", 0x00, "
187+
"ResourceConsumer, ,");
188+
dsdt_line(" )");
189+
dsdt_line(" { // Pin list");
190+
dsdt_line(" 0x001E");
191+
dsdt_line(" }");
192+
dsdt_line(" I2cSerialBusV2 (0x0070, "
193+
"ControllerInitiated, 0x00061A80,");
194+
dsdt_line(" AddressingMode7Bit, "
195+
"\"\\\\_SB.PCI%d.I2C%d\",",
196+
dev->bus, i2c_bus);
197+
dsdt_line(" 0x00, ResourceConsumer, , Exclusive,");
198+
dsdt_line(" )");
199+
dsdt_line(" })");
200+
dsdt_line(" Return (SBUF)");
201+
dsdt_line(" }");
202+
dsdt_line(" Method (_DSM, 4, NotSerialized)");
203+
dsdt_line(" {");
204+
dsdt_line(" If ((Arg0 == ToUUID ("
205+
"\"377ba76a-f390-4aff-ab38-9b1bf33a3015\")))");
206+
dsdt_line(" {");
207+
dsdt_line(" Return (\"ADV7481A\")");
208+
dsdt_line(" }");
209+
dsdt_line("");
210+
dsdt_line(" If ((Arg0 == ToUUID ("
211+
"\"ea3b7bd8-e09b-4239-ad6e-ed525f3f26ab\")))");
212+
dsdt_line(" {");
213+
dsdt_line(" Return (0x40)");
214+
dsdt_line(" }");
215+
dsdt_line("");
216+
dsdt_line(" If ((Arg0 == ToUUID ("
217+
"\"8dbe2651-70c1-4c6f-ac87-a37cb46e4af6\")))");
218+
dsdt_line(" {");
219+
dsdt_line(" Return (0xFF)");
220+
dsdt_line(" }");
221+
dsdt_line("");
222+
dsdt_line(" If ((Arg0 == ToUUID ("
223+
"\"26257549-9271-4ca4-bb43-c4899d5a4881\")))");
224+
dsdt_line(" {");
225+
dsdt_line(" If (Arg2 == One)");
226+
dsdt_line(" {");
227+
dsdt_line(" Return (0x02)");
228+
dsdt_line(" }");
229+
dsdt_line(" If (Arg2 == 0x02)");
230+
dsdt_line(" {");
231+
dsdt_line(" Return (0x02001000)");
232+
dsdt_line(" }");
233+
dsdt_line(" If (Arg2 == 0x03)");
234+
dsdt_line(" {");
235+
dsdt_line(" Return (0x02000E01)");
236+
dsdt_line(" }");
237+
dsdt_line(" }");
238+
dsdt_line(" Return (Zero)");
239+
dsdt_line(" }");
240+
dsdt_line(" }");
241+
dsdt_line("}");
242+
}
243+
244+
static void
245+
acpi_add_cam2(struct pci_vdev *dev, int i2c_bus)
246+
{
247+
dsdt_line("Scope(I2C%d)", i2c_bus);
248+
dsdt_line("{");
249+
dsdt_line(" Device (CAM2)");
250+
dsdt_line(" {");
251+
dsdt_line(" Name (_ADR, Zero) // _ADR: Address");
252+
dsdt_line(" Name (_HID, \"ADV7481B\") // _HID: Hardware ID");
253+
dsdt_line(" Name (_CID, \"ADV7481B\") // _CID: Compatible ID");
254+
dsdt_line(" Name (_UID, One) // _UID: Unique ID");
255+
dsdt_line(" Method (_CRS, 0, Serialized)");
256+
dsdt_line(" {");
257+
dsdt_line(" Name (SBUF, ResourceTemplate ()");
258+
dsdt_line(" {");
259+
dsdt_line(" GpioIo (Exclusive, PullDefault, 0x000, "
260+
"0x0000, IoRestrictionInputOnly,");
261+
dsdt_line(" \"\\\\_SB.GPO0\", 0x00, "
262+
"ResourceConsumer, ,");
263+
dsdt_line(" )");
264+
dsdt_line(" { // Pin list");
265+
dsdt_line(" 0x001E");
266+
dsdt_line(" }");
267+
dsdt_line(" I2cSerialBusV2 (0x0071, "
268+
"ControllerInitiated, 0x00061A80,");
269+
dsdt_line(" AddressingMode7Bit, "
270+
"\"\\\\_SB.PCI%d.I2C%d\",",
271+
dev->bus, i2c_bus);
272+
dsdt_line(" 0x00, ResourceConsumer, , Exclusive,");
273+
dsdt_line(" )");
274+
dsdt_line(" })");
275+
dsdt_line(" Return (SBUF)");
276+
dsdt_line(" }");
277+
dsdt_line(" Method (_DSM, 4, NotSerialized) ");
278+
dsdt_line(" {");
279+
dsdt_line(" If ((Arg0 == ToUUID ("
280+
"\"377ba76a-f390-4aff-ab38-9b1bf33a3015\")))");
281+
dsdt_line(" {");
282+
dsdt_line(" Return (\"ADV7481B\")");
283+
dsdt_line(" }");
284+
dsdt_line("");
285+
dsdt_line(" If ((Arg0 == ToUUID ("
286+
"\"ea3b7bd8-e09b-4239-ad6e-ed525f3f26ab\")))");
287+
dsdt_line(" {");
288+
dsdt_line(" Return (0x14)");
289+
dsdt_line(" }");
290+
dsdt_line("");
291+
dsdt_line(" If ((Arg0 == ToUUID ("
292+
"\"8dbe2651-70c1-4c6f-ac87-a37cb46e4af6\")))");
293+
dsdt_line(" {");
294+
dsdt_line(" Return (0xFF)");
295+
dsdt_line(" }");
296+
dsdt_line("");
297+
dsdt_line(" If ((Arg0 == ToUUID ("
298+
"\"26257549-9271-4ca4-bb43-c4899d5a4881\")))");
299+
dsdt_line(" {");
300+
dsdt_line(" If (Arg2 == One)");
301+
dsdt_line(" {");
302+
dsdt_line(" Return (0x02)");
303+
dsdt_line(" }");
304+
dsdt_line(" If (Arg2 == 0x02)");
305+
dsdt_line(" {");
306+
dsdt_line(" Return (0x02001000)");
307+
dsdt_line(" }");
308+
dsdt_line(" If (Arg2 == 0x03)");
309+
dsdt_line(" {");
310+
dsdt_line(" Return (0x02000E01)");
311+
dsdt_line(" }");
312+
dsdt_line(" }");
313+
dsdt_line(" Return (Zero)");
314+
dsdt_line(" }");
315+
dsdt_line(" }");
316+
dsdt_line("");
317+
dsdt_line("}");
318+
}
319+
320+
static void
321+
acpi_add_hdac(struct pci_vdev *dev, int i2c_bus)
322+
{
323+
dsdt_line("Scope(I2C%d)", i2c_bus);
324+
dsdt_line("{");
325+
dsdt_line(" Device (HDAC)");
326+
dsdt_line(" {");
327+
dsdt_line(" Name (_HID, \"INT34C3\") // _HID: Hardware ID");
328+
dsdt_line(" Name (_CID, \"INT34C3\") // _CID: Compatible ID");
329+
dsdt_line(" Name (_DDN, \"Intel(R) Smart Sound Technology "
330+
"Audio Codec\") // _DDN: DOS Device Name");
331+
dsdt_line(" Name (_UID, One) // _UID: Unique ID");
332+
dsdt_line(" Method (_INI, 0, NotSerialized)");
333+
dsdt_line(" {");
334+
dsdt_line(" }");
335+
dsdt_line("");
336+
dsdt_line(" Method (_CRS, 0, NotSerialized)");
337+
dsdt_line(" {");
338+
dsdt_line(" Name (SBFB, ResourceTemplate ()");
339+
dsdt_line(" {");
340+
dsdt_line(" I2cSerialBusV2 (0x006C, "
341+
"ControllerInitiated, 0x00061A80,");
342+
dsdt_line(" AddressingMode7Bit, "
343+
"\"\\\\_SB.PCI%d.I2C%d\",",
344+
dev->bus, i2c_bus);
345+
dsdt_line(" 0x00, ResourceConsumer, , Exclusive,");
346+
dsdt_line(" )");
347+
dsdt_line(" })");
348+
dsdt_line(" Name (SBFI, ResourceTemplate ()");
349+
dsdt_line(" {");
350+
dsdt_line(" })");
351+
dsdt_line(" Return (ConcatenateResTemplate (SBFB, SBFI))");
352+
dsdt_line(" }");
353+
dsdt_line("");
354+
dsdt_line(" Method (_STA, 0, NotSerialized) // _STA: Status");
355+
dsdt_line(" {");
356+
dsdt_line(" Return (0x0F)");
357+
dsdt_line(" }");
358+
dsdt_line(" }");
359+
dsdt_line("}");
360+
}
361+
362+
static void
363+
acpi_add_default(struct pci_vdev *dev, int i2c_bus)
364+
{
365+
/* Add nothing */
366+
}
367+
116368
static bool
117369
native_slave_access_ok(struct native_i2c_adapter *adapter, uint16_t addr)
118370
{
@@ -337,18 +589,20 @@ virtio_i2c_map(struct virtio_i2c *vi2c)
337589
static int
338590
virtio_i2c_parse(struct virtio_i2c *vi2c, char *optstr)
339591
{
340-
char *cp, *t;
592+
char *cp, *t, *dsdt_str, *p;
341593
uint16_t slave_addr[MAX_I2C_VDEV];
342594
int addr, bus, n_adapter, n_slave;
343595

344596
/*
345-
* virtio-i2c,<bus>:<slave_addr>[:<slave_addr>],
346-
* [<bus>:<slave_addr>[:<slave_addr>]]
597+
* virtio-i2c,<bus>:<slave_addr[@<node>]>[:<slave_addr[@<node>]>],
598+
* [<bus>:<slave_addr[@<node>]>[:<slave_addr>[@<node>]]]
347599
*
348600
* bus (dec): native adatper bus number.
349601
* e.g. 2 for /dev/i2c-2
350602
* slave_addr (hex): address for native slave device
351603
* e.g. 0x1C or 1C
604+
* @<node>: node is the acpi node name defined in acpi_node_table[]
605+
* e.g. @cam1 means adding 'cam1' node to dsdt table.
352606
*
353607
* Note: slave address can not repeat.
354608
*/
@@ -363,6 +617,7 @@ virtio_i2c_parse(struct virtio_i2c *vi2c, char *optstr)
363617
while (cp != NULL && *cp !='\0') {
364618
if (*cp == ':')
365619
cp++;
620+
366621
if (bus == -1) {
367622
if (dm_strtoi(cp, &t, 10, &bus) || bus < 0)
368623
return -1;
@@ -374,7 +629,18 @@ virtio_i2c_parse(struct virtio_i2c *vi2c, char *optstr)
374629
return -1;
375630
}
376631
slave_addr[n_slave] = (uint16_t)(addr & (MAX_I2C_VDEV - 1));
377-
DPRINTF("native i2c adapter %d:0x%x\n", bus, slave_addr[n_slave]);
632+
p = &vi2c->acpi_nodes[slave_addr[n_slave]][0];
633+
if (t != NULL && *t == '@') {
634+
t++;
635+
dsdt_str = strsep(&t, ":,");
636+
snprintf(p, MAX_NODE_NAME_LEN, "%s", dsdt_str);
637+
} else {
638+
snprintf(p, MAX_NODE_NAME_LEN, "default");
639+
}
640+
DPRINTF("native i2c adapter %d:0x%x (%s)\n",
641+
bus,
642+
slave_addr[n_slave],
643+
p);
378644
n_slave++;
379645
}
380646
cp = t;
@@ -393,6 +659,44 @@ virtio_i2c_parse(struct virtio_i2c *vi2c, char *optstr)
393659
return 0;
394660
}
395661

662+
static void
663+
virtio_i2c_dsdt(struct pci_vdev *dev)
664+
{
665+
int i, j, node_num;
666+
struct acpi_node *anode;
667+
int i2c_bus;
668+
int found;
669+
struct virtio_i2c *vi2c = (struct virtio_i2c *) dev->arg;
670+
671+
/* i2c bus number in acpi start from 0 */
672+
i2c_bus = acpi_i2c_adapter_num;
673+
/* add i2c adapter */
674+
acpi_add_i2c_adapter(dev, i2c_bus);
675+
DPRINTF("add dsdt for i2c adapter %d\n", i2c_bus);
676+
677+
/* add slave devices */
678+
node_num = sizeof(acpi_node_table) / sizeof(struct acpi_node);
679+
for (i = 0; i < MAX_I2C_VDEV; i++) {
680+
if (!native_adapter_find(vi2c, i))
681+
continue;
682+
683+
found = 0;
684+
for (j = 0; j < node_num; j++) {
685+
anode = &acpi_node_table[j];
686+
if (!strncmp(anode->node_name, vi2c->acpi_nodes[i], sizeof(anode->node_name))) {
687+
found = 1;
688+
if (anode->add_node_fn) {
689+
anode->add_node_fn(dev, i2c_bus);
690+
DPRINTF("add dsdt for %s \n", anode->node_name);
691+
}
692+
}
693+
}
694+
if (!found)
695+
WPRINTF("cannot find acpi node info for %s \n", vi2c->acpi_nodes[i]);
696+
}
697+
acpi_i2c_adapter_num++;
698+
}
699+
396700
static void
397701
virtio_i2c_reset(void *vdev)
398702
{
@@ -531,5 +835,6 @@ struct pci_vdev_ops pci_ops_virtio_i2c = {
531835
.vdev_deinit = virtio_i2c_deinit,
532836
.vdev_barwrite = virtio_pci_write,
533837
.vdev_barread = virtio_pci_read,
838+
.vdev_write_dsdt = virtio_i2c_dsdt,
534839
};
535840
DEFINE_PCI_DEVTYPE(pci_ops_virtio_i2c);

0 commit comments

Comments
 (0)