/** @file I2C Library for Quark I2C Controller. Follows I2C Controller setup instructions as detailed in Quark DataSheet (doc id: 329676) Section 19.1/19.1.3. Copyright (c) 2013-2015 Intel Corporation. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "CommonHeader.h" /** The Called to Common Service Entry. @return None. **/ VOID I2cCommonServiceEntry ( OUT UINT16 *SaveCmdPtr, OUT UINT32 *SaveBar0Ptr ) { *SaveBar0Ptr = IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0); if (((*SaveBar0Ptr) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) { IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) = FixedPcdGet32 (PcdIohI2cMmioBase) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK; // // also Save Cmd Register, Setup by InitializeInternal later during xfers. // *SaveCmdPtr = IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD); } } /** The Called on Common Service Exit. @return None. **/ VOID I2cCommonServiceExit ( IN CONST UINT16 SaveCmd, IN CONST UINT32 SaveBar0 ) { if ((SaveBar0 & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) { IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD) = SaveCmd; IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) = SaveBar0; } } /** The GetI2CIoPortBaseAddress() function gets IO port base address of I2C Controller. Always reads PCI configuration space to get MMIO base address of I2C Controller. @return The IO port base address of I2C controller. **/ UINTN GetI2CIoPortBaseAddress ( VOID ) { UINTN I2CIoPortBaseAddress; // // Get I2C Memory Mapped registers base address. // I2CIoPortBaseAddress = IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0); // // Make sure that the IO port base address has been properly set. // ASSERT (I2CIoPortBaseAddress != 0); ASSERT (I2CIoPortBaseAddress != 0xFF); return I2CIoPortBaseAddress; } /** The EnableI2CMmioSpace() function enables access to I2C MMIO space. **/ VOID EnableI2CMmioSpace ( VOID ) { UINT8 PciCmd; // // Read PCICMD. Bus=0, Dev=0, Func=0, Reg=0x4 // PciCmd = IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD); // // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0) // PciCmd |= 0x7; IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD) = PciCmd; } /** The DisableI2CController() functions disables I2C Controller. **/ VOID DisableI2CController ( VOID ) { UINTN I2CIoPortBaseAddress; UINT32 Addr; UINT32 Data; UINT8 PollCount; PollCount = 0; // // Get I2C Memory Mapped registers base address. // I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Disable the I2C Controller by setting IC_ENABLE.ENABLE to zero // Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= ~B_I2C_REG_ENABLE; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Read the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled // Data = 0xFF; Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE_STATUS; Data = *((volatile UINT32 *) (UINTN)(Addr)) & I2C_REG_ENABLE_STATUS; while (Data != 0) { // // Poll the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled, until timeout (TI2C_POLL*MAX_T_POLL_COUNT). // PollCount++; if (PollCount >= MAX_T_POLL_COUNT) { break; } MicroSecondDelay(TI2C_POLL); Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= I2C_REG_ENABLE_STATUS; } // // Asset if controller does not enter Disabled state. // ASSERT (PollCount < MAX_T_POLL_COUNT); // // Read IC_CLR_INTR register to automatically clear the combined interrupt, // all individual interrupts and the IC_TX_ABRT_SOURCE register. // Addr = I2CIoPortBaseAddress + I2C_REG_CLR_INT; Data = *((volatile UINT32 *) (UINTN)(Addr)); } /** The EnableI2CController() function enables the I2C Controller. **/ VOID EnableI2CController ( VOID ) { UINTN I2CIoPortBaseAddress; UINT32 Addr; UINT32 Data; // // Get I2C Memory Mapped registers base address. // I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Enable the I2C Controller by setting IC_ENABLE.ENABLE to 1 // Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data |= B_I2C_REG_ENABLE; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Clear overflow and abort error status bits before transactions. // Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_OVER; Data = *((volatile UINT32 *) (UINTN)(Addr)); Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_OVER; Data = *((volatile UINT32 *) (UINTN)(Addr)); Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_ABRT; Data = *((volatile UINT32 *) (UINTN)(Addr)); } /** The WaitForStopDet() function waits until I2C STOP Condition occurs, indicating transfer completion. @retval EFI_SUCCESS Stop detected. @retval EFI_TIMEOUT Timeout while waiting for stop condition. @retval EFI_ABORTED Tx abort signaled in HW status register. @retval EFI_DEVICE_ERROR Tx or Rx overflow detected. **/ EFI_STATUS WaitForStopDet ( VOID ) { UINTN I2CIoPortBaseAddress; UINT32 Addr; UINT32 Data; UINT32 PollCount; EFI_STATUS Status; Status = EFI_SUCCESS; PollCount = 0; // // Get I2C Memory Mapped registers base address. // I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Wait for STOP Detect. // Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT; do { Data = *((volatile UINT32 *) (UINTN)(Addr)); if ((Data & I2C_REG_RAW_INTR_STAT_TX_ABRT) != 0) { Status = EFI_ABORTED; break; } if ((Data & I2C_REG_RAW_INTR_STAT_TX_OVER) != 0) { Status = EFI_DEVICE_ERROR; break; } if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) { Status = EFI_DEVICE_ERROR; break; } if ((Data & I2C_REG_RAW_INTR_STAT_STOP_DET) != 0) { Status = EFI_SUCCESS; break; } MicroSecondDelay(TI2C_POLL); PollCount++; if (PollCount >= MAX_STOP_DET_POLL_COUNT) { Status = EFI_TIMEOUT; break; } } while (TRUE); return Status; } /** The InitializeInternal() function initialises internal I2C Controller register values that are commonly required for I2C Write and Read transfers. @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address. @retval EFI_SUCCESS I2C Operation completed successfully. **/ EFI_STATUS InitializeInternal ( IN EFI_I2C_ADDR_MODE AddrMode ) { UINTN I2CIoPortBaseAddress; UINTN Addr; UINT32 Data; EFI_STATUS Status; Status = EFI_SUCCESS; // // Enable access to I2C Controller MMIO space. // EnableI2CMmioSpace (); // // Disable I2C Controller initially // DisableI2CController (); // // Get I2C Memory Mapped registers base address. // I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Clear START_DET // Addr = I2CIoPortBaseAddress + I2C_REG_CLR_START_DET; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= ~B_I2C_REG_CLR_START_DET; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Clear STOP_DET // Addr = I2CIoPortBaseAddress + I2C_REG_CLR_STOP_DET; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= ~B_I2C_REG_CLR_STOP_DET; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Set addressing mode to user defined (7 or 10 bit) and // speed mode to that defined by PCD (standard mode default). // Addr = I2CIoPortBaseAddress + I2C_REG_CON; Data = *((volatile UINT32 *) (UINTN)(Addr)); // Set Addressing Mode if (AddrMode == EfiI2CSevenBitAddrMode) { Data &= ~B_I2C_REG_CON_10BITADD_MASTER; } else { Data |= B_I2C_REG_CON_10BITADD_MASTER; } // Set Speed Mode Data &= ~B_I2C_REG_CON_SPEED; if (FeaturePcdGet (PcdI2CFastModeEnabled)) { Data |= BIT2; } else { Data |= BIT1; } *((volatile UINT32 *) (UINTN)(Addr)) = Data; Data = *((volatile UINT32 *) (UINTN)(Addr)); return Status; } /** The WriteByte() function provides a standard way to execute a standard single byte write to an IC2 device (without accessing sub-addresses), as defined in the I2C Specification. @param I2CAddress I2C Slave device address @param Value The 8-bit value to write. @retval EFI_SUCCESS Transfer success. @retval EFI_UNSUPPORTED Unsupported input param. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Controller aborted xfer. @retval EFI_DEVICE_ERROR Device error detected by controller. **/ EFI_STATUS EFIAPI WriteByte ( IN UINTN I2CAddress, IN UINT8 Value ) { UINTN I2CIoPortBaseAddress; UINTN Addr; UINT32 Data; EFI_STATUS Status; // // Get I2C Memory Mapped registers base address // I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Write to the IC_TAR register the address of the slave device to be addressed // Addr = I2CIoPortBaseAddress + I2C_REG_TAR; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= ~B_I2C_REG_TAR; Data |= I2CAddress; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Enable the I2C Controller // EnableI2CController (); // // Write the data and transfer direction to the IC_DATA_CMD register. // Also specify that transfer should be terminated by STOP condition. // Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= 0xFFFFFF00; Data |= (UINT8)Value; Data &= ~B_I2C_REG_DATA_CMD_RW; Data |= B_I2C_REG_DATA_CMD_STOP; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Wait for transfer completion. // Status = WaitForStopDet (); // // Ensure I2C Controller disabled. // DisableI2CController(); return Status; } /** The ReadByte() function provides a standard way to execute a standard single byte read to an IC2 device (without accessing sub-addresses), as defined in the I2C Specification. @param I2CAddress I2C Slave device address @param ReturnDataPtr Pointer to location to receive read byte. @retval EFI_SUCCESS Transfer success. @retval EFI_UNSUPPORTED Unsupported input param. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Controller aborted xfer. @retval EFI_DEVICE_ERROR Device error detected by controller. **/ EFI_STATUS EFIAPI ReadByte ( IN UINTN I2CAddress, OUT UINT8 *ReturnDataPtr ) { UINTN I2CIoPortBaseAddress; UINTN Addr; UINT32 Data; EFI_STATUS Status; // // Get I2C Memory Mapped registers base address. // I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Write to the IC_TAR register the address of the slave device to be addressed // Addr = I2CIoPortBaseAddress + I2C_REG_TAR; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= ~B_I2C_REG_TAR; Data |= I2CAddress; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Enable the I2C Controller // EnableI2CController (); // // Write transfer direction to the IC_DATA_CMD register and // specify that transfer should be terminated by STOP condition. // Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= 0xFFFFFF00; Data |= B_I2C_REG_DATA_CMD_RW; Data |= B_I2C_REG_DATA_CMD_STOP; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Wait for transfer completion // Status = WaitForStopDet (); if (!EFI_ERROR(Status)) { // // Clear RX underflow before reading IC_DATA_CMD. // Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER; Data = *((volatile UINT32 *) (UINTN)(Addr)); // // Obtain and return read data byte from RX buffer (IC_DATA_CMD[7:0]). // Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= 0x000000FF; *ReturnDataPtr = (UINT8) Data; Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER; if (Data != 0) { Status = EFI_DEVICE_ERROR; } } // // Ensure I2C Controller disabled. // DisableI2CController (); return Status; } /** The WriteMultipleByte() function provides a standard way to execute multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or when writing block of data), as defined in the I2C Specification. @param I2CAddress The I2C slave address of the device with which to communicate. @param WriteBuffer Contains the value of byte to be written to the I2C slave device. @param Length No. of bytes to be written. @retval EFI_SUCCESS Transfer success. @retval EFI_UNSUPPORTED Unsupported input param. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Tx abort signaled in HW status register. @retval EFI_DEVICE_ERROR Tx overflow detected. **/ EFI_STATUS EFIAPI WriteMultipleByte ( IN UINTN I2CAddress, IN UINT8 *WriteBuffer, IN UINTN Length ) { UINTN I2CIoPortBaseAddress; UINTN Index; UINTN Addr; UINT32 Data; EFI_STATUS Status; if (Length > I2C_FIFO_SIZE) { return EFI_UNSUPPORTED; // Routine does not handle xfers > fifo size. } I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Write to the IC_TAR register the address of the slave device to be addressed // Addr = I2CIoPortBaseAddress + I2C_REG_TAR; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= ~B_I2C_REG_TAR; Data |= I2CAddress; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Enable the I2C Controller // EnableI2CController (); // // Write the data and transfer direction to the IC_DATA_CMD register. // Also specify that transfer should be terminated by STOP condition. // Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD; for (Index = 0; Index < Length; Index++) { Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= 0xFFFFFF00; Data |= (UINT8)WriteBuffer[Index]; Data &= ~B_I2C_REG_DATA_CMD_RW; if (Index == (Length-1)) { Data |= B_I2C_REG_DATA_CMD_STOP; } *((volatile UINT32 *) (UINTN)(Addr)) = Data; } // // Wait for transfer completion // Status = WaitForStopDet (); // // Ensure I2C Controller disabled. // DisableI2CController (); return Status; } /** The ReadMultipleByte() function provides a standard way to execute multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or when reading block of data), as defined in the I2C Specification (I2C combined write/read protocol). @param I2CAddress The I2C slave address of the device with which to communicate. @param Buffer Contains the value of byte data written or read from the I2C slave device. @param WriteLength No. of bytes to be written. In this case data written typically contains sub-address or sub-addresses in Hi-Lo format, that need to be read (I2C combined write/read protocol). @param ReadLength No. of bytes to be read from I2C slave device. @retval EFI_SUCCESS Transfer success. @retval EFI_UNSUPPORTED Unsupported input param. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Tx abort signaled in HW status register. @retval EFI_DEVICE_ERROR Rx underflow or Rx/Tx overflow detected. **/ EFI_STATUS EFIAPI ReadMultipleByte ( IN UINTN I2CAddress, IN OUT UINT8 *Buffer, IN UINTN WriteLength, IN UINTN ReadLength ) { UINTN I2CIoPortBaseAddress; UINTN Index; UINTN Addr; UINT32 Data; UINT8 PollCount; EFI_STATUS Status; if (WriteLength > I2C_FIFO_SIZE || ReadLength > I2C_FIFO_SIZE) { return EFI_UNSUPPORTED; // Routine does not handle xfers > fifo size. } I2CIoPortBaseAddress = GetI2CIoPortBaseAddress (); // // Write to the IC_TAR register the address of the slave device to be addressed // Addr = I2CIoPortBaseAddress + I2C_REG_TAR; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= ~B_I2C_REG_TAR; Data |= I2CAddress; *((volatile UINT32 *) (UINTN)(Addr)) = Data; // // Enable the I2C Controller // EnableI2CController (); // // Write the data (sub-addresses) to the IC_DATA_CMD register. // Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD; for (Index = 0; Index < WriteLength; Index++) { Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= 0xFFFFFF00; Data |= (UINT8)Buffer[Index]; Data &= ~B_I2C_REG_DATA_CMD_RW; *((volatile UINT32 *) (UINTN)(Addr)) = Data; } // // Issue Read Transfers for each byte (Restart issued when write/read bit changed). // for (Index = 0; Index < ReadLength; Index++) { Data = *((volatile UINT32 *) (UINTN)(Addr)); Data |= B_I2C_REG_DATA_CMD_RW; // Issue a STOP for last read transfer. if (Index == (ReadLength-1)) { Data |= B_I2C_REG_DATA_CMD_STOP; } *((volatile UINT32 *) (UINTN)(Addr)) = Data; } // // Wait for STOP condition. // Status = WaitForStopDet (); if (!EFI_ERROR(Status)) { // // Poll Receive FIFO Buffer Level register until valid (upto MAX_T_POLL_COUNT times). // Data = 0; PollCount = 0; Addr = I2CIoPortBaseAddress + I2C_REG_RXFLR; Data = *((volatile UINT32 *) (UINTN)(Addr)); while ((Data != ReadLength) && (PollCount < MAX_T_POLL_COUNT)) { MicroSecondDelay(TI2C_POLL); PollCount++; Data = *((volatile UINT32 *) (UINTN)(Addr)); } Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT; Data = *((volatile UINT32 *) (UINTN)(Addr)); // // If no timeout or device error then read rx data. // if (PollCount == MAX_T_POLL_COUNT) { Status = EFI_TIMEOUT; } else if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) { Status = EFI_DEVICE_ERROR; } else { // // Clear RX underflow before reading IC_DATA_CMD. // Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER; Data = *((volatile UINT32 *) (UINTN)(Addr)); // // Read data. // Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD; for (Index = 0; Index < ReadLength; Index++) { Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= 0x000000FF; *(Buffer+Index) = (UINT8)Data; } Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT; Data = *((volatile UINT32 *) (UINTN)(Addr)); Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER; if (Data != 0) { Status = EFI_DEVICE_ERROR; } else { Status = EFI_SUCCESS; } } } // // Ensure I2C Controller disabled. // DisableI2CController (); return Status; } /** The I2cWriteByte() function is a wrapper function for the WriteByte function. Provides a standard way to execute a standard single byte write to an IC2 device (without accessing sub-addresses), as defined in the I2C Specification. @param SlaveAddress The I2C slave address of the device with which to communicate. @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address. @param Buffer Contains the value of byte data to execute to the I2C slave device. @retval EFI_SUCCESS Transfer success. @retval EFI_INVALID_PARAMETER This or Buffer pointers are invalid. @retval EFI_UNSUPPORTED Unsupported input param. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Controller aborted xfer. @retval EFI_DEVICE_ERROR Device error detected by controller. **/ EFI_STATUS EFIAPI I2cWriteByte ( IN EFI_I2C_DEVICE_ADDRESS SlaveAddress, IN EFI_I2C_ADDR_MODE AddrMode, IN OUT VOID *Buffer ) { EFI_STATUS Status; UINTN I2CAddress; UINT16 SaveCmd; UINT32 SaveBar0; if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } SaveCmd = 0; SaveBar0 = 0; I2cCommonServiceEntry (&SaveCmd, &SaveBar0); Status = EFI_SUCCESS; I2CAddress = SlaveAddress.I2CDeviceAddress; Status = InitializeInternal (AddrMode); if (!EFI_ERROR(Status)) { Status = WriteByte (I2CAddress, *(UINT8 *) Buffer); } I2cCommonServiceExit (SaveCmd, SaveBar0); return Status; } /** The I2cReadByte() function is a wrapper function for the ReadByte function. Provides a standard way to execute a standard single byte read to an I2C device (without accessing sub-addresses), as defined in the I2C Specification. @param SlaveAddress The I2C slave address of the device with which to communicate. @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address. @param Buffer Contains the value of byte data read from the I2C slave device. @retval EFI_SUCCESS Transfer success. @retval EFI_INVALID_PARAMETER This or Buffer pointers are invalid. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Controller aborted xfer. @retval EFI_DEVICE_ERROR Device error detected by controller. **/ EFI_STATUS EFIAPI I2cReadByte ( IN EFI_I2C_DEVICE_ADDRESS SlaveAddress, IN EFI_I2C_ADDR_MODE AddrMode, IN OUT VOID *Buffer ) { EFI_STATUS Status; UINTN I2CAddress; UINT16 SaveCmd; UINT32 SaveBar0; if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } SaveCmd = 0; SaveBar0 =0; I2cCommonServiceEntry (&SaveCmd, &SaveBar0); Status = EFI_SUCCESS; I2CAddress = SlaveAddress.I2CDeviceAddress; Status = InitializeInternal (AddrMode); if (!EFI_ERROR(Status)) { Status = ReadByte (I2CAddress, (UINT8 *) Buffer); } I2cCommonServiceExit (SaveCmd, SaveBar0); return Status; } /** The I2cWriteMultipleByte() function is a wrapper function for the WriteMultipleByte() function. Provides a standard way to execute multiple byte writes to an I2C device (e.g. when accessing sub-addresses or writing block of data), as defined in the I2C Specification. @param SlaveAddress The I2C slave address of the device with which to communicate. @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address. @param Length No. of bytes to be written. @param Buffer Contains the value of byte to be written to the I2C slave device. @retval EFI_SUCCESS Transfer success. @retval EFI_INVALID_PARAMETER This, Length or Buffer pointers are invalid. @retval EFI_UNSUPPORTED Unsupported input param. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Controller aborted xfer. @retval EFI_DEVICE_ERROR Device error detected by controller. **/ EFI_STATUS EFIAPI I2cWriteMultipleByte ( IN EFI_I2C_DEVICE_ADDRESS SlaveAddress, IN EFI_I2C_ADDR_MODE AddrMode, IN UINTN *Length, IN OUT VOID *Buffer ) { EFI_STATUS Status; UINTN I2CAddress; UINT16 SaveCmd; UINT32 SaveBar0; if (Buffer == NULL || Length == NULL) { return EFI_INVALID_PARAMETER; } SaveCmd = 0; SaveBar0 =0; I2cCommonServiceEntry (&SaveCmd, &SaveBar0); Status = EFI_SUCCESS; I2CAddress = SlaveAddress.I2CDeviceAddress; Status = InitializeInternal (AddrMode); if (!EFI_ERROR(Status)) { Status = WriteMultipleByte (I2CAddress, Buffer, (*Length)); } I2cCommonServiceExit (SaveCmd, SaveBar0); return Status; } /** The I2cReadMultipleByte() function is a wrapper function for the ReadMultipleByte() function. Provides a standard way to execute multiple byte writes to an I2C device (e.g. when accessing sub-addresses or when reading block of data), as defined in the I2C Specification (I2C combined write/read protocol). @param SlaveAddress The I2C slave address of the device with which to communicate. @param AddrMode I2C Addressing Mode: 7-bit or 10-bit address. @param WriteLength No. of bytes to be written. In this case data written typically contains sub-address or sub-addresses in Hi-Lo format, that need to be read (I2C combined write/read protocol). @param ReadLength No. of bytes to be read from I2C slave device. @param Buffer Contains the value of byte data read from the I2C slave device. @retval EFI_SUCCESS Transfer success. @retval EFI_INVALID_PARAMETER This, WriteLength, ReadLength or Buffer pointers are invalid. @retval EFI_UNSUPPORTED Unsupported input param. @retval EFI_TIMEOUT Timeout while waiting xfer. @retval EFI_ABORTED Controller aborted xfer. @retval EFI_DEVICE_ERROR Device error detected by controller. **/ EFI_STATUS EFIAPI I2cReadMultipleByte ( IN EFI_I2C_DEVICE_ADDRESS SlaveAddress, IN EFI_I2C_ADDR_MODE AddrMode, IN UINTN *WriteLength, IN UINTN *ReadLength, IN OUT VOID *Buffer ) { EFI_STATUS Status; UINTN I2CAddress; UINT16 SaveCmd; UINT32 SaveBar0; if (Buffer == NULL || WriteLength == NULL || ReadLength == NULL) { return EFI_INVALID_PARAMETER; } SaveCmd = 0; SaveBar0 =0; I2cCommonServiceEntry (&SaveCmd, &SaveBar0); Status = EFI_SUCCESS; I2CAddress = SlaveAddress.I2CDeviceAddress; Status = InitializeInternal (AddrMode); if (!EFI_ERROR(Status)) { Status = ReadMultipleByte (I2CAddress, Buffer, (*WriteLength), (*ReadLength)); } I2cCommonServiceExit (SaveCmd, SaveBar0); return Status; }