25
25
#include "dm.h"
26
26
#include "pci_core.h"
27
27
#include "virtio.h"
28
+ #include "acpi.h"
28
29
29
30
/* I2c adapter virtualization architecture
30
31
*
@@ -62,12 +63,33 @@ static int virtio_i2c_debug=0;
62
63
do { if (virtio_i2c_debug) printf(VIRTIO_I2C_PREF fmt, ##args); } while (0)
63
64
#define WPRINTF (fmt , args ...) printf(VIRTIO_I2C_PREF fmt, ##args)
64
65
66
+ #define MAX_NODE_NAME_LEN 20
65
67
#define MAX_I2C_VDEV 128
66
68
#define MAX_NATIVE_I2C_ADAPTER 16
67
69
#define I2C_MSG_OK 0
68
70
#define I2C_MSG_ERR 1
69
71
#define I2C_NO_DEV 2
70
72
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
+
71
93
struct virtio_i2c_hdr {
72
94
uint16_t addr ; /* slave address */
73
95
uint16_t flags ;
@@ -89,6 +111,7 @@ struct virtio_i2c {
89
111
struct native_i2c_adapter * native_adapter [MAX_NATIVE_I2C_ADAPTER ];
90
112
int native_adapter_num ;
91
113
uint16_t adapter_map [MAX_I2C_VDEV ];
114
+ char acpi_nodes [MAX_I2C_VDEV ][MAX_NODE_NAME_LEN ];
92
115
struct virtio_vq_info vq ;
93
116
char ident [256 ];
94
117
pthread_t req_tid ;
@@ -113,6 +136,235 @@ static struct virtio_ops virtio_i2c_ops = {
113
136
NULL , /* called on guest set status */
114
137
};
115
138
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
+
116
368
static bool
117
369
native_slave_access_ok (struct native_i2c_adapter * adapter , uint16_t addr )
118
370
{
@@ -337,18 +589,20 @@ virtio_i2c_map(struct virtio_i2c *vi2c)
337
589
static int
338
590
virtio_i2c_parse (struct virtio_i2c * vi2c , char * optstr )
339
591
{
340
- char * cp , * t ;
592
+ char * cp , * t , * dsdt_str , * p ;
341
593
uint16_t slave_addr [MAX_I2C_VDEV ];
342
594
int addr , bus , n_adapter , n_slave ;
343
595
344
596
/*
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>] ]]
347
599
*
348
600
* bus (dec): native adatper bus number.
349
601
* e.g. 2 for /dev/i2c-2
350
602
* slave_addr (hex): address for native slave device
351
603
* 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.
352
606
*
353
607
* Note: slave address can not repeat.
354
608
*/
@@ -363,6 +617,7 @@ virtio_i2c_parse(struct virtio_i2c *vi2c, char *optstr)
363
617
while (cp != NULL && * cp != '\0' ) {
364
618
if (* cp == ':' )
365
619
cp ++ ;
620
+
366
621
if (bus == -1 ) {
367
622
if (dm_strtoi (cp , & t , 10 , & bus ) || bus < 0 )
368
623
return -1 ;
@@ -374,7 +629,18 @@ virtio_i2c_parse(struct virtio_i2c *vi2c, char *optstr)
374
629
return -1 ;
375
630
}
376
631
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 );
378
644
n_slave ++ ;
379
645
}
380
646
cp = t ;
@@ -393,6 +659,44 @@ virtio_i2c_parse(struct virtio_i2c *vi2c, char *optstr)
393
659
return 0 ;
394
660
}
395
661
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
+
396
700
static void
397
701
virtio_i2c_reset (void * vdev )
398
702
{
@@ -531,5 +835,6 @@ struct pci_vdev_ops pci_ops_virtio_i2c = {
531
835
.vdev_deinit = virtio_i2c_deinit ,
532
836
.vdev_barwrite = virtio_pci_write ,
533
837
.vdev_barread = virtio_pci_read ,
838
+ .vdev_write_dsdt = virtio_i2c_dsdt ,
534
839
};
535
840
DEFINE_PCI_DEVTYPE (pci_ops_virtio_i2c );
0 commit comments