summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2017-08-24 18:55:21 +0800
committerGuo Mang <mang.guo@intel.com>2017-08-24 18:55:21 +0800
commitdbb279c54dbed80ec700cfbd61632a64c2c08b51 (patch)
tree32b730c6cb00f40da12e9b4a27912b82a4276245
parent7f39f1555e352ce5ca12da0d645e8a8acccee79b (diff)
downloadedk2-platforms-dbb279c54dbed80ec700cfbd61632a64c2c08b51.tar.xz
BroxtonSiPkg: Add I2CLibPei
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
-rw-r--r--Platform/BroxtonPlatformPkg/PlatformDsc/Components.IA32.dsc1
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/I2CLib.h106
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsI2c.h143
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CAccess.h51
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.c49
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.h34
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c175
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h146
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.c665
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.inf51
10 files changed, 1322 insertions, 99 deletions
diff --git a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.IA32.dsc b/Platform/BroxtonPlatformPkg/PlatformDsc/Components.IA32.dsc
index f8900ea4b8..cdbba2aff7 100644
--- a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.IA32.dsc
+++ b/Platform/BroxtonPlatformPkg/PlatformDsc/Components.IA32.dsc
@@ -116,6 +116,7 @@
NULL|$(PLATFORM_NAME)/Board/MinnowBoard3/BoardInitPostMem/BoardInitPostMem.inf
NULL|$(PLATFORM_NAME)/Board/LeafHill/BoardInitPostMem/BoardInitPostMem.inf
NULL|$(PLATFORM_NAME)/Board/BensonGlacier/BoardInitPostMem/BoardInitPostMem.inf
+ I2cLibPei|$(PLATFORM_SI_PACKAGE)/SouthCluster/Library/I2CLibPei/I2CLibPei.inf
<PcdsPatchableInModule>
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6
}
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/I2CLib.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/I2CLib.h
index b593620106..b897cb9dc4 100644
--- a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/I2CLib.h
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/I2CLib.h
@@ -1,7 +1,7 @@
/** @file
Register Definitions for I2C Library.
- Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 1999 - 2017, 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
@@ -18,111 +18,19 @@
#include <Uefi.h>
#include <Library/IoLib.h>
-
//
// FIFO write workaround value.
//
#define FIFO_WRITE_DELAY 2
-//
-// MMIO Register Definitions
-//
-#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 R_IC_CLK_GATE (0xC0) ///< Clock Gate
-
-#define IC_TAR_10BITADDR_MASTER BIT12
-#define FIFO_SIZE 32
-
-
/**
Program LPSS I2C PCI controller's BAR0 and enable memory decode.
- @param[in] BusNo I2C Bus number to which the I2C device has been connected
-
- @retval EFI_SUCCESS I2C controller's BAR0 is programmed and memory decode enabled.
- @retval EFI_NOT_READY I2C controller's is not exist or its function has been disabled.
-
+ @retval EFI_SUCCESS - I2C controller's BAR0 is programmed and memory decode enabled.
**/
EFI_STATUS
ProgramPciLpssI2C (
- IN UINT8 BusNo
+ VOID
);
/**
@@ -130,7 +38,7 @@ ProgramPciLpssI2C (
This is actual I2C hardware operation function.
@param[in] BusNo I2C Bus number to which the I2C device has been connected
- @param[in] SlaveAddress Slave address of the I2C device
+ @param[in] SlaveAddress Slave address of the I2C device (7-bit)
@param[in] ReadBytes Number of bytes to be read
@param[out] ReadBuffer Address to which the value read has to be stored
@param[in] Start It controls whether a RESTART is issued before the byte is sent or received.
@@ -157,7 +65,7 @@ ByteReadI2C_Basic (
This is actual I2C hardware operation function.
@param[in] BusNo I2C Bus number to which the I2C device has been connected
- @param[in] SlaveAddress Slave address of the I2C device
+ @param[in] SlaveAddress Slave address of the I2C device (7-bit)
@param[in] WriteBytes Number of bytes to be written
@param[in] WriteBuffer Address to which the byte value has to be written
@param[in] Start It controls whether a RESTART is issued before the byte is sent or received.
@@ -183,7 +91,7 @@ ByteWriteI2C_Basic (
Read bytes from I2C Device
@param[in] BusNo I2C Bus number to which the I2C device has been connected
- @param[in] SlaveAddress Slave address of the I2C device
+ @param[in] SlaveAddress Slave address of the I2C device (7-bit)
@param[in] Offset Register offset from which the data has to be read
@param[in] ReadBytes Number of bytes to be read
@param[out] ReadBuffer Address to which the value read has to be stored
@@ -205,7 +113,7 @@ ByteReadI2C (
Write bytes to I2C Device
@param[in] BusNo I2C Bus number to which the I2C device has been connected
- @param[in] SlaveAddress Slave address of the I2C device
+ @param[in] SlaveAddress Slave address of the I2C device (7-bit)
@param[in] Offset Register offset from which the data has to be read
@param[in] WriteBytes Number of bytes to be written
@param[in] WriteBuffer Address to which the byte value has to be written
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsI2c.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsI2c.h
new file mode 100644
index 0000000000..5fc758dd07
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsI2c.h
@@ -0,0 +1,143 @@
+/** @file
+ Register names for I2C device.
+
+ Copyright (c) 2017, 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 _REGS_I2C_H_
+#define _REGS_I2C_H_
+
+#define DEFAULT_PCI_BUS_NUMBER_SC 0
+#define PCI_DEVICE_NUMBER_LPSS_I2C 30
+
+#define R_LPSS_I2C_STSCMD 0x04 ///< Status & Command
+#define B_LPSS_I2C_STSCMD_RMA BIT29 ///< RMA
+#define B_LPSS_I2C_STSCMD_RCA BIT28 ///< RCA
+#define B_LPSS_I2C_STSCMD_CAPLIST BIT20 ///< Capability List
+#define B_LPSS_I2C_STSCMD_INTRSTS BIT19 ///< Interrupt Status
+#define B_LPSS_I2C_STSCMD_INTRDIS BIT10 ///< Interrupt Disable
+#define B_LPSS_I2C_STSCMD_SERREN BIT8 ///< SERR# Enable
+#define B_LPSS_I2C_STSCMD_BME BIT2 ///< Bus Master Enable
+#define B_LPSS_I2C_STSCMD_MSE BIT1 ///< Memory Space Enable
+
+#define R_LPSS_I2C_BAR 0x10 ///< BAR0 Low
+#define B_LPSS_I2C_BAR_BA 0xFFFFF000 ///< Base Address
+#define B_LPSS_I2C_BAR_SI 0x00000FF0 ///< Size Indicator
+#define B_LPSS_I2C_BAR_PF BIT3 ///< Prefetchable
+#define B_LPSS_I2C_BAR_TYPE (BIT2 | BIT1) ///< Type
+#define B_LPSS_I2C_BAR_MS BIT0 ///< Message Space
+
+#define R_LPSS_I2C_BAR1 0x18 ///< BAR1 Low
+#define B_LPSS_I2C_BAR1_BA 0xFFFFF000 ///< Base Address
+#define B_LPSS_I2C_BAR1_SI 0x00000FF0 ///< Size Indicator
+#define B_LPSS_I2C_BAR1_PF BIT3 ///< Prefetchable
+#define B_LPSS_I2C_BAR1_TYPE (BIT2 | BIT1) ///< Type
+#define B_LPSS_I2C_BAR1_MS BIT0 ///< Message Space
+
+#define NUM_RETRIES 0xFFFF
+
+#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 R_IC_CLK_GATE (0xC0) ///< Clock Gate
+
+#define I2C_SS_SCL_HCNT_VALUE_100M 0x1DD
+#define I2C_SS_SCL_LCNT_VALUE_100M 0x1E4
+#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
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CAccess.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CAccess.h
new file mode 100644
index 0000000000..792a4834f2
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CAccess.h
@@ -0,0 +1,51 @@
+
+/** @file
+ Macros that simplify accessing I2C device's registers.
+
+ Copyright (c) 2014 - 2017, 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_SC 0
+
+#define PCI_DEVICE_NUMBER_LPC 31
+#define PCI_FUNCTION_NUMBER_LPC 0
+
+#define R_LPC_ACPI_BASE 0x40 ///< ABASE, 16bit
+#define R_LPC_ACPI_BASEADR 0x400 ///< ABASE, 16bit
+#define B_LPC_ACPI_BASE_EN BIT1 ///< Enable Bit
+#define B_LPC_ACPI_BASE_BAR 0x0000FF80 ///< Base Address, 128 Bytes
+#define V_ACPI_PM1_TMR_MAX_VAL 0x1000000 ///< The timer is 24 bit overflow
+#define B_ACPI_PM1_TMR_VAL 0xFFFFFF ///< The timer value mask
+
+#define R_ACPI_PM1_TMR 0x08 ///< Power Management 1 Timer
+#define V_ACPI_PM1_TMR_FREQUENCY 3579545 ///< Timer Frequency
+
+
+#define ScLpcPciCfg8(Register) I2CLibPeiMmioRead8 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_SC, PCI_DEVICE_NUMBER_LPC, 0, Register))
+
+#define MmPciAddress( Segment, Bus, Device, Function, Register ) \
+ ( (UINTN)PcdGet64 (PcdPciExpressBaseAddress)+ \
+ (UINTN)(Bus << 20) + \
+ (UINTN)(Device << 15) + \
+ (UINTN)(Function << 12) + \
+ (UINTN)(Register) \
+ )
+#endif
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.c
new file mode 100644
index 0000000000..409376ad14
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.c
@@ -0,0 +1,49 @@
+/** @file
+ Timer instance for I2C Pei Library.
+
+ Copyright (c) 2014 - 2017, 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.
+
+ @param[in] MicroSeconds The minimum number of microseconds to delay.
+
+ @retval EFI_SUCCESS Time delay successfully
+**/
+EFI_STATUS
+EFIAPI
+MicroSecondDelay (
+ 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/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.h
new file mode 100644
index 0000000000..53ab6e0079
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDelayPei.h
@@ -0,0 +1,34 @@
+/** @file
+ imer prototype for I2C Pei Library.
+
+ Copyright (c) 2014 - 2017, 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 at least the given number of microseconds.
+
+ @param[in] MicroSeconds The minimum number of microseconds to delay.
+
+ @retval EFI_SUCCESS Time delay successfully
+**/
+EFI_STATUS
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ );
+
+#endif
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c
new file mode 100644
index 0000000000..f4cc843b8a
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.c
@@ -0,0 +1,175 @@
+/** @file
+ IO instance for I2C Pei Library.
+
+ Copyright (c) 2014 - 2017, 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.
+
+ @retval UINT8 - The UINT8 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.
+
+ @retval UINT16 - The UINT16 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.
+
+ @retval UINT16 - The UINT16 value written.
+**/
+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.
+
+ @retval UINT32 - The UINT32 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.
+
+ @retval UINT32 - The UINT32 value written.
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioWrite32 (
+ IN UINTN Address,
+ IN UINT32 Value
+ )
+{
+ ASSERT ((Address & 3) == 0);
+ *(volatile UINT32*)Address = Value;
+ return Value;
+}
+
+/**
+ Do logical OR operation with the value read from the 32-bit MMIO register
+ and write it back to 32-bit MMIO register.
+
+ @param[in] Address - The MMIO register to write.
+ @param[in] OrData - The value to do logical OR operation with the value read from the MMIO register.
+
+ @retval UINT32 - The final value written to the MMIO register.
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioOr32 (
+ IN UINTN Address,
+ IN UINT32 OrData
+ )
+{
+ return I2CLibPeiMmioWrite32 (Address, I2CLibPeiMmioRead32 (Address) | OrData);
+}
+
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h
new file mode 100644
index 0000000000..0ea17274c5
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoLibPei.h
@@ -0,0 +1,146 @@
+/** @file
+ IO prototype for I2C Pei Library.
+
+ Copyright (c) 2014 - 2017, 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.
+
+ @retval UINT8 - The UINT8 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.
+
+ @retval UINT16 - The UINT16 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.
+
+ @retval UINT16 - The UINT16 value written.
+**/
+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.
+
+ @retval UINT32 - The UINT32 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.
+
+ @retval UINT32 - The UINT32 value written.
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioWrite32 (
+ IN UINTN Address,
+ IN UINT32 Value
+ );
+
+
+/**
+ Do logical OR operation with the value read from the 32-bit MMIO register
+ and write it back to 32-bit MMIO register.
+
+ @param[in] Address - The MMIO register to write.
+ @param[in] OrData - The value to do logical OR operation with the value read from the MMIO register.
+
+ @retval UINT32 - The final value written to the MMIO register.
+**/
+UINT32
+EFIAPI
+I2CLibPeiMmioOr32 (
+ IN UINTN Address,
+ IN UINT32 OrData
+ );
+
+#endif
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.c
new file mode 100644
index 0000000000..d15170a35c
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.c
@@ -0,0 +1,665 @@
+/** @file
+ Pei library for I2C bus driver.
+
+ Copyright (c) 2014 - 2017, 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 <Library/I2CLib.h>
+#include <PlatformBaseAddresses.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/HobLib.h>
+#include <ScRegs/RegsPcu.h>
+#include <ScRegs/RegsPmc.h>
+#include <ScRegs/RegsLpss.h>
+#include <ScRegs/RegsI2c.h>
+
+EFI_GUID mI2CPeiInitGuid = {
+ 0x96DED71A, 0xB9E7, 0x4EAD, {0x96, 0x2C, 0x01, 0x69, 0x3C, 0xED, 0x2A, 0x64}
+};
+
+
+#define LPSS_PCI_DEVICE_NUMBER 8
+
+
+#define GPIO_PAD_CFG_DW0_GPIO_124_OFFSET 0x400 ///< This is the first gpio pin of I2C0
+
+/* Name Function Offset of GPIO WEST
+ GPIO_124 LPSS_I2C0_SDA 0x400 + 16*0
+ GPIO_125 LPSS_I2C0_SCL
+
+ GPIO_126 LPSS_I2C1_SDA 0x400 + 16*1
+ GPIO_127 LPSS_I2C1_SCL
+
+ GPIO_128 LPSS_I2C2_SDA
+ GPIO_129 LPSS_I2C2_SCL
+
+ GPIO_130 LPSS_I2C3_SDA
+ GPIO_131 LPSS_I2C3_SCL
+
+ GPIO_132 LPSS_I2C4_SDA
+ GPIO_133 LPSS_I2C4_SCL
+
+ GPIO_134 LPSS_I2C5_SDA
+ GPIO_135 LPSS_I2C5_SCL
+
+ GPIO_136 LPSS_I2C6_SDA
+ GPIO_137 LPSS_I2C6_SCL
+
+ GPIO_138 LPSS_I2C7_SDA 0x400 + 16*7
+ GPIO_139 LPSS_I2C7_SCL
+*/
+
+EFI_STATUS
+EFIAPI
+IntelI2CPeiLibConstructor (
+ VOID
+ )
+{
+ UINTN Index;
+//UINT32 Value;
+ UINT32 gpio_pad_cfg_dw0_offset;
+
+ // Program GPIO pins for I2C 0~7, need to set GPIO to Function 1 and misc settings.
+ for (Index = 0; Index < 8; Index ++) {
+ // Config I2C[Index] SDA pin DW0
+ gpio_pad_cfg_dw0_offset = GPIO_PAD_CFG_DW0_GPIO_124_OFFSET + 16 * Index;
+ {
+ //Value = 0; // FIXME: the right GPIO setting, need to get updated from GPIO config owner. Dummy code here.
+ //SideBandCR32Write (SB_PORTID_GPIOW, gpio_pad_cfg_dw0_offset, Value);
+ }
+
+ // Config I2C[Index] SDA pin DW1
+ gpio_pad_cfg_dw0_offset += 4;
+ {
+ //Value = 0; // FIXME: the right GPIO setting, need to get updated from GPIO config owner. Dummy code here.
+ //SideBandCR32Write (SB_PORTID_GPIOW, gpio_pad_cfg_dw0_offset, Value);
+ }
+
+ // Config I2C[Index] SCL pin DW0
+ gpio_pad_cfg_dw0_offset += 4;
+ {
+ //Value = 0; // FIXME: the right GPIO setting, need to get updated from GPIO config owner. Dummy code here.
+ //SideBandCR32Write (SB_PORTID_GPIOW, gpio_pad_cfg_dw0_offset, Value);
+ }
+
+ // Config I2C[Index] SCL pin DW1
+ gpio_pad_cfg_dw0_offset += 4;
+ {
+ //Value = 0; // FIXME: the right GPIO setting, need to get updated from GPIO config owner. Dummy code here.
+ //SideBandCR32Write (SB_PORTID_GPIOW, gpio_pad_cfg_dw0_offset, Value);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Program LPSS I2C PCI controller's BAR0 and enable memory decode.
+
+ @retval EFI_SUCCESS - I2C controller's BAR0 is programmed and memory decode enabled.
+**/
+EFI_STATUS
+ProgramPciLpssI2C (
+ VOID
+ )
+{
+ UINT32 PmcBase;
+ UINT32 DevID;
+ UINTN PciMmBase=0;
+ UINTN Index;
+ UINTN Bar0;
+ UINTN Bar1;
+
+ DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() Start\n"));
+
+ //
+ // Set the BXT Function Disable Register to ZERO
+ //
+ PmcBase = PMC_BASE_ADDRESS;
+
+ if (I2CLibPeiMmioRead32 (PmcBase + R_PMC_FUNC_DIS) &
+ (B_PMC_FUNC_DIS_LPSS_I2C0 | B_PMC_FUNC_DIS_LPSS_I2C1 | B_PMC_FUNC_DIS_LPSS_I2C2 | B_PMC_FUNC_DIS_LPSS_I2C3|
+ B_PMC_FUNC_DIS_LPSS_I2C4 | B_PMC_FUNC_DIS_LPSS_I2C5 | B_PMC_FUNC_DIS_LPSS_I2C6 | B_PMC_FUNC_DIS_LPSS_I2C7)) {
+ I2CLibPeiMmioWrite32 (
+ PmcBase + R_PMC_FUNC_DIS,
+ I2CLibPeiMmioRead32 (PmcBase + R_PMC_FUNC_DIS) &
+ ~(B_PMC_FUNC_DIS_LPSS_I2C0| B_PMC_FUNC_DIS_LPSS_I2C1|B_PMC_FUNC_DIS_LPSS_I2C2| B_PMC_FUNC_DIS_LPSS_I2C3|
+ B_PMC_FUNC_DIS_LPSS_I2C4| B_PMC_FUNC_DIS_LPSS_I2C5|B_PMC_FUNC_DIS_LPSS_I2C6| B_PMC_FUNC_DIS_LPSS_I2C7)
+ );
+
+ DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() enable all I2C controllers\n"));
+ }
+
+ for (Index = 0; Index < LPSS_PCI_DEVICE_NUMBER; Index ++) {
+ if (Index < 4) {
+ PciMmBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_LPSS_I2C0,
+ Index,
+ 0
+ );
+ } else {
+ PciMmBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_LPSS_I2C1,
+ (Index - 4),
+ 0
+ );
+ }
+
+ DevID = I2CLibPeiMmioRead32 (PciMmBase);
+ Bar0 = LPSS_I2C0_TMP_BAR0 + Index * LPSS_I2C_TMP_BAR0_DELTA;
+ Bar1 = Bar0 + LPSS_I2C_TMP_BAR1_OFFSET;
+
+ //
+ // Check if device present
+ //
+ if (DevID != 0xFFFFFFFF) {
+ if ((I2CLibPeiMmioRead32 (PciMmBase + R_LPSS_I2C_STSCMD) & B_LPSS_I2C_STSCMD_MSE)) {
+ //
+ // In PEI stage, we always disable Bus master, and memory space enabling for BAR re-programming
+ // In DXE stage, will read existing BAR value instead of re-programming
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (PciMmBase + R_LPSS_I2C_STSCMD), 0);
+ }
+ //
+ // Program BAR 0
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (PciMmBase + R_LPSS_I2C_BAR), (UINT32) (Bar0 & B_LPSS_I2C_BAR_BA));
+
+ //
+ // Program BAR 1
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (PciMmBase + R_LPSS_I2C_BAR1), (UINT32) (Bar1 & B_LPSS_I2C_BAR1_BA));
+
+ //
+ // Bus Master Enable & Memory Space Enable
+ //
+ I2CLibPeiMmioWrite32 ((UINTN) (PciMmBase + R_LPSS_I2C_STSCMD), (UINT32) (B_LPSS_I2C_STSCMD_BME | B_LPSS_I2C_STSCMD_MSE));
+ }
+
+ //
+ // Release Resets
+ //
+ I2CLibPeiMmioWrite32 (Bar0 + R_LPSS_IO_MEM_RESETS, B_LPSS_IO_MEM_HC_RESET_REL | B_LPSS_IO_MEM_iDMA_RESET_REL);
+ }
+
+ DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() End\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable I2C host controller
+
+ @param[in] BusNo - I2C Bus number to which the I2C device has been connected
+
+ @retval EFI_SUCCESS - I2C host controller is completely inactive.
+ @retval EFI_NOT_READY - I2C host controller is still in an enabled state.
+**/
+EFI_STATUS
+I2cDisable (
+ IN UINT8 BusNo
+ )
+{
+ UINTN I2CBaseAddress;
+ UINT32 NumTries = 10000; // 0.1 seconds
+
+ I2CBaseAddress = (UINT32) LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BAR0_DELTA);
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 0);
+ while (0 != (I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_ENABLE) & 1)) {
+ MicroSecondDelay (10);
+ NumTries--;
+ if (NumTries == 0) return EFI_NOT_READY;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Enable I2C host controller
+
+ @param[in] BusNo - I2C Bus number to which the I2C device has been connected
+
+ @retval EFI_SUCCESS - I2C host controller is in an enabled state.
+ @retval EFI_NOT_READY - I2C host controller is still inactive.
+**/
+EFI_STATUS
+I2cEnable (
+ IN UINT8 BusNo
+ )
+{
+ UINTN I2CBaseAddress;
+ UINT32 NumTries = 10000; //0.1 seconds
+
+ I2CBaseAddress = (UINT32) LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BAR0_DELTA);
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 1);
+ while (0 == (I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_ENABLE ) & 1)) {
+ MicroSecondDelay (10);
+ NumTries --;
+ if (NumTries == 0) return EFI_NOT_READY;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Set the I2C controller bus clock frequency.
+
+ The software and controller do a best case effort of using the specified
+ frequency for the I2C bus. If the frequency does not match exactly then
+ the controller will use a slightly lower frequency for the I2C to avoid
+ exceeding the operating conditions for any of the I2C devices on the bus.
+ For example if 400 KHz was specified and the controller's divide network
+ only supports 402 KHz or 398 KHz then the controller would be set to 398
+ KHz. However if the desired frequency is 400 KHz and the controller only
+ supports 1 MHz and 100 KHz then this routine would return EFI_UNSUPPORTED.
+
+ @param[in] I2CBaseAddress - BAR0 address of I2C host controller
+ @param[in] BusClockHertz - New I2C bus clock frequency in Hertz
+ @param[out] I2cMode - I2C operation mode.
+ Standard Speed: 100 KHz
+ Fast Speed : 400 KHz
+ High Speed : 3.4 MHz
+
+ @retval EFI_SUCCESS - The bus frequency was set successfully.
+**/
+
+EFI_STATUS
+I2cBusFrequencySet (
+ IN UINTN I2CBaseAddress,
+ IN UINTN BusClockHertz,
+ OUT UINT16 *I2cMode,
+ IN BOOLEAN DebugFlag
+ )
+{
+ if (DebugFlag) 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 (I2CBaseAddress + R_IC_SS_SCL_HCNT, (UINT16)0x214);
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_SS_SCL_LCNT, (UINT16)0x272);
+
+ //
+ // Set the 400 KHz clock divider
+ // From Table 10 of the I2C specification
+ // High: 0.60 uS
+ // Low: 1.30 uS
+ //
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_FS_SCL_HCNT, (UINT16)0x50);
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_FS_SCL_LCNT, (UINT16)0xAD);
+
+ switch (BusClockHertz) {
+ case 100 * 1000:
+ I2CLibPeiMmioWrite32 (I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x40);//100K
+ *I2cMode |= V_SPEED_STANDARD;
+ break;
+ case 400 * 1000:
+ I2CLibPeiMmioWrite32 (I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x32);//400K
+ *I2cMode |= V_SPEED_FAST;
+ break;
+ default:
+ I2CLibPeiMmioWrite32 (I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x09);//3.4M
+ *I2cMode |= V_SPEED_HIGH;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes the host controller to execute I2C commands.
+
+ @param[in] BusNo - I2C Bus number to which the I2C device has been connected
+ @param[in] SlaveAddress - Slave address of the I2C device
+
+ @retval EFI_SUCCESS - Opcode initialization on the I2C host controller completed.
+ @retval EFI_INVALID_PARAMETER - Invalid slave address
+ @retval EFI_DEVICE_ERROR - Operation failed, device error
+ @retval Others - Failed to initialize I2C host controller
+**/
+EFI_STATUS
+I2CInit (
+ IN UINT8 BusNo,
+ IN UINT16 SlaveAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NumTries = 0;
+ UINTN I2CBaseAddress;
+ UINT16 I2cMode;
+ UINTN PciMmBase = 0;
+ BOOLEAN DebugFlag = TRUE;
+
+ if (BusNo < 4) {
+ PciMmBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_LPSS_I2C0,
+ BusNo,
+ 0
+ );
+ } else {
+ PciMmBase = MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_SC,
+ PCI_DEVICE_NUMBER_LPSS_I2C1,
+ (BusNo - 4),
+ 0
+ );
+ }
+
+ I2CBaseAddress = (I2CLibPeiMmioRead32 (PciMmBase + R_LPSS_I2C_BAR) & 0xFFFFFFF8);
+
+ //
+ // Verify the parameters
+ //
+ if (1023 < SlaveAddress) {
+ Status = EFI_INVALID_PARAMETER;
+ if (DebugFlag) DEBUG ((DEBUG_ERROR, "I2cStartRequest Exit with Status %r\r\n", Status));
+ return Status;
+ }
+
+ if (I2CBaseAddress == (LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BAR0_DELTA))) {
+ DebugFlag = FALSE;
+ } else {
+ //
+ // Need to enable the I2C PCI device
+ //
+ ProgramPciLpssI2C ();
+
+ I2CBaseAddress = (UINT32) (LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BAR0_DELTA));
+ if (DebugFlag) DEBUG ((DEBUG_INFO, "I2CBaseAddress = 0x%x \n", I2CBaseAddress));
+ }
+
+ NumTries = 10000; // 1 seconds
+ while ((1 == (I2CLibPeiMmioRead32 (I2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) {
+ MicroSecondDelay (10);
+ NumTries --;
+ if (0 == NumTries)
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = I2cDisable (BusNo);
+ if (DebugFlag) DEBUG ((DEBUG_INFO, "I2cDisable Status = %r\r\n", Status));
+
+ I2cBusFrequencySet (I2CBaseAddress, 400 * 1000, &I2cMode, DebugFlag); // Set I2cMode
+
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_INTR_MASK, 0x0);
+ if (0x7F < SlaveAddress) {
+ SlaveAddress = (SlaveAddress & 0x3FF) | IC_TAR_10BITADDR_MASTER;
+ }
+
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TAR, (UINT16) SlaveAddress);
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_RX_TL, 0);
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_TX_TL, 0);
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_CON, I2cMode);
+
+ Status = I2cEnable (BusNo);
+ if (DebugFlag) DEBUG ((DEBUG_INFO, "I2cEnable Status = %r\r\n", Status));
+
+ I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_CLR_TX_ABRT);
+ return EFI_SUCCESS;
+}
+
+/**
+ Read bytes from I2C Device
+ This is actual I2C hardware operation function.
+
+ @param[in] BusNo - I2C Bus number to which the I2C device has been connected
+ @param[in] SlaveAddress - Slave address of the I2C device (7-bit)
+ @param[in] ReadBytes - Number of bytes to be read
+ @param[out] ReadBuffer - Address to which the value read has to be stored
+ @param[in] Start - It controls whether a RESTART is issued before the byte is sent or received.
+ @param[in] End - It controls whether a STOP is issued after the byte is sent or received.
+
+ @retval EFI_SUCCESS - The byte value read successfully
+ @retval EFI_DEVICE_ERROR - Operation failed
+ @retval EFI_TIMEOUT - Hardware retry timeout
+ @retval Others - Failed to read a byte via I2C
+**/
+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 I2CBaseAddress;
+
+ I2CBaseAddress = (UINT32) (LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BAR0_DELTA));
+
+ Status = EFI_SUCCESS;
+
+ I2CInit (BusNo, SlaveAddress);
+
+ ReceiveDataEnd = &ReadBuffer [ReadBytes];
+ if (ReadBytes) {
+ ReceiveRequest = ReadBuffer;
+
+ while ((ReceiveDataEnd > ReceiveRequest) ||
+ (ReceiveDataEnd > ReadBuffer)) {
+ //
+ // Check for NACK
+ //
+ raw_intr_stat = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RAW_INTR_STAT);
+ if (0 != (raw_intr_stat & I2C_INTR_TX_ABRT)) {
+ I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_CLR_TX_ABRT);
+ Status = RETURN_DEVICE_ERROR;
+ DEBUG ((DEBUG_INFO,"TX ABRT ,%d bytes hasn't been transferred\r\n", ReceiveDataEnd - ReceiveRequest));
+ break;
+ }
+
+ //
+ // Determine if another byte was received
+ //
+ I2cStatus = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_STATUS);
+ if (0 != (I2cStatus & STAT_RFNE)) {
+ ReceiveData = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_DATA_CMD);
+ *ReadBuffer++ = (UINT8)ReceiveData;
+ }
+
+ if (ReceiveDataEnd == ReceiveRequest) {
+ continue; //Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
+ }
+
+ //
+ // Wait until a read request will fit
+ //
+ if (0 == (I2cStatus & STAT_TFNF)) {
+ MicroSecondDelay (10);
+ continue;
+ }
+
+ //
+ // Issue the next read request
+ //
+ if (End && Start) {
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD | B_CMD_RESTART | B_CMD_STOP);
+ } else if (!End && Start) {
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD | B_CMD_RESTART);
+ } else if (End && !Start) {
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD | B_CMD_STOP);
+ } else if (!End && !Start) {
+ I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD);
+ }
+ ReceiveRequest += 1;
+ }
+ }
+ return Status;
+
+}
+
+/**
+ Write bytes to I2C Device
+ This is actual I2C hardware operation function.
+
+ @param[in] BusNo - I2C Bus number to which the I2C device has been connected
+ @param[in] SlaveAddress - Slave address of the I2C device (7-bit)
+ @param[in] WriteBytes - Number of bytes to be written
+ @param[in] WriteBuffer - Address to which the byte value has to be written
+ @param[in] Start - It controls whether a RESTART is issued before the byte is sent or received.
+ @param[in] End - It controls whether a STOP is issued after the byte is sent or received.
+
+ @retval EFI_SUCCESS - The byte value written successfully
+ @retval EFI_DEVICE_ERROR - Operation failed
+ @retval EFI_TIMEOUT - Hardware retry timeout
+ @retval Others - Failed to write a byte via I2C
+**/
+EFI_STATUS
+ByteWriteI2C_Basic (
+ IN UINT8 BusNo,
+ IN UINT8 SlaveAddress,
+ IN UINTN WriteBytes,
+ IN UINT8 *WriteBuffer,
+ IN UINT8 Start,
+ IN UINT8 End
+ )
+{
+ UINT16 Data16;
+ EFI_STATUS Status;
+ UINT32 I2cStatus;
+ UINT8 *TransmitPtr;
+ UINT8 *TransmitEnd;
+ UINT16 raw_intr_stat;
+ UINTN I2CBaseAddress;
+
+
+ I2CBaseAddress = (UINT32)LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BAR0_DELTA);
+ Status = EFI_SUCCESS;
+ I2CInit (BusNo, SlaveAddress);
+
+ TransmitPtr = WriteBuffer;
+ TransmitEnd = &WriteBuffer[WriteBytes];
+ if (WriteBytes > 0x00) {
+
+
+ while (TransmitEnd > TransmitPtr) {
+ I2cStatus = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_STATUS);
+ raw_intr_stat = I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RAW_INTR_STAT);
+ if (0 != (raw_intr_stat & I2C_INTR_TX_ABRT)) {
+ I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_CLR_TX_ABRT);
+ Status = RETURN_DEVICE_ERROR;
+ DEBUG ((DEBUG_ERROR,"TX ABRT TransmitEnd:0x%x WritePtr:0x%x\r\n", TransmitEnd, TransmitPtr));
+ break;
+ }
+ if (0 == (I2cStatus & STAT_TFNF)) {
+ DEBUG ((DEBUG_INFO,"%a(#%d) - 0 == (I2cStatus & STAT_TFNF)\n", __FUNCTION__, __LINE__));
+ continue;
+ }
+
+ Data16 = (UINT16) *TransmitPtr;
+ if (End && Start) {
+ Data16 |= (B_CMD_RESTART | B_CMD_STOP);
+ } else if (!End && Start) {
+ Data16 |= B_CMD_RESTART;
+ } else if (End && !Start) {
+ Data16 |= B_CMD_STOP;
+ }
+ Data16 = I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, Data16);
+ TransmitPtr++;
+
+ //
+ // Add a small delay to work around some odd behavior being seen. Without this delay bytes get dropped.
+ //
+ MicroSecondDelay (FIFO_WRITE_DELAY);
+ }
+
+ }
+
+ if (EFI_ERROR (Status))
+ DEBUG ((EFI_D_INFO,"I2cStartRequest Exit with Status %r\r\n", Status));
+
+ return Status;
+}
+
+
+/**
+ Read bytes from I2C Device
+
+ @param[in] BusNo - I2C Bus number to which the I2C device has been connected
+ @param[in] SlaveAddress - Slave address of the I2C device (7-bit)
+ @param[in] Offset - Register offset from which the data has to be read
+ @param[in] ReadBytes - Number of bytes to be read
+ @param[out] ReadBuffer - Address to which the value read has to be stored
+
+ @retval EFI_SUCCESS - Read bytes from I2C device successfully
+ @retval Others - Return status depends on ByteReadI2C_Basic
+**/
+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)) return Status;
+ Status = ByteReadI2C_Basic (BusNo, SlaveAddress, ReadBytes, ReadBuffer, TRUE, TRUE);
+
+ return Status;
+}
+
+/**
+ Write bytes to I2C Device
+
+ @param[in] BusNo - I2C Bus number to which the I2C device has been connected
+ @param[in] SlaveAddress - Slave address of the I2C device (7-bit)
+ @param[in] Offset - Register offset from which the data has to be read
+ @param[in] WriteBytes - Number of bytes to be written
+ @param[in] WriteBuffer - Address to which the byte value has to be written
+
+ @retval EFI_SUCCESS - Write bytes to I2C device successfully
+ @retval Others - Return status depends on ByteWriteI2C_Basic
+**/
+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)) return Status;
+ Status = ByteWriteI2C_Basic (BusNo, SlaveAddress, WriteBytes, WriteBuffer, FALSE, TRUE);
+
+ return Status;
+}
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.inf
new file mode 100644
index 0000000000..1f920bb0a5
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLibPei.inf
@@ -0,0 +1,51 @@
+## @file
+# Pei library for I2C bus driver.
+#
+# Copyright (c) 1999 - 2017, 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]
+
+[PPIs]
+ gEfiPeiStallPpiGuid ## CONSUMES
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## SOMETIMES_CONSUMES
+ gEfiBxtTokenSpaceGuid.PcdPmcGcrBaseAddress ## CONSUMES
+
+
+