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