From nobody Mon Dec 23 09:50:53 2024 Delivered-To: importer@patchew.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 1518422932495400.24563759583157; Mon, 12 Feb 2018 00:08:52 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 1ACC422361E61; Mon, 12 Feb 2018 00:03:01 -0800 (PST) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) (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 7A37D222DE15F for ; Mon, 12 Feb 2018 00:02:59 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Feb 2018 00:08:47 -0800 Received: from zwei4-mobl1.ccr.corp.intel.com ([10.239.193.69]) by fmsmga001.fm.intel.com with ESMTP; 12 Feb 2018 00:08:46 -0800 X-Original-To: edk2-devel@lists.01.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; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.136; helo=mga12.intel.com; envelope-from=david.wei@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,501,1511856000"; d="scan'208";a="30042274" From: zwei4 To: edk2-devel@lists.01.org Date: Mon, 12 Feb 2018 16:08:28 +0800 Message-Id: <20180212080828.21208-1-david.wei@intel.com> X-Mailer: git-send-email 2.14.1.windows.1 Subject: [edk2] [Patch][edk2-platforms/devel-MinnowBoard3-UDK2017] SMBus Library. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 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" Apollo Lake South Cluster SMBus executive code, which is common for PEI, DX= E and SMM modules. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: zwei4 Cc: Mang Guo --- .../PeiDxeSmmScSmbusCommonLib.inf | 35 ++ .../PeiDxeSmmScSmbusCommonLib/ScSmbusExec.c | 653 +++++++++++++++++= ++++ 2 files changed, 688 insertions(+) create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Pr= ivate/PeiDxeSmmScSmbusCommonLib/PeiDxeSmmScSmbusCommonLib.inf create mode 100644 Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Pr= ivate/PeiDxeSmmScSmbusCommonLib/ScSmbusExec.c diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/P= eiDxeSmmScSmbusCommonLib/PeiDxeSmmScSmbusCommonLib.inf b/Silicon/BroxtonSoC= /BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSmmScSmbusCommonLib/PeiDxe= SmmScSmbusCommonLib.inf new file mode 100644 index 000000000..2ca6549b8 --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSm= mScSmbusCommonLib/PeiDxeSmmScSmbusCommonLib.inf @@ -0,0 +1,35 @@ +## @file +# Apollo Lake South Cluster Smbus Common Lib. +# +# Copyright (c) 1999 - 2018, 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 PeiDxeSmmPchSmbusCommonLib + FILE_GUID =3D 490CEB45-F3A8-41CD-89CB-C47BF7F7A4B4 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D ScSmbusCommonLib + +[Sources] + ScSmbusExec.c + +[Packages] + MdePkg/MdePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + BroxtonSiPkg/BroxtonSiPrivate.dec + +[LibraryClasses] + IoLib + DebugLib + MmPciLib diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/P= eiDxeSmmScSmbusCommonLib/ScSmbusExec.c b/Silicon/BroxtonSoC/BroxtonSiPkg/So= uthCluster/Library/Private/PeiDxeSmmScSmbusCommonLib/ScSmbusExec.c new file mode 100644 index 000000000..2c5fe9b7b --- /dev/null +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Library/Private/PeiDxeSm= mScSmbusCommonLib/ScSmbusExec.c @@ -0,0 +1,653 @@ +/** @file + Apollo Lake South Cluster Smbus Executive Code (common PEI/DXE/SMM code). + + Copyright (c) 2014 - 2018, 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 +#include +#include +#include +#include +#include +#include + +/** + Get SMBUS IO Base address. + + @param[in] None + + @retval UINT32 The SMBUS IO Base Address +**/ +UINT32 +SmbusGetIoBase ( + VOID + ) +{ + UINT32 SmbusIoBase; + + SmbusIoBase =3D MmioRead32 ( + MmPciBase ( + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_SMBUS, + PCI_FUNCTION_NUMBER_SMBUS) + + R_SMBUS_BASE) & B_SMBUS_BASE_BAR; + + ASSERT (SmbusIoBase !=3D B_SMBUS_BASE_BAR && SmbusIoBase !=3D 0); + + return SmbusIoBase; +} + +/** + This function provides a standard way to read PCH Smbus IO registers. + + @param[in] Offset Register offset from Smbus base IO addre= ss. + + @retval UINT8 Returns data read from IO. +**/ +UINT8 +EFIAPI +SmbusIoRead ( + IN UINT8 Offset + ) +{ + return IoRead8 (SmbusGetIoBase () + Offset); +} + +/** + This function provides a standard way to write PCH Smbus IO registers. + + @param[in] Offset Register offset from Smbus base IO addre= ss. + @param[in] Data Data to write to register. + +**/ +VOID +EFIAPI +SmbusIoWrite ( + IN UINT8 Offset, + IN UINT8 Data + ) +{ + + IoWrite8 (SmbusGetIoBase () + Offset, Data); + return; +} + +/** + This function provides a standard way to check if a SMBus transaction has + completed. + + @param[in] StsReg Not used for input. On return, contains = the + value of the SMBus status register. + + @retval TRUE Transaction is complete + @retval FALSE Otherwise. +**/ +BOOLEAN +EFIAPI +IoDone ( + IN UINT8 *StsReg + ) +{ + UINTN StallIndex; + UINTN StallTries; + + StallTries =3D STALL_TIME / STALL_PERIOD; + + for (StallIndex =3D 0; StallIndex < StallTries; StallIndex++) { + *StsReg =3D SmbusIoRead (R_SMBUS_HSTS); + if (*StsReg & (B_SMBUS_INTR | B_SMBUS_BYTE_DONE_STS | B_SMBUS_DERR | B= _SMBUS_BERR)) { + return TRUE; + } else { + MicroSecondDelay (STALL_PERIOD); + } + } + + return FALSE; +} + +/** + Check if it's ok to use the bus. + + + @retval EFI_SUCCESS SmBus is acquired and it's safe to send = commands. + @retval EFI_TIMEOUT SmBus is busy, it's not safe to send com= mands. +**/ +EFI_STATUS +AcquireBus ( + VOID + ) +{ + UINT8 StsReg; + + StsReg =3D 0; + StsReg =3D SmbusIoRead (R_SMBUS_HSTS); + if (StsReg & B_SMBUS_IUS) { + return EFI_TIMEOUT; + } else if (StsReg & B_SMBUS_HBSY) { + /// + /// Clear Status Register and exit + /// + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_HSTS_ALL); + return EFI_TIMEOUT; + } else { + /// + /// Clear out any odd status information (Will Not Clear In Use) + /// + SmbusIoWrite (R_SMBUS_HSTS, StsReg); + return EFI_SUCCESS; + } +} + +/** + This function provides a standard way to execute Smbus protocols + as defined in the SMBus Specification. The data can either be of + the Length byte, word, or a block of data. The resulting transaction wil= l be + either the SMBus Slave Device accepts this transaction or this function + returns with an error + + @param[in] SlaveAddress Smbus Slave device the command is direct= ed at + @param[in] Command Slave Device dependent + @param[in] Operation Which SMBus protocol will be used + @param[in] PecCheck Defines if Packet Error Code Checking is= to be used + @param[in, out] Length How many bytes to read. Must be 0 <=3D L= ength <=3D 32 depending on Operation + It will contain the actual number of byt= es read/written. + @param[in, out] Buffer Contain the data read/written. + + @retval EFI_SUCCESS The operation completed successfully. + @exception EFI_UNSUPPORTED The operation is unsupported. + + @retval EFI_INVALID_PARAMETER Length or Buffer is NULL for any operati= on besides + quick read or quick write. + @retval EFI_TIMEOUT The transaction did not complete within = an internally + specified timeout period, or the control= ler is not + available for use. + @retval EFI_DEVICE_ERROR There was an Smbus error (NACK) during t= he operation. + This could indicate the slave device is = not present + or is in a hung condition. +**/ +EFI_STATUS +SmbusExec ( + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT8 AuxcReg; + UINT8 AuxStsReg; + UINT8 SmbusOperation; + UINT8 StsReg; + UINT8 SlvAddrReg; + UINT8 HostCmdReg; + UINT8 BlockCount; + BOOLEAN BufferTooSmall; + UINTN Index; + UINTN BusIndex; + UINT8 *CallBuffer; + UINT8 SmbusHctl; + UINT32 Timeout; + + CallBuffer =3D Buffer; + BlockCount =3D 0; + + /// + /// For any operations besides quick read & write, the pointers to + /// Length and Buffer must not be NULL. + /// + if ((Operation !=3D EfiSmbusQuickRead) && (Operation !=3D EfiSmbusQuickW= rite)) { + if ((Length =3D=3D NULL) || (Buffer =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + } + /// + /// See if its ok to use the bus based upon INUSE_STS bit. + /// + Status =3D AcquireBus (); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// This is the main operation loop. If the operation results in a Smbus + /// collision with another master on the bus, it attempts the requested + /// transaction again at least BUS_TRIES attempts. + /// + for (BusIndex =3D 0; BusIndex < BUS_TRIES; BusIndex++) { + /// + /// Operation Specifics (pre-execution) + /// + Status =3D EFI_SUCCESS; + SmbusOperation =3D V_SMBUS_SMB_CMD_QUICK; + SlvAddrReg =3D (UINT8) ((SlaveAddress.SmbusDeviceAddress << 1) | = 1); + HostCmdReg =3D (UINT8) Command; + AuxcReg =3D 0; + + switch (Operation) { + + case EfiSmbusQuickWrite: + SlvAddrReg--; + + /// + /// The "break;" command is not present here to allow code execution + /// do drop into the next case, which contains common code to this cas= e. + /// + case EfiSmbusQuickRead: + if (PecCheck =3D=3D TRUE) { + Status =3D EFI_UNSUPPORTED; + } + break; + + case EfiSmbusSendByte: + HostCmdReg =3D CallBuffer[0]; + SlvAddrReg--; + + /// + /// The "break;" command is not present here to allow code execution + /// do drop into the next case, which contains common code to this cas= e. + /// + case EfiSmbusReceiveByte: + SmbusOperation =3D V_SMBUS_SMB_CMD_BYTE; + if (*Length < 1) { + Status =3D EFI_BUFFER_TOO_SMALL; + } + + *Length =3D 1; + break; + + case EfiSmbusWriteByte: + SmbusIoWrite (R_SMBUS_HD0, CallBuffer[0]); + SlvAddrReg--; + *Length =3D 1; + + /// + /// The "break;" command is not present here to allow code execution + /// do drop into the next case, which contains common code to this cas= e. + /// + case EfiSmbusReadByte: + if (*Length < 1) { + Status =3D EFI_BUFFER_TOO_SMALL; + } else if (*Length =3D=3D 1) { + SmbusOperation =3D V_SMBUS_SMB_CMD_BYTE_DATA; + } else if (*Length <=3D 256) { + if (PecCheck =3D=3D TRUE) { + /// + /// The I2C Read command with either PEC_EN or AAC bit set + /// produces undefined results. + /// + Status =3D EFI_UNSUPPORTED; + } + + SmbusOperation =3D V_SMBUS_SMB_CMD_IIC_READ; + } else { + Status =3D EFI_INVALID_PARAMETER; + } + + break; + + case EfiSmbusReadWord: + SmbusOperation =3D V_SMBUS_SMB_CMD_WORD_DATA; + if (*Length < 2) { + Status =3D EFI_BUFFER_TOO_SMALL; + } + + *Length =3D 2; + break; + + case EfiSmbusWriteWord: + SmbusOperation =3D V_SMBUS_SMB_CMD_WORD_DATA; + SlvAddrReg--; + SmbusIoWrite (R_SMBUS_HD1, CallBuffer[1]); + SmbusIoWrite (R_SMBUS_HD0, CallBuffer[0]); + if (*Length < 2) { + Status =3D EFI_BUFFER_TOO_SMALL; + } + + *Length =3D 2; + break; + + case EfiSmbusWriteBlock: + SmbusIoWrite (R_SMBUS_HD0, *(UINT8 *) Length); + SlvAddrReg--; + BlockCount =3D (UINT8) (*Length); + + /// + /// The "break;" command is not present here to allow code execution + /// do drop into the next case, which contains common code to this cas= e. + /// + case EfiSmbusReadBlock: + SmbusOperation =3D V_SMBUS_SMB_CMD_BLOCK; + if ((*Length < 1) || (*Length > 32)) { + Status =3D EFI_INVALID_PARAMETER; + break; + } + + AuxcReg |=3D B_SMBUS_E32B; + break; + + case EfiSmbusProcessCall: + SmbusOperation =3D V_SMBUS_SMB_CMD_PROCESS_CALL; + SmbusIoWrite (R_SMBUS_HD1, CallBuffer[1]); + SmbusIoWrite (R_SMBUS_HD0, CallBuffer[0]); + if (*Length < 2) { + Status =3D EFI_BUFFER_TOO_SMALL; + } + + *Length =3D 2; + break; + + case EfiSmbusBWBRProcessCall: + /// + /// The write byte count cannot be zero or more than + /// 32 bytes. + /// + if ((*Length < 1) || (*Length > 32)) { + Status =3D EFI_INVALID_PARAMETER; + break; + } + + SmbusIoWrite (R_SMBUS_HD0, *(UINT8 *) Length); + BlockCount =3D (UINT8) (*Length); + SmbusOperation =3D V_SMBUS_SMB_CMD_BLOCK_PROCESS; + + AuxcReg |=3D B_SMBUS_E32B; + break; + + default: + Status =3D EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR (Status)) { + break; + } + + if (PecCheck =3D=3D TRUE) { + AuxcReg |=3D B_SMBUS_AAC; + } + /// + /// Set Auxiliary Control register + /// + SmbusIoWrite (R_SMBUS_AUXC, AuxcReg); + + /// + /// Reset the pointer of the internal buffer + /// + SmbusIoRead (R_SMBUS_HCTL); + + /// + /// Now that the 32 byte buffer is turned on, we can write th block da= ta + /// into it + /// + if ((Operation =3D=3D EfiSmbusWriteBlock) || (Operation =3D=3D EfiSmbu= sBWBRProcessCall)) { + for (Index =3D 0; Index < BlockCount; Index++) { + /// + /// Write next byte + /// + SmbusIoWrite (R_SMBUS_HBD, CallBuffer[Index]); + } + } + /// + /// Set SMBus slave address for the device to send/receive from + /// + SmbusIoWrite (R_SMBUS_TSA, SlvAddrReg); + + /// + /// For I2C read, send DATA1 register for the offset (address) + /// within the serial memory chips + /// + if ((Operation =3D=3D EfiSmbusReadByte) && (*Length > 1)) { + SmbusIoWrite (R_SMBUS_HD1, HostCmdReg); + } else { + /// + /// Set Command register + /// + SmbusIoWrite (R_SMBUS_HCMD, HostCmdReg); + } + /// + /// Set Control Register (Initiate Operation, Interrupt disabled) + /// + SmbusIoWrite (R_SMBUS_HCTL, (UINT8) (SmbusOperation + B_SMBUS_START)); + + /// + /// Wait for IO to complete + /// + if (!IoDone (&StsReg)) { + Status =3D EFI_TIMEOUT; + break; + } else if (StsReg & B_SMBUS_DERR) { + AuxStsReg =3D SmbusIoRead (R_SMBUS_AUXS); + if (AuxStsReg & B_SMBUS_CRCE) { + Status =3D EFI_CRC_ERROR; + } else { + Status =3D EFI_DEVICE_ERROR; + } + break; + } else if (StsReg & B_SMBUS_BERR) { + /// + /// Clear the Bus Error for another try + /// + Status =3D EFI_DEVICE_ERROR; + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_BERR); + /// + /// Clear Status Registers + /// + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_HSTS_ALL); + SmbusIoWrite (R_SMBUS_AUXS, B_SMBUS_CRCE); + /// + /// If bus collision happens, stall some time, then try again + /// Here we choose 10 milliseconds to avoid MTCP transfer. + /// + MicroSecondDelay (STALL_PERIOD); + continue; + } + /// + /// successfull completion + /// Operation Specifics (post-execution) + /// + switch (Operation) { + + case EfiSmbusReadWord: + /// + /// The "break;" command is not present here to allow code execution + /// do drop into the next case, which contains common code to this cas= e. + /// + case EfiSmbusProcessCall: + CallBuffer[1] =3D SmbusIoRead (R_SMBUS_HD1); + CallBuffer[0] =3D SmbusIoRead (R_SMBUS_HD0); + break; + + case EfiSmbusReadByte: + if (*Length > 1) { + for (Index =3D 0; Index < *Length; Index++) { + /// + /// Read the byte + /// + CallBuffer[Index] =3D SmbusIoRead (R_SMBUS_HBD); + /// + /// After receiving byte n-1 (1-base) of the message, the + /// software will then set the LAST BYTE bit. The software + /// will then clear the BYTE_DONE_STS bit. + /// + if (Index =3D=3D ((*Length - 1) - 1)) { + SmbusHctl =3D SmbusIoRead (R_SMBUS_HCTL) | (UINT8) B_SMBUS_LAS= T_BYTE; + SmbusIoWrite (R_SMBUS_HCTL, SmbusHctl); + } else if (Index =3D=3D (*Length - 1)) { + /// + /// Clear the LAST BYTE bit after receiving byte n (1-base) of= the message + /// + SmbusHctl =3D SmbusIoRead (R_SMBUS_HCTL) & (UINT8) ~B_SMBUS_LA= ST_BYTE; + SmbusIoWrite (R_SMBUS_HCTL, SmbusHctl); + } + /// + /// Clear the BYTE_DONE_STS bit + /// + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_BYTE_DONE_STS); + /// + /// Check BYTE_DONE_STS bit to know if it has completed transmis= sion + /// of a byte. No need to check it for the last byte. + /// + if (Index < (*Length - 1)) { + /// + /// If somehow board operates at 10Khz, it will take 0.9 ms (9= /10Khz) for another byte. + /// Add 10 us delay for a loop of 100 that the total timeout i= s 1 ms to take care of + /// the slowest case. + /// + for (Timeout =3D 0; Timeout < 100; Timeout++) { + if ((SmbusIoRead (R_SMBUS_HSTS) & (UINT8) B_SMBUS_BYTE_DONE_= STS) !=3D 0) { + break; + } + /// + /// Delay 10 us + /// + MicroSecondDelay (STALL_PERIOD); + } + + if (Timeout >=3D 100) { + Status =3D EFI_TIMEOUT; + break; + } + } + } + break; + } + + case EfiSmbusReceiveByte: + CallBuffer[0] =3D SmbusIoRead (R_SMBUS_HD0); + break; + + case EfiSmbusWriteBlock: + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_BYTE_DONE_STS); + break; + + case EfiSmbusReadBlock: + BufferTooSmall =3D FALSE; + /// + /// Find out how many bytes will be in the block + /// + BlockCount =3D SmbusIoRead (R_SMBUS_HD0); + if (*Length < BlockCount) { + BufferTooSmall =3D TRUE; + } else { + for (Index =3D 0; Index < BlockCount; Index++) { + /// + /// Read the byte + /// + CallBuffer[Index] =3D SmbusIoRead (R_SMBUS_HBD); + } + } + + *Length =3D BlockCount; + if (BufferTooSmall) { + Status =3D EFI_BUFFER_TOO_SMALL; + } + break; + + case EfiSmbusBWBRProcessCall: + /// + /// Find out how many bytes will be in the block + /// + BlockCount =3D SmbusIoRead (R_SMBUS_HD0); + /// + /// The read byte count cannot be zero. + /// + if (BlockCount < 1) { + Status =3D EFI_BUFFER_TOO_SMALL; + break; + } + /// + /// The combined data payload (the write byte count + the read byte = count) + /// must not exceed 32 bytes + /// + if (((UINT8) (*Length) + BlockCount) > 32) { + Status =3D EFI_DEVICE_ERROR; + break; + } + + for (Index =3D 0; Index < BlockCount; Index++) { + /// + /// Read the byte + /// + CallBuffer[Index] =3D SmbusIoRead (R_SMBUS_HBD); + } + + *Length =3D BlockCount; + break; + + default: + break; + }; + + if ((StsReg & B_SMBUS_BERR) && (Status !=3D EFI_BUFFER_TOO_SMALL)) { + /// + /// Clear the Bus Error for another try + /// + Status =3D EFI_DEVICE_ERROR; + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_BERR); + /// + /// If bus collision happens, stall some time, then try again + /// Here we choose 10 milliseconds to avoid MTCP transfer. + /// + MicroSecondDelay (STALL_PERIOD); + continue; + } else { + break; + } + } + /// + /// Clear Status Registers and exit + /// + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_HSTS_ALL); + SmbusIoWrite (R_SMBUS_AUXS, B_SMBUS_CRCE); + SmbusIoWrite (R_SMBUS_AUXC, 0); + return Status; +} + +/** + This function initializes the Smbus Registers. + + @param[in] None + + @retval[in] None +**/ +VOID +InitializeSmbusRegisters ( + VOID + ) +{ + UINTN SmbusRegBase; + + SmbusRegBase =3D MmPciBase ( + DEFAULT_PCI_BUS_NUMBER_SC, + PCI_DEVICE_NUMBER_SMBUS, + PCI_FUNCTION_NUMBER_SMBUS + ); + /// + /// Enable the Smbus I/O Enable + /// + MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, (UINT8) EFI_PCI_COMMAND_IO_S= PACE); + + /// + /// Enable the Smbus host controller + /// + MmioAndThenOr8 ( + SmbusRegBase + R_SMBUS_HOSTC, + (UINT8) (~(B_SMBUS_HOSTC_SMI_EN | B_SMBUS_HOSTC_I2C_EN)), + B_SMBUS_HOSTC_HST_EN + ); + + SmbusIoWrite (R_SMBUS_HSTS, B_SMBUS_HSTS_ALL); +} \ No newline at end of file --=20 2.14.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel