--- /dev/null
+/** @file\r
+ Interface Definitions for I2C Lib.\r
+ \r
+ Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials are licensed and made available under\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r
+ The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php. \r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ \r
+--*/\r
+\r
+#include <Uefi.h>\r
+#include <Library/IoLib.h>\r
+\r
+#ifndef I2C_LIB_HEADER_H\r
+#define I2C_LIB_HEADER_H\r
+\r
+\r
+/**\r
+ Reads a Byte from I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be read\r
+ @param Offset Offset from which the data has to be read\r
+ @param ReadBytes Number of bytes to be read\r
+ @param *ReadBuffer Address to which the value read has to be stored\r
+ \r
+ @return EFI_SUCCESS If the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS \r
+ByteReadI2C(\r
+ IN UINT8 BusNo, \r
+ IN UINT8 SlaveAddress, \r
+ IN UINT8 Offset, \r
+ IN UINTN ReadBytes,\r
+ OUT UINT8 *ReadBuffer\r
+ );\r
+\r
+/**\r
+ Writes a Byte to I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be written\r
+ @param Offset Offset from which the data has to be written\r
+ @param WriteBytes Number of bytes to be written\r
+ @param *Byte Address to which the value written is stored\r
+ \r
+ @return EFI_SUCCESS If the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/ \r
+EFI_STATUS ByteWriteI2C(\r
+ IN UINT8 BusNo, \r
+ IN UINT8 SlaveAddress,\r
+ IN UINT8 Offset,\r
+ IN UINTN WriteBytes,\r
+ IN UINT8 *WriteBuffer\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Functions for accessing I2C registers.\r
+ \r
+ Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials are licensed and made available under\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r
+ The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php. \r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ \r
+--*/\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <PchRegs/PchRegsPcu.h> \r
+#include <PchRegs.h>\r
+#include <PlatformBaseAddresses.h>\r
+#include <PchRegs/PchRegsLpss.h> \r
+#include <Library/I2CLib.h>\r
+#include <Protocol/GlobalNvsArea.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <I2CRegs.h>\r
+\r
+#define GLOBAL_NVS_OFFSET(Field) (UINTN)((CHAR8*)&((EFI_GLOBAL_NVS_AREA*)0)->Field - (CHAR8*)0)\r
+\r
+#define PCIEX_BASE_ADDRESS 0xE0000000\r
+#define PCI_EXPRESS_BASE_ADDRESS ((VOID *) (UINTN) PCIEX_BASE_ADDRESS)\r
+#define MmPciAddress( Segment, Bus, Device, Function, Register ) \\r
+ ((UINTN)PCI_EXPRESS_BASE_ADDRESS + \\r
+ (UINTN)(Bus << 20) + \\r
+ (UINTN)(Device << 15) + \\r
+ (UINTN)(Function << 12) + \\r
+ (UINTN)(Register) \\r
+ )\r
+#define PCI_D31F0_REG_BASE PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)\r
+\r
+typedef struct _LPSS_PCI_DEVICE_INFO {\r
+ UINTN Segment;\r
+ UINTN BusNum;\r
+ UINTN DeviceNum;\r
+ UINTN FunctionNum;\r
+ UINTN Bar0;\r
+ UINTN Bar1;\r
+} LPSS_PCI_DEVICE_INFO;\r
+\r
+LPSS_PCI_DEVICE_INFO mLpssPciDeviceList[] = {\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_DMAC1, PCI_FUNCTION_NUMBER_PCH_LPSS_DMAC, 0xFE900000, 0xFE908000},\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C0, 0xFE910000, 0xFE918000},\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C1, 0xFE920000, 0xFE928000},\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C2, 0xFE930000, 0xFE938000},\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C3, 0xFE940000, 0xFE948000},\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C4, 0xFE950000, 0xFE958000},\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C5, 0xFE960000, 0xFE968000},\r
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C6, 0xFE970000, 0xFE978000}\r
+};\r
+\r
+#define LPSS_PCI_DEVICE_NUMBER sizeof(mLpssPciDeviceList)/sizeof(LPSS_PCI_DEVICE_INFO)\r
+\r
+STATIC UINTN mI2CBaseAddress = 0;\r
+STATIC UINT16 mI2CSlaveAddress = 0;\r
+\r
+UINT16 mI2cMode=B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE ;\r
+\r
+UINTN mI2cNvsBaseAddress[] = {\r
+ GLOBAL_NVS_OFFSET(LDMA2Addr),\r
+ GLOBAL_NVS_OFFSET(I2C1Addr),\r
+ GLOBAL_NVS_OFFSET(I2C2Addr),\r
+ GLOBAL_NVS_OFFSET(I2C3Addr),\r
+ GLOBAL_NVS_OFFSET(I2C4Addr),\r
+ GLOBAL_NVS_OFFSET(I2C5Addr),\r
+ GLOBAL_NVS_OFFSET(I2C6Addr),\r
+ GLOBAL_NVS_OFFSET(I2C7Addr)\r
+ };\r
+\r
+/**\r
+ This function get I2Cx controller base address (BAR0).\r
+\r
+ @param I2cControllerIndex Bus Number of I2C controller.\r
+\r
+ @return I2C BAR. \r
+**/\r
+UINTN\r
+GetI2cBarAddr(\r
+ IN UINT8 I2cControllerIndex\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;\r
+ UINTN AcpiBaseAddr;\r
+ UINTN PciMmBase=0;\r
+\r
+ ASSERT(gBS!=NULL);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiGlobalNvsAreaProtocolGuid,\r
+ NULL,\r
+ &GlobalNvsArea\r
+ );\r
+ \r
+ //\r
+ // PCI mode from PEI ( Global NVS is not ready).\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_INFO, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status));\r
+ //\r
+ // Global NVS is not ready.\r
+ //\r
+ return 0;\r
+ }\r
+\r
+ AcpiBaseAddr = *(UINTN*)((CHAR8*)GlobalNvsArea->Area + mI2cNvsBaseAddress[I2cControllerIndex + 1]);\r
+ \r
+ //\r
+ //PCI mode from DXE (global NVS protocal) to LPSS OnReadytoBoot(swith to ACPI).\r
+ //\r
+ if(AcpiBaseAddr==0) {\r
+ PciMmBase = MmPciAddress (\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].Segment,\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].BusNum,\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].DeviceNum,\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].FunctionNum,\r
+ 0\r
+ );\r
+ DEBUG((EFI_D_ERROR, "\nGetI2cBarAddr() I2C Device %x %x %x PciMmBase:%x\n", \\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].BusNum, \\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].DeviceNum, \\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].FunctionNum, PciMmBase));\r
+\r
+ if (MmioRead32 (PciMmBase) != 0xFFFFFFFF) {\r
+ if((MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_STSCMD)& B_PCH_LPSS_I2C_STSCMD_MSE)) {\r
+ //\r
+ // Get the address allocted.\r
+ //\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].Bar0=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR); \r
+ mLpssPciDeviceList[I2cControllerIndex + 1].Bar1=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR1);\r
+ }\r
+ }\r
+ AcpiBaseAddr =mLpssPciDeviceList[I2cControllerIndex+1].Bar0;\r
+ }\r
+ \r
+ //\r
+ // ACPI mode from BDS: LPSS OnReadytoBoot\r
+ //\r
+ else {\r
+ DEBUG ((EFI_D_INFO, "GetI2cBarAddr() NVS Varialable is updated by this LIB or LPSS \n"));\r
+ }\r
+ \r
+ DEBUG ((EFI_D_INFO, "GetI2cBarAddr() I2cControllerIndex+1 0x%x AcpiBaseAddr:0x%x \n", (I2cControllerIndex + 1), AcpiBaseAddr));\r
+ return AcpiBaseAddr;\r
+}\r
+\r
+\r
+/**\r
+ This function enables I2C controllers.\r
+\r
+ @param I2cControllerIndex Bus Number of I2C controllers.\r
+\r
+ @return Result of the I2C initialization.\r
+**/\r
+EFI_STATUS\r
+ProgramPciLpssI2C (\r
+ IN UINT8 I2cControllerIndex\r
+ )\r
+{\r
+ UINT32 PmcBase;\r
+ UINTN PciMmBase=0;\r
+ EFI_STATUS Status;\r
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;\r
+\r
+ UINT32 PmcFunctionDsiable[]= {\r
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1,\r
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2,\r
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3,\r
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4,\r
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5,\r
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6,\r
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7\r
+ };\r
+\r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Start\n"));\r
+\r
+ //\r
+ // Set the VLV Function Disable Register to ZERO\r
+ //\r
+ PmcBase = MmioRead32 (PCI_D31F0_REG_BASE + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR;\r
+ if(MmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)&PmcFunctionDsiable[I2cControllerIndex]) {\r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() End:I2C[%x] is disabled\n",I2cControllerIndex));\r
+ return EFI_NOT_READY;\r
+ }\r
+ \r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C()------------I2cControllerIndex=%x,PMC=%x\n",I2cControllerIndex,MmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)));\r
+\r
+ {\r
+ PciMmBase = MmPciAddress (\r
+ mLpssPciDeviceList[I2cControllerIndex+1].Segment,\r
+ mLpssPciDeviceList[I2cControllerIndex+1].BusNum,\r
+ mLpssPciDeviceList[I2cControllerIndex+1].DeviceNum,\r
+ mLpssPciDeviceList[I2cControllerIndex+1].FunctionNum,\r
+ 0\r
+ );\r
+ \r
+ DEBUG((EFI_D_ERROR, "Program Pci Lpss I2C Device %x %x %x PciMmBase:%x\n", \\r
+ mLpssPciDeviceList[I2cControllerIndex+1].BusNum, \\r
+ mLpssPciDeviceList[I2cControllerIndex+1].DeviceNum, \\r
+ mLpssPciDeviceList[I2cControllerIndex+1].FunctionNum, PciMmBase));\r
+\r
+ if (MmioRead32 (PciMmBase) != 0xFFFFFFFF) {\r
+ if((MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_STSCMD)& B_PCH_LPSS_I2C_STSCMD_MSE)) {\r
+ //\r
+ // Get the address allocted.\r
+ //\r
+ mLpssPciDeviceList[I2cControllerIndex+1].Bar0=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR); \r
+ mLpssPciDeviceList[I2cControllerIndex+1].Bar1=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR1);\r
+ DEBUG((EFI_D_ERROR, "ProgramPciLpssI2C() bar0:0x%x bar1:0x%x\n",mLpssPciDeviceList[I2cControllerIndex+1].Bar0, mLpssPciDeviceList[I2cControllerIndex+1].Bar1));\r
+ } else {\r
+ \r
+ //\r
+ // Program BAR 0\r
+ //\r
+ ASSERT (((mLpssPciDeviceList[I2cControllerIndex+1].Bar0 & B_PCH_LPSS_I2C_BAR_BA) == mLpssPciDeviceList[I2cControllerIndex+1].Bar0) && (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 != 0));\r
+ MmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR), (UINT32) (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 & B_PCH_LPSS_I2C_BAR_BA));\r
+ \r
+ //\r
+ // Program BAR 1\r
+ //\r
+ ASSERT (((mLpssPciDeviceList[I2cControllerIndex+1].Bar1 & B_PCH_LPSS_I2C_BAR1_BA) == mLpssPciDeviceList[I2cControllerIndex+1].Bar1) && (mLpssPciDeviceList[I2cControllerIndex+1].Bar1 != 0));\r
+ MmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR1), (UINT32) (mLpssPciDeviceList[I2cControllerIndex+1].Bar1 & B_PCH_LPSS_I2C_BAR1_BA));\r
+ \r
+ //\r
+ // Bus Master Enable & Memory Space Enable\r
+ //\r
+ MmioOr32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_STSCMD), (UINT32) (B_PCH_LPSS_I2C_STSCMD_BME | B_PCH_LPSS_I2C_STSCMD_MSE));\r
+ ASSERT (MmioRead32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0) != 0xFFFFFFFF);\r
+ }\r
+ \r
+ //\r
+ // Release Resets\r
+ //\r
+ MmioWrite32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 + R_PCH_LPIO_I2C_MEM_RESETS,(B_PCH_LPIO_I2C_MEM_RESETS_FUNC | B_PCH_LPIO_I2C_MEM_RESETS_APB));\r
+ \r
+ //\r
+ // Activate Clocks\r
+ //\r
+ MmioWrite32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 + R_PCH_LPSS_I2C_MEM_PCP,0x80020003);//No use for A0\r
+\r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Programmed()\n"));\r
+ }\r
+ \r
+ //\r
+ // BDS: already switched to ACPI mode\r
+ //\r
+ else {\r
+ ASSERT(gBS!=NULL);\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiGlobalNvsAreaProtocolGuid,\r
+ NULL,\r
+ &GlobalNvsArea\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_INFO, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status));\r
+ //\r
+ // gEfiGlobalNvsAreaProtocolGuid is not ready.\r
+ //\r
+ return 0;\r
+ }\r
+ mLpssPciDeviceList[I2cControllerIndex + 1].Bar0 = *(UINTN*)((CHAR8*)GlobalNvsArea->Area + mI2cNvsBaseAddress[I2cControllerIndex + 1]);\r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C(): is switched to ACPI 0x:%x \n",mLpssPciDeviceList[I2cControllerIndex + 1].Bar0));\r
+ }\r
+ }\r
+ \r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() End\n"));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Disable I2C Bus.\r
+\r
+ @param VOID.\r
+\r
+ @return Result of the I2C disabling.\r
+**/\r
+RETURN_STATUS\r
+I2cDisable (\r
+ VOID\r
+ )\r
+{ \r
+ //\r
+ // 0.1 seconds\r
+ //\r
+ UINT32 NumTries = 10000;\r
+ \r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_ENABLE, 0 );\r
+ while ( 0 != ( MmioRead32 ( mI2CBaseAddress + R_IC_ENABLE_STATUS) & 1)) {\r
+ MicroSecondDelay (10);\r
+ NumTries --;\r
+ if(0 == NumTries) {\r
+ return RETURN_NOT_READY;\r
+ }\r
+ }\r
+ \r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Enable I2C Bus.\r
+\r
+ @param VOID.\r
+\r
+ @return Result of the I2C disabling.\r
+**/\r
+RETURN_STATUS\r
+I2cEnable (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // 0.1 seconds\r
+ //\r
+ UINT32 NumTries = 10000;\r
+ \r
+ MmioWrite32 (mI2CBaseAddress + R_IC_ENABLE, 1);\r
+ \r
+ while (0 == (MmioRead32 (mI2CBaseAddress + R_IC_ENABLE_STATUS) & 1)) {\r
+ MicroSecondDelay (10);\r
+ NumTries --;\r
+ if(0 == NumTries){\r
+ return RETURN_NOT_READY;\r
+ }\r
+ }\r
+ \r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Enable I2C Bus.\r
+\r
+ @param VOID.\r
+\r
+ @return Result of the I2C enabling.\r
+**/\r
+RETURN_STATUS\r
+I2cBusFrequencySet (\r
+ IN UINTN BusClockHertz\r
+ )\r
+{\r
+ DEBUG((EFI_D_INFO,"InputFreq BusClockHertz: %d\r\n",BusClockHertz));\r
+ \r
+ //\r
+ // Set the 100 KHz clock divider according to SV result and I2C spec\r
+ //\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_SS_SCL_HCNT, (UINT16)0x214 );\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_SS_SCL_LCNT, (UINT16)0x272 );\r
+ \r
+ //\r
+ // Set the 400 KHz clock divider according to SV result and I2C spec\r
+ //\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_FS_SCL_HCNT, (UINT16)0x50 );\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_FS_SCL_LCNT, (UINT16)0xAD );\r
+\r
+ switch ( BusClockHertz ) {\r
+ case 100 * 1000:\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x40);//100K\r
+ mI2cMode = V_SPEED_STANDARD;\r
+ break;\r
+ case 400 * 1000:\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x32);//400K\r
+ mI2cMode = V_SPEED_FAST;\r
+ break;\r
+ default:\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x09);//3.4M\r
+ mI2cMode = V_SPEED_HIGH;\r
+ }\r
+\r
+ //\r
+ // Select the frequency counter,\r
+ // Enable restart condition,\r
+ // Enable master FSM, disable slave FSM.\r
+ //\r
+ mI2cMode |= B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initializes the host controller to execute I2C commands.\r
+\r
+ @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device. \r
+ \r
+ @return EFI_SUCCESS Opcode initialization on the I2C host controller completed.\r
+ @return EFI_DEVICE_ERROR Device error, operation failed.\r
+**/\r
+EFI_STATUS\r
+I2CInit (\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT16 SlaveAddress\r
+ )\r
+{\r
+ EFI_STATUS Status=RETURN_SUCCESS;\r
+ UINT32 NumTries = 0;\r
+ UINTN GnvsI2cBarAddr=0;\r
+ \r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if ((1023 < SlaveAddress) || (6 < I2cControllerIndex)) {\r
+ Status = RETURN_INVALID_PARAMETER;\r
+ DEBUG((EFI_D_INFO,"I2CInit Exit with RETURN_INVALID_PARAMETER\r\n"));\r
+ return Status;\r
+ }\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_TAR, (UINT16)SlaveAddress );\r
+ mI2CSlaveAddress = SlaveAddress;\r
+\r
+ //\r
+ // 1.PEI: program and init ( before pci enumeration).\r
+ // 2.DXE:update address and re-init ( after pci enumeration).\r
+ // 3.BDS:update ACPI address and re-init ( after acpi mode is enabled).\r
+ //\r
+ if(mI2CBaseAddress == mLpssPciDeviceList[I2cControllerIndex + 1].Bar0) {\r
+ \r
+ //\r
+ // I2CInit is already called.\r
+ //\r
+ GnvsI2cBarAddr=GetI2cBarAddr(I2cControllerIndex);\r
+ \r
+ if((GnvsI2cBarAddr == 0)||(GnvsI2cBarAddr == mI2CBaseAddress)) {\r
+ DEBUG((EFI_D_INFO,"I2CInit Exit with mI2CBaseAddress:%x == [%x].Bar0\r\n",mI2CBaseAddress,I2cControllerIndex+1));\r
+ return RETURN_SUCCESS;\r
+ }\r
+ }\r
+ \r
+ Status=ProgramPciLpssI2C(I2cControllerIndex);\r
+ if(Status!=EFI_SUCCESS) {\r
+ return Status;\r
+ }\r
+\r
+\r
+ mI2CBaseAddress = (UINT32) mLpssPciDeviceList[I2cControllerIndex + 1].Bar0;\r
+ DEBUG ((EFI_D_ERROR, "mI2CBaseAddress = 0x%x \n",mI2CBaseAddress));\r
+ \r
+ //\r
+ // 1 seconds.\r
+ //\r
+ NumTries = 10000; \r
+ while ((1 == ( MmioRead32 ( mI2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) {\r
+ MicroSecondDelay(10);\r
+ NumTries --;\r
+ if(0 == NumTries) {\r
+ DEBUG((EFI_D_INFO, "Try timeout\r\n"));\r
+ return RETURN_DEVICE_ERROR;\r
+ }\r
+ }\r
+ \r
+ Status = I2cDisable();\r
+ DEBUG((EFI_D_INFO, "I2cDisable Status = %r\r\n", Status));\r
+ I2cBusFrequencySet(400 * 1000);\r
+\r
+ MmioWrite32(mI2CBaseAddress + R_IC_INTR_MASK, 0x0);\r
+ if (0x7f < SlaveAddress )\r
+ SlaveAddress = ( SlaveAddress & 0x3ff ) | IC_TAR_10BITADDR_MASTER;\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_TAR, (UINT16)SlaveAddress );\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_RX_TL, 0);\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_TX_TL, 0 );\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_CON, mI2cMode);\r
+ Status = I2cEnable();\r
+\r
+ DEBUG((EFI_D_INFO, "I2cEnable Status = %r\r\n", Status));\r
+ MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Reads a Byte from I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be read\r
+ @param Offset Offset from which the data has to be read\r
+ @param *Byte Address to which the value read has to be stored\r
+ @param Start Whether a RESTART is issued before the byte is sent or received\r
+ @param End Whether STOP is generated after a data byte is sent or received \r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS \r
+ByteReadI2CBasic(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINTN ReadBytes,\r
+ OUT UINT8 *ReadBuffer,\r
+ IN UINT8 Start,\r
+ IN UINT8 End\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ UINT32 I2cStatus;\r
+ UINT16 ReceiveData;\r
+ UINT8 *ReceiveDataEnd;\r
+ UINT8 *ReceiveRequest;\r
+ UINT16 RawIntrStat;\r
+ UINT32 Count=0;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ ReceiveDataEnd = &ReadBuffer [ReadBytes];\r
+ if( ReadBytes ) {\r
+\r
+ ReceiveRequest = ReadBuffer;\r
+ DEBUG((EFI_D_INFO,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd - ReceiveRequest));\r
+\r
+ while ((ReceiveDataEnd > ReceiveRequest) || (ReceiveDataEnd > ReadBuffer)) {\r
+ \r
+ //\r
+ // Check for NACK\r
+ //\r
+ RawIntrStat = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_RawIntrStat);\r
+ if ( 0 != ( RawIntrStat & I2C_INTR_TX_ABRT )) {\r
+ MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );\r
+ Status = RETURN_DEVICE_ERROR;\r
+ DEBUG((EFI_D_INFO,"TX ABRT ,%d bytes hasn't been transferred\r\n",ReceiveDataEnd - ReceiveRequest));\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Determine if another byte was received\r
+ //\r
+ I2cStatus = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_STATUS);\r
+ if (0 != ( I2cStatus & STAT_RFNE )) {\r
+ ReceiveData = (UINT16)MmioRead32 ( mI2CBaseAddress + R_IC_DATA_CMD );\r
+ *ReadBuffer++ = (UINT8)ReceiveData;\r
+ DEBUG((EFI_D_INFO,"MmioRead32 ,1 byte 0x:%x is received\r\n",ReceiveData));\r
+ }\r
+\r
+ if(ReceiveDataEnd == ReceiveRequest) {\r
+ MicroSecondDelay ( FIFO_WRITE_DELAY );\r
+ DEBUG((EFI_D_INFO,"ReceiveDataEnd==ReceiveRequest------------%x\r\n",I2cStatus & STAT_RFNE));\r
+ Count++;\r
+ if(Count<1024) {\r
+ //\r
+ // To avoid sys hung without ul-pmc device on RVP,\r
+ // waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.\r
+ //\r
+ continue;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Wait until a read request will fit.\r
+ //\r
+ if (0 == (I2cStatus & STAT_TFNF)) {\r
+ DEBUG((EFI_D_INFO,"Wait until a read request will fit\r\n"));\r
+ MicroSecondDelay (10);\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Issue the next read request.\r
+ //\r
+ if(End && Start) {\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART|B_CMD_STOP);\r
+ } else if (!End && Start) {\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART);\r
+ } else if (End && !Start) {\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_STOP);\r
+ } else if (!End && !Start) {\r
+ MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD);\r
+ }\r
+ MicroSecondDelay (FIFO_WRITE_DELAY);\r
+\r
+ ReceiveRequest += 1;\r
+ }\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Writes a Byte to I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be written\r
+ @param Offset Offset from which the data has to be read\r
+ @param *Byte Address to which the value written is stored\r
+ @param Start Whether a RESTART is issued before the byte is sent or received\r
+ @param End Whether STOP is generated after a data byte is sent or received \r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully written\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS ByteWriteI2CBasic(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINTN WriteBytes,\r
+ IN UINT8 *WriteBuffer,\r
+ IN UINT8 Start,\r
+ IN UINT8 End\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ UINT32 I2cStatus;\r
+ UINT8 *TransmitEnd;\r
+ UINT16 RawIntrStat;\r
+ UINT32 Count=0;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ Status=I2CInit(I2cControllerIndex, SlaveAddress);\r
+ if(Status!=EFI_SUCCESS)\r
+ return Status;\r
+\r
+ TransmitEnd = &WriteBuffer[WriteBytes];\r
+ if( WriteBytes ) {\r
+ DEBUG((EFI_D_INFO,"Write: --------------%d bytes to TX\r\n",TransmitEnd - WriteBuffer));\r
+ while (TransmitEnd > WriteBuffer) {\r
+ I2cStatus = MmioRead32 (mI2CBaseAddress + R_IC_STATUS);\r
+ RawIntrStat = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_RawIntrStat);\r
+ if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {\r
+ MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT);\r
+ Status = RETURN_DEVICE_ERROR;\r
+ DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));\r
+ break;\r
+ }\r
+ if (0 == (I2cStatus & STAT_TFNF)) {\r
+ //\r
+ // If TX not full , will send cmd or continue to wait\r
+ //\r
+ MicroSecondDelay (FIFO_WRITE_DELAY);\r
+ continue;\r
+ }\r
+\r
+ if(End && Start) {\r
+ MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART|B_CMD_STOP);\r
+ } else if (!End && Start) {\r
+ MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART);\r
+ } else if (End && !Start) {\r
+ MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_STOP);\r
+ } else if (!End && !Start ) {\r
+ MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++));\r
+ }\r
+ \r
+ //\r
+ // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped.\r
+ //\r
+ MicroSecondDelay ( FIFO_WRITE_DELAY );//wait after send cmd\r
+ \r
+ //\r
+ // Time out\r
+ //\r
+ while(1) {\r
+ RawIntrStat = MmioRead16 ( mI2CBaseAddress + R_IC_RawIntrStat );\r
+ if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {\r
+ MmioRead16 (mI2CBaseAddress + R_IC_CLR_TX_ABRT);\r
+ Status = RETURN_DEVICE_ERROR;\r
+ DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));\r
+ }\r
+ if(0 == MmioRead16(mI2CBaseAddress + R_IC_TXFLR)) break;\r
+\r
+ MicroSecondDelay (FIFO_WRITE_DELAY);\r
+ Count++;\r
+ if(Count<1024) {\r
+ //\r
+ // to avoid sys hung without ul-pmc device on RVP.\r
+ // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.\r
+ //\r
+ continue;\r
+ } else {\r
+ break;\r
+ }\r
+ }//while( 1 )\r
+ }\r
+\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Reads a Byte from I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be read\r
+ @param Offset Offset from which the data has to be read\r
+ @param ReadBytes Number of bytes to be read\r
+ @param *ReadBuffer Address to which the value read has to be stored\r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS ByteReadI2C(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINT8 Offset,\r
+ IN UINTN ReadBytes,\r
+ OUT UINT8 *ReadBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((EFI_D_INFO, "ByteReadI2C:---offset:0x%x\n",Offset));\r
+ Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,1,&Offset,TRUE,FALSE);\r
+ Status = ByteReadI2CBasic(I2cControllerIndex, SlaveAddress,ReadBytes,ReadBuffer,TRUE,TRUE);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Writes a Byte to I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be written\r
+ @param Offset Offset from which the data has to be written\r
+ @param WriteBytes Number of bytes to be written\r
+ @param *Byte Address to which the value written is stored\r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS ByteWriteI2C(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINT8 Offset,\r
+ IN UINTN WriteBytes,\r
+ IN UINT8 *WriteBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((EFI_D_INFO, "ByteWriteI2C:---offset/bytes/buf:0x%x,0x%x,0x%x,0x%x\n",Offset,WriteBytes,WriteBuffer,*WriteBuffer));\r
+ Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,1,&Offset,TRUE,FALSE);\r
+ Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,WriteBytes,WriteBuffer,FALSE,TRUE);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+## @file\r
+# Instance of I2C Library.\r
+#\r
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = I2CLib\r
+ FILE_GUID = 7f62bf44-2ba7-4c2d-9d4a-91c8906ff053\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = I2CLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION\r
+ \r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ I2CLib.c\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ IoLib\r
+ TimerLib\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ Vlv2TbltDevicePkg/PlatformPkg.dec\r
+ Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec\r
+\r
+[Protocols]\r
+ gEfiGlobalNvsAreaProtocolGuid\r
--- /dev/null
+/** @file\r
+ Register Definitions for I2C Driver/PEIM.\r
+ \r
+ Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials are licensed and made available under\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r
+ The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php. \r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ \r
+--*/\r
+\r
+#ifndef I2C_REGS_H\r
+#define I2C_REGS_H\r
+\r
+//\r
+// FIFO write delay value.\r
+//\r
+#define FIFO_WRITE_DELAY 2\r
+\r
+//\r
+// MMIO Register Definitions.\r
+//\r
+#define R_IC_CON ( 0x00) // I2C Control \r
+#define B_IC_RESTART_EN BIT5\r
+#define B_IC_SLAVE_DISABLE BIT6\r
+#define V_SPEED_STANDARD 0x02\r
+#define V_SPEED_FAST 0x04\r
+#define V_SPEED_HIGH 0x06\r
+#define B_MASTER_MODE BIT0\r
+\r
+#define R_IC_TAR ( 0x04) // I2C Target Address\r
+#define IC_TAR_10BITADDR_MASTER BIT12\r
+\r
+#define R_IC_SAR ( 0x08) // I2C Slave Address\r
+#define R_IC_HS_MADDR ( 0x0C) // I2C HS MasterMode Code Address\r
+#define R_IC_DATA_CMD ( 0x10) // I2C Rx/Tx Data Buffer and Command\r
+\r
+#define B_READ_CMD BIT8 // 1 = read, 0 = write\r
+#define B_CMD_STOP BIT9 // 1 = STOP\r
+#define B_CMD_RESTART BIT10 // 1 = IC_RESTART_EN\r
+\r
+#define V_WRITE_CMD_MASK ( 0xFF)\r
+\r
+#define R_IC_SS_SCL_HCNT ( 0x14) // Standard Speed I2C Clock SCL High Count\r
+#define R_IC_SS_SCL_LCNT ( 0x18) // Standard Speed I2C Clock SCL Low Count\r
+#define R_IC_FS_SCL_HCNT ( 0x1C) // Full Speed I2C Clock SCL High Count\r
+#define R_IC_FS_SCL_LCNT ( 0x20) // Full Speed I2C Clock SCL Low Count\r
+#define R_IC_HS_SCL_HCNT ( 0x24) // High Speed I2C Clock SCL High Count\r
+#define R_IC_HS_SCL_LCNT ( 0x28) // High Speed I2C Clock SCL Low Count\r
+#define R_IC_INTR_STAT ( 0x2C) // I2C Inetrrupt Status\r
+#define R_IC_INTR_MASK ( 0x30) // I2C Interrupt Mask\r
+#define I2C_INTR_GEN_CALL BIT11 // General call received\r
+#define I2C_INTR_START_DET BIT10\r
+#define I2C_INTR_STOP_DET BIT9\r
+#define I2C_INTR_ACTIVITY BIT8\r
+#define I2C_INTR_TX_ABRT BIT6 // Set on NACK\r
+#define I2C_INTR_TX_EMPTY BIT4\r
+#define I2C_INTR_TX_OVER BIT3\r
+#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold\r
+#define I2C_INTR_RX_OVER BIT1\r
+#define I2C_INTR_RX_UNDER BIT0\r
+#define R_IC_RawIntrStat ( 0x34) // I2C Raw Interrupt Status\r
+#define R_IC_RX_TL ( 0x38) // I2C Receive FIFO Threshold\r
+#define R_IC_TX_TL ( 0x3C) // I2C Transmit FIFO Threshold\r
+#define R_IC_CLR_INTR ( 0x40) // Clear Combined and Individual Interrupts\r
+#define R_IC_CLR_RX_UNDER ( 0x44) // Clear RX_UNDER Interrupt\r
+#define R_IC_CLR_RX_OVER ( 0x48) // Clear RX_OVERinterrupt\r
+#define R_IC_CLR_TX_OVER ( 0x4C) // Clear TX_OVER interrupt\r
+#define R_IC_CLR_RD_REQ ( 0x50) // Clear RD_REQ interrupt\r
+#define R_IC_CLR_TX_ABRT ( 0x54) // Clear TX_ABRT interrupt\r
+#define R_IC_CLR_RX_DONE ( 0x58) // Clear RX_DONE interrupt\r
+#define R_IC_CLR_ACTIVITY ( 0x5C) // Clear ACTIVITY interrupt\r
+#define R_IC_CLR_STOP_DET ( 0x60) // Clear STOP_DET interrupt\r
+#define R_IC_CLR_START_DET ( 0x64) // Clear START_DET interrupt\r
+#define R_IC_CLR_GEN_CALL ( 0x68) // Clear GEN_CALL interrupt\r
+#define R_IC_ENABLE ( 0x6C) // I2C Enable\r
+#define R_IC_STATUS ( 0x70) // I2C Status\r
+\r
+#define R_IC_SDA_HOLD ( 0x7C) // I2C IC_DEFAULT_SDA_HOLD//16bits\r
+\r
+#define STAT_MST_ACTIVITY BIT5 // Master FSM Activity Status.\r
+#define STAT_RFF BIT4 // RX FIFO is completely full\r
+#define STAT_RFNE BIT3 // RX FIFO is not empty\r
+#define STAT_TFE BIT2 // TX FIFO is completely empty\r
+#define STAT_TFNF BIT1 // TX FIFO is not full\r
+\r
+#define R_IC_TXFLR ( 0x74) // Transmit FIFO Level Register\r
+#define R_IC_RXFLR ( 0x78) // Receive FIFO Level Register\r
+#define R_IC_TX_ABRT_SOURCE ( 0x80) // I2C Transmit Abort Status Register\r
+#define R_IC_SLV_DATA_NACK_ONLY ( 0x84) // Generate SLV_DATA_NACK Register\r
+#define R_IC_DMA_CR ( 0x88) // DMA Control Register\r
+#define R_IC_DMA_TDLR ( 0x8C) // DMA Transmit Data Level\r
+#define R_IC_DMA_RDLR ( 0x90) // DMA Receive Data Level\r
+#define R_IC_SDA_SETUP ( 0x94) // I2C SDA Setup Register\r
+#define R_IC_ACK_GENERAL_CALL ( 0x98) // I2C ACK General Call Register\r
+#define R_IC_ENABLE_STATUS ( 0x9C) // I2C Enable Status Register\r
+#define R_IC_COMP_PARAM ( 0xF4) // Component Parameter Register\r
+#define R_IC_COMP_VERSION ( 0xF8) // Component Version ID\r
+#define R_IC_COMP_TYPE ( 0xFC) // Component Type\r
+\r
+#define I2C_SS_SCL_HCNT_VALUE_100M 0x1DD\r
+#define I2C_SS_SCL_LCNT_VALUE_100M 0x1E4\r
+#define I2C_FS_SCL_HCNT_VALUE_100M 0x54\r
+#define I2C_FS_SCL_LCNT_VALUE_100M 0x9a\r
+#define I2C_HS_SCL_HCNT_VALUE_100M 0x7\r
+#define I2C_HS_SCL_LCNT_VALUE_100M 0xE\r
+\r
+#define IC_TAR_10BITADDR_MASTER BIT12\r
+#define FIFO_SIZE 32\r
+#define R_IC_INTR_STAT ( 0x2C) // I2c Inetrrupt Status\r
+#define R_IC_INTR_MASK ( 0x30) // I2c Interrupt Mask\r
+#define I2C_INTR_GEN_CALL BIT11 // General call received\r
+#define I2C_INTR_START_DET BIT10\r
+#define I2C_INTR_STOP_DET BIT9\r
+#define I2C_INTR_ACTIVITY BIT8\r
+#define I2C_INTR_TX_ABRT BIT6 // Set on NACK\r
+#define I2C_INTR_TX_EMPTY BIT4\r
+#define I2C_INTR_TX_OVER BIT3\r
+#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold\r
+#define I2C_INTR_RX_OVER BIT1\r
+#define I2C_INTR_RX_UNDER BIT0\r
+\r
+#define R_PCH_LPIO_I2C_MEM_RESETS 0x804 // Software Reset\r
+#define B_PCH_LPIO_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset\r
+#define B_PCH_LPIO_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset\r
+#define R_PCH_LPSS_I2C_MEM_PCP 0x800 // Private Clock Parameters\r
+\r
+#endif
\ No newline at end of file
--- /dev/null
+/** @file\r
+ Misc Registers Definition.\r
+ \r
+ Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials are licensed and made available under\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r
+ The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php. \r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ \r
+--*/\r
+\r
+#ifndef _I2C_ACCESS_H_\r
+#define _I2C_ACCESS_H_\r
+\r
+#include "I2CIoLibPei.h"\r
+\r
+#define DEFAULT_PCI_BUS_NUMBER_PCH 0\r
+\r
+#define PCI_DEVICE_NUMBER_PCH_LPC 31\r
+#define PCI_FUNCTION_NUMBER_PCH_LPC 0\r
+\r
+#define R_PCH_LPC_ACPI_BASE 0x40 // ABASE, 16bit\r
+#define R_PCH_LPC_ACPI_BASEADR 0x400 // ABASE, 16bit\r
+#define B_PCH_LPC_ACPI_BASE_EN BIT1 // Enable Bit\r
+#define B_PCH_LPC_ACPI_BASE_BAR 0x0000FF80 // Base Address, 128 Bytes\r
+#define V_PCH_ACPI_PM1_TMR_MAX_VAL 0x1000000 // The timer is 24 bit overflow\r
+#define B_PCH_ACPI_PM1_TMR_VAL 0xFFFFFF // The timer value mask\r
+\r
+#define R_PCH_ACPI_PM1_TMR 0x08 // Power Management 1 Timer\r
+#define V_PCH_ACPI_PM1_TMR_FREQUENCY 3579545 // Timer Frequency\r
+\r
+\r
+#define PchLpcPciCfg8(Register) I2CLibPeiMmioRead8 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, Register))\r
+\r
+#define PCIEX_BASE_ADDRESS 0xE0000000\r
+#define PCI_EXPRESS_BASE_ADDRESS ((VOID *) (UINTN) PCIEX_BASE_ADDRESS)\r
+\r
+#define MmPciAddress( Segment, Bus, Device, Function, Register ) \\r
+ ( (UINTN)PCI_EXPRESS_BASE_ADDRESS + \\r
+ (UINTN)(Bus << 20) + \\r
+ (UINTN)(Device << 15) + \\r
+ (UINTN)(Function << 12) + \\r
+ (UINTN)(Register) \\r
+ )\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ MicroSecondDelay implementation of ACPI Timer.\r
+ \r
+ Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials are licensed and made available under\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r
+ The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php. \r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ \r
+--*/\r
+\r
+#include "PiPei.h"\r
+#include "I2CAccess.h"\r
+#include "I2CDelayPei.h"\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+#include <Ppi/Stall.h>\r
+\r
+/**\r
+ Stalls the CPU for at least the given number of microseconds.\r
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.\r
+\r
+ @param MicroSeconds The minimum number of microseconds to delay.\r
+\r
+ @return EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MicroSecondDelay (\r
+ IN UINTN MicroSeconds\r
+ )\r
+{\r
+\r
+ EFI_PEI_STALL_PPI *StallPpi;\r
+ EFI_STATUS Status;\r
+ CONST EFI_PEI_SERVICES **PeiServices;\r
+ \r
+ PeiServices = GetPeiServicesTablePointer();\r
+\r
+\r
+ Status = (**PeiServices).LocatePpi (PeiServices, &gEfiPeiStallPpiGuid, 0, NULL, &StallPpi);\r
+ ASSERT(!EFI_ERROR(Status));\r
+\r
+ StallPpi->Stall (PeiServices, StallPpi, MicroSeconds);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ MicroSecondDelay implementation of ACPI Timer.\r
+\r
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __I2C_DELAY_PEI__\r
+\r
+#define __I2C_DELAY_PEI__\r
+#include "PiPei.h"\r
+\r
+/**\r
+ Stalls the CPU for at least the given number of microseconds.\r
+\r
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.\r
+\r
+ @param MicroSeconds The minimum number of microseconds to delay.\r
+\r
+ @return MicroSeconds\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MicroSecondDelay (\r
+ IN UINTN MicroSeconds\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Functions for access I2C MMIO register.\r
+\r
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+\r
+/**\r
+ Reads an 8-bit MMIO register.\r
+\r
+ Reads the 8-bit MMIO register specified by Address. The 8-bit read value is\r
+ returned. This function must guarantee that all MMIO read and write\r
+ operations are serialized.\r
+\r
+ If 8-bit MMIO register operations are not supported, then ASSERT().\r
+\r
+ @param Address The MMIO register to read.\r
+\r
+ @return The value read.\r
+\r
+**/\r
+UINT8\r
+EFIAPI\r
+I2CLibPeiMmioRead8 (\r
+ IN UINTN Address\r
+ )\r
+{\r
+ UINT8 Value;\r
+\r
+ Value = *(volatile UINT8*)Address;\r
+ return Value;\r
+}\r
+\r
+/**\r
+ Reads a 16-bit MMIO register.\r
+\r
+ Reads the 16-bit MMIO register specified by Address. The 16-bit read value is\r
+ returned. This function must guarantee that all MMIO read and write\r
+ operations are serialized.\r
+\r
+ If 16-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 16-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to read.\r
+\r
+ @return The value read.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+I2CLibPeiMmioRead16 (\r
+ IN UINTN Address\r
+ )\r
+{\r
+ UINT16 Value;\r
+\r
+ ASSERT ((Address & 1) == 0);\r
+ Value = *(volatile UINT16*)Address;\r
+ return Value;\r
+}\r
+\r
+/**\r
+ Writes a 16-bit MMIO register.\r
+\r
+ Writes the 16-bit MMIO register specified by Address with the value specified\r
+ by Value and returns Value. This function must guarantee that all MMIO read\r
+ and write operations are serialized.\r
+\r
+ If 16-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 16-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to write.\r
+ @param Value The value to write to the MMIO register.\r
+\r
+ @return Value.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+I2CLibPeiMmioWrite16 (\r
+ IN UINTN Address,\r
+ IN UINT16 Value\r
+ )\r
+{\r
+ ASSERT ((Address & 1) == 0);\r
+ *(volatile UINT16*)Address = Value;\r
+ return Value;\r
+}\r
+\r
+/**\r
+ Reads a 32-bit MMIO register.\r
+\r
+ Reads the 32-bit MMIO register specified by Address. The 32-bit read value is\r
+ returned. This function must guarantee that all MMIO read and write\r
+ operations are serialized.\r
+\r
+ If 32-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 32-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to read.\r
+\r
+ @return The value read.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+I2CLibPeiMmioRead32 (\r
+ IN UINTN Address\r
+ )\r
+{\r
+ UINT32 Value;\r
+\r
+ ASSERT ((Address & 3) == 0);\r
+ Value = *(volatile UINT32*)Address;\r
+\r
+ return Value;\r
+}\r
+\r
+/**\r
+ Writes a 32-bit MMIO register.\r
+\r
+ Writes the 32-bit MMIO register specified by Address with the value specified\r
+ by Value and returns Value. This function must guarantee that all MMIO read\r
+ and write operations are serialized.\r
+\r
+ If 32-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 32-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to write.\r
+ @param Value The value to write to the MMIO register.\r
+\r
+ @return Value.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+I2CLibPeiMmioWrite32 (\r
+ IN UINTN Address,\r
+ IN UINT32 Value\r
+ )\r
+{\r
+ ASSERT ((Address & 3) == 0);\r
+ *(volatile UINT32*)Address = Value;\r
+ return Value;\r
+}\r
+\r
+/**\r
+ OR a 32-bit MMIO register.\r
+\r
+ OR the 32-bit MMIO register specified by Address with the value specified\r
+ by Value and returns Value. This function must guarantee that all MMIO read\r
+ and write operations are serialized.\r
+\r
+ If 32-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 32-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to write OR.\r
+ @param Value The value to OR to the MMIO register.\r
+\r
+ @return Value.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+I2CLibPeiMmioOr32 (\r
+ IN UINTN Address,\r
+ IN UINT32 OrData\r
+ )\r
+{\r
+ return I2CLibPeiMmioWrite32 (Address, I2CLibPeiMmioRead32(Address) | OrData);\r
+}\r
+\r
+\r
--- /dev/null
+/** @file\r
+ Functions for access I2C MMIO register.\r
+\r
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __I2C_IOLIB_PEI__\r
+\r
+#define __I2C_IOLIB_PEI__\r
+#include <PiPei.h>\r
+\r
+\r
+/**\r
+ Reads an 8-bit MMIO register.\r
+\r
+ Reads the 8-bit MMIO register specified by Address. The 8-bit read value is\r
+ returned. This function must guarantee that all MMIO read and write\r
+ operations are serialized.\r
+\r
+ If 8-bit MMIO register operations are not supported, then ASSERT().\r
+\r
+ @param Address The MMIO register to read.\r
+\r
+ @return The value read.\r
+\r
+**/\r
+\r
+UINT8\r
+EFIAPI\r
+I2CLibPeiMmioRead8 (\r
+ IN UINTN Address\r
+ );\r
+\r
+\r
+/**\r
+ Reads a 16-bit MMIO register.\r
+\r
+ Reads the 16-bit MMIO register specified by Address. The 16-bit read value is\r
+ returned. This function must guarantee that all MMIO read and write\r
+ operations are serialized.\r
+\r
+ If 16-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 16-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to read.\r
+\r
+ @return The value read.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+I2CLibPeiMmioRead16 (\r
+ IN UINTN Address\r
+ );\r
+\r
+\r
+/**\r
+ Writes a 16-bit MMIO register.\r
+\r
+ Writes the 16-bit MMIO register specified by Address with the value specified\r
+ by Value and returns Value. This function must guarantee that all MMIO read\r
+ and write operations are serialized.\r
+\r
+ If 16-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 16-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to write.\r
+ @param Value The value to write to the MMIO register.\r
+\r
+ @return Value.\r
+\r
+**/\r
+UINT16\r
+EFIAPI\r
+I2CLibPeiMmioWrite16 (\r
+ IN UINTN Address,\r
+ IN UINT16 Value\r
+ );\r
+\r
+\r
+/**\r
+ Reads a 32-bit MMIO register.\r
+\r
+ Reads the 32-bit MMIO register specified by Address. The 32-bit read value is\r
+ returned. This function must guarantee that all MMIO read and write\r
+ operations are serialized.\r
+\r
+ If 32-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 32-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to read.\r
+\r
+ @return The value read.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+I2CLibPeiMmioRead32 (\r
+ IN UINTN Address\r
+ );\r
+\r
+\r
+/**\r
+ Writes a 32-bit MMIO register.\r
+\r
+ Writes the 32-bit MMIO register specified by Address with the value specified\r
+ by Value and returns Value. This function must guarantee that all MMIO read\r
+ and write operations are serialized.\r
+\r
+ If 32-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 32-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to write.\r
+ @param Value The value to write to the MMIO register.\r
+\r
+ @return Value.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+I2CLibPeiMmioWrite32 (\r
+ IN UINTN Address,\r
+ IN UINT32 Value\r
+ );\r
+\r
+\r
+/**\r
+ OR a 32-bit MMIO register.\r
+\r
+ OR the 32-bit MMIO register specified by Address with the value specified\r
+ by Value and returns Value. This function must guarantee that all MMIO read\r
+ and write operations are serialized.\r
+\r
+ If 32-bit MMIO register operations are not supported, then ASSERT().\r
+ If Address is not aligned on a 32-bit boundary, then ASSERT().\r
+\r
+ @param Address The MMIO register to write OR.\r
+ @param Value The value to OR to the MMIO register.\r
+\r
+ @return Value.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+I2CLibPeiMmioOr32 (\r
+ IN UINTN Address,\r
+ IN UINT32 OrData\r
+ );\r
+\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ I2C PEI Lib Instance.\r
+\r
+ Copyright (c) 1999- 2015, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "I2CDelayPei.h"\r
+#include "I2CIoLibPei.h"\r
+#include "I2CAccess.h"\r
+#include "I2CLibPei.h"\r
+#include <PlatformBaseAddresses.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+#include <Library/HobLib.h>\r
+#include <PchRegs/PchRegsPcu.h> \r
+#include <PchRegs/PchRegsLpss.h> \r
+\r
+#define LPSS_PCI_DEVICE_NUMBER 8\r
+\r
+#define R_PCH_LPIO_I2C_MEM_RESETS 0x804 // Software Reset\r
+#define B_PCH_LPIO_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset\r
+#define B_PCH_LPIO_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset\r
+#define R_PCH_LPSS_I2C_MEM_PCP 0x800 // Private Clock Parameters\r
+\r
+#define PEI_TEPM_LPSS_DMA_BAR 0xFE900000\r
+#define PEI_TEPM_LPSS_I2C0_BAR 0xFE910000\r
+#define PCI_CONFIG_SPACE_SIZE 0x10000\r
+\r
+EFI_GUID mI2CPeiInitGuid = {\r
+ 0x96DED71A, 0xB9E7, 0x4EAD, 0x96, 0x2C, 0x01, 0x69, 0x3C, 0xED, 0x2A, 0x64\r
+};\r
+\r
+\r
+UINT16 I2CGPIO[]= {\r
+ //\r
+ // 19.1.6 I2C0\r
+ // I2C0_SDA-OD-O - write 0x2003CC81 to IOBASE + 0x0210\r
+ // I2C0_SCL-OD-O - write 0x2003CC81 to IOBASE + 0x0200\r
+ //\r
+ 0x0210,\r
+ 0x0200,\r
+\r
+ //\r
+ // 19.1.7 I2C1\r
+ // I2C1_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01F0\r
+ // I2C1_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01E0\r
+ //\r
+ 0x01F0,\r
+ 0x01E0,\r
+\r
+ //\r
+ // 19.1.8 I2C2\r
+ // I2C2_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01D0\r
+ // I2C2_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01B0\r
+ //\r
+ 0x01D0,\r
+ 0x01B0,\r
+\r
+ //\r
+ // 19.1.9 I2C3\r
+ // I2C3_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0190\r
+ // I2C3_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x01C0\r
+ // \r
+ 0x0190,\r
+ 0x01C0,\r
+\r
+ //\r
+ // 19.1.10 I2C4\r
+ // I2C4_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x01A0\r
+ // I2C4_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0170\r
+ //\r
+ 0x01A0,\r
+ 0x0170,\r
+\r
+ // \r
+ // 19.1.11 I2C5\r
+ // I2C5_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0150\r
+ // I2C5_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0140\r
+ // \r
+ 0x0150,\r
+ 0x0140,\r
+\r
+ //\r
+ // 19.1.12 I2C6\r
+ // I2C6_SDA-OD-O/I - write 0x2003CC81 to IOBASE + 0x0180\r
+ // I2C6_SCL-OD-O/I - write 0x2003CC81 to IOBASE + 0x0160\r
+ // \r
+ 0x0180,\r
+ 0x0160\r
+};\r
+\r
+/**\r
+ Constructor of this library.\r
+\r
+ @param VOID\r
+\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IntelI2CPeiLibConstructor (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN CONST EFI_PEI_SERVICES **PeiServices\r
+ )\r
+{\r
+ UINTN Index;\r
+ \r
+ for (Index = 0; Index < sizeof(I2CGPIO)/sizeof(UINT16); Index ++) {\r
+ I2CLibPeiMmioWrite32(IO_BASE_ADDRESS+I2CGPIO[Index], 0x2003CC81);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Programe all I2C controllers on LPSS. \r
+ \r
+ I2C0 is function 1 of LPSS. I2C1 is function 2 of LPSS, etc..\r
+\r
+ @param VOID\r
+\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+ProgramPciLpssI2C (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 PmcBase;\r
+ UINT32 DevID;\r
+ UINTN PciMmBase=0;\r
+ UINTN Index;\r
+ UINTN Bar0;\r
+ UINTN Bar1;\r
+ DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() Start\n"));\r
+ \r
+ //\r
+ // Set the VLV Function Disable Register to ZERO\r
+ //\r
+ PmcBase = I2CLibPeiMmioRead32(PciD31F0RegBase + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR;\r
+ \r
+ if(I2CLibPeiMmioRead32(PmcBase + R_PCH_PMC_FUNC_DIS)&\r
+ (B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2\r
+ | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5\r
+ | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7)) {\r
+ I2CLibPeiMmioWrite32(\r
+ PmcBase+R_PCH_PMC_FUNC_DIS,\r
+ I2CLibPeiMmioRead32(PmcBase + R_PCH_PMC_FUNC_DIS)& \\r
+ ~(B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2 \\r
+ | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4 \\r
+ | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5 | B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6|B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7)\r
+ );\r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() enable all I2C controllers\n"));\r
+ }\r
+\r
+ for(Index = 0; Index < LPSS_PCI_DEVICE_NUMBER; Index ++) {\r
+\r
+ PciMmBase = MmPciAddress (\r
+ 0,\r
+ DEFAULT_PCI_BUS_NUMBER_PCH,\r
+ PCI_DEVICE_NUMBER_PCH_LPSS_I2C,\r
+ Index,\r
+ 0\r
+ );\r
+ DevID = I2CLibPeiMmioRead32(PciMmBase);\r
+\r
+ Bar0 = PEI_TEPM_LPSS_DMA_BAR + (Index * PCI_CONFIG_SPACE_SIZE);\r
+ Bar1 = Bar0 + 0x8000;\r
+\r
+ DEBUG((EFI_D_ERROR, "Program Pci Lpss I2C Device Function=%x DevID=%08x\n", Index, DevID));\r
+ \r
+ //\r
+ // Check if device present\r
+ //\r
+ if (DevID != 0xFFFFFFFF) {\r
+ if(!(I2CLibPeiMmioRead32 (PciMmBase + R_PCH_LPSS_I2C_STSCMD) & B_PCH_LPSS_I2C_STSCMD_MSE)) {\r
+ //\r
+ // Program BAR 0\r
+ //\r
+ I2CLibPeiMmioWrite32((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR), (UINT32)(Bar0 & B_PCH_LPSS_I2C_BAR_BA));\r
+ \r
+ DEBUG ((EFI_D_ERROR, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR)));\r
+ \r
+ //\r
+ // Program BAR 1\r
+ //\r
+ I2CLibPeiMmioWrite32 ((UINTN)(PciMmBase + R_PCH_LPSS_I2C_BAR1), (UINT32)(Bar1 & B_PCH_LPSS_I2C_BAR1_BA));\r
+ DEBUG ((EFI_D_ERROR, "I2CBaseAddress1 = 0x%x \n",I2CLibPeiMmioRead32(PciMmBase+R_PCH_LPSS_I2C_BAR1)));\r
+ \r
+ //\r
+ // Bus Master Enable & Memory Space Enable\r
+ //\r
+ I2CLibPeiMmioWrite32((UINTN) (PciMmBase + R_PCH_LPSS_I2C_STSCMD), (UINT32)(B_PCH_LPSS_I2C_STSCMD_BME | B_PCH_LPSS_I2C_STSCMD_MSE));\r
+ }\r
+ \r
+ //\r
+ // Release Resets\r
+ //\r
+ I2CLibPeiMmioWrite32 (Bar0 + R_PCH_LPIO_I2C_MEM_RESETS, (B_PCH_LPIO_I2C_MEM_RESETS_FUNC | B_PCH_LPIO_I2C_MEM_RESETS_APB));\r
+ \r
+ //\r
+ // Activate Clocks\r
+ //\r
+ I2CLibPeiMmioWrite32 (Bar0 + R_PCH_LPSS_I2C_MEM_PCP, 0x80020003);//No use for A0\r
+\r
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Programmed()\n"));\r
+ }\r
+\r
+ }\r
+ \r
+ DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() End\n"));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Disable I2C Bus.\r
+\r
+ @param I2cControllerIndex Index of I2C controller.\r
+\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+I2cDisable (\r
+ IN UINT8 I2cControllerIndex\r
+ )\r
+{\r
+ UINTN I2CBaseAddress;\r
+ UINT32 NumTries = 10000; // 0.1 seconds\r
+ \r
+ I2CBaseAddress = (UINT32) PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE;\r
+ \r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 0);\r
+ while (0 != ( I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_ENABLE_STATUS ) & 1)) {\r
+ MicroSecondDelay (10);\r
+ NumTries --;\r
+ if(0 == NumTries) return EFI_NOT_READY;\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Enable I2C Bus.\r
+\r
+ @param I2cControllerIndex Index of I2C controller.\r
+\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+I2cEnable (\r
+ IN UINT8 I2cControllerIndex\r
+ )\r
+{\r
+ UINTN I2CBaseAddress;\r
+ UINT32 NumTries = 10000; // 0.1 seconds\r
+ \r
+ I2CBaseAddress = (UINT32) PEI_TEPM_LPSS_I2C0_BAR+ I2cControllerIndex * PCI_CONFIG_SPACE_SIZE;\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 1);\r
+ while (0 == ( I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_ENABLE_STATUS ) & 1)) {\r
+ MicroSecondDelay (10);\r
+ NumTries --;\r
+ if(0 == NumTries) return EFI_NOT_READY;\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Set the I2C controller bus clock frequency.\r
+\r
+ @param[in] This Address of the library's I2C context structure\r
+ @param[in] PlatformData Address of the platform configuration data\r
+ @param[in] BusClockHertz New I2C bus clock frequency in Hertz\r
+\r
+ @retval RETURN_SUCCESS The bus frequency was set successfully.\r
+ @retval RETURN_UNSUPPORTED The controller does not support this frequency.\r
+\r
+**/\r
+EFI_STATUS\r
+I2cBusFrequencySet (\r
+ IN UINTN I2CBaseAddress,\r
+ IN UINTN BusClockHertz,\r
+ IN UINT16 *I2cMode\r
+ )\r
+{\r
+ DEBUG((EFI_D_INFO,"InputFreq BusClockHertz: %d\r\n",BusClockHertz));\r
+\r
+ *I2cMode = B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE;\r
+\r
+ //\r
+ // Set the 100 KHz clock divider\r
+ //\r
+ // From Table 10 of the I2C specification\r
+ //\r
+ // High: 4.00 uS\r
+ // Low: 4.70 uS\r
+ //\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_SS_SCL_HCNT, (UINT16)0x214 );\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_SS_SCL_LCNT, (UINT16)0x272 );\r
+ \r
+ //\r
+ // Set the 400 KHz clock divider\r
+ //\r
+ // From Table 10 of the I2C specification\r
+ //\r
+ // High: 0.60 uS\r
+ // Low: 1.30 uS\r
+ //\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_FS_SCL_HCNT, (UINT16)0x50 );\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_FS_SCL_LCNT, (UINT16)0xAD );\r
+\r
+ switch ( BusClockHertz ) {\r
+ case 100 * 1000:\r
+ I2CLibPeiMmioWrite32 ( I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x40);//100K\r
+ *I2cMode |= V_SPEED_STANDARD;\r
+ break;\r
+ case 400 * 1000:\r
+ I2CLibPeiMmioWrite32 ( I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x32);//400K\r
+ *I2cMode |= V_SPEED_FAST;\r
+ break;\r
+ default:\r
+ I2CLibPeiMmioWrite32 ( I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x09);//3.4M\r
+ *I2cMode |= V_SPEED_HIGH;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initializes the host controller to execute I2C commands.\r
+\r
+ @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device. \r
+ \r
+ @return EFI_SUCCESS Opcode initialization on the I2C host controller completed.\r
+ @return EFI_DEVICE_ERROR Device error, operation failed.\r
+**/\r
+EFI_STATUS\r
+I2CInit (\r
+ UINT8 I2cControllerIndex, \r
+ UINT16 SlaveAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 NumTries = 0;\r
+ UINTN I2CBaseAddress;\r
+ UINT16 I2cMode;\r
+ UINTN PciMmBase=0;\r
+\r
+\r
+ PciMmBase = MmPciAddress (\r
+ 0,\r
+ DEFAULT_PCI_BUS_NUMBER_PCH,\r
+ PCI_DEVICE_NUMBER_PCH_LPSS_I2C,\r
+ (I2cControllerIndex + 1),\r
+ 0\r
+ );\r
+\r
+ I2CBaseAddress = I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR);\r
+\r
+ //\r
+ // Verify the parameters\r
+ //\r
+ if (1023 < SlaveAddress ) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ DEBUG((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ if(I2CBaseAddress == (PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ ProgramPciLpssI2C();\r
+\r
+ I2CBaseAddress = (UINT32) (PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE);\r
+ DEBUG ((EFI_D_ERROR, "I2CBaseAddress = 0x%x \n",I2CBaseAddress));\r
+ NumTries = 10000; // 1 seconds\r
+ while ((1 == ( I2CLibPeiMmioRead32 ( I2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) {\r
+ MicroSecondDelay(10);\r
+ NumTries --;\r
+ if(0 == NumTries)\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = I2cDisable (I2cControllerIndex);\r
+ DEBUG((EFI_D_INFO, "I2cDisable Status = %r\r\n", Status));\r
+\r
+ I2cBusFrequencySet(I2CBaseAddress, 400 * 1000, &I2cMode);//Set I2cMode\r
+\r
+ I2CLibPeiMmioWrite16(I2CBaseAddress + R_IC_INTR_MASK, 0x0);\r
+ if (0x7F < SlaveAddress) {\r
+ SlaveAddress = (SlaveAddress & 0x3ff ) | IC_TAR_10BITADDR_MASTER;\r
+ }\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TAR, (UINT16) SlaveAddress );\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_RX_TL, 0);\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TX_TL, 0 );\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_CON, I2cMode);\r
+\r
+ Status = I2cEnable(I2cControllerIndex);\r
+ DEBUG((EFI_D_INFO, "I2cEnable Status = %r\r\n", Status));\r
+ I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_CLR_TX_ABRT );\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Reads a Byte from I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be read\r
+ @param Offset Offset from which the data has to be read\r
+ @param *Byte Address to which the value read has to be stored\r
+ \r
+ @return EFI_SUCCESS If the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS ByteReadI2CBasic(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINTN ReadBytes,\r
+ OUT UINT8 *ReadBuffer,\r
+ IN UINT8 Start,\r
+ IN UINT8 End\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ UINT32 I2cStatus;\r
+ UINT16 ReceiveData;\r
+ UINT8 *ReceiveDataEnd;\r
+ UINT8 *ReceiveRequest;\r
+ UINT16 RawIntrStat;\r
+ UINTN I2CBaseAddress;\r
+\r
+ I2CBaseAddress = (UINT32)(PEI_TEPM_LPSS_I2C0_BAR + I2cControllerIndex * PCI_CONFIG_SPACE_SIZE);\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ I2CInit(I2cControllerIndex, SlaveAddress);\r
+\r
+ ReceiveDataEnd = &ReadBuffer [ReadBytes];\r
+ if(ReadBytes) {\r
+ ReceiveRequest = ReadBuffer;\r
+ DEBUG((EFI_D_INFO,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd - ReceiveRequest));\r
+\r
+ while ((ReceiveDataEnd > ReceiveRequest) || (ReceiveDataEnd > ReadBuffer)) {\r
+ //\r
+ // Check for NACK\r
+ //\r
+ RawIntrStat = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RawIntrStat );\r
+ if ( 0 != (RawIntrStat & I2C_INTR_TX_ABRT )) {\r
+ I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_CLR_TX_ABRT );\r
+ Status = RETURN_DEVICE_ERROR;\r
+ DEBUG((EFI_D_INFO,"TX ABRT ,%d bytes hasn't been transferred\r\n",ReceiveDataEnd - ReceiveRequest));\r
+ break;\r
+ }\r
+ \r
+ //\r
+ // Determine if another byte was received\r
+ //\r
+ I2cStatus = I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_STATUS );\r
+ if ( 0 != ( I2cStatus & STAT_RFNE )) {\r
+ ReceiveData = I2CLibPeiMmioRead16 ( I2CBaseAddress + R_IC_DATA_CMD );\r
+ *ReadBuffer++ = (UINT8)ReceiveData;\r
+ DEBUG((EFI_D_INFO,"MmioRead32 ,1 byte 0x:%x is received\r\n",ReceiveData));\r
+ }\r
+\r
+ if(ReceiveDataEnd==ReceiveRequest) {\r
+ //\r
+ // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.\r
+ //\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Wait until a read request will fit\r
+ //\r
+ if ( 0 == ( I2cStatus & STAT_TFNF )) {\r
+ MicroSecondDelay ( 10 );\r
+ continue;\r
+ }\r
+ \r
+ //\r
+ // Issue the next read request\r
+ //\r
+ if(End && Start ) {\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART|B_CMD_STOP);\r
+ } else if (!End && Start ) {\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART);\r
+ } else if (End && !Start ) {\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_STOP);\r
+ } else if (!End && !Start ) {\r
+ I2CLibPeiMmioWrite16 ( I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD);\r
+ }\r
+ ReceiveRequest += 1;\r
+ }\r
+\r
+ }\r
+ return Status;\r
+\r
+}\r
+\r
+/**\r
+ Writes a Byte to I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be written\r
+ @param Offset Offset from which the data has to be read\r
+ @param *Byte Address to which the value written is stored\r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully written\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS \r
+ByteWriteI2CBasic(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINTN WriteBytes,\r
+ IN UINT8 *WriteBuffer,\r
+ IN UINT8 Start,\r
+ IN UINT8 End\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ UINT32 I2cStatus;\r
+ UINT8 *TransmitEnd;\r
+ UINT16 RawIntrStat;\r
+ UINTN I2CBaseAddress;\r
+\r
+ I2CBaseAddress = (UINT32)PEI_TEPM_LPSS_I2C0_BAR+ I2cControllerIndex * PCI_CONFIG_SPACE_SIZE;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ I2CInit(I2cControllerIndex, SlaveAddress);\r
+\r
+ TransmitEnd = &WriteBuffer [WriteBytes];\r
+ if( WriteBytes ) {\r
+\r
+ DEBUG((EFI_D_INFO,"Write: --------------%d bytes to TX\r\n", TransmitEnd - WriteBuffer));\r
+\r
+ while ( TransmitEnd > WriteBuffer) {\r
+ I2cStatus = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_STATUS);\r
+ RawIntrStat = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RawIntrStat);\r
+ if ( 0 != (RawIntrStat & I2C_INTR_TX_ABRT)) {\r
+ I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_CLR_TX_ABRT);\r
+ Status = RETURN_DEVICE_ERROR;\r
+ DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));\r
+ break;\r
+ }\r
+ if (0 == ( I2cStatus & STAT_TFNF)) {\r
+ continue;\r
+ }\r
+ if(End && Start) {\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++) | B_CMD_RESTART | B_CMD_STOP);\r
+ } else if (!End && Start ) {\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++) | B_CMD_RESTART);\r
+ } else if (End && !Start ) {\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++) | B_CMD_STOP);\r
+ } else if (!End && !Start ) {\r
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++));\r
+ }\r
+ \r
+ // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped.\r
+ MicroSecondDelay ( FIFO_WRITE_DELAY );\r
+ }\r
+\r
+ }\r
+ \r
+ if(EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n",Status));\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+ Reads a Byte from I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be read\r
+ @param Offset Offset from which the data has to be read\r
+ @param ReadBytes Number of bytes to be read\r
+ @param *ReadBuffer Address to which the value read has to be stored\r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS \r
+ByteReadI2C(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINT8 Offset,\r
+ IN UINTN ReadBytes,\r
+ OUT UINT8 *ReadBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((EFI_D_ERROR, "ByteReadI2C:---offset:0x%x\n",Offset));\r
+ Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress, 1, &Offset,TRUE,FALSE);\r
+ Status = ByteReadI2CBasic(I2cControllerIndex, SlaveAddress, ReadBytes, ReadBuffer, TRUE, TRUE);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Writes a Byte to I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be written\r
+ @param Offset Offset from which the data has to be written\r
+ @param WriteBytes Number of bytes to be written\r
+ @param *Byte Address to which the value written is stored\r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS ByteWriteI2C(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINT8 Offset,\r
+ IN UINTN WriteBytes,\r
+ IN UINT8 *WriteBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((EFI_D_ERROR, "ByteWriteI2C:---offset/bytes/buf:0x%x,0x%x,0x%x,0x%x\n",Offset,WriteBytes,WriteBuffer,*WriteBuffer));\r
+ Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress, 1, &Offset, TRUE, FALSE);\r
+ Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress, WriteBytes, WriteBuffer, FALSE, TRUE);\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/** @file\r
+ I2C PEI Lib Instance.\r
+\r
+ Copyright (c) 1999- 2015, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef I2C_PEI_REGS_H\r
+#define I2C_PEI_REGS_H\r
+\r
+#include "PiPei.h"\r
+\r
+#define R_PCH_LPC_PMC_BASE 0x44\r
+#define B_PCH_LPC_PMC_BASE_BAR 0xFFFFFE00\r
+#define R_PCH_PMC_FUNC_DIS 0x34 // Function Disable Register\r
+#define PCIEX_BASE_ADDRESS 0xE0000000\r
+#define PciD31F0RegBase PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC7 BIT7 // LPSS SPI Disable\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC6 BIT6 // LPSS HSUART #2 Disable\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC5 BIT5 // LPSS HSUART #1 Disable\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC4 BIT4 // LPSS I2S Disable\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC3 BIT3 // LPSS PCM Disable\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC2 BIT2 // LPSS I2C #2 Disable\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC1 BIT1 // LPSS I2C #1 Disable\r
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC0 BIT0 // LPSS DMA Disable\r
+\r
+\r
+#define DEFAULT_PCI_BUS_NUMBER_PCH 0\r
+\r
+#define R_PCH_LPSS_I2C_STSCMD 0x04 // Status & Command\r
+#define B_PCH_LPSS_I2C_STSCMD_RMA BIT29 // RMA\r
+#define B_PCH_LPSS_I2C_STSCMD_RCA BIT28 // RCA\r
+#define B_PCH_LPSS_I2C_STSCMD_CAPLIST BIT20 // Capability List\r
+#define B_PCH_LPSS_I2C_STSCMD_INTRSTS BIT19 // Interrupt Status\r
+#define B_PCH_LPSS_I2C_STSCMD_INTRDIS BIT10 // Interrupt Disable\r
+#define B_PCH_LPSS_I2C_STSCMD_SERREN BIT8 // SERR# Enable\r
+#define B_PCH_LPSS_I2C_STSCMD_BME BIT2 // Bus Master Enable\r
+#define B_PCH_LPSS_I2C_STSCMD_MSE BIT1 // Memory Space Enable\r
+\r
+#define R_PCH_LPSS_I2C_BAR 0x10 // BAR\r
+#define B_PCH_LPSS_I2C_BAR_BA 0xFFFFF000 // Base Address\r
+#define B_PCH_LPSS_I2C_BAR_SI 0x00000FF0 // Size Indicator\r
+#define B_PCH_LPSS_I2C_BAR_PF BIT3 // Prefetchable\r
+#define B_PCH_LPSS_I2C_BAR_TYPE (BIT2 | BIT1) // Type\r
+#define B_PCH_LPSS_I2C_BAR_MS BIT0 // Message Space\r
+\r
+#define R_PCH_LPSS_I2C_BAR1 0x14 // BAR 1\r
+#define B_PCH_LPSS_I2C_BAR1_BA 0xFFFFF000 // Base Address\r
+#define B_PCH_LPSS_I2C_BAR1_SI 0x00000FF0 // Size Indicator\r
+#define B_PCH_LPSS_I2C_BAR1_PF BIT3 // Prefetchable\r
+#define B_PCH_LPSS_I2C_BAR1_TYPE (BIT2 | BIT1) // Type\r
+#define B_PCH_LPSS_I2C_BAR1_MS BIT0 // Message Space\r
+\r
+#define NUM_RETRIES 0xFFFF\r
+\r
+//\r
+// LPIO I2C Module Memory Space Registers\r
+//\r
+#define R_PCH_LPIO_I2C_MEM_RESETS 0x804 // Software Reset\r
+#define B_PCH_LPIO_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset\r
+#define B_PCH_LPIO_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset\r
+\r
+#define R_PCH_LPSS_I2C_MEM_PCP 0x800 // Private Clock Parameters\r
+\r
+#define bit(a) 1 << (a)\r
+\r
+//\r
+// MMIO Register Definitions\r
+//\r
+\r
+#define I2C0_REG_SPACE_ADDR_BASE 0xFF138000 //01K\r
+\r
+#define R_IC_CON ( 0x00) // I2C Control\r
+#define B_IC_RESTART_EN BIT5\r
+#define B_IC_SLAVE_DISABLE BIT6\r
+#define V_SPEED_STANDARD 0x02\r
+#define V_SPEED_FAST 0x04\r
+#define V_SPEED_HIGH 0x06\r
+#define B_MASTER_MODE BIT0\r
+\r
+#define R_IC_TAR ( 0x04) // I2C Target Address\r
+#define IC_TAR_10BITADDR_MASTER BIT12\r
+\r
+#define R_IC_SAR ( 0x08) // I2C Slave Address\r
+#define R_IC_HS_MADDR ( 0x0C) // I2C HS MasterMode Code Address\r
+#define R_IC_DATA_CMD ( 0x10) // I2C Rx/Tx Data Buffer and Command\r
+\r
+#define B_READ_CMD BIT8 // 1 = read, 0 = write\r
+#define B_CMD_STOP BIT9 // 1 = STOP\r
+#define B_CMD_RESTART BIT10 // 1 = IC_RESTART_EN\r
+\r
+#define V_WRITE_CMD_MASK ( 0xFF)\r
+\r
+#define R_IC_SS_SCL_HCNT ( 0x14) // Standard Speed I2C Clock SCL High Count\r
+#define R_IC_SS_SCL_LCNT ( 0x18) // Standard Speed I2C Clock SCL Low Count\r
+#define R_IC_FS_SCL_HCNT ( 0x1C) // Full Speed I2C Clock SCL High Count\r
+#define R_IC_FS_SCL_LCNT ( 0x20) // Full Speed I2C Clock SCL Low Count\r
+#define R_IC_HS_SCL_HCNT ( 0x24) // High Speed I2C Clock SCL High Count\r
+#define R_IC_HS_SCL_LCNT ( 0x28) // High Speed I2C Clock SCL Low Count\r
+#define R_IC_INTR_STAT ( 0x2C) // I2C Inetrrupt Status\r
+#define R_IC_INTR_MASK ( 0x30) // I2C Interrupt Mask\r
+#define I2C_INTR_GEN_CALL BIT11 // General call received\r
+#define I2C_INTR_START_DET BIT10\r
+#define I2C_INTR_STOP_DET BIT9\r
+#define I2C_INTR_ACTIVITY BIT8\r
+#define I2C_INTR_TX_ABRT BIT6 // Set on NACK\r
+#define I2C_INTR_TX_EMPTY BIT4\r
+#define I2C_INTR_TX_OVER BIT3\r
+#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold\r
+#define I2C_INTR_RX_OVER BIT1\r
+#define I2C_INTR_RX_UNDER BIT0\r
+#define R_IC_RawIntrStat ( 0x34) // I2C Raw Interrupt Status\r
+#define R_IC_RX_TL ( 0x38) // I2C Receive FIFO Threshold\r
+#define R_IC_TX_TL ( 0x3C) // I2C Transmit FIFO Threshold\r
+#define R_IC_CLR_INTR ( 0x40) // Clear Combined and Individual Interrupts\r
+#define R_IC_CLR_RX_UNDER ( 0x44) // Clear RX_UNDER Interrupt\r
+#define R_IC_CLR_RX_OVER ( 0x48) // Clear RX_OVERinterrupt\r
+#define R_IC_CLR_TX_OVER ( 0x4C) // Clear TX_OVER interrupt\r
+#define R_IC_CLR_RD_REQ ( 0x50) // Clear RD_REQ interrupt\r
+#define R_IC_CLR_TX_ABRT ( 0x54) // Clear TX_ABRT interrupt\r
+#define R_IC_CLR_RX_DONE ( 0x58) // Clear RX_DONE interrupt\r
+#define R_IC_CLR_ACTIVITY ( 0x5C) // Clear ACTIVITY interrupt\r
+#define R_IC_CLR_STOP_DET ( 0x60) // Clear STOP_DET interrupt\r
+#define R_IC_CLR_START_DET ( 0x64) // Clear START_DET interrupt\r
+#define R_IC_CLR_GEN_CALL ( 0x68) // Clear GEN_CALL interrupt\r
+#define R_IC_ENABLE ( 0x6C) // I2C Enable\r
+#define R_IC_STATUS ( 0x70) // I2C Status\r
+\r
+#define R_IC_SDA_HOLD ( 0x7C) // I2C IC_DEFAULT_SDA_HOLD//16bits\r
+\r
+#define STAT_MST_ACTIVITY BIT5 // Master FSM Activity Status.\r
+#define STAT_RFF BIT4 // RX FIFO is completely full\r
+#define STAT_RFNE BIT3 // RX FIFO is not empty\r
+#define STAT_TFE BIT2 // TX FIFO is completely empty\r
+#define STAT_TFNF BIT1 // TX FIFO is not full\r
+\r
+#define R_IC_TXFLR ( 0x74) // Transmit FIFO Level Register\r
+#define R_IC_RXFLR ( 0x78) // Receive FIFO Level Register\r
+#define R_IC_TX_ABRT_SOURCE ( 0x80) // I2C Transmit Abort Status Register\r
+#define R_IC_SLV_DATA_NACK_ONLY ( 0x84) // Generate SLV_DATA_NACK Register\r
+#define R_IC_DMA_CR ( 0x88) // DMA Control Register\r
+#define R_IC_DMA_TDLR ( 0x8C) // DMA Transmit Data Level\r
+#define R_IC_DMA_RDLR ( 0x90) // DMA Receive Data Level\r
+#define R_IC_SDA_SETUP ( 0x94) // I2C SDA Setup Register\r
+#define R_IC_ACK_GENERAL_CALL ( 0x98) // I2C ACK General Call Register\r
+#define R_IC_ENABLE_STATUS ( 0x9C) // I2C Enable Status Register\r
+#define R_IC_COMP_PARAM ( 0xF4) // Component Parameter Register\r
+#define R_IC_COMP_VERSION ( 0xF8) // Component Version ID\r
+#define R_IC_COMP_TYPE ( 0xFC) // Component Type\r
+\r
+#define I2C_SS_SCL_HCNT_VALUE_100M 0x1DD\r
+#define I2C_SS_SCL_LCNT_VALUE_100M 0x1E4\r
+#define I2C_FS_SCL_HCNT_VALUE_100M 0x54\r
+#define I2C_FS_SCL_LCNT_VALUE_100M 0x9a\r
+#define I2C_HS_SCL_HCNT_VALUE_100M 0x7\r
+#define I2C_HS_SCL_LCNT_VALUE_100M 0xE\r
+\r
+//\r
+// FIFO write workaround value.\r
+//\r
+#define FIFO_WRITE_DELAY 2\r
+#define IC_TAR_10BITADDR_MASTER BIT12\r
+#define FIFO_SIZE 32\r
+#define R_IC_INTR_STAT ( 0x2C) // I2c Inetrrupt Status\r
+#define R_IC_INTR_MASK ( 0x30) // I2c Interrupt Mask\r
+#define I2C_INTR_GEN_CALL BIT11 // General call received\r
+#define I2C_INTR_START_DET BIT10\r
+#define I2C_INTR_STOP_DET BIT9\r
+#define I2C_INTR_ACTIVITY BIT8\r
+#define I2C_INTR_TX_ABRT BIT6 // Set on NACK\r
+#define I2C_INTR_TX_EMPTY BIT4\r
+#define I2C_INTR_TX_OVER BIT3\r
+#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold\r
+#define I2C_INTR_RX_OVER BIT1\r
+#define I2C_INTR_RX_UNDER BIT0\r
+\r
+/**\r
+ Programe all I2C controllers on LPSS. \r
+ \r
+ I2C0 is function 1 of LPSS. I2C1 is function 2 of LPSS, etc..\r
+\r
+ @param VOID\r
+\r
+ @return EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+ProgramPciLpssI2C (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Reads a Byte from I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be read\r
+ @param Offset Offset from which the data has to be read\r
+ @param *Byte Address to which the value read has to be stored\r
+ @param Start Whether a RESTART is issued before the byte is sent or received\r
+ @param End Whether STOP is generated after a data byte is sent or received \r
+ \r
+ @return EFI_SUCCESS If the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS\r
+ByteReadI2CBasic(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINTN ReadBytes,\r
+ OUT UINT8 *ReadBuffer,\r
+ IN UINT8 Start,\r
+ IN UINT8 End\r
+ );\r
+\r
+/**\r
+ Writes a Byte to I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be written\r
+ @param Offset Offset from which the data has to be read\r
+ @param *Byte Address to which the value written is stored\r
+ @param Start Whether a RESTART is issued before the byte is sent or received\r
+ @param End Whether STOP is generated after a data byte is sent or received \r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully written\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS\r
+ByteWriteI2CBasic(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINTN WriteBytes,\r
+ IN UINT8 *WriteBuffer,\r
+ IN UINT8 Start,\r
+ IN UINT8 End\r
+ );\r
+\r
+/**\r
+ Reads a Byte from I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be read\r
+ @param Offset Offset from which the data has to be read\r
+ @param ReadBytes Number of bytes to be read\r
+ @param *ReadBuffer Address to which the value read has to be stored\r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS\r
+ByteReadI2C(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINT8 Offset,\r
+ IN UINTN ReadBytes,\r
+ OUT UINT8 *ReadBuffer\r
+ );\r
+\r
+/**\r
+ Writes a Byte to I2C Device.\r
+ \r
+ @param I2cControllerIndex I2C Bus no to which the I2C device has been connected\r
+ @param SlaveAddress Device Address from which the byte value has to be written\r
+ @param Offset Offset from which the data has to be written\r
+ @param WriteBytes Number of bytes to be written\r
+ @param *Byte Address to which the value written is stored\r
+ \r
+ @return EFI_SUCCESS IF the byte value has been successfully read\r
+ @return EFI_DEVICE_ERROR Operation Failed, Device Error\r
+**/\r
+EFI_STATUS\r
+ByteWriteI2C(\r
+ IN UINT8 I2cControllerIndex,\r
+ IN UINT8 SlaveAddress,\r
+ IN UINT8 Offset,\r
+ IN UINTN WriteBytes,\r
+ IN UINT8 *WriteBuffer\r
+ );\r
+\r
+#endif\r
--- /dev/null
+## @file\r
+# Instance of I2C Library.\r
+#\r
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = I2CLibPei\r
+ FILE_GUID = 8EF61509-890B-4FF2-B352-1C0E9CDDEC8B\r
+ MODULE_TYPE = PEIM\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = LockBoxLib|PEIM\r
+ CONSTRUCTOR = IntelI2CPeiLibConstructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ I2CLibPei.c\r
+ I2CIoLibPei.c\r
+\r
+[LibraryClasses]\r
+ TimerLib\r
+\r
+[PPIs]\r
+ gEfiPeiStallPpiGuid\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ Vlv2DeviceRefCodePkg/Vlv2DeviceRefCodePkg.dec\r
+\r
+\r