Home | History | Annotate | Download | only in I2CLib
      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 
     31 VOID I2C_Delay(UINT32 ulCount)
     32 {
     33     MicroSecondDelay(ulCount);
     34     return;
     35 }
     36 
     37 
     38 EFI_STATUS
     39 EFIAPI
     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
     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 
    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
    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
    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 
    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
    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
    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
    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
    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
    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
    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