VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxVgaDxe/VBoxVgaI2c.c@ 67356

Last change on this file since 67356 was 62500, checked in by vboxsync, 9 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1/* $Id: VBoxVgaI2c.c 62500 2016-07-22 19:06:59Z vboxsync $ */
2/** @file
3 * VBoxVgaI2c.c
4 */
5
6/*
7 * Copyright (C) 2009-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*
28 This code is based on:
29
30 I2C Bus implementation upon CirrusLogic.
31
32 Copyright (c) 2008 - 2009, Intel Corporation
33 All rights reserved. This program and the accompanying materials
34 are licensed and made available under the terms and conditions of the BSD License
35 which accompanies this distribution. The full text of the license may be found at
36 http://opensource.org/licenses/bsd-license.php
37
38 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
39 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
40
41*/
42
43#include "VBoxVga.h"
44#include "VBoxVgaI2c.h"
45
46#define SEQ_ADDRESS_REGISTER 0x3c4
47#define SEQ_DATA_REGISTER 0x3c5
48
49#define I2C_CONTROL 0x08
50#define I2CDAT_IN 7
51#define I2CCLK_IN 2
52#define I2CDAT_OUT 1
53#define I2CCLK_OUT 0
54
55#define I2C_BUS_SPEED 100 //100kbps
56
57/**
58 PCI I/O byte write function.
59
60 @param PciIo The pointer to PCI_IO_PROTOCOL.
61 @param Address The bit map of I2C Data or I2C Clock pins.
62 @param Data The date to write.
63
64**/
65VOID
66I2cOutb (
67 EFI_PCI_IO_PROTOCOL *PciIo,
68 UINTN Address,
69 UINT8 Data
70 )
71{
72 PciIo->Io.Write (
73 PciIo,
74 EfiPciIoWidthUint8,
75 EFI_PCI_IO_PASS_THROUGH_BAR,
76 Address,
77 1,
78 &Data
79 );
80}
81/**
82 PCI I/O byte read function.
83
84 @param PciIo The pointer to PCI_IO_PROTOCOL.
85 @param Address The bit map of I2C Data or I2C Clock pins.
86
87 return byte value read from PCI I/O space.
88
89**/
90UINT8
91I2cInb (
92 EFI_PCI_IO_PROTOCOL *PciIo,
93 UINTN Address
94 )
95{
96 UINT8 Data;
97
98 PciIo->Io.Read (
99 PciIo,
100 EfiPciIoWidthUint8,
101 EFI_PCI_IO_PASS_THROUGH_BAR,
102 Address,
103 1,
104 &Data
105 );
106 return Data;
107}
108
109/**
110 Read status of I2C Data and I2C Clock Pins.
111
112 @param PciIo The pointer to PCI_IO_PROTOCOL.
113 @param Blt The bit map of I2C Data or I2C Clock pins.
114
115 @retval 0 Low on I2C Data or I2C Clock Pin.
116 @retval 1 High on I2C Data or I2C Clock Pin.
117
118**/
119UINT8
120I2cPinRead (
121 EFI_PCI_IO_PROTOCOL *PciIo,
122 UINT8 Bit
123 )
124{
125 I2cOutb (PciIo, SEQ_ADDRESS_REGISTER, I2C_CONTROL);
126 return (UINT8) ((I2cInb (PciIo, SEQ_DATA_REGISTER) >> Bit ) & 0xfe);
127}
128
129
130/**
131 Set/Clear I2C Data and I2C Clock Pins.
132
133 @param PciIo The pointer to PCI_IO_PROTOCOL.
134 @param Blt The bit map to controller I2C Data or I2C Clock pins.
135 @param Value 1 or 0 stands for Set or Clear I2C Data and I2C Clock Pins.
136
137**/
138VOID
139I2cPinWrite (
140 EFI_PCI_IO_PROTOCOL *PciIo,
141 UINT8 Bit,
142 UINT8 Value
143 )
144{
145 UINT8 Byte;
146 I2cOutb (PciIo, SEQ_ADDRESS_REGISTER, I2C_CONTROL);
147 Byte = (UINT8) (I2cInb (PciIo, SEQ_DATA_REGISTER) & (UINT8) ~(1 << Bit)) ;
148 Byte = (UINT8) (Byte | ((Value & 0x01) << Bit));
149 I2cOutb (PciIo, SEQ_DATA_REGISTER, (UINT8) (Byte | 0x40));
150 return;
151}
152
153/**
154 Read/write delay according to I2C Bus Speed.
155
156**/
157VOID
158I2cDelay (
159 VOID
160 )
161{
162 MicroSecondDelay (1000 / I2C_BUS_SPEED);
163}
164
165/**
166 Write a 8-bit data onto I2C Data Pin.
167
168 @param PciIo The pointer to PCI_IO_PROTOCOL.
169 @param Data The byte data to write.
170
171**/
172VOID
173I2cSendByte (
174 EFI_PCI_IO_PROTOCOL *PciIo,
175 UINT8 Data
176 )
177{
178 UINTN Index;
179 //
180 // Send byte data onto I2C Bus
181 //
182 for (Index = 0; Index < 8; Index --) {
183 I2cPinWrite (PciIo, I2CDAT_OUT, (UINT8) (Data >> (7 - Index)));
184 I2cPinWrite (PciIo, I2CCLK_OUT, 1);
185 I2cDelay ();
186 I2cPinWrite (PciIo, I2CCLK_OUT, 0);
187 }
188}
189
190/**
191 Read a 8-bit data from I2C Data Pin.
192
193 @param PciIo The pointer to PCI_IO_PROTOCOL.
194
195 Return the byte data read from I2C Data Pin.
196**/
197UINT8
198I2cReceiveByte (
199 EFI_PCI_IO_PROTOCOL *PciIo
200 )
201{
202 UINT8 Data;
203 UINTN Index;
204
205 Data = 0;
206 //
207 // Read byte data from I2C Bus
208 //
209 for (Index = 0; Index < 8; Index --) {
210 I2cPinWrite (PciIo, I2CCLK_OUT, 1);
211 I2cDelay ();
212 Data = (UINT8) (Data << 1);
213 Data = (UINT8) (Data | I2cPinRead (PciIo, I2CDAT_IN));
214 I2cPinWrite (PciIo, I2CCLK_OUT, 0);
215 }
216
217 return Data;
218}
219
220/**
221 Receive an ACK signal from I2C Bus.
222
223 @param PciIo The pointer to PCI_IO_PROTOCOL.
224
225**/
226BOOLEAN
227I2cWaitAck (
228 EFI_PCI_IO_PROTOCOL *PciIo
229 )
230{
231 //
232 // Wait for ACK signal
233 //
234 I2cPinWrite (PciIo, I2CDAT_OUT, 1);
235 I2cPinWrite (PciIo, I2CCLK_OUT, 1);
236 I2cDelay ();
237 if (I2cPinRead (PciIo, I2CDAT_IN) == 0) {
238 I2cPinWrite (PciIo, I2CDAT_OUT, 1);
239 return TRUE;
240 } else {
241 return FALSE;
242 }
243}
244
245/**
246 Send an ACK signal onto I2C Bus.
247
248 @param PciIo The pointer to PCI_IO_PROTOCOL.
249
250**/
251VOID
252I2cSendAck (
253 EFI_PCI_IO_PROTOCOL *PciIo
254 )
255{
256 I2cPinWrite (PciIo, I2CCLK_OUT, 1);
257 I2cPinWrite (PciIo, I2CDAT_OUT, 1);
258 I2cPinWrite (PciIo, I2CDAT_OUT, 0);
259 I2cPinWrite (PciIo, I2CCLK_OUT, 0);
260}
261
262/**
263 Start a I2C transfer on I2C Bus.
264
265 @param PciIo The pointer to PCI_IO_PROTOCOL.
266
267**/
268VOID
269I2cStart (
270 EFI_PCI_IO_PROTOCOL *PciIo
271 )
272{
273 //
274 // Init CLK and DAT pins
275 //
276 I2cPinWrite (PciIo, I2CCLK_OUT, 1);
277 I2cPinWrite (PciIo, I2CDAT_OUT, 1);
278 //
279 // Start a I2C transfer, set SDA low from high, when SCL is high
280 //
281 I2cPinWrite (PciIo, I2CDAT_OUT, 0);
282 I2cPinWrite (PciIo, I2CCLK_OUT, 0);
283}
284
285/**
286 Stop a I2C transfer on I2C Bus.
287
288 @param PciIo The pointer to PCI_IO_PROTOCOL.
289
290**/
291VOID
292I2cStop (
293 EFI_PCI_IO_PROTOCOL *PciIo
294 )
295{
296 //
297 // Stop a I2C transfer, set SDA high from low, when SCL is high
298 //
299 I2cPinWrite (PciIo, I2CDAT_OUT, 0);
300 I2cPinWrite (PciIo, I2CCLK_OUT, 1);
301 I2cPinWrite (PciIo, I2CDAT_OUT, 1);
302}
303
304/**
305 Read one byte data on I2C Bus.
306
307 Read one byte data from the slave device connected to I2C Bus.
308 If Data is NULL, then ASSERT().
309
310 @param PciIo The pointer to PCI_IO_PROTOCOL.
311 @param DeviceAddress Slave device's address.
312 @param RegisterAddress The register address on slave device.
313 @param Data The pointer to returned data if EFI_SUCCESS returned.
314
315 @retval EFI_DEVICE_ERROR
316 @retval EFI_SUCCESS
317
318**/
319EFI_STATUS
320EFIAPI
321I2cReadByte (
322 EFI_PCI_IO_PROTOCOL *PciIo,
323 UINT8 DeviceAddress,
324 UINT8 RegisterAddress,
325 UINT8 *Data
326 )
327{
328 ASSERT (Data != NULL);
329
330 //
331 // Start I2C transfer
332 //
333 I2cStart (PciIo);
334
335 //
336 // Send slave address with enabling write flag
337 //
338 I2cSendByte (PciIo, (UINT8) (DeviceAddress & 0xfe));
339
340 //
341 // Wait for ACK signal
342 //
343 if (I2cWaitAck (PciIo) == FALSE) {
344 return EFI_DEVICE_ERROR;
345 }
346
347 //
348 // Send register address
349 //
350 I2cSendByte (PciIo, RegisterAddress);
351
352 //
353 // Wait for ACK signal
354 //
355 if (I2cWaitAck (PciIo) == FALSE) {
356 return EFI_DEVICE_ERROR;
357 }
358
359 //
360 // Send slave address with enabling read flag
361 //
362 I2cSendByte (PciIo, (UINT8) (DeviceAddress | 0x01));
363
364 //
365 // Wait for ACK signal
366 //
367 if (I2cWaitAck (PciIo) == FALSE) {
368 return EFI_DEVICE_ERROR;
369 }
370
371 //
372 // Read byte data from I2C Bus
373 //
374 *Data = I2cReceiveByte (PciIo);
375
376 //
377 // Send ACK signal onto I2C Bus
378 //
379 I2cSendAck (PciIo);
380
381 //
382 // Stop a I2C transfer
383 //
384 I2cStop (PciIo);
385
386 return EFI_SUCCESS;
387}
388
389/**
390 Write one byte data onto I2C Bus.
391
392 Write one byte data to the slave device connected to I2C Bus.
393 If Data is NULL, then ASSERT().
394
395 @param PciIo The pointer to PCI_IO_PROTOCOL.
396 @param DeviceAddress Slave device's address.
397 @param RegisterAddress The register address on slave device.
398 @param Data The pointer to write data.
399
400 @retval EFI_DEVICE_ERROR
401 @retval EFI_SUCCESS
402
403**/
404EFI_STATUS
405EFIAPI
406I2cWriteByte (
407 EFI_PCI_IO_PROTOCOL *PciIo,
408 UINT8 DeviceAddress,
409 UINT8 RegisterAddress,
410 UINT8 *Data
411 )
412{
413 ASSERT (Data != NULL);
414
415 I2cStart (PciIo);
416 //
417 // Send slave address with enabling write flag
418 //
419 I2cSendByte (PciIo, (UINT8) (DeviceAddress & 0xfe));
420
421 //
422 // Wait for ACK signal
423 //
424 if (I2cWaitAck (PciIo) == FALSE) {
425 return EFI_DEVICE_ERROR;
426 }
427
428 //
429 // Send register address
430 //
431 I2cSendByte (PciIo, RegisterAddress);
432
433 //
434 // Wait for ACK signal
435 //
436 if (I2cWaitAck (PciIo) == FALSE) {
437 return EFI_DEVICE_ERROR;
438 }
439
440 //
441 // Send byte data onto I2C Bus
442 //
443 I2cSendByte (PciIo, *Data);
444
445 //
446 // Wait for ACK signal
447 //
448 if (I2cWaitAck (PciIo) == FALSE) {
449 return EFI_DEVICE_ERROR;
450 }
451
452 //
453 // Stop a I2C transfer
454 //
455 I2cStop (PciIo);
456
457 return EFI_SUCCESS;
458}
459
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette