From nobody Thu Dec 26 11:54:49 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1503544650219277.7049308048878; Wed, 23 Aug 2017 20:17:30 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 0FAC821D2E640; Wed, 23 Aug 2017 20:14:54 -0700 (PDT) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 56E932095B9CF for ; Wed, 23 Aug 2017 20:14:53 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 23 Aug 2017 20:17:27 -0700 Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by fmsmga001.fm.intel.com with ESMTP; 23 Aug 2017 20:17:27 -0700 Received: from fmsmsx158.amr.corp.intel.com (10.18.116.75) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 23 Aug 2017 20:17:25 -0700 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by fmsmsx158.amr.corp.intel.com (10.18.116.75) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 23 Aug 2017 20:17:24 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.183]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.93]) with mapi id 14.03.0319.002; Thu, 24 Aug 2017 11:17:22 +0800 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,419,1498546800"; d="dat'59?scan'59,208,59";a="1187564487" From: "Guo, Mang" To: "edk2-devel@lists.01.org" Thread-Topic: [Patch][edk2-platforms/devel-MinnowBoard3-UDK2017 06/1BroxtonSiPkg: Add I2CLibPei Thread-Index: AdMch4BUa3AX8x7STKGyoug+MiieXQ== Date: Thu, 24 Aug 2017 03:17:22 +0000 Message-ID: <22D2C85ED001C54AA20BFE3B0E4751D15253FC40@shsmsx102.ccr.corp.intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: <22D2C85ED001C54AA20BFE3B0E4751D15253FC40@shsmsx102.ccr.corp.intel.com> x-originating-ip: [10.239.127.40] MIME-Version: 1.0 X-Content-Filtered-By: Mailman/MimeDel 2.1.22 Subject: [edk2] [Patch][edk2-platforms/devel-MinnowBoard3-UDK2017 06/1BroxtonSiPkg: Add I2CLibPei X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../PlatformDsc/Components.IA32.dsc | 1 + .../SouthCluster/Include/Library/I2CLib.h | 106 +--- .../SouthCluster/Include/ScRegs/RegsI2c.h | 143 +++++ .../SouthCluster/Library/I2CLibPei/I2CAccess.h | 51 ++ .../SouthCluster/Library/I2CLibPei/I2CDelayPei.c | 49 ++ .../SouthCluster/Library/I2CLibPei/I2CDelayPei.h | 34 ++ .../SouthCluster/Library/I2CLibPei/I2CIoLibPei.c | 175 ++++++ .../SouthCluster/Library/I2CLibPei/I2CIoLibPei.h | 146 +++++ .../SouthCluster/Library/I2CLibPei/I2CLibPei.c | 665 +++++++++++++++++= ++++ .../SouthCluster/Library/I2CLibPei/I2CLibPei.inf | 51 ++ 10 files changed, 1322 insertions(+), 99 deletions(-) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Sc= Regs/RegsI2c.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2= CLibPei/I2CAccess.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2= CLibPei/I2CDelayPei.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2= CLibPei/I2CDelayPei.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2= CLibPei/I2CIoLibPei.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2= CLibPei/I2CIoLibPei.h create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2= CLibPei/I2CLibPei.c create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2= CLibPei/I2CLibPei.inf diff --git a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.IA32.dsc b/= Platform/BroxtonPlatformPkg/PlatformDsc/Components.IA32.dsc index f8900ea..cdbba2a 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/BoardInit= PostMem.inf NULL|$(PLATFORM_NAME)/Board/LeafHill/BoardInitPostMem/BoardInitPost= Mem.inf NULL|$(PLATFORM_NAME)/Board/BensonGlacier/BoardInitPostMem/BoardIni= tPostMem.inf + I2cLibPei|$(PLATFORM_SI_PACKAGE)/SouthCluster/Library/I2CLibPei/I2C= LibPei.inf gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x803805c6 } diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/I= 2CLib.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/Library/I2CL= ib.h index b593620..b897cb9 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. =20 - Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License @@ -18,111 +18,19 @@ =20 #include #include - // // FIFO write workaround value. // #define FIFO_WRITE_DELAY 2 =20 -// -// 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 Bu= ffer and Command - -#define B_READ_CMD BIT8 ///< 1 =3D read, 0 =3D= write -#define B_CMD_STOP BIT9 ///< 1 =3D STOP -#define B_CMD_RESTART BIT10 ///< 1 =3D IC_RESTART_= EN - -#define V_WRITE_CMD_MASK (0xFF) - -#define R_IC_SS_SCL_HCNT (0x14) ///< Standard Speed I= 2C Clock SCL High Count -#define R_IC_SS_SCL_LCNT (0x18) ///< Standard Speed I= 2C Clock SCL Low Count -#define R_IC_FS_SCL_HCNT (0x1C) ///< Full Speed I2C C= lock SCL High Count -#define R_IC_FS_SCL_LCNT (0x20) ///< Full Speed I2C C= lock SCL Low Count -#define R_IC_HS_SCL_HCNT (0x24) ///< High Speed I2C C= lock SCL High Count -#define R_IC_HS_SCL_LCNT (0x28) ///< High Speed I2C C= lock SCL Low Count -#define R_IC_INTR_STAT (0x2C) ///< I2C Inetrrupt St= atus -#define R_IC_INTR_MASK (0x30) ///< I2C Interrupt Ma= sk -#define I2C_INTR_GEN_CALL BIT11 ///< General call rec= eived -#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 Interrup= t Status -#define R_IC_RX_TL (0x38) ///< I2C Receive FIFO= Threshold -#define R_IC_TX_TL (0x3C) ///< I2C Transmit FIF= O Threshold -#define R_IC_CLR_INTR (0x40) ///< Clear Combined a= nd Individual Interrupts -#define R_IC_CLR_RX_UNDER (0x44) ///< Clear RX_UNDER I= nterrupt -#define R_IC_CLR_RX_OVER (0x48) ///< Clear RX_OVERint= errupt -#define R_IC_CLR_TX_OVER (0x4C) ///< Clear TX_OVER in= terrupt -#define R_IC_CLR_RD_REQ (0x50) ///< Clear RD_REQ int= errupt -#define R_IC_CLR_TX_ABRT (0x54) ///< Clear TX_ABRT in= terrupt -#define R_IC_CLR_RX_DONE (0x58) ///< Clear RX_DONE in= terrupt -#define R_IC_CLR_ACTIVITY (0x5C) ///< Clear ACTIVITY i= nterrupt -#define R_IC_CLR_STOP_DET (0x60) ///< Clear STOP_DET i= nterrupt -#define R_IC_CLR_START_DET (0x64) ///< Clear START_DET = interrupt -#define R_IC_CLR_GEN_CALL (0x68) ///< Clear GEN_CALL i= nterrupt -#define R_IC_ENABLE (0x6C) ///< I2C Enable -#define R_IC_STATUS (0x70) ///< I2C Status - -#define R_IC_SDA_HOLD (0x7C) ///< I2C IC_DEFAULT_S= DA_HOLD//16bits - -#define STAT_MST_ACTIVITY BIT5 ///< Master FSM Activi= ty Status. -#define STAT_RFF BIT4 ///< RX FIFO is comple= tely full -#define STAT_RFNE BIT3 ///< RX FIFO is not em= pty -#define STAT_TFE BIT2 ///< TX FIFO is comple= tely empty -#define STAT_TFNF BIT1 ///< TX FIFO is not fu= ll - -#define R_IC_TXFLR (0x74) ///< Transmit FIFO Le= vel Register -#define R_IC_RXFLR (0x78) ///< Receive FIFO Lev= el Register -#define R_IC_TX_ABRT_SOURCE (0x80) ///< I2C Transmit Abo= rt Status Register -#define R_IC_SLV_DATA_NACK_ONLY (0x84) ///< Generate SLV_DAT= A_NACK Register -#define R_IC_DMA_CR (0x88) ///< DMA Control Regi= ster -#define R_IC_DMA_TDLR (0x8C) ///< DMA Transmit Dat= a Level -#define R_IC_DMA_RDLR (0x90) ///< DMA Receive Data= Level -#define R_IC_SDA_SETUP (0x94) ///< I2C SDA Setup Re= gister -#define R_IC_ACK_GENERAL_CALL (0x98) ///< I2C ACK General = Call Register -#define R_IC_ENABLE_STATUS (0x9C) ///< I2C Enable Statu= s Register -#define R_IC_COMP_PARAM (0xF4) ///< Component Parame= ter Register -#define R_IC_COMP_VERSION (0xF8) ///< Component Versio= n 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. =20 - @param[in] BusNo I2C Bus number to which the I2C device= has been connected - - @retval EFI_SUCCESS I2C controller's BAR0 is programmed an= d memory decode enabled. - @retval EFI_NOT_READY I2C controller's is not exist or its f= unction has been disabled. - + @retval EFI_SUCCESS - I2C controller's BAR0 is programmed and = memory decode enabled. **/ EFI_STATUS ProgramPciLpssI2C ( - IN UINT8 BusNo + VOID ); =20 /** @@ -130,7 +38,7 @@ ProgramPciLpssI2C ( This is actual I2C hardware operation function. =20 @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 issue= d before the byte is sent or received. @@ -157,7 +65,7 @@ ByteReadI2C_Basic ( This is actual I2C hardware operation function. =20 @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 issue= d before the byte is sent or received. @@ -183,7 +91,7 @@ ByteWriteI2C_Basic ( Read bytes from I2C Device =20 @param[in] BusNo I2C Bus number to which the I2C device h= as 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 b= e stored @@ -205,7 +113,7 @@ ByteReadI2C ( Write bytes to I2C Device =20 @param[in] BusNo I2C Bus number to which the I2C device h= as 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 b= e written diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/Re= gsI2c.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsI= 2c.h new file mode 100644 index 0000000..5fc758d --- /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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#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 Bu= ffer and Command + +#define B_READ_CMD BIT8 ///< 1 =3D read, 0 =3D= write +#define B_CMD_STOP BIT9 ///< 1 =3D STOP +#define B_CMD_RESTART BIT10 ///< 1 =3D IC_RESTART_= EN + +#define V_WRITE_CMD_MASK (0xFF) + +#define R_IC_SS_SCL_HCNT (0x14) ///< Standard Speed I2= C Clock SCL High Count +#define R_IC_SS_SCL_LCNT (0x18) ///< Standard Speed I2= C Clock SCL Low Count +#define R_IC_FS_SCL_HCNT (0x1C) ///< Full Speed I2C Cl= ock SCL High Count +#define R_IC_FS_SCL_LCNT (0x20) ///< Full Speed I2C Cl= ock SCL Low Count +#define R_IC_HS_SCL_HCNT (0x24) ///< High Speed I2C Cl= ock SCL High Count +#define R_IC_HS_SCL_LCNT (0x28) ///< High Speed I2C Cl= ock SCL Low Count +#define R_IC_INTR_STAT (0x2C) ///< I2C Inetrrupt Sta= tus +#define R_IC_INTR_MASK (0x30) ///< I2C Interrupt Mask +#define I2C_INTR_GEN_CALL BIT11 ///< General call recei= ved +#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 F= IFO 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 an= d Individual Interrupts +#define R_IC_CLR_RX_UNDER (0x44) ///< Clear RX_UNDER In= terrupt +#define R_IC_CLR_RX_OVER (0x48) ///< Clear RX_OVERinte= rrupt +#define R_IC_CLR_TX_OVER (0x4C) ///< Clear TX_OVER int= errupt +#define R_IC_CLR_RD_REQ (0x50) ///< Clear RD_REQ inte= rrupt +#define R_IC_CLR_TX_ABRT (0x54) ///< Clear TX_ABRT int= errupt +#define R_IC_CLR_RX_DONE (0x58) ///< Clear RX_DONE int= errupt +#define R_IC_CLR_ACTIVITY (0x5C) ///< Clear ACTIVITY in= terrupt +#define R_IC_CLR_STOP_DET (0x60) ///< Clear STOP_DET in= terrupt +#define R_IC_CLR_START_DET (0x64) ///< Clear START_DET i= nterrupt +#define R_IC_CLR_GEN_CALL (0x68) ///< Clear GEN_CALL in= terrupt +#define R_IC_ENABLE (0x6C) ///< I2C Enable +#define R_IC_STATUS (0x70) ///< I2C Status + +#define R_IC_SDA_HOLD (0x7C) ///< I2C IC_DEFAULT_SD= A_HOLD//16bits + +#define STAT_MST_ACTIVITY BIT5 ///< Master FSM Activit= y Status. +#define STAT_RFF BIT4 ///< RX FIFO is complet= ely full +#define STAT_RFNE BIT3 ///< RX FIFO is not emp= ty +#define STAT_TFE BIT2 ///< TX FIFO is complet= ely empty +#define STAT_TFNF BIT1 ///< TX FIFO is not full + +#define R_IC_TXFLR (0x74) ///< Transmit FIFO Lev= el Register +#define R_IC_RXFLR (0x78) ///< Receive FIFO Leve= l Register +#define R_IC_TX_ABRT_SOURCE (0x80) ///< I2C Transmit Abor= t Status Register +#define R_IC_SLV_DATA_NACK_ONLY (0x84) ///< Generate SLV_DATA= _NACK Register +#define R_IC_DMA_CR (0x88) ///< DMA Control Regis= ter +#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 Reg= ister +#define R_IC_ACK_GENERAL_CALL (0x98) ///< I2C ACK General C= all Register +#define R_IC_ENABLE_STATUS (0x9C) ///< I2C Enable Status= Register +#define R_IC_COMP_PARAM (0xF4) ///< Component Paramet= er 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/I2CLibP= ei/I2CAccess.h new file mode 100644 index 0000000..792a483 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CAcc= ess.h @@ -0,0 +1,51 @@ + +/** @file + Macros that simplify accessing I2C device's registers. + + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#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 Byt= es +#define V_ACPI_PM1_TMR_MAX_VAL 0x1000000 ///< The timer is 24 bit o= verflow +#define B_ACPI_PM1_TMR_VAL 0xFFFFFF ///< The timer value mask + +#define R_ACPI_PM1_TMR 0x08 ///< Power Management 1 Ti= mer +#define V_ACPI_PM1_TMR_FREQUENCY 3579545 ///< Timer Frequency + + +#define ScLpcPciCfg8(Register) I2CLibPeiMmioRead8 (MmPciAddress (0, D= EFAULT_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/I2CLi= bPei/I2CDelayPei.c new file mode 100644 index 0000000..409376a --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDel= ayPei.c @@ -0,0 +1,49 @@ +/** @file + Timer instance for I2C Pei Library. + + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include +#include "I2CAccess.h" +#include "I2CDelayPei.h" +#include +#include +#include + +/** + 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 =3D GetPeiServicesTablePointer (); + + Status =3D (**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/I2CLi= bPei/I2CDelayPei.h new file mode 100644 index 0000000..53ab6e0 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CDel= ayPei.h @@ -0,0 +1,34 @@ +/** @file + imer prototype for I2C Pei Library. + + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _I2C_DELAY_PEI_ +#define _I2C_DELAY_PEI_ + +#include + +/** + 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/I2CLi= bPei/I2CIoLibPei.c new file mode 100644 index 0000000..f4cc843 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoL= ibPei.c @@ -0,0 +1,175 @@ +/** @file + IO instance for I2C Pei Library. + + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include +#include +#include + + +/** + 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 =3D *(volatile UINT8*)Address; + return Value; +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read val= ue 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) =3D=3D 0); + Value =3D *(volatile UINT16*)Address; + return Value; +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value spec= ified + by Value and returns Value. This function must guarantee that all MMIO r= ead + 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) =3D=3D 0); + *(volatile UINT16*)Address =3D Value; + return Value; +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read val= ue 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) =3D=3D 0); + Value =3D *(volatile UINT32*)Address; + + return Value; +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value spec= ified + by Value and returns Value. This function must guarantee that all MMIO r= ead + 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) =3D=3D 0); + *(volatile UINT32*)Address =3D Value; + return Value; +} + +/** + Do logical OR operation with the value read from the 32-bit MMIO regist= er + 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 val= ue 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) | Or= Data); +} + + diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei= /I2CIoLibPei.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLi= bPei/I2CIoLibPei.h new file mode 100644 index 0000000..0ea1727 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CIoL= ibPei.h @@ -0,0 +1,146 @@ +/** @file + IO prototype for I2C Pei Library. + + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _I2C_IOLIB_PEI_ +#define _I2C_IOLIB_PEI_ + +#include + +/** + 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 val= ue 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 spec= ified + by Value and returns Value. This function must guarantee that all MMIO r= ead + 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 val= ue 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 spec= ified + by Value and returns Value. This function must guarantee that all MMIO r= ead + 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 regist= er + 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 val= ue 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/I2CLibP= ei/I2CLibPei.c new file mode 100644 index 0000000..fd66671 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLib= Pei.c @@ -0,0 +1,665 @@ +/** @file + Pei library for I2C bus driver. + + Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "I2CDelayPei.h" +#include "I2CIoLibPei.h" +#include "I2CAccess.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EFI_GUID mI2CPeiInitGuid =3D { + 0x96DED71A, 0xB9E7, 0x4EAD, 0x96, 0x2C, 0x01, 0x69, 0x3C, 0xED, 0x2A, 0x= 64 +}; + + +#define LPSS_PCI_DEVICE_NUMBER 8 + + +#define GPIO_PAD_CFG_DW0_GPIO_124_OFFSET 0x400 ///< This is the first gp= io 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 mis= c settings. + for (Index =3D 0; Index < 8; Index ++) { + // Config I2C[Index] SDA pin DW0 + gpio_pad_cfg_dw0_offset =3D GPIO_PAD_CFG_DW0_GPIO_124_OFFSET + 16 * In= dex; + { + //Value =3D 0; // FIXME: the right GPIO setting, need to get update= d 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 +=3D 4; + { + //Value =3D 0; // FIXME: the right GPIO setting, need to get update= d 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 +=3D 4; + { + //Value =3D 0; // FIXME: the right GPIO setting, need to get update= d 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 +=3D 4; + { + //Value =3D 0; // FIXME: the right GPIO setting, need to get update= d 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=3D0; + UINTN Index; + UINTN Bar0; + UINTN Bar1; + + DEBUG ((EFI_D_INFO, "Pei ProgramPciLpssI2C() Start\n")); + + // + // Set the BXT Function Disable Register to ZERO + // + PmcBase =3D 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_DI= S_LPSS_I2C2 | B_PMC_FUNC_DIS_LPSS_I2C3| + B_PMC_FUNC_DIS_LPSS_I2C4 | B_PMC_FUNC_DIS_LPSS_I2C5 | B_PMC_FUNC_DI= S_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_FUN= C_DIS_LPSS_I2C2| B_PMC_FUNC_DIS_LPSS_I2C3| + B_PMC_FUNC_DIS_LPSS_I2C4| B_PMC_FUNC_DIS_LPSS_I2C5|B_PMC_FUN= C_DIS_LPSS_I2C6| B_PMC_FUNC_DIS_LPSS_I2C7) + ); + + DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() enable all I2C controllers\n"= )); + } + + for (Index =3D 0; Index < LPSS_PCI_DEVICE_NUMBER; Index ++) { + if (Index < 4) { + PciMmBase =3D MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_LPSS_I2C0, + Index, + 0 + ); + } else { + PciMmBase =3D MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_LPSS_I2C1, + (Index - 4), + 0 + ); + } + + DevID =3D I2CLibPeiMmioRead32 (PciMmBase); + Bar0 =3D LPSS_I2C0_TMP_BAR0 + Index * LPSS_I2C_TMP_BAR0_DELTA; + Bar1 =3D Bar0 + LPSS_I2C_TMP_BAR1_OFFSET; + + // + // Check if device present + // + if (DevID !=3D 0xFFFFFFFF) { + if ((I2CLibPeiMmioRead32 (PciMmBase + R_LPSS_I2C_STSCMD) & B_LPSS_I2= C_STSCMD_MSE)) { + // + // In PEI stage, we always disable Bus master, and memory space en= abling for BAR re-programming + // In DXE stage, will read existing BAR value instead of re-progra= mming + // + 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), (UINT= 32) (B_LPSS_I2C_STSCMD_BME | B_LPSS_I2C_STSCMD_MSE)); + } + + // + // Release Resets + // + I2CLibPeiMmioWrite32 (Bar0 + R_LPSS_IO_MEM_RESETS, B_LPSS_IO_MEM_HC_RE= SET_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 h= as been connected + + @retval EFI_SUCCESS - I2C host controller is completely inacti= ve. + @retval EFI_NOT_READY - I2C host controller is still in an enabl= ed state. +**/ +EFI_STATUS +I2cDisable ( + IN UINT8 BusNo + ) +{ + UINTN I2CBaseAddress; + UINT32 NumTries =3D 10000; // 0.1 seconds + + I2CBaseAddress =3D (UINT32) LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_B= AR0_DELTA); + I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 0); + while (0 !=3D (I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_ENABLE) & 1)) { + MicroSecondDelay (10); + NumTries--; + if (NumTries =3D=3D 0) return EFI_NOT_READY; + } + return EFI_SUCCESS; +} + + +/** + Enable I2C host controller + + @param[in] BusNo - I2C Bus number to which the I2C device h= as been connected + + @retval EFI_SUCCESS - I2C host controller is in an enabled sta= te. + @retval EFI_NOT_READY - I2C host controller is still inactive. +**/ +EFI_STATUS +I2cEnable ( + IN UINT8 BusNo + ) +{ + UINTN I2CBaseAddress; + UINT32 NumTries =3D 10000; //0.1 seconds + + I2CBaseAddress =3D (UINT32) LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_B= AR0_DELTA); + I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_ENABLE, 1); + while (0 =3D=3D (I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_ENABLE ) & 1= )) { + MicroSecondDelay (10); + NumTries --; + if (NumTries =3D=3D 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_UNSUPPORTE= D. + + @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", Bu= sClockHertz)); + + *I2cMode =3D 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 |=3D V_SPEED_STANDARD; + break; + case 400 * 1000: + I2CLibPeiMmioWrite32 (I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x32);= //400K + *I2cMode |=3D V_SPEED_FAST; + break; + default: + I2CLibPeiMmioWrite32 (I2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x09);= //3.4M + *I2cMode |=3D 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 controll= er +**/ +EFI_STATUS +I2CInit ( + IN UINT8 BusNo, + IN UINT16 SlaveAddress + ) +{ + EFI_STATUS Status; + UINT32 NumTries =3D 0; + UINTN I2CBaseAddress; + UINT16 I2cMode; + UINTN PciMmBase =3D 0; + BOOLEAN DebugFlag =3D TRUE; + + if (BusNo < 4) { + PciMmBase =3D MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_LPSS_I2C0, + BusNo, + 0 + ); + } else { + PciMmBase =3D MmPciAddress ( + 0, + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_LPSS_I2C1, + (BusNo - 4), + 0 + ); + } + + I2CBaseAddress =3D (I2CLibPeiMmioRead32 (PciMmBase + R_LPSS_I2C_BAR) & 0= xFFFFFFF8); + + // + // Verify the parameters + // + if (1023 < SlaveAddress) { + Status =3D EFI_INVALID_PARAMETER; + if (DebugFlag) DEBUG ((DEBUG_ERROR, "I2cStartRequest Exit with Status = %r\r\n", Status)); + return Status; + } + + if (I2CBaseAddress =3D=3D (LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BA= R0_DELTA))) { + DebugFlag =3D FALSE; + } else { + // + // Need to enable the I2C PCI device + // + ProgramPciLpssI2C (); + + I2CBaseAddress =3D (UINT32) (LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TM= P_BAR0_DELTA)); + if (DebugFlag) DEBUG ((DEBUG_INFO, "I2CBaseAddress =3D 0x%x \n", I2CBa= seAddress)); + } + + NumTries =3D 10000; // 1 seconds=20 + while ((1 =3D=3D (I2CLibPeiMmioRead32 (I2CBaseAddress + R_IC_STATUS) & S= TAT_MST_ACTIVITY ))) { + MicroSecondDelay (10); + NumTries --; + if (0 =3D=3D NumTries) + return EFI_DEVICE_ERROR; + } + + Status =3D I2cDisable (BusNo); + if (DebugFlag) DEBUG ((DEBUG_INFO, "I2cDisable Status =3D %r\r\n", Statu= s)); + + I2cBusFrequencySet (I2CBaseAddress, 400 * 1000, &I2cMode, DebugFlag); //= Set I2cMode + + I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_INTR_MASK, 0x0); + if (0x7F < SlaveAddress) { + SlaveAddress =3D (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 =3D I2cEnable (BusNo); + if (DebugFlag) DEBUG ((DEBUG_INFO, "I2cEnable Status =3D %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 h= as 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 b= e 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 aft= er 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 =3D (UINT32) (LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_= BAR0_DELTA)); + + Status =3D EFI_SUCCESS; + + I2CInit (BusNo, SlaveAddress); + + ReceiveDataEnd =3D &ReadBuffer [ReadBytes]; + if (ReadBytes) { + ReceiveRequest =3D ReadBuffer; + + while ((ReceiveDataEnd > ReceiveRequest) || + (ReceiveDataEnd > ReadBuffer)) { + // + // Check for NACK + // + raw_intr_stat =3D I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RAW_INT= R_STAT); + if (0 !=3D (raw_intr_stat & I2C_INTR_TX_ABRT)) { + I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_CLR_TX_ABRT); + Status =3D 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 =3D I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_STATUS); + if (0 !=3D (I2cStatus & STAT_RFNE)) { + ReceiveData =3D I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_DATA_CM= D); + *ReadBuffer++ =3D (UINT8)ReceiveData; + } + + if (ReceiveDataEnd =3D=3D ReceiveRequest) { + continue; //Waiting the last request to get data and make (Receive= DataEnd > ReadBuffer) =3DTRUE. + } + + // + // Wait until a read request will fit + // + if (0 =3D=3D (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 +=3D 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 h= as 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 b= e 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 aft= er 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 =3D (UINT32)LPSS_I2C0_TMP_BAR0 + (BusNo * LPSS_I2C_TMP_BA= R0_DELTA); + Status =3D EFI_SUCCESS; + I2CInit (BusNo, SlaveAddress); + + TransmitPtr =3D WriteBuffer; + TransmitEnd =3D &WriteBuffer[WriteBytes]; + if (WriteBytes > 0x00) { + + + while (TransmitEnd > TransmitPtr) { + I2cStatus =3D I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_STATUS); + raw_intr_stat =3D I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_RAW_INT= R_STAT); + if (0 !=3D (raw_intr_stat & I2C_INTR_TX_ABRT)) { + I2CLibPeiMmioRead16 (I2CBaseAddress + R_IC_CLR_TX_ABRT); + Status =3D RETURN_DEVICE_ERROR; + DEBUG ((DEBUG_ERROR,"TX ABRT TransmitEnd:0x%x WritePtr:0x%x\r\n", = TransmitEnd, TransmitPtr)); + break; + } + if (0 =3D=3D (I2cStatus & STAT_TFNF)) { + DEBUG ((DEBUG_INFO,"%a(#%d) - 0 =3D=3D (I2cStatus & STAT_TFNF)\n",= __FUNCTION__, __LINE__)); + continue; + } + + Data16 =3D (UINT16) *TransmitPtr; + if (End && Start) { + Data16 |=3D (B_CMD_RESTART | B_CMD_STOP); + } else if (!End && Start) { + Data16 |=3D B_CMD_RESTART; + } else if (End && !Start) { + Data16 |=3D B_CMD_STOP; + } + Data16 =3D I2CLibPeiMmioWrite16 (I2CBaseAddress + R_IC_DATA_CMD, Dat= a16); + TransmitPtr++; + + // + // Add a small delay to work around some odd behavior being seen. W= ithout 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 h= as 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 b= e stored + + @retval EFI_SUCCESS - Read bytes from I2C device successfully + @retval Others - Return status depends on ByteReadI2C_Bas= ic +**/ +EFI_STATUS +ByteReadI2C ( + IN UINT8 BusNo, + IN UINT8 SlaveAddress, + IN UINT8 Offset, + IN UINTN ReadBytes, + OUT UINT8 *ReadBuffer + ) +{ + EFI_STATUS Status; + + Status =3D ByteWriteI2C_Basic (BusNo, SlaveAddress, 1, &Offset, TRUE, FA= LSE); + if (EFI_ERROR (Status)) return Status; + Status =3D 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 h= as 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 b= e written + + @retval EFI_SUCCESS - Write bytes to I2C device successfully + @retval Others - Return status depends on ByteWriteI2C_Ba= sic +**/ +EFI_STATUS +ByteWriteI2C ( + IN UINT8 BusNo, + IN UINT8 SlaveAddress, + IN UINT8 Offset, + IN UINTN WriteBytes, + IN UINT8 *WriteBuffer + ) +{ + EFI_STATUS Status; + + Status =3D ByteWriteI2C_Basic (BusNo, SlaveAddress, 1, &Offset, TRUE, FA= LSE); + if (EFI_ERROR (Status)) return Status; + Status =3D ByteWriteI2C_Basic (BusNo, SlaveAddress, WriteBytes, WriteBuf= fer, FALSE, TRUE); + + return Status; +} diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei= /I2CLibPei.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLi= bPei/I2CLibPei.inf new file mode 100644 index 0000000..1f920bb --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/I2CLibPei/I2CLib= Pei.inf @@ -0,0 +1,51 @@ +## @file +# Pei library for I2C bus driver. +# +# Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e 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 IM= PLIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D I2CLibPei + FILE_GUID =3D 8EF61509-890B-4FF2-B352-1C0E9CDDEC8B + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D I2CLibPei + + CONSTRUCTOR =3D IntelI2CPeiLibConstructor + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D 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 + + + --=20 2.10.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel