summaryrefslogtreecommitdiff
path: root/ChvRefCodePkg
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-06-02 13:54:41 +0800
committerHao Wu <hao.a.wu@intel.com>2016-06-07 09:55:38 +0800
commit7fb6833abbc05a81976ac0f0507e406749b35154 (patch)
treec40fff9eaf86ffc6d1059382f4cbf288cfb7f880 /ChvRefCodePkg
parent2998c3474aabe1fb17d88292376d612b44c81f74 (diff)
downloadedk2-platforms-7fb6833abbc05a81976ac0f0507e406749b35154.tar.xz
ChvRefCodePkg: Add I2CLibPei.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'ChvRefCodePkg')
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CAccess.h54
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.c52
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.h35
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c174
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h136
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.c820
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.h282
-rw-r--r--ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.inf50
8 files changed, 1603 insertions, 0 deletions
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CAccess.h b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CAccess.h
new file mode 100644
index 0000000000..5d32d4922c
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CAccess.h
@@ -0,0 +1,54 @@
+/** @file
+ Macros that simplify accessing PCH devices's PCI registers.
+ ** NOTE ** these macros assume the PCH device is on BUS 0
+
+ Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _I2C_ACCESS_H_
+#define _I2C_ACCESS_H_
+
+///
+/// Memory Mapped PCI Access macros
+///
+
+#include "I2CIoLibPei.h"
+
+#define DEFAULT_PCI_BUS_NUMBER_PCH 0
+
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define PCI_FUNCTION_NUMBER_PCH_LPC 0
+
+#define R_PCH_LPC_ACPI_BASE 0x40 // ABASE, 16bit
+#define R_PCH_LPC_ACPI_BASEADR 0x400 // ABASE, 16bit
+#define B_PCH_LPC_ACPI_BASE_EN BIT1 // Enable Bit
+#define B_PCH_LPC_ACPI_BASE_BAR 0x0000FF80 // Base Address, 128 Bytes
+#define V_PCH_ACPI_PM1_TMR_MAX_VAL 0x1000000 // The timer is 24 bit overflow
+#define B_PCH_ACPI_PM1_TMR_VAL 0xFFFFFF // The timer value mask
+
+#define R_PCH_ACPI_PM1_TMR 0x08 // Power Management 1 Timer
+#define V_PCH_ACPI_PM1_TMR_FREQUENCY 3579545 // Timer Frequency
+
+#define PchLpcPciCfg8(Register) I2CLibPeiMmioRead8 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, Register))
+
+#define PCIEX_BASE_ADDRESS 0xE0000000
+#define PCI_EXPRESS_BASE_ADDRESS ((VOID *) (UINTN) PCIEX_BASE_ADDRESS)
+
+#define MmPciAddress( Segment, Bus, Device, Function, Register ) \
+ ( (UINTN)PCI_EXPRESS_BASE_ADDRESS + \
+ (UINTN)(Bus << 20) + \
+ (UINTN)(Device << 15) + \
+ (UINTN)(Function << 12) + \
+ (UINTN)(Register) \
+ )
+#endif
+
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.c b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.c
new file mode 100644
index 0000000000..ee7fda6631
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.c
@@ -0,0 +1,52 @@
+/** @file
+ ICH9 ACPI Timer implements one instance of Timer Library.
+
+ Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PiPei.h"
+#include "I2CAccess.h"
+#include "I2CDelayPei.h"
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Ppi/Stall.h>
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param[in] MicroSeconds The minimum number of microseconds to delay.
+
+ @return MicroSeconds
+
+**/
+EFI_STATUS
+EFIAPI
+I2CMicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+
+ EFI_PEI_STALL_PPI *StallPpi;
+ EFI_STATUS Status;
+ CONST EFI_PEI_SERVICES **PeiServices;
+
+ PeiServices = GetPeiServicesTablePointer ();
+
+ Status = (**PeiServices).LocatePpi (PeiServices, &gEfiPeiStallPpiGuid, 0, NULL, (void **) &StallPpi);
+ ASSERT(!EFI_ERROR(Status));
+
+ StallPpi->Stall (PeiServices, StallPpi, MicroSeconds);
+
+ return EFI_SUCCESS;
+}
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.h b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.h
new file mode 100644
index 0000000000..c6352adf3d
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CDelayPei.h
@@ -0,0 +1,35 @@
+/** @file
+ ICH9 ACPI Timer implements one instance of Timer Library.
+
+ Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __I2C_DELAY_PEI__
+
+#define __I2C_DELAY_PEI__
+#include "PiPei.h"
+
+/**
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param[in] MicroSeconds The minimum number of microseconds to delay.
+
+ @return MicroSeconds
+
+**/
+EFI_STATUS
+EFIAPI
+I2CMicroSecondDelay (
+ IN UINTN MicroSeconds
+ );
+
+#endif
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c
new file mode 100644
index 0000000000..ecacffc4be
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c
@@ -0,0 +1,174 @@
+/** @file
+ I/O Library. The implementations are based on EFI_PEI_SERVICE->CpuIo interface.
+
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+
+/**
+ Reads an 8-bit MMIO register.
+
+ Reads the 8-bit MMIO register specified by Address. The 8-bit read value is
+ returned. This function must guarantee that all MMIO read and write
+ operations are serialized.
+
+ If 8-bit MMIO register operations are not supported, then ASSERT().
+
+ @param[in] Address The MMIO register to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+I2CLibPeiMmioRead8 (
+ IN UINTN Address
+ )
+{
+ UINT8 Value;
+
+ Value = *(volatile UINT8*)Address;
+ return Value;
+}
+
+/**
+ Reads a 16-bit MMIO register.
+
+ Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
+ returned. This function must guarantee that all MMIO read and write
+ operations are serialized.
+
+ If 16-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to read.
+
+ @return The value read.
+
+**/
+UINT16
+EFIAPI
+I2CLibPeiMmioRead16 (
+ IN UINTN Address
+ )
+{
+ UINT16 Value;
+
+ ASSERT ((Address & 1) == 0);
+ Value = *(volatile UINT16*)Address;
+ return Value;
+}
+
+/**
+ Writes a 16-bit MMIO register.
+
+ Writes the 16-bit MMIO register specified by Address with the value specified
+ by Value and returns Value. This function must guarantee that all MMIO read
+ and write operations are serialized.
+
+ If 16-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to write.
+ @param[in] Value The value to write to the MMIO register.
+
+ @return Value.
+
+**/
+UINT16
+EFIAPI
+I2CLibPeiMmioWrite16 (
+ IN UINTN Address,
+ IN UINT16 Value
+ )
+{
+ ASSERT ((Address & 1) == 0);
+ *(volatile UINT16*)Address = Value;
+
+ return Value;
+}
+
+/**
+ Reads a 32-bit MMIO register.
+
+ Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
+ returned. This function must guarantee that all MMIO read and write
+ operations are serialized.
+
+ If 32-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to read.
+
+ @return The value read.
+
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioRead32 (
+ IN UINTN Address
+ )
+{
+ UINT32 Value;
+
+ ASSERT ((Address & 3) == 0);
+ Value = *(volatile UINT32*)Address;
+
+ return Value;
+}
+
+/**
+ Writes a 32-bit MMIO register.
+
+ Writes the 32-bit MMIO register specified by Address with the value specified
+ by Value and returns Value. This function must guarantee that all MMIO read
+ and write operations are serialized.
+
+ If 32-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to write.
+ @param[in] Value The value to write to the MMIO register.
+
+ @return Value.
+
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioWrite32 (
+ IN UINTN Address,
+ IN UINT32 Value
+ )
+{
+ ASSERT ((Address & 3) == 0);
+ *(volatile UINT32*)Address = Value;
+
+ return Value;
+}
+
+/**
+ @todo add description
+
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioOr32 (
+ IN UINTN Address,
+ IN UINT32 OrData
+ )
+{
+ return I2CLibPeiMmioWrite32 (Address, I2CLibPeiMmioRead32 (Address) | OrData);
+}
+
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h
new file mode 100644
index 0000000000..c5473667a6
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h
@@ -0,0 +1,136 @@
+/** @file
+ I/O Library. The implementations are based on EFI_PEI_SERVICE->CpuIo interface.
+
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __I2C_IOLIB_PEI__
+
+#define __I2C_IOLIB_PEI__
+#include <PiPei.h>
+
+/**
+ Reads an 8-bit MMIO register.
+
+ Reads the 8-bit MMIO register specified by Address. The 8-bit read value is
+ returned. This function must guarantee that all MMIO read and write
+ operations are serialized.
+
+ If 8-bit MMIO register operations are not supported, then ASSERT().
+
+ @param[in] Address The MMIO register to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+I2CLibPeiMmioRead8 (
+ IN UINTN Address
+ );
+
+/**
+ Reads a 16-bit MMIO register.
+
+ Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
+ returned. This function must guarantee that all MMIO read and write
+ operations are serialized.
+
+ If 16-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to read.
+
+ @return The value read.
+
+**/
+UINT16
+EFIAPI
+I2CLibPeiMmioRead16 (
+ IN UINTN Address
+ );
+
+/**
+ Writes a 16-bit MMIO register.
+
+ Writes the 16-bit MMIO register specified by Address with the value specified
+ by Value and returns Value. This function must guarantee that all MMIO read
+ and write operations are serialized.
+
+ If 16-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to write.
+ @param[in] Value The value to write to the MMIO register.
+
+ @return Value.
+
+**/
+UINT16
+EFIAPI
+I2CLibPeiMmioWrite16 (
+ IN UINTN Address,
+ IN UINT16 Value
+ );
+
+/**
+ Reads a 32-bit MMIO register.
+
+ Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
+ returned. This function must guarantee that all MMIO read and write
+ operations are serialized.
+
+ If 32-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to read.
+
+ @return The value read.
+
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioRead32 (
+ IN UINTN Address
+ );
+
+/**
+ Writes a 32-bit MMIO register.
+
+ Writes the 32-bit MMIO register specified by Address with the value specified
+ by Value and returns Value. This function must guarantee that all MMIO read
+ and write operations are serialized.
+
+ If 32-bit MMIO register operations are not supported, then ASSERT().
+ If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+ @param[in] Address The MMIO register to write.
+ @param[in] Value The value to write to the MMIO register.
+
+ @return Value.
+
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioWrite32 (
+ IN UINTN Address,
+ IN UINT32 Value
+ );
+
+UINT32
+EFIAPI
+I2CLibPeiMmioOr32 (
+ IN UINTN Address,
+ IN UINT32 OrData
+ );
+
+#endif
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.c b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.c
new file mode 100644
index 0000000000..7d490e35bc
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.c
@@ -0,0 +1,820 @@
+/** @file
+
+ Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "I2CDelayPei.h"
+#include "I2CIoLibPei.h"
+#include "I2CAccess.h"
+#include "I2CLibPei.h"
+#include <PlatformBaseAddresses.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/HobLib.h>
+#include <PchRegs/PchRegsPcu.h>
+#include <PchRegs/PchRegsLpss.h>
+
+EFI_GUID mI2CPeiInitGuid = {
+ 0x96DED71A, 0xB9E7, 0x4EAD, {0x96, 0x2C, 0x01, 0x69, 0x3C, 0xED, 0x2A, 0x64}
+};
+
+typedef struct _LPSS_PCI_DEVICE_INFO {
+ UINTN Segment;
+ UINTN BusNum;
+ UINTN DeviceNum;
+ UINTN FunctionNum;
+ UINTN Bar0;
+ UINTN Bar1;
+} LPSS_PCI_DEVICE_INFO;
+
+LPSS_PCI_DEVICE_INFO mLpssPciDeviceList[] = {
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_DMAC1, PCI_FUNCTION_NUMBER_PCH_LPSS_DMAC, 0xFE900000, 0xFE908000},
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C0, 0xFE910000, 0xFE918000},
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C1, 0xFE920000, 0xFE928000},
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C2, 0xFE930000, 0xFE938000},
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C3, 0xFE940000, 0xFE948000},
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C4, 0xFE950000, 0xFE958000},
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C5, 0xFE960000, 0xFE968000},
+ {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C, PCI_FUNCTION_NUMBER_PCH_LPSS_I2C6, 0xFE970000, 0xFE978000}
+};
+#define LPSS_PCI_DEVICE_NUMBER sizeof(mLpssPciDeviceList)/sizeof(LPSS_PCI_DEVICE_INFO)
+
+#define R_PCH_LPIO_I2C_MEM_RESETS 0x804 // Software Reset
+#define B_PCH_LPIO_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset
+#define B_PCH_LPIO_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset
+
+/**
+ @todo add description
+
+**/
+EFI_STATUS
+EFIAPI
+IntelI2CPeiLibConstructor (
+ VOID
+ )
+{
+ //
+ // LPSS I2C0
+ // I2C0_SCL - IOBASE + 0x05428 [31:0] = 0x00C10300
+ // I2C0_SDA - IOBASE + 0x05408 [31:0] = 0x00C10300
+ //
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05428, 0x00C10300);
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05408, 0x00C10300);
+ //
+ // LPSS I2C1
+ // I2C1_SCL - IOBASE + 0x05418 [31:0] = 0x00910300
+ // I2C1_SDA - IOBASE + 0x05400 [31:0] = 0x00910300
+ //
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05418, 0x00910300);
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05400, 0x00910300);
+ //
+ // LPSS I2C2
+ // I2C2_SCL - IOBASE + 0x05430 [31:0] = 0x00910300
+ // I2C2_SDA - IOBASE + 0x05410 [31:0] = 0x00910300
+ //
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05430, 0x00910300);
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05410, 0x00910300);
+ //
+ // LPSS I2C3
+ // I2C3_SCL - IOBASE + 0x05438 [31:0] = 0x00910300
+ // I2C3_SDA - IOBASE + 0x05420 [31:0] = 0x00910300
+ //
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05438, 0x00910300);
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05420, 0x00910300);
+ //
+ // LPSS I2C4
+ // I2C4_SCL - IOBASE + 0x05028 [31:0] = 0x00910300
+ // I2C4_SDA - IOBASE + 0x05008 [31:0] = 0x00910300
+ //
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05028, 0x00910300);
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05008, 0x00910300);
+ //
+ // LPSS I2C5
+ // I2C5_SCL - IOBASE + 0x05018 [31:0] = 0x00910300
+ // I2C5_SDA - IOBASE + 0x05000 [31:0] = 0x00910300
+ //
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05018, 0x00910300);
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05000, 0x00910300);
+ //
+ // LPSS I2C6
+ // I2C6_SCL - IOBASE + 0x05030 [31:0] = 0x00910300
+ // I2C6_SDA - IOBASE + 0x05010 [31:0] = 0x00910300
+ //
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05030, 0x00910300);
+ I2CLibPeiMmioWrite32 (IO_BASE_ADDRESS + 0x05010, 0x00910300);
+
+ return EFI_SUCCESS;
+}
+/**
+@todo add description
+
+**/
+EFI_STATUS
+ProgramAllPciLpssI2C (
+ VOID
+ )
+{
+ UINT8 i;
+ for (i =0; i<7; i++) {
+ ProgramPciLpssI2C (i);
+ }
+ DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssAllI2C() Done\n"));
+ return EFI_SUCCESS;
+}
+/**
+@todo add description
+
+**/
+EFI_STATUS
+ProgramPciLpssI2C (
+ IN UINT8 BusNo
+ )
+{
+ UINT32 PmcBase;
+ UINT32 DevID;
+ UINTN PciMmBase;
+
+ UINT32 PMC_DIS[]= {
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1,
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2,
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3,
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4,
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5,
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6,
+ B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7
+ };
+
+ DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() Start\n"));
+
+ PciMmBase = 0;
+ //
+ // Set the CHV Function Disable Register to ZERO
+ //
+ PmcBase = I2CLibPeiMmioRead32 (PciD31F0RegBase + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR;
+ if (I2CLibPeiMmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)&PMC_DIS[BusNo]) {
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() enable:I2C[%x]\n",BusNo));
+ I2CLibPeiMmioWrite32(
+ PmcBase+R_PCH_PMC_FUNC_DIS,
+ I2CLibPeiMmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)&(~PMC_DIS[BusNo])
+ );
+ }
+
+
+ PciMmBase = MmPciAddress (
+ mLpssPciDeviceList[BusNo+1].Segment,
+ mLpssPciDeviceList[BusNo+1].BusNum,
+ mLpssPciDeviceList[BusNo+1].DeviceNum,
+ mLpssPciDeviceList[BusNo+1].FunctionNum,
+ 0
+ );
+ DEBUG((EFI_D_ERROR, "Program Pci Lpss I2C Device %x %x %x PciMmBase:%x\n", \
+ mLpssPciDeviceList[BusNo+1].BusNum, \
+ mLpssPciDeviceList[BusNo+1].DeviceNum, \
+ mLpssPciDeviceList[BusNo+1].FunctionNum, PciMmBase));
+
+ //
+ // Check if device present
+ //
+
+ DevID = I2CLibPeiMmioRead32(PciMmBase);
+
+ if (DevID != 0xFFFFFFFF) {
+ if (!(I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_STSCMD)& B_PCH_LPSS_I2C_STSCMD_MSE)) {
+ //
+ // Program BAR 0
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR), (UINT32) (mLpssPciDeviceList[BusNo+1].Bar0 & B_PCH_LPSS_I2C_BAR_BA));
+ //
+ // Program BAR 1
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR1), (UINT32) (mLpssPciDeviceList[BusNo+1].Bar1 & B_PCH_LPSS_I2C_BAR1_BA));
+ //
+ // Bus Master Enable & Memory Space Enable
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_STSCMD), (UINT32) (B_PCH_LPSS_I2C_STSCMD_BME | B_PCH_LPSS_I2C_STSCMD_MSE));
+ //
+ // Release Resets
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (mLpssPciDeviceList[BusNo+1].Bar0 + R_PCH_LPIO_I2C_MEM_RESETS), (UINT32) (B_PCH_LPIO_I2C_MEM_RESETS_FUNC | B_PCH_LPIO_I2C_MEM_RESETS_APB));
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() End\n"));
+
+ return EFI_SUCCESS;
+}
+/**
+@todo add description
+
+**/
+EFI_STATUS
+I2cDisable (
+ IN UINT8 BusNo
+ )
+{
+ UINTN mI2CBaseAddress;
+ UINT32 NumTries = 10000; /* 0.1 seconds */
+ mI2CBaseAddress = mLpssPciDeviceList[BusNo+1].Bar0;
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_ENABLE, 0 );
+ while ( 0 != ( I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_ENABLE_STATUS ) & 1 )) {
+ I2CMicroSecondDelay ( 10 );
+ NumTries --;
+ if (0 == NumTries) {
+ return EFI_NOT_READY;
+ }
+ }
+ return EFI_SUCCESS;
+}
+/**
+@todo add description
+
+**/
+EFI_STATUS
+I2cEnable (
+ IN UINT8 BusNo
+ )
+{
+ UINTN mI2CBaseAddress;
+ UINT32 NumTries = 10000; /* 0.1 seconds */
+ mI2CBaseAddress = mLpssPciDeviceList[BusNo+1].Bar0;
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_ENABLE, 1 );
+ while ( 0 == ( I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_ENABLE_STATUS ) & 1 )) {
+ I2CMicroSecondDelay ( 10 );
+ NumTries --;
+ if (0 == NumTries) {
+ return EFI_NOT_READY;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the I2C controller bus clock frequency.
+
+ @param[in] This Address of the library's I2C context structure
+ @param[in] PlatformData Address of the platform configuration data
+ @param[in] BusClockHertz New I2C bus clock frequency in Hertz
+
+ @retval RETURN_SUCCESS The bus frequency was set successfully.
+ @retval RETURN_UNSUPPORTED The controller does not support this frequency.
+
+**/
+EFI_STATUS
+I2cBusFrequencySet (
+ IN UINTN mI2CBaseAddress,
+ IN UINTN BusClockHertz,
+ IN UINT16 *I2cMode
+ )
+{
+ DEBUG ((EFI_D_INFO,"InputFreq BusClockHertz: %d\r\n",BusClockHertz));
+
+ *I2cMode = B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE;
+
+ //
+ // Set the 100 KHz clock divider
+ //
+ // From Table 10 of the I2C specification
+ //
+ // High: 4.00 uS
+ // Low: 4.70 uS
+ //
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_SS_SCL_HCNT, (UINT16)0x28F );
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_SS_SCL_LCNT, (UINT16)0x2BA );
+ //
+ // Set the 400 KHz clock divider
+ //
+ // From Table 10 of the I2C specification
+ //
+ // High: 0.60 uS
+ // Low: 1.30 uS
+ //
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_FS_SCL_HCNT, (UINT16)0x71 );
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_FS_SCL_LCNT, (UINT16)0xCE );
+
+ switch ( BusClockHertz ) {
+ case 100 * 1000:
+ I2CLibPeiMmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x06);//100K
+ I2CLibPeiMmioWrite32 ( mI2CBaseAddress + R_IC_SDA_SETUP, (UINT16)0x06);
+ *I2cMode |= V_SPEED_STANDARD;
+ break;
+ case 400 * 1000:
+ I2CLibPeiMmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x06);//400K
+ I2CLibPeiMmioWrite32 ( mI2CBaseAddress + R_IC_SDA_SETUP, (UINT16)0x06);
+ *I2cMode |= V_SPEED_FAST;
+ break;
+ default:
+ I2CLibPeiMmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x06);//1.7M
+ I2CLibPeiMmioWrite32 ( mI2CBaseAddress + R_IC_SDA_SETUP, (UINT16)0x06);
+ *I2cMode |= V_SPEED_HIGH;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+@todo add description
+
+**/
+EFI_STATUS
+I2CInit (
+ UINT8 BusNo,
+ UINT16 SlaveAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NumTries;
+ UINTN mI2CBaseAddress;
+ UINT16 I2cMode;
+ UINTN PciMmBase;
+
+ NumTries = 0;
+ PciMmBase = 0;
+ PciMmBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPSS_I2C,
+ (BusNo + 1),
+ 0
+ );
+ if (I2CLibPeiMmioRead32 (PciMmBase) == 0xFFFFFFFF) {
+ DEBUG ((EFI_D_INFO,"I2CInit() Exit with Status EFI_NOT_READY\r\n"));
+ return EFI_NOT_READY;
+ }
+
+ mI2CBaseAddress = I2CLibPeiMmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR) & B_PCH_LPSS_I2C_BAR_BA;
+ //
+ // Verify the parameters
+ //
+ if ( 1023 < SlaveAddress ) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n", Status));
+ return Status;
+ }
+ I2CLibPeiMmioWrite32 ( mI2CBaseAddress + R_IC_TAR, (UINT16)SlaveAddress );
+
+ //
+ // Program I2C base address if needed
+ //
+ if (mI2CBaseAddress == mLpssPciDeviceList[BusNo+1].Bar0) {
+ DEBUG((EFI_D_ERROR, "I2CInit() This device is already configured so ignore and return \n"));
+ return EFI_SUCCESS;
+ }
+ ProgramPciLpssI2C(BusNo);
+
+ mI2CBaseAddress = mLpssPciDeviceList[BusNo+1].Bar0;
+ DEBUG ((EFI_D_ERROR, "mI2CBaseAddress = 0x%x \n",mI2CBaseAddress));
+ NumTries = 10000; /* 1 seconds */
+ while (( 1 == ( I2CLibPeiMmioRead32 ( mI2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) {
+ I2CMicroSecondDelay (10);
+ NumTries --;
+ if (0 == NumTries) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ Status = I2cDisable ( BusNo);
+ DEBUG ((EFI_D_INFO, "I2cDisable Status = %r\r\n", Status));
+ //
+ // Set I2cMode
+ //
+ I2cBusFrequencySet (mI2CBaseAddress, 400 * 1000, &I2cMode);
+
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_INTR_MASK, 0x0);
+ if ( 0x7F < SlaveAddress ) {
+ SlaveAddress = ( SlaveAddress & 0x3ff ) | IC_TAR_10BITADDR_MASTER;
+ }
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_TAR, (UINT16) SlaveAddress );
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_RX_TL, 0);
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_TX_TL, 0 );
+ I2CLibPeiMmioWrite16 ( mI2CBaseAddress + R_IC_CON, I2cMode);
+
+ Status = I2cEnable (BusNo);
+ I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );
+ return EFI_SUCCESS;
+}
+/**
+ Reads a Byte from I2C Device
+
+ @param[in] BusNo I2C Bus no to which the I2C device has been connected
+ @param[in] SlaveAddress Device Address from which the byte value has to be read
+ @param[in] Offset Offset from which the data has to be read
+ @param[in] *Byte Address to which the value read has to be stored
+ @param[out] Readbuffer @todo add description
+ @param[in] ReadBytes @todo add description
+
+ @retval EFI_SUCCESS IF the byte value has been successfully read
+ @retval EFI_DEVICE_ERROR Operation Failed, Device Error
+
+**/
+EFI_STATUS
+ByteReadI2C_Basic (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINTN ReadBytes,
+ OUT UINT8 *ReadBuffer,
+ IN UINT8 Start,
+ IN UINT8 End
+)
+
+{
+
+ EFI_STATUS Status;
+ UINT32 I2cStatus;
+ UINT16 ReceiveData;
+ UINT8 *ReceiveDataEnd;
+ UINT8 *ReceiveRequest;
+ UINT16 raw_intr_stat;
+ UINTN mI2CBaseAddress;
+ UINT32 Count;
+ mI2CBaseAddress = (UINT32) (0xFE910000+ BusNo *0x10000);
+
+ Status = EFI_SUCCESS;
+ Count = 0;
+
+ Status = I2CInit (BusNo, SlaveAddress);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ ReceiveDataEnd = &ReadBuffer [ ReadBytes ];
+ if (ReadBytes) {
+ ReceiveRequest = ReadBuffer;
+
+ while ( (ReceiveDataEnd > ReceiveRequest) ||
+ (ReceiveDataEnd > ReadBuffer)) {
+ //
+ // Check for NACK
+ //
+ raw_intr_stat = I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_RAW_INTR_STAT );
+ if ( 0 != ( raw_intr_stat & I2C_INTR_TX_ABRT )) {
+ I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );
+ Status = RETURN_DEVICE_ERROR;
+ break;
+ }
+ //
+ // Determine if another byte was received
+ //
+ I2cStatus = I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_STATUS );
+ if ( 0 != ( I2cStatus & STAT_RFNE )) {
+ ReceiveData = I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_DATA_CMD );
+ *ReadBuffer++ = (UINT8)ReceiveData;
+ }
+
+ if (ReceiveDataEnd==ReceiveRequest) {
+ I2CMicroSecondDelay ( FIFO_WRITE_DELAY );
+ Count++;
+ if (Count < 1024) {
+ continue;
+ } else {
+ //
+ // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) = TRUE.
+ //
+ break;
+ }
+ }
+ //
+ // Wait until a read request will fit
+ //
+ if ( 0 == ( I2cStatus & STAT_TFNF )) {
+ I2CMicroSecondDelay ( 10 );
+ continue;
+ }
+ //
+ // Issue the next read request
+ //
+ if (End && Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART|B_CMD_STOP);
+ else if (!End && Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART);
+ else if (End && !Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_STOP);
+ else if (!End && !Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD);
+ //
+ // Wait after send cmd
+ //
+ I2CMicroSecondDelay (FIFO_WRITE_DELAY);
+ ReceiveRequest += 1;
+ }
+ //local_irq_restore(eflags);
+ }
+ return Status;
+
+}
+
+/**
+ Writes a Byte to I2C Device
+
+@param[in] BusNo I2C Bus no to which the I2C device has been connected
+@param[in] SlaveAddress Device Address from which the byte value has to be read
+@param[in] WriteBytes @todo add description
+@param[in] WriteBuffer @todo add description
+@param[in] Start @todo add description
+@param[in] End @todo add description
+
+@retval EFI_SUCCESS IF the byte value written successfully
+@retval EFI_DEVICE_ERROR Operation Failed, Device Error
+
+**/
+EFI_STATUS
+ByteWriteI2C_Basic (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINTN WriteBytes,
+ IN UINT8 *WriteBuffer,
+ IN UINT8 Start,
+ IN UINT8 End
+)
+{
+ EFI_STATUS Status;
+ UINT32 I2cStatus;
+ UINT8 *TransmitEnd;
+ UINT16 raw_intr_stat;
+ UINTN mI2CBaseAddress;
+ UINT32 Count;
+ mI2CBaseAddress = (UINT32) 0xFE910000 + BusNo * 0x10000;
+
+ Status = EFI_SUCCESS;
+ Count = 0;
+ //
+ // Initialise I2C Device
+ //
+ Status = I2CInit(BusNo, SlaveAddress);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ TransmitEnd = &WriteBuffer [ WriteBytes ];
+ if ( WriteBytes ) {
+ while ( TransmitEnd > WriteBuffer ) {
+ I2cStatus = I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_STATUS );
+ raw_intr_stat = I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_RAW_INTR_STAT );
+ if ( 0 != ( raw_intr_stat & I2C_INTR_TX_ABRT )) {
+ I2CLibPeiMmioRead16 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );
+ Status = RETURN_DEVICE_ERROR;
+ DEBUG ((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
+ break;
+ }
+ //
+ // If tx not full , will send cmd or continue to wait
+ //
+ if ( 0 == ( I2cStatus & STAT_TFNF )) {
+ I2CMicroSecondDelay (FIFO_WRITE_DELAY);
+ continue;
+ }
+ if (End && Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART|B_CMD_STOP);
+ else if (!End && Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART);
+ else if (End && !Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_STOP);
+ else if (!End && !Start )
+ I2CLibPeiMmioWrite16 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++));
+ //
+ // Add a small delay to work around some odd behavior being seen.
+ // Without this delay bytes get dropped.
+ //
+ I2CMicroSecondDelay (FIFO_WRITE_DELAY);
+ //
+ // Time out
+ //
+ while (1) {
+ raw_intr_stat = I2CLibPeiMmioRead16 ((UINTN) (mI2CBaseAddress + R_IC_RAW_INTR_STAT));
+ if (0 != (raw_intr_stat & I2C_INTR_TX_ABRT)) {
+ I2CLibPeiMmioRead16 ((UINTN) (mI2CBaseAddress + R_IC_CLR_TX_ABRT));
+ Status = RETURN_DEVICE_ERROR;
+ DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
+ }
+ if (0 == I2CLibPeiMmioRead16 ((UINTN) (mI2CBaseAddress + R_IC_TXFLR))) {
+ break;
+ }
+ I2CMicroSecondDelay ( FIFO_WRITE_DELAY );
+ Count++;
+ if (Count < 1024) {
+ //
+ // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) = TRUE.
+ //
+ continue;
+ } else {
+ break;
+ }
+ } // while(1)
+ }
+ }
+ if (EFI_ERROR(Status))
+ DEBUG((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n",Status));
+ return Status;
+}
+/**
+@todo add description
+
+**/
+EFI_STATUS
+ByteReadI2C (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINT8 Offset,
+ IN UINTN ReadBytes,
+ OUT UINT8 *ReadBuffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = ByteWriteI2C_Basic (BusNo, SlaveAddress, 1, &Offset, TRUE, FALSE);
+ if (!EFI_ERROR(Status)) {
+ Status = ByteReadI2C_Basic(BusNo, SlaveAddress,ReadBytes,ReadBuffer,TRUE,TRUE);
+ }
+ return Status;
+}
+/**
+@todo add description
+
+**/
+EFI_STATUS
+ByteWriteI2C (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINT8 Offset,
+ IN UINTN WriteBytes,
+ IN UINT8 *WriteBuffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = ByteWriteI2C_Basic (BusNo, SlaveAddress, 1, &Offset, TRUE, FALSE);
+ if (!EFI_ERROR(Status)) {
+ Status = ByteWriteI2C_Basic(BusNo, SlaveAddress,WriteBytes,WriteBuffer,FALSE,TRUE);
+ }
+ return Status;
+}
+/**
+ This function initiates an I2C operation on the controller.
+
+ The operation is performed by selecting the I2C device with its slave
+ address and then sending all write data to the I2C device. If read data
+ is requested, a restart is sent followed by the slave address and then
+ the read data is clocked into the I2C controller and placed in the read
+ buffer. When the operation completes, the status value is returned and
+ then the event is set.
+
+ @param[in] BusNo I2C Bus no to which the I2C device has been connected
+ @param[in] SlaveAddress Device Address from which the byte value has to be read
+ @param[in] WriteBytes Number of bytes to send
+ @param[in] WriteBuffer Address of buffer containing data to send
+ @param[in] ReadBytes Number of bytes to read
+ @param[out] ReadBuffer Address of buffer to receive data
+
+ @retval RETURN_SUCCESS The operation completed successfully.
+ @retval RETURN_DEVICE_ERROR There was an I2C error (NACK) during the operation.
+ This could indicate the slave device is not present
+
+**/
+EFI_STATUS
+I2cRequest (
+ IN UINT8 BusNo,
+ IN UINT16 SlaveAddress,
+ IN UINTN WriteBytes,
+ IN UINT8 *WriteBuffer,
+ IN UINTN ReadBytes,
+ OUT UINT8 *ReadBuffer
+ )
+{
+ UINT32 I2cStatus;
+ UINT16 ReceiveData;
+ UINT8 *ReceiveDataEnd;
+ UINT8 *ReceiveRequest;
+ RETURN_STATUS Status;
+ UINT8 *TransmitEnd;
+ UINT16 RawInitStart;
+ UINTN BaseAddr;
+
+ DEBUG((EFI_D_INFO, "I2cRequest Entered\r\n"));
+
+ ReceiveRequest = NULL;
+ RawInitStart = 0;
+ BaseAddr = (UINT32)(0xFE910000+ BusNo *0x10000);
+ ReceiveDataEnd = &ReadBuffer[ReadBytes];
+ TransmitEnd = &WriteBuffer[WriteBytes];
+
+ Status = I2CInit (BusNo, SlaveAddress);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ Status = EFI_SUCCESS;
+ if ( WriteBytes ) {
+ while ( TransmitEnd > WriteBuffer ) {
+ I2cStatus = I2CLibPeiMmioRead16 ( BaseAddr + R_IC_STATUS );
+ RawInitStart = I2CLibPeiMmioRead16 ( BaseAddr + R_IC_RAW_INTR_STAT );
+ if ( 0 != ( RawInitStart & I2C_INTR_TX_ABRT )) {
+ I2CLibPeiMmioRead16 ( BaseAddr + R_IC_CLR_TX_ABRT );
+ Status = RETURN_DEVICE_ERROR;
+ DEBUG((EFI_D_INFO, "TX ABRT TransmitEnd:0x%016Lx WriteBuffer:0x%016Lx\r\n", (UINT64)(UINTN)TransmitEnd, (UINT64)(UINTN)WriteBuffer));
+ break;
+ }
+ if ( 0 == ( I2cStatus & STAT_TFNF )) {
+ continue;
+ }
+ if ( TransmitEnd == (WriteBuffer + 1) ) {
+ //
+ // For WRITE only transaction, write B_CMD_STOP to issue bus stop signal
+ // For WRITE-READ sequence, READ loop will issue bus stop signal
+ //
+ if ( ReadBytes == 0 ) {
+ I2CLibPeiMmioWrite16 ( BaseAddr + R_IC_DATA_CMD, *WriteBuffer | B_CMD_STOP );
+ } else {
+ I2CLibPeiMmioWrite16 ( BaseAddr + R_IC_DATA_CMD, *WriteBuffer );
+ }
+ WriteBuffer ++;
+ } else {
+ I2CLibPeiMmioWrite16 ( BaseAddr + R_IC_DATA_CMD, *WriteBuffer++ );
+ }
+ //
+ // Add a small delay to work around some odd behavior being seen. Without
+ // this delay bytes get dropped.
+ //
+ I2CMicroSecondDelay ( FIFO_WRITE_DELAY );
+ }
+
+ if ( EFI_ERROR(Status) ) {
+ goto ExirI2cRequest;
+ }
+ //
+ // If this transaction is WRITE only, rather than WRITE-READ sequence,wait for bytes to go
+ // Write into Tx fifo doesn't mean the dat will go correctly on the SDA data line
+ //
+ if ( ReadBytes == 0) {
+ while( 1 ) {
+ RawInitStart = I2CLibPeiMmioRead16 ( BaseAddr + R_IC_RAW_INTR_STAT );
+ if ( 0 != ( RawInitStart & I2C_INTR_TX_ABRT )) {
+ I2CLibPeiMmioRead16 ( BaseAddr + R_IC_CLR_TX_ABRT );
+ Status = RETURN_DEVICE_ERROR;
+ DEBUG((EFI_D_INFO, "TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
+ goto ExirI2cRequest;
+ }
+ if ( 0 == I2CLibPeiMmioRead16(BaseAddr + R_IC_TXFLR ) ) {
+ break;
+ }
+ }
+ }
+ }
+
+ if(EFI_ERROR(Status)) {
+ goto ExirI2cRequest;
+ }
+
+ if (ReadBytes) {
+ ReceiveRequest = ReadBuffer;
+ while ( (ReceiveDataEnd > ReceiveRequest) ||
+ (ReceiveDataEnd > ReadBuffer)) {
+ RawInitStart = I2CLibPeiMmioRead16 ( BaseAddr + R_IC_RAW_INTR_STAT );
+ if ( 0 != ( RawInitStart & I2C_INTR_TX_ABRT )) {
+ I2CLibPeiMmioRead16 ( BaseAddr + R_IC_CLR_TX_ABRT );
+ Status = RETURN_DEVICE_ERROR;
+ DEBUG((EFI_D_INFO, "TX ABRT ,%d bytes hasn't been transferred\r\n", ReceiveDataEnd - ReceiveRequest));
+ break;
+ }
+ //
+ // Determine if another byte was received
+ //
+ I2cStatus = I2CLibPeiMmioRead16 ( BaseAddr + R_IC_STATUS );
+ if ( 0 != ( I2cStatus & STAT_RFNE )) {
+ ReceiveData = I2CLibPeiMmioRead16 ( BaseAddr + R_IC_DATA_CMD );
+ *ReadBuffer++ = (UINT8)ReceiveData;
+ }
+
+ if (ReceiveDataEnd == ReceiveRequest) {
+ continue;
+ }
+ //
+ // Wait until a read request will fit
+ //
+ if ( 0 == ( I2cStatus & STAT_TFNF )) {
+ I2CMicroSecondDelay ( 10 );
+ continue;
+ }
+ //
+ // Issue the next read request
+ //
+ if (ReceiveDataEnd == ( ReceiveRequest + 1 ) ) {
+ I2CLibPeiMmioWrite16 ( BaseAddr + R_IC_DATA_CMD, B_READ_CMD | B_CMD_STOP );
+ } else {
+ I2CLibPeiMmioWrite16 ( BaseAddr + R_IC_DATA_CMD, B_READ_CMD );
+ }
+ ReceiveRequest += 1;
+ }
+ }
+
+ExirI2cRequest:
+ DEBUG((EFI_D_INFO, "I2cRequest Exit with Status %r\r\n",Status));
+ return Status;
+}
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.h b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.h
new file mode 100644
index 0000000000..8f684a6b4f
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.h
@@ -0,0 +1,282 @@
+/** @file
+
+ Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PiPei.h"
+#ifndef I2C_PEI_REGS_A0_H
+#define I2C_PEI_REGS_A0_H
+
+#define R_PCH_LPC_PMC_BASE 0x44
+#define B_PCH_LPC_PMC_BASE_BAR 0xFFFFFE00
+#define R_PCH_PMC_FUNC_DIS 0x34 // Function Disable Register
+#define PCIEX_BASE_ADDRESS 0xE0000000
+#define PciD31F0RegBase PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC7 BIT7 // LPSS SPI Disable
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC6 BIT6 // LPSS HSUART #2 Disable
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC5 BIT5 // LPSS HSUART #1 Disable
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC4 BIT4 // LPSS I2S Disable
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC3 BIT3 // LPSS PCM Disable
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC2 BIT2 // LPSS I2C #2 Disable
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC1 BIT1 // LPSS I2C #1 Disable
+#define B_PCH_PMC_FUNC_DIS_LPSS_FUNC0 BIT0 // LPSS DMA Disable
+
+#define DEFAULT_PCI_BUS_NUMBER_PCH 0
+
+#define R_PCH_LPSS_I2C_STSCMD 0x04 // Status & Command
+#define B_PCH_LPSS_I2C_STSCMD_RMA BIT29 // RMA
+#define B_PCH_LPSS_I2C_STSCMD_RCA BIT28 // RCA
+#define B_PCH_LPSS_I2C_STSCMD_CAPLIST BIT20 // Capability List
+#define B_PCH_LPSS_I2C_STSCMD_INTRSTS BIT19 // Interrupt Status
+#define B_PCH_LPSS_I2C_STSCMD_INTRDIS BIT10 // Interrupt Disable
+#define B_PCH_LPSS_I2C_STSCMD_SERREN BIT8 // SERR# Enable
+#define B_PCH_LPSS_I2C_STSCMD_BME BIT2 // Bus Master Enable
+#define B_PCH_LPSS_I2C_STSCMD_MSE BIT1 // Memory Space Enable
+
+#define R_PCH_LPSS_I2C_BAR 0x10 // BAR
+#define B_PCH_LPSS_I2C_BAR_BA 0xFFFFF000 // Base Address
+#define B_PCH_LPSS_I2C_BAR_SI 0x00000FF0 // Size Indicator
+#define B_PCH_LPSS_I2C_BAR_PF BIT3 // Prefetchable
+#define B_PCH_LPSS_I2C_BAR_TYPE (BIT2 | BIT1) // Type
+#define B_PCH_LPSS_I2C_BAR_MS BIT0 // Message Space
+
+#define R_PCH_LPSS_I2C_BAR1 0x14 // BAR 1
+#define B_PCH_LPSS_I2C_BAR1_BA 0xFFFFF000 // Base Address
+#define B_PCH_LPSS_I2C_BAR1_SI 0x00000FF0 // Size Indicator
+#define B_PCH_LPSS_I2C_BAR1_PF BIT3 // Prefetchable
+#define B_PCH_LPSS_I2C_BAR1_TYPE (BIT2 | BIT1) // Type
+#define B_PCH_LPSS_I2C_BAR1_MS BIT0 // Message Space
+
+#define NUM_RETRIES 0xFFFF
+
+//
+// LPIO I2C Module
+// Memory Space Registers
+//
+#define R_PCH_LPIO_I2C_MEM_RESETS 0x804 // Software Reset
+#define B_PCH_LPIO_I2C_MEM_RESETS_FUNC BIT1 // Function Clock Domain Reset
+#define B_PCH_LPIO_I2C_MEM_RESETS_APB BIT0 // APB Domain Reset
+
+#define bit(a) 1 << (a)
+
+//
+// MMI/O Register Definitions
+//
+#define I2C0_REG_SPACE_ADDR_BASE 0xFF138000 //01K
+
+#define R_IC_CON ( 0x00) // I2C Control
+#define B_IC_RESTART_EN BIT5
+#define B_IC_SLAVE_DISABLE BIT6
+#define V_SPEED_STANDARD 0x02
+#define V_SPEED_FAST 0x04
+#define V_SPEED_HIGH 0x06
+#define B_MASTER_MODE BIT0
+
+#define R_IC_TAR ( 0x04) // I2C Target Address
+#define IC_TAR_10BITADDR_MASTER BIT12
+
+#define R_IC_SAR ( 0x08) // I2C Slave Address
+#define R_IC_HS_MADDR ( 0x0C) // I2C HS MasterMode Code Address
+#define R_IC_DATA_CMD ( 0x10) // I2C Rx/Tx Data Buffer and Command
+
+#define B_READ_CMD BIT8 // 1 = read, 0 = write
+#define B_CMD_STOP BIT9 // 1 = STOP
+#define B_CMD_RESTART BIT10 // 1 = IC_RESTART_EN
+
+#define V_WRITE_CMD_MASK ( 0xFF)
+
+#define R_IC_SS_SCL_HCNT ( 0x14) // Standard Speed I2C Clock SCL High Count
+#define R_IC_SS_SCL_LCNT ( 0x18) // Standard Speed I2C Clock SCL Low Count
+#define R_IC_FS_SCL_HCNT ( 0x1C) // Full Speed I2C Clock SCL High Count
+#define R_IC_FS_SCL_LCNT ( 0x20) // Full Speed I2C Clock SCL Low Count
+#define R_IC_HS_SCL_HCNT ( 0x24) // High Speed I2C Clock SCL High Count
+#define R_IC_HS_SCL_LCNT ( 0x28) // High Speed I2C Clock SCL Low Count
+#define R_IC_INTR_STAT ( 0x2C) // I2C Inetrrupt Status
+#define R_IC_INTR_MASK ( 0x30) // I2C Interrupt Mask
+#define I2C_INTR_GEN_CALL BIT11 // General call received
+#define I2C_INTR_START_DET BIT10
+#define I2C_INTR_STOP_DET BIT9
+#define I2C_INTR_ACTIVITY BIT8
+#define I2C_INTR_TX_ABRT BIT6 // Set on NACK
+#define I2C_INTR_TX_EMPTY BIT4
+#define I2C_INTR_TX_OVER BIT3
+#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold
+#define I2C_INTR_RX_OVER BIT1
+#define I2C_INTR_RX_UNDER BIT0
+#define R_IC_RAW_INTR_STAT ( 0x34) // I2C Raw Interrupt Status
+#define R_IC_RX_TL ( 0x38) // I2C Receive FIFO Threshold
+#define R_IC_TX_TL ( 0x3C) // I2C Transmit FIFO Threshold
+#define R_IC_CLR_INTR ( 0x40) // Clear Combined and Individual Interrupts
+#define R_IC_CLR_RX_UNDER ( 0x44) // Clear RX_UNDER Interrupt
+#define R_IC_CLR_RX_OVER ( 0x48) // Clear RX_OVERinterrupt
+#define R_IC_CLR_TX_OVER ( 0x4C) // Clear TX_OVER interrupt
+#define R_IC_CLR_RD_REQ ( 0x50) // Clear RD_REQ interrupt
+#define R_IC_CLR_TX_ABRT ( 0x54) // Clear TX_ABRT interrupt
+#define R_IC_CLR_RX_DONE ( 0x58) // Clear RX_DONE interrupt
+#define R_IC_CLR_ACTIVITY ( 0x5C) // Clear ACTIVITY interrupt
+#define R_IC_CLR_STOP_DET ( 0x60) // Clear STOP_DET interrupt
+#define R_IC_CLR_START_DET ( 0x64) // Clear START_DET interrupt
+#define R_IC_CLR_GEN_CALL ( 0x68) // Clear GEN_CALL interrupt
+#define R_IC_ENABLE ( 0x6C) // I2C Enable
+#define R_IC_STATUS ( 0x70) // I2C Status
+
+#define R_IC_SDA_HOLD ( 0x7C) // I2C IC_DEFAULT_SDA_HOLD//16bits
+
+#define STAT_MST_ACTIVITY BIT5 // Master FSM Activity Status.
+#define STAT_RFF BIT4 // RX FIFO is completely full
+#define STAT_RFNE BIT3 // RX FIFO is not empty
+#define STAT_TFE BIT2 // TX FIFO is completely empty
+#define STAT_TFNF BIT1 // TX FIFO is not full
+
+#define R_IC_TXFLR ( 0x74) // Transmit FIFO Level Register
+#define R_IC_RXFLR ( 0x78) // Receive FIFO Level Register
+#define R_IC_TX_ABRT_SOURCE ( 0x80) // I2C Transmit Abort Status Register
+#define R_IC_SLV_DATA_NACK_ONLY ( 0x84) // Generate SLV_DATA_NACK Register
+#define R_IC_DMA_CR ( 0x88) // DMA Control Register
+#define R_IC_DMA_TDLR ( 0x8C) // DMA Transmit Data Level
+#define R_IC_DMA_RDLR ( 0x90) // DMA Receive Data Level
+#define R_IC_SDA_SETUP ( 0x94) // I2C SDA Setup Register
+#define R_IC_ACK_GENERAL_CALL ( 0x98) // I2C ACK General Call Register
+#define R_IC_ENABLE_STATUS ( 0x9C) // I2C Enable Status Register
+#define R_IC_COMP_PARAM ( 0xF4) // Component Parameter Register
+#define R_IC_COMP_VERSION ( 0xF8) // Component Version ID
+#define R_IC_COMP_TYPE ( 0xFC) // Component Type
+
+#define I2C_FS_SCL_HCNT_VALUE_100M 0x54
+#define I2C_FS_SCL_LCNT_VALUE_100M 0x9a
+#define I2C_HS_SCL_HCNT_VALUE_100M 0x7
+#define I2C_HS_SCL_LCNT_VALUE_100M 0xE
+
+//
+// FIFO write workaround value.
+//
+#define FIFO_WRITE_DELAY 2
+#define IC_TAR_10BITADDR_MASTER BIT12
+#define FIFO_SIZE 32
+#define R_IC_INTR_STAT ( 0x2C) // I2c Inetrrupt Status
+#define R_IC_INTR_MASK ( 0x30) // I2c Interrupt Mask
+#define I2C_INTR_GEN_CALL BIT11 // General call received
+#define I2C_INTR_START_DET BIT10
+#define I2C_INTR_STOP_DET BIT9
+#define I2C_INTR_ACTIVITY BIT8
+#define I2C_INTR_TX_ABRT BIT6 // Set on NACK
+#define I2C_INTR_TX_EMPTY BIT4
+#define I2C_INTR_TX_OVER BIT3
+#define I2C_INTR_RX_FULL BIT2 // Data bytes in RX FIFO over threshold
+#define I2C_INTR_RX_OVER BIT1
+#define I2C_INTR_RX_UNDER BIT0
+
+EFI_STATUS
+ProgramPciLpssI2C (
+ IN UINT8 BusNo
+);
+
+EFI_STATUS
+ProgramAllPciLpssI2C (
+ VOID
+);
+
+EFI_STATUS
+ByteReadI2C_Basic (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINTN ReadBytes,
+ OUT UINT8 *ReadBuffer,
+ IN UINT8 Start,
+ IN UINT8 End
+);
+
+EFI_STATUS
+ByteWriteI2C_Basic(
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINTN WriteBytes,
+ IN UINT8 *WriteBuffer,
+ IN UINT8 Start,
+ IN UINT8 End
+);
+
+EFI_STATUS
+ByteReadI2C (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINT8 Offset,
+ IN UINTN ReadBytes,
+ OUT UINT8 *ReadBuffer
+);
+/**
+ Reads a Byte from I2C Device
+
+ @param [in] BusNo I2C Bus no to which the I2C device has been connected
+ @param [in] SlaveAddress Device Address from which the byte value has to be read
+ @param [in] Offset Offset from which the data has to be read
+ @param [in] *Byte Address to which the value read has to be stored
+
+ @retval EFI_SUCCESS IF the byte value has been successfully read
+ @retval EFI_DEVICE_ERROR Operation Failed, Device Error
+
+**/
+EFI_STATUS
+ByteWriteI2C (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINT8 Offset,
+ //IN UINT8 *Byte,
+ IN UINTN WriteBytes,
+ IN UINT8 *WriteBuffer
+);
+
+/**
+ Writes a Byte to I2C Device
+
+ @param [in] BusNo I2C Bus no to which the I2C device has been connected
+ @param [in] SlaveAddress Device Address from which the byte value has to be read
+ @param [in] Offset Offset from which the data has to be read
+ @param [in] *Byte Address to which the byte value has to be written
+
+ @retval EFI_SUCCESS IF the byte value written successfully
+ @retval EFI_DEVICE_ERROR Operation Failed, Device Error
+
+**/
+EFI_STATUS
+I2cRequest (
+ IN UINT8 BusNo,
+ IN UINT16 SlaveAddress,
+ IN UINTN WriteBytes,
+ IN UINT8 *WriteBuffer,
+ IN UINTN ReadBytes,
+ OUT UINT8 *ReadBuffer
+ );
+
+/**
+ This function initiates an I2C operation on the controller.
+
+ The operation is performed by selecting the I2C device with its slave
+ address and then sending all write data to the I2C device. If read data
+ is requested, a restart is sent followed by the slave address and then
+ the read data is clocked into the I2C controller and placed in the read
+ buffer. When the operation completes, the status value is returned and
+ then the event is set.
+
+ @param[in] BusNo I2C Bus no to which the I2C device has been connected
+ @param[in] SlaveAddress Device Address from which the byte value has to be read
+ @param[in] WriteBytes Number of bytes to send
+ @param[in] WriteBuffer Address of buffer containing data to send
+ @param[in] ReadBytes Number of bytes to read
+ @param[out] ReadBuffer Address of buffer to receive data
+
+ @retval RETURN_SUCCESS The operation completed successfully.
+ @retval RETURN_DEVICE_ERROR There was an I2C error (NACK) during the operation.
+ This could indicate the slave device is not present
+
+**/
+#endif // I2C_PEI_REGS_A0_H
diff --git a/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.inf b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.inf
new file mode 100644
index 0000000000..60dfb7ff72
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/SouthCluster/Library/I2CLibPei/I2CLibPei.inf
@@ -0,0 +1,50 @@
+## @file
+# I2C PEI library
+#
+# This library provides functions for I2C bus operations in pei phase.
+#
+# Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = I2CLibPei
+ FILE_GUID = 8EF61509-890B-4FF2-B352-1C0E9CDDEC8B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = I2CLibPei
+
+ CONSTRUCTOR = IntelI2CPeiLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ I2CLibPei.c
+ I2CDelayPei.c
+ I2CIoLibPei.c
+
+[LibraryClasses]
+ TimerLib
+
+[PPIs]
+ gEfiPeiStallPpiGuid ## SOMETIMES_CONSUMES
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ChvRefCodePkg/ChvRefCodePkg.dec
+
+