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