1 /** @file
2 *
3 *  Copyright (c) 2015, Hisilicon Limited. All rights reserved.
4 *  Copyright (c) 2015, Linaro Limited. All rights reserved.
5 *
6 *  This program and the accompanying materials
7 *  are licensed and made available under the terms and conditions of the BSD License
8 *  which accompanies this distribution.  The full text of the license may be found at
9 *  http://opensource.org/licenses/bsd-license.php
10 *
11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15 
16 
17 
18 #include <PiDxe.h>
19 #include <Library/DebugLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/ArmLib.h>
22 #include <Library/BaseLib.h>
23 #include <Library/I2CLib.h>
24 #include <Library/TimerLib.h>
25 
26 #include <Library/PlatformSysCtrlLib.h>
27 
28 #include "I2CLibInternal.h"
29 #include "I2CHw.h"
30 
I2C_Delay(UINT32 ulCount)31 VOID I2C_Delay(UINT32 ulCount)
32 {
33     MicroSecondDelay(ulCount);
34     return;
35 }
36 
37 
38 EFI_STATUS
39 EFIAPI
I2C_Disable(UINT32 Socket,UINT8 Port)40 I2C_Disable(UINT32 Socket,UINT8 Port)
41 {
42     UINT32                  ulTimeCnt = I2C_READ_TIMEOUT;
43     I2C0_STATUS_U           I2cStatusReg;
44     I2C0_ENABLE_U           I2cEnableReg;
45     I2C0_ENABLE_STATUS_U    I2cEnableStatusReg;
46 
47     UINTN Base = GetI2cBase(Socket, Port);
48 
49     I2C_REG_READ((Base + I2C_STATUS_OFFSET), I2cStatusReg.Val32);
50 
51     while (I2cStatusReg.bits.activity)
52     {
53         I2C_Delay(10000);
54 
55         ulTimeCnt--;
56         I2C_REG_READ(Base + I2C_STATUS_OFFSET, I2cStatusReg.Val32);
57         if (0 == ulTimeCnt)
58         {
59             return EFI_DEVICE_ERROR;
60         }
61     }
62 
63 
64     I2C_REG_READ(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32);
65     I2cEnableReg.bits.enable = 0;
66     I2C_REG_WRITE(Base + I2C_ENABLE_OFFSET,I2cEnableReg.Val32);
67 
68     I2C_REG_READ(Base + I2C_ENABLE_OFFSET,I2cEnableStatusReg.Val32);
69     if (0 == I2cEnableStatusReg.bits.ic_en)
70     {
71         return EFI_SUCCESS;
72     }
73     else
74     {
75         return EFI_DEVICE_ERROR;
76     }
77 }
78 
79 
80 EFI_STATUS
81 EFIAPI
I2C_Enable(UINT32 Socket,UINT8 Port)82 I2C_Enable(UINT32 Socket,UINT8 Port)
83 {
84     I2C0_ENABLE_U           I2cEnableReg;
85     I2C0_ENABLE_STATUS_U    I2cEnableStatusReg;
86 
87     UINTN Base = GetI2cBase(Socket, Port);
88 
89 
90     I2C_REG_READ(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32);
91     I2cEnableReg.bits.enable = 1;
92     I2C_REG_WRITE(Base + I2C_ENABLE_OFFSET, I2cEnableReg.Val32);
93 
94 
95     I2C_REG_READ(Base + I2C_ENABLE_STATUS_OFFSET, I2cEnableStatusReg.Val32);
96     if (1 == I2cEnableStatusReg.bits.ic_en)
97     {
98         return EFI_SUCCESS;
99     }
100     else
101     {
102         return EFI_DEVICE_ERROR;
103     }
104 }
105 
I2C_SetTarget(UINT32 Socket,UINT8 Port,UINT32 I2cDeviceAddr)106 void I2C_SetTarget(UINT32 Socket,UINT8 Port,UINT32 I2cDeviceAddr)
107 {
108     I2C0_TAR_U    I2cTargetReg;
109     UINTN Base = GetI2cBase(Socket, Port);
110 
111 
112     I2C_REG_READ(Base + I2C_TAR_OFFSET, I2cTargetReg.Val32);
113     I2cTargetReg.bits.ic_tar = I2cDeviceAddr;
114     I2C_REG_WRITE(Base + I2C_TAR_OFFSET, I2cTargetReg.Val32);
115 
116     return;
117 }
118 
119 
120 EFI_STATUS
121 EFIAPI
I2CInit(UINT32 Socket,UINT32 Port,SPEED_MODE SpeedMode)122 I2CInit(UINT32 Socket, UINT32 Port, SPEED_MODE SpeedMode)
123 {
124     I2C0_CON_U              I2cControlReg;
125     I2C0_SS_SCL_HCNT_U      I2cStandardSpeedSclHighCount;
126     I2C0_SS_SCL_LCNT_U      I2cStandardSpeedSclLowCount;
127     I2C0_RX_TL_U            I2cRxFifoReg;
128     I2C0_TX_TL_U            I2cTxFifoReg;
129     I2C0_INTR_MASK_U        I2cIntrMask;
130     EFI_STATUS              Status;
131 
132     UINTN Base = GetI2cBase(Socket, Port);
133 
134     if((Socket >= MAX_SOCKET) || (Port >= I2C_PORT_MAX) || (SpeedMode >= SPEED_MODE_MAX)){
135         return EFI_INVALID_PARAMETER;
136     }
137 
138 
139     Status = I2C_Disable(Socket,Port);
140     if(EFI_ERROR(Status))
141     {
142         return EFI_DEVICE_ERROR;
143     }
144 
145 
146     I2C_REG_READ(Base + I2C_CON_OFFSET, I2cControlReg.Val32);
147     I2cControlReg.bits.master = 1;
148     I2cControlReg.bits.spedd = 0x1;
149     I2cControlReg.bits.restart_en = 1;
150     I2cControlReg.bits.slave_disable = 1;
151     I2C_REG_WRITE(Base + I2C_CON_OFFSET,I2cControlReg.Val32);
152 
153 
154     if(Normal == SpeedMode)
155     {
156         I2C_REG_READ(Base + I2C_SS_SCL_HCNT_OFFSET,I2cStandardSpeedSclHighCount.Val32);
157         I2cStandardSpeedSclHighCount.bits.ic_ss_scl_hcnt = I2C_SS_SCLHCNT;
158         I2C_REG_WRITE(Base + I2C_SS_SCL_HCNT_OFFSET, I2cStandardSpeedSclHighCount.Val32);
159         I2C_REG_READ(Base + I2C_SS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
160         I2cStandardSpeedSclLowCount.bits.ic_ss_scl_lcnt = I2C_SS_SCLLCNT;
161         I2C_REG_WRITE(Base + I2C_SS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
162     }
163     else
164     {
165         I2C_REG_READ(Base + I2C_FS_SCL_HCNT_OFFSET,I2cStandardSpeedSclHighCount.Val32);
166         I2cStandardSpeedSclHighCount.bits.ic_ss_scl_hcnt = I2C_SS_SCLHCNT;
167         I2C_REG_WRITE(Base + I2C_FS_SCL_HCNT_OFFSET, I2cStandardSpeedSclHighCount.Val32);
168         I2C_REG_READ(Base + I2C_FS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
169         I2cStandardSpeedSclLowCount.bits.ic_ss_scl_lcnt = I2C_SS_SCLLCNT;
170         I2C_REG_WRITE(Base + I2C_FS_SCL_LCNT_OFFSET, I2cStandardSpeedSclLowCount.Val32);
171     }
172 
173 
174     I2C_REG_READ(Base + I2C_RX_TL_OFFSET, I2cRxFifoReg.Val32);
175     I2cRxFifoReg.bits.rx_tl = I2C_TXRX_THRESHOLD;
176     I2C_REG_WRITE(Base + I2C_RX_TL_OFFSET, I2cRxFifoReg.Val32);
177     I2C_REG_READ(Base + I2C_TX_TL_OFFSET,I2cTxFifoReg.Val32);
178     I2cTxFifoReg.bits.tx_tl = I2C_TXRX_THRESHOLD;
179     I2C_REG_WRITE(Base + I2C_TX_TL_OFFSET, I2cTxFifoReg.Val32);
180 
181 
182     I2C_REG_READ(Base + I2C_INTR_MASK_OFFSET, I2cIntrMask.Val32);
183     I2cIntrMask.Val32 = 0x0;
184     I2C_REG_WRITE(Base + I2C_INTR_MASK_OFFSET, I2cIntrMask.Val32);
185 
186 
187     Status = I2C_Enable(Socket,Port);
188     if(EFI_ERROR(Status))
189     {
190         return EFI_DEVICE_ERROR;
191     }
192 
193     return I2cLibRuntimeSetup (Socket, Port);
194 }
195 
196 EFI_STATUS
197 EFIAPI
I2CSdaConfig(UINT32 Socket,UINT32 Port)198 I2CSdaConfig(UINT32 Socket, UINT32 Port)
199 {
200 
201     UINTN Base = GetI2cBase(Socket, Port);
202 
203     if((Socket >= MAX_SOCKET) || (Port >= I2C_PORT_MAX)){
204         return EFI_INVALID_PARAMETER;
205     }
206 
207     I2C_REG_WRITE(Base + I2C_SDA_HOLD, 0x14);
208 
209     return EFI_SUCCESS;
210 }
211 
212 
213 
I2C_GetTxStatus(UINT32 Socket,UINT8 Port)214 UINT32 I2C_GetTxStatus(UINT32 Socket,UINT8 Port)
215 {
216     I2C0_TXFLR_U ulFifo;
217     UINTN Base = GetI2cBase(Socket, Port);
218 
219     I2C_REG_READ(Base + I2C_TXFLR_OFFSET, ulFifo.Val32);
220     return ulFifo.bits.txflr;
221 }
222 
223 UINT32
I2C_GetRxStatus(UINT32 Socket,UINT8 Port)224 I2C_GetRxStatus(UINT32 Socket,UINT8 Port)
225 {
226     I2C0_RXFLR_U ulFifo;
227     UINTN Base = GetI2cBase(Socket, Port);
228 
229     I2C_REG_READ(Base + I2C_RXFLR_OFFSET, ulFifo.Val32);
230     return ulFifo.bits.rxflr;
231 }
232 
233 EFI_STATUS
234 EFIAPI
WriteBeforeRead(I2C_DEVICE * I2cInfo,UINT32 ulLength,UINT8 * pBuf)235 WriteBeforeRead(I2C_DEVICE *I2cInfo, UINT32 ulLength, UINT8 *pBuf)
236 {
237     UINT32 ulFifo;
238     UINT32 ulCnt;
239     UINT32 ulTimes = 0;
240 
241     UINTN  Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
242 
243 
244     I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
245 
246     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
247     while(0 != ulFifo)
248     {
249         I2C_Delay(2);
250         if(++ulTimes > I2C_READ_TIMEOUT)
251         {
252             return EFI_TIMEOUT;
253         }
254         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
255     }
256 
257     for(ulCnt = 0; ulCnt < ulLength; ulCnt++)
258     {
259         ulTimes = 0;
260         while(ulFifo > I2C_TXRX_THRESHOLD)
261         {
262             I2C_Delay(2);
263             if(++ulTimes > I2C_READ_TIMEOUT)
264             {
265                 return EFI_TIMEOUT;
266             }
267             ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
268         }
269 
270         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, *pBuf++);
271         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
272     }
273 
274     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
275     ulTimes = 0;
276     while(0 != ulFifo)
277     {
278         I2C_Delay(2);
279 
280         if(++ulTimes > I2C_READ_TIMEOUT)
281         {
282             return EFI_TIMEOUT;
283         }
284         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
285     }
286 
287     return EFI_SUCCESS;
288 }
289 
290 
291 EFI_STATUS
292 EFIAPI
I2CWrite(I2C_DEVICE * I2cInfo,UINT16 InfoOffset,UINT32 ulLength,UINT8 * pBuf)293 I2CWrite(I2C_DEVICE *I2cInfo, UINT16 InfoOffset, UINT32 ulLength, UINT8 *pBuf)
294 {
295     UINT32 ulFifo;
296     UINT32 ulTimes = 0;
297     UINT32  Idx;
298     UINTN  Base;
299 
300 
301     if(I2cInfo->Port >= I2C_PORT_MAX)
302     {
303         return EFI_INVALID_PARAMETER;
304     }
305 
306     Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
307 
308     (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
309 
310     I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
311 
312     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
313     while(0 != ulFifo)
314     {
315         I2C_Delay(2);
316         if(++ulTimes > I2C_READ_TIMEOUT)
317         {
318             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
319             return EFI_TIMEOUT;
320         }
321         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
322     }
323 
324 
325     if(I2cInfo->DeviceType)
326     {
327         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff);
328         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
329     }
330     else
331     {
332         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
333     }
334 
335     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
336     ulTimes = 0;
337     while(0 != ulFifo)
338     {
339         I2C_Delay(2);
340         if(++ulTimes > I2C_READ_TIMEOUT)
341         {
342             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
343             return EFI_TIMEOUT;
344         }
345         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
346     }
347 
348     for(Idx = 0; Idx < ulLength; Idx++)
349     {
350         ulTimes = 0;
351         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
352         while(ulFifo > I2C_TXRX_THRESHOLD)
353         {
354             I2C_Delay(2);
355             if(++ulTimes > I2C_READ_TIMEOUT)
356             {
357                 (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
358                 return EFI_TIMEOUT;
359             }
360             ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
361         }
362 
363         if (Idx < ulLength - 1) {
364             I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (*pBuf++));
365         } else {
366             //Send command stop bit for the last transfer
367             I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (*pBuf++) | I2C_CMD_STOP_BIT);
368         }
369     }
370 
371     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
372     ulTimes = 0;
373     while(0 != ulFifo)
374     {
375         I2C_Delay(2);
376 
377         if(++ulTimes > I2C_READ_TIMEOUT)
378         {
379             DEBUG ((EFI_D_ERROR, "I2C Write try to finished,time out!\n"));
380             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
381             return EFI_TIMEOUT;
382         }
383         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
384     }
385     (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
386 
387     return EFI_SUCCESS;
388 }
389 
390 EFI_STATUS
391 EFIAPI
I2CRead(I2C_DEVICE * I2cInfo,UINT16 InfoOffset,UINT32 ulRxLen,UINT8 * pBuf)392 I2CRead(I2C_DEVICE *I2cInfo, UINT16 InfoOffset,UINT32 ulRxLen,UINT8 *pBuf)
393 {
394     UINT32 ulFifo;
395     UINT32 ulTimes = 0;
396     UINT8  I2CWAddr[2];
397     EFI_STATUS  Status;
398     UINT32  Idx = 0;
399     UINTN Base;
400 
401 
402     if(I2cInfo->Port >= I2C_PORT_MAX)
403     {
404         return EFI_INVALID_PARAMETER;
405     }
406 
407     (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
408     Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
409     if(I2cInfo->DeviceType)
410     {
411         I2CWAddr[0] = (InfoOffset >> 8) & 0xff;
412         I2CWAddr[1] = (InfoOffset & 0xff);
413         Status = WriteBeforeRead(I2cInfo, 2,I2CWAddr);
414         if(EFI_ERROR(Status))
415         {
416             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
417             return EFI_ABORTED;
418         }
419     }
420     else
421     {
422         I2CWAddr[0] = (InfoOffset & 0xff);
423         Status = WriteBeforeRead(I2cInfo, 1,I2CWAddr);
424         if(EFI_ERROR(Status))
425         {
426             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
427             return EFI_ABORTED;
428         }
429     }
430 
431     I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
432 
433     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
434     while(0 != ulFifo)
435     {
436         I2C_Delay(2);
437 
438         while(++ulTimes > I2C_READ_TIMEOUT)
439         {
440             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
441             return EFI_TIMEOUT;
442         }
443         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
444     }
445 
446     while (ulRxLen > 0) {
447         if (ulRxLen > 1) {
448             I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL);
449         } else {
450             //Send command stop bit for the last transfer
451             I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL | I2C_CMD_STOP_BIT);
452         }
453 
454         ulTimes = 0;
455         do {
456             I2C_Delay(2);
457 
458             while(++ulTimes > I2C_READ_TIMEOUT) {
459                 (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
460                 return EFI_TIMEOUT;
461             }
462             ulFifo = I2C_GetRxStatus(I2cInfo->Socket,I2cInfo->Port);
463         }while(0 == ulFifo);
464 
465         I2C_REG_READ(Base + I2C_DATA_CMD_OFFSET, pBuf[Idx++]);
466 
467         ulRxLen --;
468     }
469     (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
470 
471     return EFI_SUCCESS;
472 }
473 
474 EFI_STATUS
475 EFIAPI
I2CReadMultiByte(I2C_DEVICE * I2cInfo,UINT32 InfoOffset,UINT32 ulRxLen,UINT8 * pBuf)476 I2CReadMultiByte(I2C_DEVICE *I2cInfo, UINT32 InfoOffset,UINT32 ulRxLen,UINT8 *pBuf)
477 {
478     UINT32 ulCnt;
479     UINT16 usTotalLen = 0;
480     UINT32 ulFifo;
481     UINT32 ulTimes = 0;
482     UINT8  I2CWAddr[4];
483     EFI_STATUS  Status;
484     UINT32  BytesLeft;
485     UINT32  Idx = 0;
486     UINTN Base;
487 
488 
489     if(I2cInfo->Port >= I2C_PORT_MAX)
490     {
491         return EFI_INVALID_PARAMETER;
492     }
493 
494     (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
495     Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
496     if(I2cInfo->DeviceType == DEVICE_TYPE_E2PROM)
497     {
498         I2CWAddr[0] = (InfoOffset >> 8) & 0xff;
499         I2CWAddr[1] = (InfoOffset & 0xff);
500         Status = WriteBeforeRead(I2cInfo, 2,I2CWAddr);
501         if(EFI_ERROR(Status))
502         {
503             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
504             return EFI_ABORTED;
505         }
506     }
507 
508     else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_3BYTE_OPERANDS)
509     {
510         I2CWAddr[0] = (InfoOffset >> 16) & 0xff;
511         I2CWAddr[1] = (InfoOffset >> 8) & 0xff;
512         I2CWAddr[2] = (InfoOffset & 0xff);
513         Status = WriteBeforeRead(I2cInfo, 3,I2CWAddr);
514         if(EFI_ERROR(Status))
515         {
516             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
517             return EFI_ABORTED;
518         }
519     }
520 
521     else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_4BYTE_OPERANDS)
522     {
523         I2CWAddr[0] = (InfoOffset >> 24) & 0xff;
524         I2CWAddr[1] = (InfoOffset >> 16) & 0xff;
525         I2CWAddr[2] = (InfoOffset >> 8) & 0xff;
526         I2CWAddr[3] = (InfoOffset & 0xff);
527         Status = WriteBeforeRead(I2cInfo, 4,I2CWAddr);
528         if(EFI_ERROR(Status))
529         {
530             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
531             return EFI_ABORTED;
532         }
533     }
534 
535     else
536     {
537         I2CWAddr[0] = (InfoOffset & 0xff);
538         Status = WriteBeforeRead(I2cInfo, 1,I2CWAddr);
539         if(EFI_ERROR(Status))
540         {
541             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
542             return EFI_ABORTED;
543         }
544     }
545 
546 
547     I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
548     usTotalLen = ulRxLen;
549     BytesLeft = usTotalLen;
550 
551     for(ulCnt = 0; ulCnt < BytesLeft; ulCnt++) {
552         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, I2C_READ_SIGNAL);
553     }
554 
555 
556     for(ulCnt = 0; ulCnt < BytesLeft; ulCnt++) {
557         ulTimes = 0;
558         do {
559             I2C_Delay(2);
560 
561             while(++ulTimes > I2C_READ_TIMEOUT) {
562                 (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
563                 return EFI_TIMEOUT;
564             }
565             ulFifo = I2C_GetRxStatus(I2cInfo->Socket,I2cInfo->Port);
566         }while(0 == ulFifo);
567 
568         I2C_REG_READ(Base + I2C_DATA_CMD_OFFSET, pBuf[Idx++]);
569     }
570     (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
571 
572     return EFI_SUCCESS;
573 }
574 
575 EFI_STATUS
576 EFIAPI
I2CWriteMultiByte(I2C_DEVICE * I2cInfo,UINT32 InfoOffset,UINT32 ulLength,UINT8 * pBuf)577 I2CWriteMultiByte(I2C_DEVICE *I2cInfo, UINT32 InfoOffset, UINT32 ulLength, UINT8 *pBuf)
578 {
579     UINT32 ulFifo;
580     UINT32 ulTimes = 0;
581     UINT32  Idx;
582     UINTN  Base;
583 
584 
585     if(I2cInfo->Port >= I2C_PORT_MAX)
586     {
587         return EFI_INVALID_PARAMETER;
588     }
589 
590     Base = GetI2cBase(I2cInfo->Socket, I2cInfo->Port);
591 
592     (VOID)I2C_Enable(I2cInfo->Socket, I2cInfo->Port);
593 
594     I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress);
595 
596     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
597     while(0 != ulFifo)
598     {
599         I2C_Delay(2);
600         if(++ulTimes > I2C_READ_TIMEOUT)
601         {
602             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
603             return EFI_TIMEOUT;
604         }
605         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
606     }
607 
608 
609     if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_3BYTE_OPERANDS)
610     {
611         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 16) & 0xff);
612         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff);
613         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
614     }
615 
616     else if(I2cInfo->DeviceType == DEVICE_TYPE_CPLD_4BYTE_OPERANDS)
617     {
618         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 24) & 0xff);
619         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 16) & 0xff);
620         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, (InfoOffset >> 8) & 0xff);
621         I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, InfoOffset & 0xff);
622     }
623 
624     else
625     {
626 
627     }
628 
629     ulTimes = 0;
630     for(Idx = 0; Idx < ulLength; Idx++)
631     {
632 
633        I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, *pBuf++);
634 
635     }
636 
637     ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
638     ulTimes = 0;
639     while(0 != ulFifo)
640     {
641         I2C_Delay(2);
642 
643         if(++ulTimes > I2C_READ_TIMEOUT)
644         {
645             DEBUG ((EFI_D_ERROR, "I2C Write try to finished,time out!\n"));
646             (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
647             return EFI_TIMEOUT;
648         }
649         ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port);
650     }
651     (VOID)I2C_Disable(I2cInfo->Socket, I2cInfo->Port);
652 
653     return EFI_SUCCESS;
654 }
655 
656