VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/VBoxVgaDxe/VBoxVgaI2c.c@ 37808

Last change on this file since 37808 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

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