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