19b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/** @file
29b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyI2C Library for Quark I2C Controller.
39b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyFollows I2C Controller setup instructions as detailed in
49b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyQuark DataSheet (doc id: 329676) Section 19.1/19.1.3.
59b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
69b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
79b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyCopyright (c) 2013-2015 Intel Corporation.
89b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
99b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyThis program and the accompanying materials
109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyare licensed and made available under the terms and conditions of the BSD License
119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneywhich accompanies this distribution.  The full text of the license may be found at
129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyhttp://opensource.org/licenses/bsd-license.php
139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#include "CommonHeader.h"
209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The Called to Common Service Entry.
239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @return None.
259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyVOID
299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyI2cCommonServiceEntry  (
309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  OUT UINT16 *SaveCmdPtr,
319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  OUT UINT32 *SaveBar0Ptr
329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *SaveBar0Ptr = IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);
359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (((*SaveBar0Ptr) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {
369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) =
389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      FixedPcdGet32 (PcdIohI2cMmioBase) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK;
399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // also Save Cmd Register, Setup by InitializeInternal later during xfers.
429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    *SaveCmdPtr = IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD);
449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The Called on Common Service Exit.
499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @return None.
519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyVOID
549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyI2cCommonServiceExit  (
559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN CONST UINT16 SaveCmd,
569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN CONST UINT32 SaveBar0
579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if ((SaveBar0 & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0) {
619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    IohMmPci16 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_CMD) = SaveCmd;
629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    IohMmPci32 (0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0) = SaveBar0;
639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The GetI2CIoPortBaseAddress() function gets IO port base address of I2C Controller.
699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Always reads PCI configuration space to get MMIO base address of I2C Controller.
719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @return The IO port base address of I2C controller.
739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyUINTN
769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyGetI2CIoPortBaseAddress (
779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  VOID
789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN     I2CIoPortBaseAddress;
819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Get I2C Memory Mapped registers base address.
849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = IohMmPci32(0, I2C_Bus, I2C_Device, I2C_Func, PCI_BAR0);
869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Make sure that the IO port base address has been properly set.
899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ASSERT (I2CIoPortBaseAddress != 0);
919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ASSERT (I2CIoPortBaseAddress != 0xFF);
929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return I2CIoPortBaseAddress;
949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The EnableI2CMmioSpace() function enables access to I2C MMIO space.
999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
1019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyVOID
1029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEnableI2CMmioSpace (
1039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  VOID
1049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
1059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
1069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT8 PciCmd;
1079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Read PCICMD.  Bus=0, Dev=0, Func=0, Reg=0x4
1109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  PciCmd = IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD);
1129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0)
1159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  PciCmd |= 0x7;
1179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IohMmPci8(0, I2C_Bus, I2C_Device, I2C_Func, PCI_REG_PCICMD) = PciCmd;
1189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
1209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
1229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The DisableI2CController() functions disables I2C Controller.
1239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
1259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyVOID
1269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyDisableI2CController (
1279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  VOID
1289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
1299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
1309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       I2CIoPortBaseAddress;
1319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Addr;
1329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Data;
1339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT8       PollCount;
1349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  PollCount = 0;
1369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Get I2C Memory Mapped registers base address.
1399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
1419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Disable the I2C Controller by setting IC_ENABLE.ENABLE to zero
1449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
1469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
1479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_ENABLE;
1489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
1499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Read the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled
1529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = 0xFF;
1549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE_STATUS;
1559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr)) & I2C_REG_ENABLE_STATUS;
1569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  while (Data != 0) {
1579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
1589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // Poll the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled, until timeout (TI2C_POLL*MAX_T_POLL_COUNT).
1599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
1609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    PollCount++;
1619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (PollCount >= MAX_T_POLL_COUNT) {
1629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
1639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
1649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MicroSecondDelay(TI2C_POLL);
1659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
1669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= I2C_REG_ENABLE_STATUS;
1679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
1689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Asset if controller does not enter Disabled state.
1719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ASSERT (PollCount < MAX_T_POLL_COUNT);
1739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Read IC_CLR_INTR register to automatically clear the combined interrupt,
1769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // all individual interrupts and the IC_TX_ABRT_SOURCE register.
1779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_INT;
1799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
1809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
1829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
1849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The EnableI2CController() function enables the I2C Controller.
1859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
1879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyVOID
1889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEnableI2CController (
1899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  VOID
1909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
1919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
1929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN   I2CIoPortBaseAddress;
1939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32  Addr;
1949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32  Data;
1959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Get I2C Memory Mapped registers base address.
1989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
1999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
2009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Enable the I2C Controller by setting IC_ENABLE.ENABLE to 1
2039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
2059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
2069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= B_I2C_REG_ENABLE;
2079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
2089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Clear overflow and abort error status bits before transactions.
2119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_OVER;
2139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
2149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_OVER;
2159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
2169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_ABRT;
2179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
2189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
2209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
2229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The WaitForStopDet() function waits until I2C STOP Condition occurs,
2239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  indicating transfer completion.
2249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           Stop detected.
2269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT           Timeout while waiting for stop condition.
2279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED           Tx abort signaled in HW status register.
2289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR      Tx or Rx overflow detected.
2299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
2319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
2329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyWaitForStopDet (
2339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  VOID
2349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
2359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
2369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       I2CIoPortBaseAddress;
2379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Addr;
2389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Data;
2399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      PollCount;
2409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS  Status;
2419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = EFI_SUCCESS;
2439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  PollCount = 0;
2459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Get I2C Memory Mapped registers base address.
2489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
2509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Wait for STOP Detect.
2539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
2549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
2559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  do {
2579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
2589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if ((Data & I2C_REG_RAW_INTR_STAT_TX_ABRT) != 0) {
2599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_ABORTED;
2609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
2619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
2629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if ((Data & I2C_REG_RAW_INTR_STAT_TX_OVER) != 0) {
2639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_DEVICE_ERROR;
2649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
2659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
2669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) {
2679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_DEVICE_ERROR;
2689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
2699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
2709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if ((Data & I2C_REG_RAW_INTR_STAT_STOP_DET) != 0) {
2719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_SUCCESS;
2729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
2739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
2749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MicroSecondDelay(TI2C_POLL);
2759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    PollCount++;
2769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (PollCount >= MAX_STOP_DET_POLL_COUNT) {
2779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_TIMEOUT;
2789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
2799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
2809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } while (TRUE);
2829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
2849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
2859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
2879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The InitializeInternal() function initialises internal I2C Controller
2899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  register values that are commonly required for I2C Write and Read transfers.
2909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
2929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           I2C Operation completed successfully.
2949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
2969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
2979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyInitializeInternal (
2989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  EFI_I2C_ADDR_MODE  AddrMode
2999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
3009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
3019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       I2CIoPortBaseAddress;
3029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       Addr;
3039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Data;
3049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS  Status;
3059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = EFI_SUCCESS;
3079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Enable access to I2C Controller MMIO space.
3109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EnableI2CMmioSpace ();
3129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Disable I2C Controller initially
3159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DisableI2CController ();
3179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Get I2C Memory Mapped registers base address.
3209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
3229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Clear START_DET
3259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_START_DET;
3279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
3289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_CLR_START_DET;
3299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
3309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Clear STOP_DET
3339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_CLR_STOP_DET;
3359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
3369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_CLR_STOP_DET;
3379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
3389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Set addressing mode to user defined (7 or 10 bit) and
3419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // speed mode to that defined by PCD (standard mode default).
3429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_CON;
3449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
3459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Set Addressing Mode
3469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (AddrMode == EfiI2CSevenBitAddrMode) {
3479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= ~B_I2C_REG_CON_10BITADD_MASTER;
3489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } else {
3499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data |= B_I2C_REG_CON_10BITADD_MASTER;
3509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
3519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Set Speed Mode
3529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_CON_SPEED;
3539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (FeaturePcdGet (PcdI2CFastModeEnabled)) {
3549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data |= BIT2;
3559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } else {
3569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data |= BIT1;
3579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
3589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
3599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
3619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
3639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
3659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
3679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The WriteByte() function provides a standard way to execute a
3699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  standard single byte write to an IC2 device (without accessing
3709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  sub-addresses), as defined in the I2C Specification.
3719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param  I2CAddress      I2C Slave device address
3739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param  Value           The 8-bit value to write.
3749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           Transfer success.
3769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_UNSUPPORTED       Unsupported input param.
3779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT           Timeout while waiting xfer.
3789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED           Controller aborted xfer.
3799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR      Device error detected by controller.
3809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
3829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
3839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
3849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyWriteByte (
3859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINTN          I2CAddress,
3869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINT8          Value
3879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
3889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
3899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       I2CIoPortBaseAddress;
3909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       Addr;
3919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Data;
3929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS  Status;
3939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Get I2C Memory Mapped registers base address
3969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
3979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
3989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write to the IC_TAR register the address of the slave device to be addressed
4019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
4039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
4049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_TAR;
4059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= I2CAddress;
4069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
4079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Enable the I2C Controller
4109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EnableI2CController ();
4129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write the data and transfer direction to the IC_DATA_CMD register.
4159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Also specify that transfer should be terminated by STOP condition.
4169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
4189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
4199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= 0xFFFFFF00;
4209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= (UINT8)Value;
4219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_DATA_CMD_RW;
4229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= B_I2C_REG_DATA_CMD_STOP;
4239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
4249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Wait for transfer completion.
4279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = WaitForStopDet ();
4299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Ensure I2C Controller disabled.
4329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DisableI2CController();
4349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
4369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
4379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
4399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The ReadByte() function provides a standard way to execute a
4419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  standard single byte read to an IC2 device (without accessing
4429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  sub-addresses), as defined in the I2C Specification.
4439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param  I2CAddress      I2C Slave device address
4459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param  ReturnDataPtr   Pointer to location to receive read byte.
4469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           Transfer success.
4489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_UNSUPPORTED       Unsupported input param.
4499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT           Timeout while waiting xfer.
4509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED           Controller aborted xfer.
4519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR      Device error detected by controller.
4529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
4549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
4559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
4569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyReadByte (
4579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINTN          I2CAddress,
4589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  OUT UINT8          *ReturnDataPtr
4599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
4609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
4619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       I2CIoPortBaseAddress;
4629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       Addr;
4639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Data;
4649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS  Status;
4659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Get I2C Memory Mapped registers base address.
4689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
4709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write to the IC_TAR register the address of the slave device to be addressed
4739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
4759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
4769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_TAR;
4779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= I2CAddress;
4789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
4799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Enable the I2C Controller
4829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EnableI2CController ();
4849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write transfer direction to the IC_DATA_CMD register and
4879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // specify that transfer should be terminated by STOP condition.
4889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
4909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
4919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= 0xFFFFFF00;
4929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= B_I2C_REG_DATA_CMD_RW;
4939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= B_I2C_REG_DATA_CMD_STOP;
4949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
4959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Wait for transfer completion
4989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
4999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = WaitForStopDet ();
5009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (!EFI_ERROR(Status)) {
5019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
5039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // Clear RX underflow before reading IC_DATA_CMD.
5049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
5059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER;
5069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
5079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
5099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // Obtain and return read data byte from RX buffer (IC_DATA_CMD[7:0]).
5109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
5119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
5129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
5139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= 0x000000FF;
5149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    *ReturnDataPtr = (UINT8) Data;
5159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
5179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
5189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER;
5199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (Data != 0) {
5209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_DEVICE_ERROR;
5219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
5229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
5239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Ensure I2C Controller disabled.
5269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DisableI2CController ();
5289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
5309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
5319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
5339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The WriteMultipleByte() function provides a standard way to execute
5359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
5369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  when writing block of data), as defined in the I2C Specification.
5379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param I2CAddress   The I2C slave address of the device
5399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      with which to communicate.
5409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param WriteBuffer  Contains the value of byte to be written to the
5429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      I2C slave device.
5439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param Length       No. of bytes to be written.
5459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           Transfer success.
5479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_UNSUPPORTED       Unsupported input param.
5489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT           Timeout while waiting xfer.
5499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED           Tx abort signaled in HW status register.
5509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR      Tx overflow detected.
5519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
5539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
5549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
5559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyWriteMultipleByte (
5569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINTN          I2CAddress,
5579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINT8          *WriteBuffer,
5589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINTN          Length
5599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
5609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
5619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       I2CIoPortBaseAddress;
5629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       Index;
5639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       Addr;
5649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Data;
5659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS  Status;
5669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (Length > I2C_FIFO_SIZE) {
5689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    return EFI_UNSUPPORTED;  // Routine does not handle xfers > fifo size.
5699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
5709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
5729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write to the IC_TAR register the address of the slave device to be addressed
5759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
5779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
5789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_TAR;
5799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= I2CAddress;
5809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
5819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Enable the I2C Controller
5849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EnableI2CController ();
5869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write the data and transfer direction to the IC_DATA_CMD register.
5899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Also specify that transfer should be terminated by STOP condition.
5909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
5919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
5929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (Index = 0; Index < Length; Index++) {
5939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
5949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= 0xFFFFFF00;
5959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data |= (UINT8)WriteBuffer[Index];
5969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= ~B_I2C_REG_DATA_CMD_RW;
5979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (Index == (Length-1)) {
5989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Data |= B_I2C_REG_DATA_CMD_STOP;
5999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
6009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    *((volatile UINT32 *) (UINTN)(Addr)) = Data;
6019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
6029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Wait for transfer completion
6059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = WaitForStopDet ();
6079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Ensure I2C Controller disabled.
6109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DisableI2CController ();
6129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
6139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
6149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
6169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The ReadMultipleByte() function provides a standard way to execute
6189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  multiple byte writes to an IC2 device (e.g. when accessing sub-addresses or
6199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  when reading block of data), as defined in the I2C Specification (I2C combined
6209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  write/read protocol).
6219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param I2CAddress   The I2C slave address of the device
6239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      with which to communicate.
6249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param Buffer       Contains the value of byte data written or read from the
6269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      I2C slave device.
6279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param WriteLength  No. of bytes to be written. In this case data
6299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      written typically contains sub-address or sub-addresses
6309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      in Hi-Lo format, that need to be read (I2C combined
6319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      write/read protocol).
6329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param ReadLength   No. of bytes to be read from I2C slave device.
6349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           Transfer success.
6369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_UNSUPPORTED       Unsupported input param.
6379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT           Timeout while waiting xfer.
6389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED           Tx abort signaled in HW status register.
6399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR      Rx underflow or Rx/Tx overflow detected.
6409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
6429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
6439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
6449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyReadMultipleByte (
6459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINTN          I2CAddress,
6469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  OUT UINT8      *Buffer,
6479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINTN          WriteLength,
6489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN  UINTN          ReadLength
6499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
6509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
6519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       I2CIoPortBaseAddress;
6529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       Index;
6539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN       Addr;
6549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32      Data;
6559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT8       PollCount;
6569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS  Status;
6579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (WriteLength > I2C_FIFO_SIZE || ReadLength > I2C_FIFO_SIZE) {
6599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    return EFI_UNSUPPORTED;  // Routine does not handle xfers > fifo size.
6609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
6619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
6639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write to the IC_TAR register the address of the slave device to be addressed
6669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
6689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data = *((volatile UINT32 *) (UINTN)(Addr));
6699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data &= ~B_I2C_REG_TAR;
6709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Data |= I2CAddress;
6719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *((volatile UINT32 *) (UINTN)(Addr)) = Data;
6729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Enable the I2C Controller
6759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EnableI2CController ();
6779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Write the data (sub-addresses) to the IC_DATA_CMD register.
6809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
6829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (Index = 0; Index < WriteLength; Index++) {
6839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
6849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= 0xFFFFFF00;
6859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data |= (UINT8)Buffer[Index];
6869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data &= ~B_I2C_REG_DATA_CMD_RW;
6879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    *((volatile UINT32 *) (UINTN)(Addr)) = Data;
6889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
6899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Issue Read Transfers for each byte (Restart issued when write/read bit changed).
6929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
6939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (Index = 0; Index < ReadLength; Index++) {
6949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
6959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data |= B_I2C_REG_DATA_CMD_RW;
6969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // Issue a STOP for last read transfer.
6979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (Index == (ReadLength-1)) {
6989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Data |= B_I2C_REG_DATA_CMD_STOP;
6999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
7009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    *((volatile UINT32 *) (UINTN)(Addr)) = Data;
7019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
7029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
7049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Wait for STOP condition.
7059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
7069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = WaitForStopDet ();
7079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (!EFI_ERROR(Status)) {
7089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
7109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // Poll Receive FIFO Buffer Level register until valid (upto MAX_T_POLL_COUNT times).
7119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
7129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = 0;
7139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    PollCount = 0;
7149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Addr = I2CIoPortBaseAddress + I2C_REG_RXFLR;
7159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
7169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    while ((Data != ReadLength) && (PollCount < MAX_T_POLL_COUNT)) {
7179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      MicroSecondDelay(TI2C_POLL);
7189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      PollCount++;
7199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Data = *((volatile UINT32 *) (UINTN)(Addr));
7209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
7219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
7239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Data = *((volatile UINT32 *) (UINTN)(Addr));
7249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
7269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // If no timeout or device error then read rx data.
7279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    //
7289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (PollCount == MAX_T_POLL_COUNT) {
7299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_TIMEOUT;
7309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    } else if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0) {
7319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Status = EFI_DEVICE_ERROR;
7329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    } else {
7339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      //
7359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // Clear RX underflow before reading IC_DATA_CMD.
7369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      //
7379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER;
7389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Data = *((volatile UINT32 *) (UINTN)(Addr));
7399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      //
7419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // Read data.
7429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      //
7439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
7449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      for (Index = 0; Index < ReadLength; Index++) {
7459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        Data = *((volatile UINT32 *) (UINTN)(Addr));
7469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        Data &= 0x000000FF;
7479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        *(Buffer+Index) = (UINT8)Data;
7489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
7499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
7509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Data = *((volatile UINT32 *) (UINTN)(Addr));
7519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER;
7529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      if (Data != 0) {
7539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        Status = EFI_DEVICE_ERROR;
7549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      } else {
7559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        Status = EFI_SUCCESS;
7569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
7579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
7589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
7599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
7619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Ensure I2C Controller disabled.
7629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //
7639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DisableI2CController ();
7649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
7669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
7679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
7699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The I2cWriteByte() function is a wrapper function for the WriteByte function.
7719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Provides a standard way to execute a standard single byte write to an IC2 device
7729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  (without accessing sub-addresses), as defined in the I2C Specification.
7739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param SlaveAddress The I2C slave address of the device
7759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      with which to communicate.
7769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
7789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param Buffer       Contains the value of byte data to execute to the
7809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      I2C slave device.
7819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           Transfer success.
7849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_INVALID_PARAMETER  This or Buffer pointers are invalid.
7859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_UNSUPPORTED       Unsupported input param.
7869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT           Timeout while waiting xfer.
7879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED           Controller aborted xfer.
7889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR      Device error detected by controller.
7899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
7919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
7929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
7939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyI2cWriteByte (
7949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
7959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_ADDR_MODE       AddrMode,
7969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN OUT VOID                       *Buffer
7979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
7989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
7999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS Status;
8009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN      I2CAddress;
8019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT16            SaveCmd;
8029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32            SaveBar0;
8039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (Buffer == NULL) {
8059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    return EFI_INVALID_PARAMETER;
8069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
8079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveCmd = 0;
8089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveBar0 = 0;
8099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
8119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = EFI_SUCCESS;
8139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CAddress = SlaveAddress.I2CDeviceAddress;
8159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = InitializeInternal (AddrMode);
8169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (!EFI_ERROR(Status)) {
8179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Status = WriteByte (I2CAddress, *(UINT8 *) Buffer);
8189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
8199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceExit (SaveCmd, SaveBar0);
8219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
8229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
8239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
8259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The I2cReadByte() function is a wrapper function for the ReadByte function.
8279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Provides a standard way to execute a standard single byte read to an I2C device
8289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  (without accessing sub-addresses), as defined in the I2C Specification.
8299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param SlaveAddress The I2C slave address of the device
8319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      with which to communicate.
8329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
8349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param Buffer       Contains the value of byte data read from the
8369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      I2C slave device.
8379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS           Transfer success.
8409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_INVALID_PARAMETER This or Buffer pointers are invalid.
8419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT           Timeout while waiting xfer.
8429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED           Controller aborted xfer.
8439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR      Device error detected by controller.
8449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
8479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
8489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
8499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyI2cReadByte (
8509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
8519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_ADDR_MODE       AddrMode,
8529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN OUT    VOID                    *Buffer
8539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
8549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
8559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS Status;
8569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN      I2CAddress;
8579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT16     SaveCmd;
8589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32     SaveBar0;
8599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (Buffer == NULL) {
8619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    return EFI_INVALID_PARAMETER;
8629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
8639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveCmd = 0;
8649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveBar0 =0;
8659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
8679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = EFI_SUCCESS;
8699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CAddress = SlaveAddress.I2CDeviceAddress;
8719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = InitializeInternal (AddrMode);
8739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (!EFI_ERROR(Status)) {
8749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Status = ReadByte (I2CAddress, (UINT8 *) Buffer);
8759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
8769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceExit (SaveCmd, SaveBar0);
8779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
8789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
8799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
8819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The I2cWriteMultipleByte() function is a wrapper function for the
8839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  WriteMultipleByte() function. Provides a standard way to execute multiple
8849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  byte writes to an I2C device (e.g. when accessing sub-addresses or writing
8859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  block of data), as defined in the I2C Specification.
8869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param SlaveAddress The I2C slave address of the device
8889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      with which to communicate.
8899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
8919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param Length       No. of bytes to be written.
8939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param Buffer       Contains the value of byte to be written to the
8959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      I2C slave device.
8969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS            Transfer success.
8989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_INVALID_PARAMETER  This, Length or Buffer pointers are invalid.
8999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_UNSUPPORTED        Unsupported input param.
9009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT            Timeout while waiting xfer.
9019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED            Controller aborted xfer.
9029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR       Device error detected by controller.
9039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
9059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
9069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
9079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyI2cWriteMultipleByte (
9089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
9099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_ADDR_MODE       AddrMode,
9109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN UINTN                          *Length,
9119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN OUT    VOID                    *Buffer
9129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
9139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
9149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS Status;
9159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN      I2CAddress;
9169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT16     SaveCmd;
9179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32     SaveBar0;
9189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (Buffer == NULL || Length == NULL) {
9209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    return EFI_INVALID_PARAMETER;
9219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
9229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveCmd = 0;
9239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveBar0 =0;
9249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
9269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = EFI_SUCCESS;
9279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CAddress = SlaveAddress.I2CDeviceAddress;
9299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = InitializeInternal (AddrMode);
9319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (!EFI_ERROR(Status)) {
9329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Status = WriteMultipleByte (I2CAddress, Buffer, (*Length));
9339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
9349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceExit (SaveCmd, SaveBar0);
9369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
9379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
9389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/**
9409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  The I2cReadMultipleByte() function is a wrapper function for the ReadMultipleByte() function.
9429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Provides a standard way to execute multiple byte writes to an I2C device
9439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  (e.g. when accessing sub-addresses or when reading block of data), as defined
9449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  in the I2C Specification (I2C combined write/read protocol).
9459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param SlaveAddress The I2C slave address of the device
9479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      with which to communicate.
9489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param AddrMode     I2C Addressing Mode: 7-bit or 10-bit address.
9509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param WriteLength  No. of bytes to be written. In this case data
9529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      written typically contains sub-address or sub-addresses
9539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      in Hi-Lo format, that need to be read (I2C combined
9549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      write/read protocol).
9559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param ReadLength   No. of bytes to be read from I2C slave device.
9579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @param Buffer       Contains the value of byte data read from the
9599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                      I2C slave device.
9609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_SUCCESS            Transfer success.
9629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_INVALID_PARAMETER  This, WriteLength, ReadLength or Buffer
9639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                                 pointers are invalid.
9649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_UNSUPPORTED        Unsupported input param.
9659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_TIMEOUT            Timeout while waiting xfer.
9669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_ABORTED            Controller aborted xfer.
9679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  @retval EFI_DEVICE_ERROR       Device error detected by controller.
9689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney**/
9709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFI_STATUS
9719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyEFIAPI
9729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael KinneyI2cReadMultipleByte (
9739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_DEVICE_ADDRESS  SlaveAddress,
9749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN        EFI_I2C_ADDR_MODE       AddrMode,
9759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN UINTN                          *WriteLength,
9769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN UINTN                          *ReadLength,
9779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  IN OUT    VOID                    *Buffer
9789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  )
9799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
9809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  EFI_STATUS        Status;
9819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINTN             I2CAddress;
9829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT16            SaveCmd;
9839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  UINT32            SaveBar0;
9849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (Buffer == NULL || WriteLength == NULL || ReadLength == NULL) {
9869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    return EFI_INVALID_PARAMETER;
9879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
9889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveCmd = 0;
9899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  SaveBar0 =0;
9909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceEntry (&SaveCmd, &SaveBar0);
9929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = EFI_SUCCESS;
9949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2CAddress = SlaveAddress.I2CDeviceAddress;
9969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Status = InitializeInternal (AddrMode);
9979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (!EFI_ERROR(Status)) {
9989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    Status = ReadMultipleByte (I2CAddress, Buffer, (*WriteLength), (*ReadLength));
9999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
10009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  I2cCommonServiceExit (SaveCmd, SaveBar0);
10019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return Status;
10029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
10039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1005