Home | History | Annotate | Download | only in I2cLib
      1 /** @file
      2 I2C Library for Quark I2C Controller.
      3 Follows I2C Controller setup instructions as detailed in
      4 Quark DataSheet (doc id: 329676) Section 19.1/19.1.3.
      5 
      6 
      7 Copyright (c) 2013-2015 Intel Corporation.
      8 
      9 This program and the accompanying materials
     10 are licensed and made available under the terms and conditions of the BSD License
     11 which accompanies this distribution.  The full text of the license may be found at
     12 http://opensource.org/licenses/bsd-license.php
     13 
     14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 
     17 **/
     18 
     19 #include "CommonHeader.h"
     20 
     21 /**
     22   The Called to Common Service Entry.
     23 
     24   @return None.
     25 
     26 **/
     27 
     28 VOID
     29 I2cCommonServiceEntry  (
     30   OUT UINT16 *SaveCmdPtr,
     31   OUT UINT32 *SaveBar0Ptr
     32   )
     33 {
     34   *SaveBar0Ptr = IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);
     35   if (((*SaveBar0Ptr) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {
     36 
     37     IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) =
     38       FixedPcdGet32 (PcdIohI2cMmioBase) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK;
     39 
     40     //
     41     // also Save Cmd Register, Setup by InitializeInternal later during xfers.
     42     //
     43     *SaveCmdPtr = IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD);
     44   }
     45 }
     46 
     47 /**
     48   The Called on Common Service Exit.
     49 
     50   @return None.
     51 
     52 **/
     53 VOID
     54 I2cCommonServiceExit  (
     55   IN CONST UINT16 SaveCmd,
     56   IN CONST UINT32 SaveBar0
     57 
     58   )
     59 {
     60   if ((SaveBar0 & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {
     61     IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD) = SaveCmd;
     62     IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) = SaveBar0;
     63   }
     64 }
     65 
     66 
     67 /**
     68   The GetI2CIoPortBaseAddress() function gets IO port base address of I2C Controller.
     69 
     70   Always reads PCI configuration space to get MMIO base address of I2C Controller.
     71 
     72   @return The IO port base address of I2C controller.
     73 
     74 **/
     75 UINTN
     76 GetI2CIoPortBaseAddress (
     77   VOID
     78   )
     79 {
     80   UINTN     I2CIoPortBaseAddress;
     81 
     82   //
     83   // Get I2C Memory Mapped registers base address.
     84   //
     85   I2CIoPortBaseAddress = IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);
     86 
     87   //
     88   // Make sure that the IO port base address has been properly set.
     89   //
     90   ASSERT (I2CIoPortBaseAddress != 0);
     91   ASSERT (I2CIoPortBaseAddress != 0xFF);
     92 
     93   return I2CIoPortBaseAddress;
     94 }
     95 
     96 
     97 /**
     98   The EnableI2CMmioSpace() function enables access to I2C MMIO space.
     99 
    100 **/
    101 VOID
    102 EnableI2CMmioSpace (
    103   VOID
    104   )
    105 {
    106   UINT8 PciCmd;
    107 
    108   //
    109   // Read PCICMD.  Bus=0, Dev=0, Func=0, Reg=0x4
    110   //
    111   PciCmd = IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD);
    112 
    113   //
    114   // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0)
    115   //
    116   PciCmd |= 0x7;
    117   IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD) = PciCmd;
    118 
    119 }
    120 
    121 /**
    122   The DisableI2CController() functions disables I2C Controller.
    123 
    124 **/
    125 VOID
    126 DisableI2CController (
    127   VOID
    128   )
    129 {
    130   UINTN       I2CIoPortBaseAddress;
    131   UINT32      Addr;
    132   UINT32      Data;
    133   UINT8       PollCount;
    134 
    135   PollCount = 0;
    136 
    137   //
    138   // Get I2C Memory Mapped registers base address.
    139   //
    140   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    141 
    142   //
    143   // Disable the I2C Controller by setting IC_ENABLE.ENABLE to zero
    144   //
    145   Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
    146   Data = *((volatile UINT32 *) (UINTN)(Addr));
    147   Data &= ~B_I2C_REG_ENABLE;
    148   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    149 
    150   //
    151   // Read the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled
    152   //
    153   Data = 0xFF;
    154   Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE_STATUS;
    155   Data = *((volatile UINT32 *) (UINTN)(Addr)) & I2C_REG_ENABLE_STATUS;
    156   while (Data != 0) {
    157     //
    158     // Poll the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled, until timeout (TI2C_POLL*MAX_T_POLL_COUNT).
    159     //
    160     PollCount++;
    161     if (PollCount >= MAX_T_POLL_COUNT) {
    162       break;
    163     }
    164     MicroSecondDelay(TI2C_POLL);
    165     Data = *((volatile UINT32 *) (UINTN)(Addr));
    166     Data &= I2C_REG_ENABLE_STATUS;
    167   }
    168 
    169   //
    170   // Asset if controller does not enter Disabled state.
    171   //
    172   ASSERT (PollCount < MAX_T_POLL_COUNT);
    173 
    174   //
    175   // Read IC_CLR_INTR register to automatically clear the combined interrupt,
    176   // all individual interrupts and the IC_TX_ABRT_SOURCE register.
    177   //
    178   Addr = I2CIoPortBaseAddress + I2C_REG_CLR_INT;
    179   Data = *((volatile UINT32 *) (UINTN)(Addr));
    180 
    181 }
    182 
    183 /**
    184   The EnableI2CController() function enables the I2C Controller.
    185 
    186 **/
    187 VOID
    188 EnableI2CController (
    189   VOID
    190   )
    191 {
    192   UINTN   I2CIoPortBaseAddress;
    193   UINT32  Addr;
    194   UINT32  Data;
    195 
    196   //
    197   // Get I2C Memory Mapped registers base address.
    198   //
    199   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    200 
    201   //
    202   // Enable the I2C Controller by setting IC_ENABLE.ENABLE to 1
    203   //
    204   Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
    205   Data = *((volatile UINT32 *) (UINTN)(Addr));
    206   Data |= B_I2C_REG_ENABLE;
    207   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    208 
    209   //
    210   // Clear overflow and abort error status bits before transactions.
    211   //
    212   Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_OVER;
    213   Data = *((volatile UINT32 *) (UINTN)(Addr));
    214   Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_OVER;
    215   Data = *((volatile UINT32 *) (UINTN)(Addr));
    216   Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_ABRT;
    217   Data = *((volatile UINT32 *) (UINTN)(Addr));
    218 
    219 }
    220 
    221 /**
    222   The WaitForStopDet() function waits until I2C STOP Condition occurs,
    223   indicating transfer completion.
    224 
    225   @retval EFI_SUCCESS           Stop detected.
    226   @retval EFI_TIMEOUT           Timeout while waiting for stop condition.
    227   @retval EFI_ABORTED           Tx abort signaled in HW status register.
    228   @retval EFI_DEVICE_ERROR      Tx or Rx overflow detected.
    229 
    230 **/
    231 EFI_STATUS
    232 WaitForStopDet (
    233   VOID
    234   )
    235 {
    236   UINTN       I2CIoPortBaseAddress;
    237   UINT32      Addr;
    238   UINT32      Data;
    239   UINT32      PollCount;
    240   EFI_STATUS  Status;
    241 
    242   Status = EFI_SUCCESS;
    243 
    244   PollCount = 0;
    245 
    246   //
    247   // Get I2C Memory Mapped registers base address.
    248   //
    249   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    250 
    251   //
    252   // Wait for STOP Detect.
    253   //
    254   Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
    255 
    256   do {
    257     Data = *((volatile UINT32 *) (UINTN)(Addr));
    258     if ((Data & I2C_REG_RAW_INTR_STAT_TX_ABRT) != 0) {
    259       Status = EFI_ABORTED;
    260       break;
    261     }
    262     if ((Data & I2C_REG_RAW_INTR_STAT_TX_OVER) != 0) {
    263       Status = EFI_DEVICE_ERROR;
    264       break;
    265     }
    266     if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) {
    267       Status = EFI_DEVICE_ERROR;
    268       break;
    269     }
    270     if ((Data & I2C_REG_RAW_INTR_STAT_STOP_DET) != 0) {
    271       Status = EFI_SUCCESS;
    272       break;
    273     }
    274     MicroSecondDelay(TI2C_POLL);
    275     PollCount++;
    276     if (PollCount >= MAX_STOP_DET_POLL_COUNT) {
    277       Status = EFI_TIMEOUT;
    278       break;
    279     }
    280 
    281   } while (TRUE);
    282 
    283   return Status;
    284 }
    285 
    286 /**
    287 
    288   The InitializeInternal() function initialises internal I2C Controller
    289   register values that are commonly required for I2C Write and Read transfers.
    290 
    291   @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
    292 
    293   @retval EFI_SUCCESS           I2C Operation completed successfully.
    294 
    295 **/
    296 EFI_STATUS
    297 InitializeInternal (
    298   IN  EFI_I2C_ADDR_MODE  AddrMode
    299   )
    300 {
    301   UINTN       I2CIoPortBaseAddress;
    302   UINTN       Addr;
    303   UINT32      Data;
    304   EFI_STATUS  Status;
    305 
    306   Status = EFI_SUCCESS;
    307 
    308   //
    309   // Enable access to I2C Controller MMIO space.
    310   //
    311   EnableI2CMmioSpace ();
    312 
    313   //
    314   // Disable I2C Controller initially
    315   //
    316   DisableI2CController ();
    317 
    318   //
    319   // Get I2C Memory Mapped registers base address.
    320   //
    321   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    322 
    323   //
    324   // Clear START_DET
    325   //
    326   Addr = I2CIoPortBaseAddress + I2C_REG_CLR_START_DET;
    327   Data = *((volatile UINT32 *) (UINTN)(Addr));
    328   Data &= ~B_I2C_REG_CLR_START_DET;
    329   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    330 
    331   //
    332   // Clear STOP_DET
    333   //
    334   Addr = I2CIoPortBaseAddress + I2C_REG_CLR_STOP_DET;
    335   Data = *((volatile UINT32 *) (UINTN)(Addr));
    336   Data &= ~B_I2C_REG_CLR_STOP_DET;
    337   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    338 
    339   //
    340   // Set addressing mode to user defined (7 or 10 bit) and
    341   // speed mode to that defined by PCD (standard mode default).
    342   //
    343   Addr = I2CIoPortBaseAddress + I2C_REG_CON;
    344   Data = *((volatile UINT32 *) (UINTN)(Addr));
    345   // Set Addressing Mode
    346   if (AddrMode == EfiI2CSevenBitAddrMode) {
    347     Data &= ~B_I2C_REG_CON_10BITADD_MASTER;
    348   } else {
    349     Data |= B_I2C_REG_CON_10BITADD_MASTER;
    350   }
    351   // Set Speed Mode
    352   Data &= ~B_I2C_REG_CON_SPEED;
    353   if (FeaturePcdGet (PcdI2CFastModeEnabled)) {
    354     Data |= BIT2;
    355   } else {
    356     Data |= BIT1;
    357   }
    358   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    359 
    360   Data = *((volatile UINT32 *) (UINTN)(Addr));
    361 
    362   return Status;
    363 
    364 }
    365 
    366 /**
    367 
    368   The WriteByte() function provides a standard way to execute a
    369   standard single byte write to an IC2 device (without accessing
    370   sub-addresses), as defined in the I2C Specification.
    371 
    372   @param  I2CAddress      I2C Slave device address
    373   @param  Value           The 8-bit value to write.
    374 
    375   @retval EFI_SUCCESS           Transfer success.
    376   @retval EFI_UNSUPPORTED       Unsupported input param.
    377   @retval EFI_TIMEOUT           Timeout while waiting xfer.
    378   @retval EFI_ABORTED           Controller aborted xfer.
    379   @retval EFI_DEVICE_ERROR      Device error detected by controller.
    380 
    381 **/
    382 EFI_STATUS
    383 EFIAPI
    384 WriteByte (
    385   IN  UINTN          I2CAddress,
    386   IN  UINT8          Value
    387   )
    388 {
    389   UINTN       I2CIoPortBaseAddress;
    390   UINTN       Addr;
    391   UINT32      Data;
    392   EFI_STATUS  Status;
    393 
    394   //
    395   // Get I2C Memory Mapped registers base address
    396   //
    397   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    398 
    399   //
    400   // Write to the IC_TAR register the address of the slave device to be addressed
    401   //
    402   Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
    403   Data = *((volatile UINT32 *) (UINTN)(Addr));
    404   Data &= ~B_I2C_REG_TAR;
    405   Data |= I2CAddress;
    406   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    407 
    408   //
    409   // Enable the I2C Controller
    410   //
    411   EnableI2CController ();
    412 
    413   //
    414   // Write the data and transfer direction to the IC_DATA_CMD register.
    415   // Also specify that transfer should be terminated by STOP condition.
    416   //
    417   Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
    418   Data = *((volatile UINT32 *) (UINTN)(Addr));
    419   Data &= 0xFFFFFF00;
    420   Data |= (UINT8)Value;
    421   Data &= ~B_I2C_REG_DATA_CMD_RW;
    422   Data |= B_I2C_REG_DATA_CMD_STOP;
    423   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    424 
    425   //
    426   // Wait for transfer completion.
    427   //
    428   Status = WaitForStopDet ();
    429 
    430   //
    431   // Ensure I2C Controller disabled.
    432   //
    433   DisableI2CController();
    434 
    435   return Status;
    436 }
    437 
    438 /**
    439 
    440   The ReadByte() function provides a standard way to execute a
    441   standard single byte read to an IC2 device (without accessing
    442   sub-addresses), as defined in the I2C Specification.
    443 
    444   @param  I2CAddress      I2C Slave device address
    445   @param  ReturnDataPtr   Pointer to location to receive read byte.
    446 
    447   @retval EFI_SUCCESS           Transfer success.
    448   @retval EFI_UNSUPPORTED       Unsupported input param.
    449   @retval EFI_TIMEOUT           Timeout while waiting xfer.
    450   @retval EFI_ABORTED           Controller aborted xfer.
    451   @retval EFI_DEVICE_ERROR      Device error detected by controller.
    452 
    453 **/
    454 EFI_STATUS
    455 EFIAPI
    456 ReadByte (
    457   IN  UINTN          I2CAddress,
    458   OUT UINT8          *ReturnDataPtr
    459   )
    460 {
    461   UINTN       I2CIoPortBaseAddress;
    462   UINTN       Addr;
    463   UINT32      Data;
    464   EFI_STATUS  Status;
    465 
    466   //
    467   // Get I2C Memory Mapped registers base address.
    468   //
    469   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    470 
    471   //
    472   // Write to the IC_TAR register the address of the slave device to be addressed
    473   //
    474   Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
    475   Data = *((volatile UINT32 *) (UINTN)(Addr));
    476   Data &= ~B_I2C_REG_TAR;
    477   Data |= I2CAddress;
    478   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    479 
    480   //
    481   // Enable the I2C Controller
    482   //
    483   EnableI2CController ();
    484 
    485   //
    486   // Write transfer direction to the IC_DATA_CMD register and
    487   // specify that transfer should be terminated by STOP condition.
    488   //
    489   Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
    490   Data = *((volatile UINT32 *) (UINTN)(Addr));
    491   Data &= 0xFFFFFF00;
    492   Data |= B_I2C_REG_DATA_CMD_RW;
    493   Data |= B_I2C_REG_DATA_CMD_STOP;
    494   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    495 
    496   //
    497   // Wait for transfer completion
    498   //
    499   Status = WaitForStopDet ();
    500   if (!EFI_ERROR(Status)) {
    501 
    502     //
    503     // Clear RX underflow before reading IC_DATA_CMD.
    504     //
    505     Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER;
    506     Data = *((volatile UINT32 *) (UINTN)(Addr));
    507 
    508     //
    509     // Obtain and return read data byte from RX buffer (IC_DATA_CMD[7:0]).
    510     //
    511     Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
    512     Data = *((volatile UINT32 *) (UINTN)(Addr));
    513     Data &= 0x000000FF;
    514     *ReturnDataPtr = (UINT8) Data;
    515 
    516     Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
    517     Data = *((volatile UINT32 *) (UINTN)(Addr));
    518     Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER;
    519     if (Data != 0) {
    520       Status = EFI_DEVICE_ERROR;
    521     }
    522   }
    523 
    524   //
    525   // Ensure I2C Controller disabled.
    526   //
    527   DisableI2CController ();
    528 
    529   return Status;
    530 }
    531 
    532 /**
    533 
    534   The WriteMultipleByte() function provides a standard way to execute
    535   multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
    536   when writing block of data), as defined in the I2C Specification.
    537 
    538   @param I2CAddress   The I2C slave address of the device
    539                       with which to communicate.
    540 
    541   @param WriteBuffer  Contains the value of byte to be written to the
    542                       I2C slave device.
    543 
    544   @param Length       No. of bytes to be written.
    545 
    546   @retval EFI_SUCCESS           Transfer success.
    547   @retval EFI_UNSUPPORTED       Unsupported input param.
    548   @retval EFI_TIMEOUT           Timeout while waiting xfer.
    549   @retval EFI_ABORTED           Tx abort signaled in HW status register.
    550   @retval EFI_DEVICE_ERROR      Tx overflow detected.
    551 
    552 **/
    553 EFI_STATUS
    554 EFIAPI
    555 WriteMultipleByte (
    556   IN  UINTN          I2CAddress,
    557   IN  UINT8          *WriteBuffer,
    558   IN  UINTN          Length
    559   )
    560 {
    561   UINTN       I2CIoPortBaseAddress;
    562   UINTN       Index;
    563   UINTN       Addr;
    564   UINT32      Data;
    565   EFI_STATUS  Status;
    566 
    567   if (Length > I2C_FIFO_SIZE) {
    568     return EFI_UNSUPPORTED;  // Routine does not handle xfers > fifo size.
    569   }
    570 
    571   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    572 
    573   //
    574   // Write to the IC_TAR register the address of the slave device to be addressed
    575   //
    576   Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
    577   Data = *((volatile UINT32 *) (UINTN)(Addr));
    578   Data &= ~B_I2C_REG_TAR;
    579   Data |= I2CAddress;
    580   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    581 
    582   //
    583   // Enable the I2C Controller
    584   //
    585   EnableI2CController ();
    586 
    587   //
    588   // Write the data and transfer direction to the IC_DATA_CMD register.
    589   // Also specify that transfer should be terminated by STOP condition.
    590   //
    591   Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
    592   for (Index = 0; Index < Length; Index++) {
    593     Data = *((volatile UINT32 *) (UINTN)(Addr));
    594     Data &= 0xFFFFFF00;
    595     Data |= (UINT8)WriteBuffer[Index];
    596     Data &= ~B_I2C_REG_DATA_CMD_RW;
    597     if (Index == (Length-1)) {
    598       Data |= B_I2C_REG_DATA_CMD_STOP;
    599     }
    600     *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    601   }
    602 
    603   //
    604   // Wait for transfer completion
    605   //
    606   Status = WaitForStopDet ();
    607 
    608   //
    609   // Ensure I2C Controller disabled.
    610   //
    611   DisableI2CController ();
    612   return Status;
    613 }
    614 
    615 /**
    616 
    617   The ReadMultipleByte() function provides a standard way to execute
    618   multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
    619   when reading block of data), as defined in the I2C Specification (I2C combined
    620   write/read protocol).
    621 
    622   @param I2CAddress   The I2C slave address of the device
    623                       with which to communicate.
    624 
    625   @param Buffer       Contains the value of byte data written or read from the
    626                       I2C slave device.
    627 
    628   @param WriteLength  No. of bytes to be written. In this case data
    629                       written typically contains sub-address or sub-addresses
    630                       in Hi-Lo format, that need to be read (I2C combined
    631                       write/read protocol).
    632 
    633   @param ReadLength   No. of bytes to be read from I2C slave device.
    634 
    635   @retval EFI_SUCCESS           Transfer success.
    636   @retval EFI_UNSUPPORTED       Unsupported input param.
    637   @retval EFI_TIMEOUT           Timeout while waiting xfer.
    638   @retval EFI_ABORTED           Tx abort signaled in HW status register.
    639   @retval EFI_DEVICE_ERROR      Rx underflow or Rx/Tx overflow detected.
    640 
    641 **/
    642 EFI_STATUS
    643 EFIAPI
    644 ReadMultipleByte (
    645   IN  UINTN          I2CAddress,
    646   IN  OUT UINT8      *Buffer,
    647   IN  UINTN          WriteLength,
    648   IN  UINTN          ReadLength
    649   )
    650 {
    651   UINTN       I2CIoPortBaseAddress;
    652   UINTN       Index;
    653   UINTN       Addr;
    654   UINT32      Data;
    655   UINT8       PollCount;
    656   EFI_STATUS  Status;
    657 
    658   if (WriteLength > I2C_FIFO_SIZE || ReadLength > I2C_FIFO_SIZE) {
    659     return EFI_UNSUPPORTED;  // Routine does not handle xfers > fifo size.
    660   }
    661 
    662   I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
    663 
    664   //
    665   // Write to the IC_TAR register the address of the slave device to be addressed
    666   //
    667   Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
    668   Data = *((volatile UINT32 *) (UINTN)(Addr));
    669   Data &= ~B_I2C_REG_TAR;
    670   Data |= I2CAddress;
    671   *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    672 
    673   //
    674   // Enable the I2C Controller
    675   //
    676   EnableI2CController ();
    677 
    678   //
    679   // Write the data (sub-addresses) to the IC_DATA_CMD register.
    680   //
    681   Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
    682   for (Index = 0; Index < WriteLength; Index++) {
    683     Data = *((volatile UINT32 *) (UINTN)(Addr));
    684     Data &= 0xFFFFFF00;
    685     Data |= (UINT8)Buffer[Index];
    686     Data &= ~B_I2C_REG_DATA_CMD_RW;
    687     *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    688   }
    689 
    690   //
    691   // Issue Read Transfers for each byte (Restart issued when write/read bit changed).
    692   //
    693   for (Index = 0; Index < ReadLength; Index++) {
    694     Data = *((volatile UINT32 *) (UINTN)(Addr));
    695     Data |= B_I2C_REG_DATA_CMD_RW;
    696     // Issue a STOP for last read transfer.
    697     if (Index == (ReadLength-1)) {
    698       Data |= B_I2C_REG_DATA_CMD_STOP;
    699     }
    700     *((volatile UINT32 *) (UINTN)(Addr)) = Data;
    701   }
    702 
    703   //
    704   // Wait for STOP condition.
    705   //
    706   Status = WaitForStopDet ();
    707   if (!EFI_ERROR(Status)) {
    708 
    709     //
    710     // Poll Receive FIFO Buffer Level register until valid (upto MAX_T_POLL_COUNT times).
    711     //
    712     Data = 0;
    713     PollCount = 0;
    714     Addr = I2CIoPortBaseAddress + I2C_REG_RXFLR;
    715     Data = *((volatile UINT32 *) (UINTN)(Addr));
    716     while ((Data != ReadLength) && (PollCount < MAX_T_POLL_COUNT)) {
    717       MicroSecondDelay(TI2C_POLL);
    718       PollCount++;
    719       Data = *((volatile UINT32 *) (UINTN)(Addr));
    720     }
    721 
    722     Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
    723     Data = *((volatile UINT32 *) (UINTN)(Addr));
    724 
    725     //
    726     // If no timeout or device error then read rx data.
    727     //
    728     if (PollCount == MAX_T_POLL_COUNT) {
    729       Status = EFI_TIMEOUT;
    730     } else if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) {
    731       Status = EFI_DEVICE_ERROR;
    732     } else {
    733 
    734       //
    735       // Clear RX underflow before reading IC_DATA_CMD.
    736       //
    737       Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER;
    738       Data = *((volatile UINT32 *) (UINTN)(Addr));
    739 
    740       //
    741       // Read data.
    742       //
    743       Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
    744       for (Index = 0; Index < ReadLength; Index++) {
    745         Data = *((volatile UINT32 *) (UINTN)(Addr));
    746         Data &= 0x000000FF;
    747         *(Buffer+Index) = (UINT8)Data;
    748       }
    749       Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
    750       Data = *((volatile UINT32 *) (UINTN)(Addr));
    751       Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER;
    752       if (Data != 0) {
    753         Status = EFI_DEVICE_ERROR;
    754       } else {
    755         Status = EFI_SUCCESS;
    756       }
    757     }
    758   }
    759 
    760   //
    761   // Ensure I2C Controller disabled.
    762   //
    763   DisableI2CController ();
    764 
    765   return Status;
    766 }
    767 
    768 /**
    769 
    770   The I2cWriteByte() function is a wrapper function for the WriteByte function.
    771   Provides a standard way to execute a standard single byte write to an IC2 device
    772   (without accessing sub-addresses), as defined in the I2C Specification.
    773 
    774   @param SlaveAddress The I2C slave address of the device
    775                       with which to communicate.
    776 
    777   @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
    778 
    779   @param Buffer       Contains the value of byte data to execute to the
    780                       I2C slave device.
    781 
    782 
    783   @retval EFI_SUCCESS           Transfer success.
    784   @retval EFI_INVALID_PARAMETER  This or Buffer pointers are invalid.
    785   @retval EFI_UNSUPPORTED       Unsupported input param.
    786   @retval EFI_TIMEOUT           Timeout while waiting xfer.
    787   @retval EFI_ABORTED           Controller aborted xfer.
    788   @retval EFI_DEVICE_ERROR      Device error detected by controller.
    789 
    790 **/
    791 EFI_STATUS
    792 EFIAPI
    793 I2cWriteByte (
    794   IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
    795   IN        EFI_I2C_ADDR_MODE       AddrMode,
    796   IN OUT VOID                       *Buffer
    797   )
    798 {
    799   EFI_STATUS Status;
    800   UINTN      I2CAddress;
    801   UINT16            SaveCmd;
    802   UINT32            SaveBar0;
    803 
    804   if (Buffer == NULL) {
    805     return EFI_INVALID_PARAMETER;
    806   }
    807   SaveCmd = 0;
    808   SaveBar0 = 0;
    809 
    810   I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
    811 
    812   Status = EFI_SUCCESS;
    813 
    814   I2CAddress = SlaveAddress.I2CDeviceAddress;
    815   Status = InitializeInternal (AddrMode);
    816   if (!EFI_ERROR(Status)) {
    817     Status = WriteByte (I2CAddress, *(UINT8 *) Buffer);
    818   }
    819 
    820   I2cCommonServiceExit (SaveCmd, SaveBar0);
    821   return Status;
    822 }
    823 
    824 /**
    825 
    826   The I2cReadByte() function is a wrapper function for the ReadByte function.
    827   Provides a standard way to execute a standard single byte read to an I2C device
    828   (without accessing sub-addresses), as defined in the I2C Specification.
    829 
    830   @param SlaveAddress The I2C slave address of the device
    831                       with which to communicate.
    832 
    833   @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
    834 
    835   @param Buffer       Contains the value of byte data read from the
    836                       I2C slave device.
    837 
    838 
    839   @retval EFI_SUCCESS           Transfer success.
    840   @retval EFI_INVALID_PARAMETER This or Buffer pointers are invalid.
    841   @retval EFI_TIMEOUT           Timeout while waiting xfer.
    842   @retval EFI_ABORTED           Controller aborted xfer.
    843   @retval EFI_DEVICE_ERROR      Device error detected by controller.
    844 
    845 
    846 **/
    847 EFI_STATUS
    848 EFIAPI
    849 I2cReadByte (
    850   IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
    851   IN        EFI_I2C_ADDR_MODE       AddrMode,
    852   IN OUT    VOID                    *Buffer
    853   )
    854 {
    855   EFI_STATUS Status;
    856   UINTN      I2CAddress;
    857   UINT16     SaveCmd;
    858   UINT32     SaveBar0;
    859 
    860   if (Buffer == NULL) {
    861     return EFI_INVALID_PARAMETER;
    862   }
    863   SaveCmd = 0;
    864   SaveBar0 =0;
    865 
    866   I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
    867 
    868   Status = EFI_SUCCESS;
    869 
    870   I2CAddress = SlaveAddress.I2CDeviceAddress;
    871 
    872   Status = InitializeInternal (AddrMode);
    873   if (!EFI_ERROR(Status)) {
    874     Status = ReadByte (I2CAddress, (UINT8 *) Buffer);
    875   }
    876   I2cCommonServiceExit (SaveCmd, SaveBar0);
    877   return Status;
    878 }
    879 
    880 /**
    881 
    882   The I2cWriteMultipleByte() function is a wrapper function for the
    883   WriteMultipleByte() function. Provides a standard way to execute multiple
    884   byte writes to an I2C device (e.g. when accessing sub-addresses or writing
    885   block of data), as defined in the I2C Specification.
    886 
    887   @param SlaveAddress The I2C slave address of the device
    888                       with which to communicate.
    889 
    890   @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
    891 
    892   @param Length       No. of bytes to be written.
    893 
    894   @param Buffer       Contains the value of byte to be written to the
    895                       I2C slave device.
    896 
    897   @retval EFI_SUCCESS            Transfer success.
    898   @retval EFI_INVALID_PARAMETER  This, Length or Buffer pointers are invalid.
    899   @retval EFI_UNSUPPORTED        Unsupported input param.
    900   @retval EFI_TIMEOUT            Timeout while waiting xfer.
    901   @retval EFI_ABORTED            Controller aborted xfer.
    902   @retval EFI_DEVICE_ERROR       Device error detected by controller.
    903 
    904 **/
    905 EFI_STATUS
    906 EFIAPI
    907 I2cWriteMultipleByte (
    908   IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
    909   IN        EFI_I2C_ADDR_MODE       AddrMode,
    910   IN UINTN                          *Length,
    911   IN OUT    VOID                    *Buffer
    912   )
    913 {
    914   EFI_STATUS Status;
    915   UINTN      I2CAddress;
    916   UINT16     SaveCmd;
    917   UINT32     SaveBar0;
    918 
    919     if (Buffer == NULL || Length == NULL) {
    920     return EFI_INVALID_PARAMETER;
    921   }
    922   SaveCmd = 0;
    923   SaveBar0 =0;
    924 
    925   I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
    926   Status = EFI_SUCCESS;
    927 
    928   I2CAddress = SlaveAddress.I2CDeviceAddress;
    929 
    930   Status = InitializeInternal (AddrMode);
    931   if (!EFI_ERROR(Status)) {
    932     Status = WriteMultipleByte (I2CAddress, Buffer, (*Length));
    933   }
    934 
    935   I2cCommonServiceExit (SaveCmd, SaveBar0);
    936   return Status;
    937 }
    938 
    939 /**
    940 
    941   The I2cReadMultipleByte() function is a wrapper function for the ReadMultipleByte() function.
    942   Provides a standard way to execute multiple byte writes to an I2C device
    943   (e.g. when accessing sub-addresses or when reading block of data), as defined
    944   in the I2C Specification (I2C combined write/read protocol).
    945 
    946   @param SlaveAddress The I2C slave address of the device
    947                       with which to communicate.
    948 
    949   @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
    950 
    951   @param WriteLength  No. of bytes to be written. In this case data
    952                       written typically contains sub-address or sub-addresses
    953                       in Hi-Lo format, that need to be read (I2C combined
    954                       write/read protocol).
    955 
    956   @param ReadLength   No. of bytes to be read from I2C slave device.
    957 
    958   @param Buffer       Contains the value of byte data read from the
    959                       I2C slave device.
    960 
    961   @retval EFI_SUCCESS            Transfer success.
    962   @retval EFI_INVALID_PARAMETER  This, WriteLength, ReadLength or Buffer
    963                                  pointers are invalid.
    964   @retval EFI_UNSUPPORTED        Unsupported input param.
    965   @retval EFI_TIMEOUT            Timeout while waiting xfer.
    966   @retval EFI_ABORTED            Controller aborted xfer.
    967   @retval EFI_DEVICE_ERROR       Device error detected by controller.
    968 
    969 **/
    970 EFI_STATUS
    971 EFIAPI
    972 I2cReadMultipleByte (
    973   IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
    974   IN        EFI_I2C_ADDR_MODE       AddrMode,
    975   IN UINTN                          *WriteLength,
    976   IN UINTN                          *ReadLength,
    977   IN OUT    VOID                    *Buffer
    978   )
    979 {
    980   EFI_STATUS        Status;
    981   UINTN             I2CAddress;
    982   UINT16            SaveCmd;
    983   UINT32            SaveBar0;
    984 
    985   if (Buffer == NULL || WriteLength == NULL || ReadLength == NULL) {
    986     return EFI_INVALID_PARAMETER;
    987   }
    988   SaveCmd = 0;
    989   SaveBar0 =0;
    990 
    991   I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
    992 
    993   Status = EFI_SUCCESS;
    994 
    995   I2CAddress = SlaveAddress.I2CDeviceAddress;
    996   Status = InitializeInternal (AddrMode);
    997   if (!EFI_ERROR(Status)) {
    998     Status = ReadMultipleByte (I2CAddress, Buffer, (*WriteLength), (*ReadLength));
    999   }
   1000   I2cCommonServiceExit (SaveCmd, SaveBar0);
   1001   return Status;
   1002 }
   1003 
   1004 
   1005