From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: nathaniel.l.desimone@intel.com) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by groups.io with SMTP; Fri, 16 Aug 2019 17:52:57 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Aug 2019 17:52:56 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,395,1559545200"; d="scan'208";a="177350049" Received: from orsmsx110.amr.corp.intel.com ([10.22.240.8]) by fmsmga008.fm.intel.com with ESMTP; 16 Aug 2019 17:52:55 -0700 Received: from orsmsx123.amr.corp.intel.com (10.22.240.116) by ORSMSX110.amr.corp.intel.com (10.22.240.8) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 16 Aug 2019 17:52:55 -0700 Received: from orsmsx114.amr.corp.intel.com ([169.254.8.96]) by ORSMSX123.amr.corp.intel.com ([169.254.1.245]) with mapi id 14.03.0439.000; Fri, 16 Aug 2019 17:52:55 -0700 From: "Nate DeSimone" To: "Kubacki, Michael A" , "devel@edk2.groups.io" CC: "Chaganty, Rangasai V" , "Chiu, Chasel" , "Gao, Liming" , "Kinney, Michael D" , "Sinha, Ankit" Subject: Re: [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base library instances Thread-Topic: [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Base library instances Thread-Index: AQHVVJEXDqM+WNIf6U6iOFLSyAmbSab+gw7g Date: Sat, 17 Aug 2019 00:52:54 +0000 Message-ID: <02A34F284D1DA44BB705E61F7180EF0AAEE129F8@ORSMSX114.amr.corp.intel.com> References: <20190817001603.30632-1-michael.a.kubacki@intel.com> <20190817001603.30632-22-michael.a.kubacki@intel.com> In-Reply-To: <20190817001603.30632-22-michael.a.kubacki@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiNDAzYWEyMDQtNGExNS00YjhmLWI0MTYtNGNkYjExOTI5MjI2IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiRVBBcXlaUmhrZTVBMUczU0dZaW51XC9xXC94ZkthdWpyV3FsR3J6azJ3M2JBRUdLK2hGbGhVMElsT3RpU2ZrSWlXIn0= x-ctpclassification: CTP_NT x-originating-ip: [10.22.254.139] MIME-Version: 1.0 Return-Path: nathaniel.l.desimone@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Nate DeSimone -----Original Message----- From: Kubacki, Michael A=20 Sent: Friday, August 16, 2019 5:16 PM To: devel@edk2.groups.io Cc: Chaganty, Rangasai V ; Chiu, Chasel ; Desimone, Nathaniel L = ; Gao, Liming ; Kinney, Michael D ; Sinha, Ankit Subject: [edk2-platforms][PATCH V1 21/37] CoffeelakeSiliconPkg/Pch: Add Bas= e library instances REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D2082 Adds Pch/Library/Private Base library class instances. * BaseGpioHelpersLibNull * BasePchSpiCommonlib * BaseSiScheduleResetLib * BaseSiScheduleResetLibFsp Cc: Sai Chaganty Cc: Chasel Chiu Cc: Nate DeSimone Cc: Liming Gao Cc: Michael D Kinney Cc: Ankit Sinha Signed-off-by: Michael Kubacki --- Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibN= ull/BaseGpioHelpersLibNull.inf | 26 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib= /BasePchSpiCommonLib.inf | 28 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleReset= Lib/BaseSiScheduleResetLib.inf | 40 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleReset= Lib/BaseSiScheduleResetLibFsp.inf | 40 + Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelpersLibN= ull/BaseGpioHelpersLibNull.c | 108 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiCommonLib= /SpiCommon.c | 1081 ++++++++++++++++++++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleReset= Lib/BaseSiScheduleResetLib.c | 70 ++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleReset= Lib/BaseSiScheduleResetLibCommon.c | 125 +++ Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiScheduleReset= Lib/BaseSiScheduleResetLibFsp.c | 61 ++ 9 files changed, 1579 insertions(+) diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpi= oHelpersLibNull/BaseGpioHelpersLibNull.inf b/Silicon/Intel/CoffeelakeSilico= nPkg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.inf new file mode 100644 index 0000000000..5502af824f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelper= sLibNull/BaseGpioHelpersLibNull.inf @@ -0,0 +1,26 @@ +## @file +# Component description file for the NULL GpioHelpersLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D BaseGpioHelpersLib +FILE_GUID =3D AB282608-2A50-4AE3-9242-64064ECF40D4 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D GpioHelpersLib + + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + + +[Sources] +BaseGpioHelpersLibNull.c + diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePch= SpiCommonLib/BasePchSpiCommonLib.inf b/Silicon/Intel/CoffeelakeSiliconPkg/P= ch/Library/Private/BasePchSpiCommonLib/BasePchSpiCommonLib.inf new file mode 100644 index 0000000000..ea23e628c8 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiComm= onLib/BasePchSpiCommonLib.inf @@ -0,0 +1,28 @@ +## @file +# Component description file for the PchSpiCommonLib +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D BasePchSpiCommonLib + FILE_GUID =3D A37CB67E-7D85-45B3-B07E-BF65BDB603E8 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PchSpiCommonLib + +[Sources] + SpiCommon.c + +[Packages] + MdePkg/MdePkg.dec + CoffeelakeSiliconPkg/SiPkg.dec + +[LibraryClasses] + IoLib + DebugLib + PmcLib diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiS= cheduleResetLib/BaseSiScheduleResetLib.inf b/Silicon/Intel/CoffeelakeSilico= nPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.inf new file mode 100644 index 0000000000..de7f6eeb73 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiSchedule= ResetLib/BaseSiScheduleResetLib.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for Si Reset Schedule Library. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D BaseSiScheduleResetLib +FILE_GUID =3D E6F3D551-36C0-4737-80C7-47FC57593163 +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D SiScheduleResetLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF +# + +[LibraryClasses] +BaseLib +IoLib +DebugLib +HobLib +ResetSystemLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + +[Guids] +gSiScheduleResetHobGuid +gPchConfigHobGuid + +[Sources] +BaseSiScheduleResetLibCommon.c +BaseSiScheduleResetLib.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiS= cheduleResetLib/BaseSiScheduleResetLibFsp.inf b/Silicon/Intel/CoffeelakeSil= iconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFs= p.inf new file mode 100644 index 0000000000..c8fe9e6079 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiSchedule= ResetLib/BaseSiScheduleResetLibFsp.inf @@ -0,0 +1,40 @@ +## @file +# Component description file for Si Reset Schedule Library. +# +# Copyright (c) 2019 Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] +INF_VERSION =3D 0x00010017 +BASE_NAME =3D BaseSiScheduleResetLibFsp +FILE_GUID =3D 1478D005-8DEC-4A6E-9619-309C6A7F313A +VERSION_STRING =3D 1.0 +MODULE_TYPE =3D BASE +LIBRARY_CLASS =3D SiScheduleResetLib +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF +# + +[LibraryClasses] +BaseLib +IoLib +DebugLib +HobLib +PeiServicesTablePointerLib + +[Packages] +MdePkg/MdePkg.dec +CoffeelakeSiliconPkg/SiPkg.dec + +[Guids] +gSiScheduleResetHobGuid +gPchConfigHobGuid + +[Sources] +BaseSiScheduleResetLibCommon.c +BaseSiScheduleResetLibFsp.c diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpi= oHelpersLibNull/BaseGpioHelpersLibNull.c b/Silicon/Intel/CoffeelakeSiliconP= kg/Pch/Library/Private/BaseGpioHelpersLibNull/BaseGpioHelpersLibNull.c new file mode 100644 index 0000000000..46390eeca1 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseGpioHelper= sLibNull/BaseGpioHelpersLibNull.c @@ -0,0 +1,108 @@ +/** @file + This file contains NULL implementation for GPIO Helpers Lib + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include + +/** + This procedure stores GPIO pad unlock information + + @param[in] GpioPad GPIO pad + @param[in] GpioLockConfig GPIO Lock Configuration + + @retval Status +**/ +EFI_STATUS +GpioStoreUnlockData ( + IN GPIO_PAD GpioPad, + IN GPIO_LOCK_CONFIG GpioLockConfig + ) +{ + return EFI_SUCCESS; +} + +/** + This procedure stores GPIO group data about pads which PadConfig needs t= o be unlocked. + + @param[in] GroupIndex GPIO group index + @param[in] DwNum DWORD index for a group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] UnlockedPads DWORD bitmask for pads which are going t= o be left unlocked + Bit position - PadNumber + Bit value - 0: Skip, 1: Leave unlocked + + @retval Status +**/ +EFI_STATUS +GpioStoreGroupDwUnlockPadConfigData ( + IN UINT32 GroupIndex, + IN UINT32 DwNum, + IN UINT32 UnlockedPads + ) +{ + return EFI_SUCCESS; +} + +/** + This procedure stores GPIO group data about pads which Output state need= s to be unlocked. + + @param[in] GroupIndex GPIO group index + @param[in] DwNum DWORD index for a group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @param[in] UnlockedPads DWORD bitmask for pads which are going t= o be left unlocked + Bit position - PadNumber + Bit value - 0: Skip, 1: Leave unlocked + @retval Status +**/ +EFI_STATUS +GpioStoreGroupDwUnlockOutputData ( + IN UINT32 GroupIndex, + IN UINT32 DwNum, + IN UINT32 UnlockedPads + ) +{ + return EFI_SUCCESS; +} + +/** + This procedure will get GPIO group data with pads, which PadConfig is su= pposed to be left unlock + + @param[in] GroupIndex GPIO group index + @param[in] DwNum DWORD index for a group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @retval UnlockedPads DWORD bitmask for pads which are going t= o be left unlocked + Bit position - PadNumber + Bit value - 0: to be locked, 1: Leave un= locked +**/ +UINT32 +GpioGetGroupDwUnlockPadConfigMask ( + IN UINT32 GroupIndex, + IN UINT32 DwNum + ) +{ + return 0; +} + +/** + This procedure will get GPIO group data with pads, which Output is suppo= sed to be left unlock + + @param[in] GroupIndex GPIO group index + @param[in] DwNum DWORD index for a group. + For group which has less then 32 pads pe= r group DwNum must be 0. + @retval UnlockedPads DWORD bitmask for pads which are going t= o be left unlocked + Bit position - PadNumber + Bit value - 0: to be locked, 1: Leave un= locked +**/ +UINT32 +GpioGetGroupDwUnlockOutputMask ( + IN UINT32 GroupIndex, + IN UINT32 DwNum + ) +{ + return 0; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePch= SpiCommonLib/SpiCommon.c b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/P= rivate/BasePchSpiCommonLib/SpiCommon.c new file mode 100644 index 0000000000..bc84a4f27f --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BasePchSpiComm= onLib/SpiCommon.c @@ -0,0 +1,1081 @@ +/** @file + PCH SPI Common Driver implements the SPI Host Controller Compatibility I= nterface. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Initialize an SPI protocol instance. + + @param[in] SpiInstance Pointer to SpiInstance to initialize + + @retval EFI_SUCCESS The protocol instance was properly initi= alized + @exception EFI_UNSUPPORTED The PCH is not supported by this module +**/ +EFI_STATUS +SpiProtocolConstructor ( + IN SPI_INSTANCE *SpiInstance + ) +{ + UINTN PchSpiBar0; + UINT32 Data32; + + // + // Initialize the SPI protocol instance + // + SpiInstance->Signature =3D PCH_SPI_PRIVATE_DATA_SIGNA= TURE; + SpiInstance->Handle =3D NULL; + SpiInstance->SpiProtocol.Revision =3D PCH_SPI_SERVICES_REVISION; + SpiInstance->SpiProtocol.FlashRead =3D SpiProtocolFlashRead; + SpiInstance->SpiProtocol.FlashWrite =3D SpiProtocolFlashWrite; + SpiInstance->SpiProtocol.FlashErase =3D SpiProtocolFlashErase; + SpiInstance->SpiProtocol.FlashReadSfdp =3D SpiProtocolFlashReadSfdp; + SpiInstance->SpiProtocol.FlashReadJedecId =3D SpiProtocolFlashReadJedecI= d; + SpiInstance->SpiProtocol.FlashWriteStatus =3D SpiProtocolFlashWriteStatu= s; + SpiInstance->SpiProtocol.FlashReadStatus =3D SpiProtocolFlashReadStatus= ; + SpiInstance->SpiProtocol.GetRegionAddress =3D SpiProtocolGetRegionAddres= s; + SpiInstance->SpiProtocol.ReadPchSoftStrap =3D SpiProtocolReadPchSoftStra= p; + SpiInstance->SpiProtocol.ReadCpuSoftStrap =3D SpiProtocolReadCpuSoftStra= p; + + SpiInstance->PchSpiBase =3D PCI_SEGMENT_LIB_ADDRESS ( + DEFAULT_PCI_SEGMENT_NUMBER_PCH, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_SPI, + PCI_FUNCTION_NUMBER_PCH_SPI, + 0 + ); + + SpiInstance->PchAcpiBase =3D PmcGetAcpiBase (); + ASSERT (SpiInstance->PchAcpiBase !=3D 0); + + PchSpiBar0 =3D PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR= 0) & ~(B_SPI_CFG_BAR0_MASK); + if (PchSpiBar0 =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "ERROR : PchSpiBar0 is invalid!\n")); + ASSERT (FALSE); + } + + if ((MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC) & B_SPI_MEM_HSFSC_FDV) = =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "ERROR : SPI Flash Signature invalid, cannot use = the Hardware Sequencing registers!\n")); + ASSERT (FALSE); + } + + // + // Get Region 0 - 7 read Permission bits, region 8 and above are not per= mitted. + // + SpiInstance->ReadPermission =3D MmioRead8 (PchSpiBar0 + R_SPI_MEM_FRAP) = & B_SPI_MEM_FRAP_BRRA_MASK; + DEBUG ((DEBUG_INFO, "Flash Region read Permission : %0x\n", SpiInstance-= >ReadPermission)); + // + // Get Region 0 - 7 write Permission bits, region 8 and above are not pe= rmitted. + // + SpiInstance->WritePermission =3D (UINT8) ((MmioRead16 (PchSpiBar0 + R_SP= I_MEM_FRAP) & + B_SPI_MEM_FRAP_BRWA_MASK) >> N_= SPI_MEM_FRAP_BRWA); + DEBUG ((DEBUG_INFO, "Flash Region write Permission : %0x\n", SpiInstance= ->WritePermission)); + + SpiInstance->SfdpVscc0Value =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP0= _VSCC0); + DEBUG ((DEBUG_INFO, "Component 0 SFDP VSCC value : %0x\n", SpiInstance->= SfdpVscc0Value)); + SpiInstance->SfdpVscc1Value =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_SFDP1= _VSCC1); + DEBUG ((DEBUG_INFO, "Component 1 SFDP VSCC value : %0x\n", SpiInstance->= SfdpVscc1Value)); + + // + // Select to Flash Map 0 Register to get the number of flash Component + // + MmioAndThenOr32 ( + PchSpiBar0 + R_SPI_MEM_FDOC, + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)), + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_SPI_FLASH_FDBAR_FLASH_MAP0) + ); + + // + // Copy Zero based Number Of Components + // + SpiInstance->NumberOfComponents =3D (UINT8) ((MmioRead16 (PchSpiBar0 + R= _SPI_MEM_FDOD) & B_SPI_FLASH_FDBAR_NC) >> N_SPI_FLASH_FDBAR_NC); + DEBUG ((DEBUG_INFO, "Component Number : %0x\n", SpiInstance->NumberOfCom= ponents + 1)); + + MmioAndThenOr32 ( + PchSpiBar0 + R_SPI_MEM_FDOC, + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)), + (UINT32) (V_SPI_MEM_FDOC_FDSS_COMP | R_SPI_FLASH_FCBA_FLCOMP) + ); + + // + // Copy Component 0 Density + // + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD); + if (SpiInstance->NumberOfComponents > 0) { + SpiInstance->Component1StartAddr =3D V_SPI_FLASH_FLCOMP_COMP_512KB << + (Data32 & B_SPI_FLASH_FLCOMP_COMP0_MASK); + DEBUG ((DEBUG_INFO, "Component 1 StartAddr : %0x\n", SpiInstance->Comp= onent1StartAddr)); + SpiInstance->TotalFlashSize =3D SpiInstance->Component1StartAddr + + (V_SPI_FLASH_FLCOMP_COMP_512KB << + ((Data32 & B_SPI_FLASH_FLCOMP_COMP1_MASK) >> + N_SPI_FLASH_FLCOMP_COMP1)); + } else { + SpiInstance->TotalFlashSize =3D V_SPI_FLASH_FLCOMP_COMP_512KB << + (Data32 & B_SPI_FLASH_FLCOMP_COMP0_MASK); + } + DEBUG ((DEBUG_INFO, "Total Flash Size : %0x\n", SpiInstance->TotalFlashS= ize)); + + // + // Select FLASH_MAP1 to get Flash PCH Strap Base Address + // + MmioAndThenOr32 ( + (PchSpiBar0 + R_SPI_MEM_FDOC), + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)), + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_SPI_FLASH_FDBAR_FLASH_MAP1) + ); + // + // Align FPSBA with address bits for the PCH Strap portion of flash desc= riptor + // + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD); + SpiInstance->PchStrapBaseAddr =3D (UINT16) (((Data32 & B_SPI_FLASH_FDBAR= _FPSBA) + >> N_SPI_FLASH_FDBAR_FPSBA) + << N_SPI_FLASH_FDBAR_FPSBA_REP= R); + DEBUG ((DEBUG_INFO, "PchStrapBaseAddr : %0x\n", SpiInstance->PchStrapBas= eAddr)); + ASSERT (SpiInstance->PchStrapBaseAddr !=3D 0); + // + // PCH Strap Length, [31:24] represents number of Dwords + // + SpiInstance->PchStrapSize =3D (UINT16) (((Data32 & B_SPI_FLASH_FDBAR_PCH= SL) + >> N_SPI_FLASH_FDBAR_PCHSL) + * sizeof (UINT32)); + DEBUG ((DEBUG_INFO, "PchStrapSize : %0x\n", SpiInstance->PchStrapSize)); + + // + // Select FLASH_MAP2 to get Flash CPU Strap Base Address + // + MmioAndThenOr32 ( + (PchSpiBar0 + R_SPI_MEM_FDOC), + (UINT32) (~(B_SPI_MEM_FDOC_FDSS_MASK | B_SPI_MEM_FDOC_FDSI_MASK)), + (UINT32) (V_SPI_MEM_FDOC_FDSS_FSDM | R_SPI_FLASH_FDBAR_FLASH_MAP2) + ); + // + // Align FPSBA with address bits for the PCH Strap portion of flash desc= riptor + // + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_FDOD); + SpiInstance->CpuStrapBaseAddr =3D (UINT16) (((Data32 & B_SPI_FLASH_FDBAR= _FCPUSBA) + >> N_SPI_FLASH_FDBAR_FCPUSBA) + << N_SPI_FLASH_FDBAR_FCPUSBA_R= EPR); + DEBUG ((DEBUG_INFO, "CpuStrapBaseAddr : %0x\n", SpiInstance->CpuStrapBas= eAddr)); + ASSERT (SpiInstance->CpuStrapBaseAddr !=3D 0); + // + // CPU Strap Length, [15:8] represents number of Dwords + // + SpiInstance->CpuStrapSize =3D (UINT16) (((Data32 & B_SPI_FLASH_FDBAR_CPU= SL) + >> N_SPI_FLASH_FDBAR_CPUSL) + * sizeof (UINT32)); + DEBUG ((DEBUG_INFO, "CpuStrapSize : %0x\n", SpiInstance->CpuStrapSize)); + + return EFI_SUCCESS; +} + +/** + Delay for at least the request number of microseconds for Runtime usage. + + @param[in] ABase Acpi base address + @param[in] Microseconds Number of microseconds to delay. + +**/ +VOID +EFIAPI +PchPmTimerStallRuntimeSafe ( + IN UINT16 ABase, + IN UINTN Microseconds + ) +{ + UINTN Ticks; + UINTN Counts; + UINTN CurrentTick; + UINTN OriginalTick; + UINTN RemainingTick; + + if (Microseconds =3D=3D 0) { + return; + } + + OriginalTick =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_AC= PI_IO_PM1_TMR_VAL; + CurrentTick =3D OriginalTick; + + // + // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks + // + Ticks =3D Microseconds * 358 / 100 + OriginalTick + 1; + + // + // The loops needed by timer overflow + // + Counts =3D Ticks / V_ACPI_IO_PM1_TMR_MAX_VAL; + + // + // Remaining clocks within one loop + // + RemainingTick =3D Ticks % V_ACPI_IO_PM1_TMR_MAX_VAL; + + // + // not intend to use TMROF_STS bit of register PM1_STS, because this add= s extra + // one I/O operation, and maybe generate SMI + // + while ((Counts !=3D 0) || (RemainingTick > CurrentTick)) { + CurrentTick =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_PM1_TMR)) & B_ACP= I_IO_PM1_TMR_VAL; + // + // Check if timer overflow + // + if ((CurrentTick < OriginalTick)) { + if (Counts !=3D 0) { + Counts--; + } else { + // + // If timer overflow and Counts equ to 0, that means we already st= alled more than + // RemainingTick, break the loop here + // + break; + } + } + + OriginalTick =3D CurrentTick; + } +} + +/** + Wait execution cycle to complete on the SPI interface. + + @param[in] This The SPI protocol instance + @param[in] PchSpiBar0 Spi MMIO base address + @param[in] ErrorCheck TRUE if the SpiCycle needs to do the err= or check + + @retval TRUE SPI cycle completed on the interface. + @retval FALSE Time out while waiting the SPI cycle to = complete. + It's not safe to program the next comman= d on the SPI interface. +**/ +STATIC +BOOLEAN +WaitForSpiCycleComplete ( + IN PCH_SPI_PROTOCOL *This, + IN UINTN PchSpiBar0, + IN BOOLEAN ErrorCheck + ) +{ + UINT64 WaitTicks; + UINT64 WaitCount; + UINT32 Data32; + SPI_INSTANCE *SpiInstance; + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + + // + // Convert the wait period allowed into to tick count + // + WaitCount =3D SPI_WAIT_TIME / SPI_WAIT_PERIOD; + // + // Wait for the SPI cycle to complete. + // + for (WaitTicks =3D 0; WaitTicks < WaitCount; WaitTicks++) { + Data32 =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC); + if ((Data32 & B_SPI_MEM_HSFSC_SCIP) =3D=3D 0) { + MmioWrite32 (PchSpiBar0 + R_SPI_MEM_HSFSC, B_SPI_MEM_HSFSC_FCERR | B= _SPI_MEM_HSFSC_FDONE); + if (((Data32 & B_SPI_MEM_HSFSC_FCERR) !=3D 0) && (ErrorCheck =3D=3D = TRUE)) { + return FALSE; + } else { + return TRUE; + } + } + PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, SPI_WAIT_PERIOD)= ; + } + return FALSE; +} + +/** + This function sends the programmed SPI command to the slave device. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] SpiRegionType The SPI Region type for flash cycle whic= h is listed in the Descriptor + @param[in] FlashCycleType The Flash SPI cycle type list in HSFC (H= ardware Sequencing Flash Control Register) register + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle. + @param[in,out] Buffer Pointer to caller-allocated buffer conta= ining the dada received or sent during the SPI cycle. + + @retval EFI_SUCCESS SPI command completes successfully. + @retval EFI_DEVICE_ERROR Device error, the command aborts abnorma= lly. + @retval EFI_ACCESS_DENIED Some unrecognized or blocked command enc= ountered in hardware sequencing mode + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. +**/ +STATIC +EFI_STATUS +SendSpiCmd ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + IN FLASH_CYCLE_TYPE FlashCycleType, + IN UINT32 Address, + IN UINT32 ByteCount, + IN OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Index; + SPI_INSTANCE *SpiInstance; + UINT64 SpiBaseAddress; + UINTN PchSpiBar0; + UINT32 HardwareSpiAddr; + UINT32 FlashRegionSize; + UINT32 SpiDataCount; + UINT32 FlashCycle; + UINT8 BiosCtlSave; + UINT32 SmiEnSave; + UINT16 ABase; + UINT32 HsfstsCtl; + + // + // For flash write, there is a requirement that all CPU threads are in S= MM + // before the flash protection is disabled. + // + if ((FlashCycleType =3D=3D FlashCycleWrite) || (FlashCycleType =3D=3D Fl= ashCycleErase)) { + if (!IsSpiFlashWriteGranted ()) { + return EFI_ACCESS_DENIED; + } + } + + Status =3D EFI_SUCCESS; + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + SpiBaseAddress =3D SpiInstance->PchSpiBase; + PchSpiBar0 =3D AcquireSpiBar0 (SpiInstance); + ABase =3D SpiInstance->PchAcpiBase; + + // + // Disable SMIs to make sure normal mode flash access is not interrupted= by an SMI + // whose SMI handler accesses flash (e.g. for error logging) + // + // *** NOTE: if the SMI_LOCK bit is set (i.e., PMC PCI Offset A0h [4]=3D= '1'), + // clearing B_GBL_SMI_EN will not have effect. In this situation, some o= ther + // synchronization methods must be applied here or in the consumer of th= e + // SendSpiCmd. An example method is disabling the specific SMI sources + // whose SMI handlers access flash before flash cycle and re-enabling th= e SMI + // sources after the flash cycle . + // + SmiEnSave =3D IoRead32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN)); + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave & (UINT32) (~B_= ACPI_IO_SMI_EN_GBL_SMI)); + BiosCtlSave =3D PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_= CFG_BC_SRC; + + // + // If it's write cycle, disable Prefetching, Caching and disable BIOS Wr= ite Protect + // + if ((FlashCycleType =3D=3D FlashCycleWrite) || + (FlashCycleType =3D=3D FlashCycleErase)) { + Status =3D DisableBiosWriteProtect (); + if (EFI_ERROR (Status)) { + goto SendSpiCmdEnd; + } + PciSegmentAndThenOr8 ( + SpiBaseAddress + R_SPI_CFG_BC, + (UINT8) (~B_SPI_CFG_BC_SRC), + (UINT8) (V_SPI_CFG_BC_SRC_PREF_DIS_CACHE_DIS << N_SPI_CFG_BC_SRC) + ); + } + // + // Make sure it's safe to program the command. + // + if (!WaitForSpiCycleComplete (This, PchSpiBar0, FALSE)) { + Status =3D EFI_DEVICE_ERROR; + goto SendSpiCmdEnd; + } + + // + // Check if Write Status isn't disabled in HW Sequencing + // + if (FlashCycleType =3D=3D FlashCycleWriteStatus) { + HsfstsCtl =3D MmioRead32 (PchSpiBar0 + R_SPI_MEM_HSFSC); + if ((HsfstsCtl & B_SPI_MEM_HSFSC_WRSDIS) !=3D 0) { + Status =3D EFI_ACCESS_DENIED; + goto SendSpiCmdEnd; + } + } + + Status =3D SpiProtocolGetRegionAddress (This, FlashRegionType, &Hardware= SpiAddr, &FlashRegionSize); + if (EFI_ERROR (Status)) { + goto SendSpiCmdEnd; + } + HardwareSpiAddr +=3D Address; + if ((Address + ByteCount) > FlashRegionSize) { + Status =3D EFI_INVALID_PARAMETER; + goto SendSpiCmdEnd; + } + + // + // Check for PCH SPI hardware sequencing required commands + // + FlashCycle =3D 0; + switch (FlashCycleType) { + case FlashCycleRead: + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ << N_SPI_MEM_HSF= SC_CYCLE); + break; + case FlashCycleWrite: + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE << N_SPI_MEM_HS= FSC_CYCLE); + break; + case FlashCycleErase: + if (((ByteCount % SIZE_4KB) !=3D 0) || + ((HardwareSpiAddr % SIZE_4KB) !=3D 0)) { + ASSERT (FALSE); + Status =3D EFI_INVALID_PARAMETER; + goto SendSpiCmdEnd; + } + break; + case FlashCycleReadSfdp: + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_SFDP << N_SPI_ME= M_HSFSC_CYCLE); + break; + case FlashCycleReadJedecId: + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_JEDEC_ID << N_SP= I_MEM_HSFSC_CYCLE); + break; + case FlashCycleWriteStatus: + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_WRITE_STATUS << N_SPI= _MEM_HSFSC_CYCLE); + break; + case FlashCycleReadStatus: + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_READ_STATUS << N_SPI_= MEM_HSFSC_CYCLE); + break; + default: + // + // Unrecognized Operation + // + ASSERT (FALSE); + Status =3D EFI_INVALID_PARAMETER; + goto SendSpiCmdEnd; + break; + } + + do { + SpiDataCount =3D ByteCount; + if ((FlashCycleType =3D=3D FlashCycleRead) || + (FlashCycleType =3D=3D FlashCycleWrite) || + (FlashCycleType =3D=3D FlashCycleReadSfdp)) { + // + // Trim at 256 byte boundary per operation, + // - PCH SPI controller requires trimming at 4KB boundary + // - Some SPI chips require trimming at 256 byte boundary for write = operation + // - Trimming has limited performance impact as we can read / write = atmost 64 byte + // per operation + // + if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 = - 1))) { + SpiDataCount =3D (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)= ) - (UINT32) (HardwareSpiAddr); + } + // + // Calculate the number of bytes to shift in/out during the SPI data= cycle. + // Valid settings for the number of bytes duing each data portion of= the + // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48= , 56, 64 + // + if (SpiDataCount >=3D 64) { + SpiDataCount =3D 64; + } else if ((SpiDataCount &~0x07) !=3D 0) { + SpiDataCount =3D SpiDataCount &~0x07; + } + } + if (FlashCycleType =3D=3D FlashCycleErase) { + if (((ByteCount / SIZE_64KB) !=3D 0) && + ((ByteCount % SIZE_64KB) =3D=3D 0) && + ((HardwareSpiAddr % SIZE_64KB) =3D=3D 0)) { + if (HardwareSpiAddr < SpiInstance->Component1StartAddr) { + // + // Check whether Component0 support 64k Erase + // + if ((SpiInstance->SfdpVscc0Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K)= !=3D 0) { + SpiDataCount =3D SIZE_64KB; + } else { + SpiDataCount =3D SIZE_4KB; + } + } else { + // + // Check whether Component1 support 64k Erase + // + if ((SpiInstance->SfdpVscc1Value & B_SPI_MEM_SFDPX_VSCCX_EO_64K)= !=3D 0) { + SpiDataCount =3D SIZE_64KB; + } else { + SpiDataCount =3D SIZE_4KB; + } + } + } else { + SpiDataCount =3D SIZE_4KB; + } + if (SpiDataCount =3D=3D SIZE_4KB) { + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_4K_ERASE << N_SPI_M= EM_HSFSC_CYCLE); + } else { + FlashCycle =3D (UINT32) (V_SPI_MEM_HSFSC_CYCLE_64K_ERASE << N_SPI_= MEM_HSFSC_CYCLE); + } + } + // + // If it's write cycle, load data into the SPI data buffer. + // + if ((FlashCycleType =3D=3D FlashCycleWrite) || (FlashCycleType =3D=3D = FlashCycleWriteStatus)) { + if ((SpiDataCount & 0x07) !=3D 0) { + // + // Use Byte write if Data Count is 0, 1, 2, 3, 4, 5, 6, 7 + // + for (Index =3D 0; Index < SpiDataCount; Index++) { + MmioWrite8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, Buffer[Index= ]); + } + } else { + // + // Use Dword write if Data Count is 8, 16, 24, 32, 40, 48, 56, 64 + // + for (Index =3D 0; Index < SpiDataCount; Index +=3D sizeof (UINT32)= ) { + MmioWrite32 (PchSpiBar0 + R_SPI_MEM_FDATA00 + Index, *(UINT32 *)= (Buffer + Index)); + } + } + } + + // + // Set the Flash Address + // + MmioWrite32 ( + (PchSpiBar0 + R_SPI_MEM_FADDR), + (UINT32) (HardwareSpiAddr & B_SPI_MEM_FADDR_MASK) + ); + + // + // Set Data count, Flash cycle, and Set Go bit to start a cycle + // + MmioAndThenOr32 ( + PchSpiBar0 + R_SPI_MEM_HSFSC, + (UINT32) (~(B_SPI_MEM_HSFSC_FDBC_MASK | B_SPI_MEM_HSFSC_CYCLE_MASK))= , + (UINT32) ((((SpiDataCount - 1) << N_SPI_MEM_HSFSC_FDBC) & B_SPI_MEM_= HSFSC_FDBC_MASK) | FlashCycle | B_SPI_MEM_HSFSC_CYCLE_FGO) + ); + // + // end of command execution + // + // Wait the SPI cycle to complete. + // + if (!WaitForSpiCycleComplete (This, PchSpiBar0, TRUE)) { + ASSERT (FALSE); + Status =3D EFI_DEVICE_ERROR; + goto SendSpiCmdEnd; + } + // + // If it's read cycle, load data into the call's buffer. + // + if ((FlashCycleType =3D=3D FlashCycleRead) || + (FlashCycleType =3D=3D FlashCycleReadSfdp) || + (FlashCycleType =3D=3D FlashCycleReadJedecId) || + (FlashCycleType =3D=3D FlashCycleReadStatus)) { + if ((SpiDataCount & 0x07) !=3D 0) { + // + // Use Byte read if Data Count is 0, 1, 2, 3, 4, 5, 6, 7 + // + for (Index =3D 0; Index < SpiDataCount; Index++) { + Buffer[Index] =3D MmioRead8 (PchSpiBar0 + R_SPI_MEM_FDATA00 + In= dex); + } + } else { + // + // Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64 + // + for (Index =3D 0; Index < SpiDataCount; Index +=3D sizeof (UINT32)= ) { + *(UINT32 *) (Buffer + Index) =3D MmioRead32 (PchSpiBar0 + R_SPI_= MEM_FDATA00 + Index); + } + } + } + + HardwareSpiAddr +=3D SpiDataCount; + Buffer +=3D SpiDataCount; + ByteCount -=3D SpiDataCount; + } while (ByteCount > 0); + +SendSpiCmdEnd: + // + // Restore the settings for SPI Prefetching and Caching and enable BIOS = Write Protect + // + if ((FlashCycleType =3D=3D FlashCycleWrite) || + (FlashCycleType =3D=3D FlashCycleErase)) { + EnableBiosWriteProtect (); + PciSegmentAndThenOr8 ( + SpiBaseAddress + R_SPI_CFG_BC, + (UINT8) ~B_SPI_CFG_BC_SRC, + BiosCtlSave + ); + } + // + // Restore SMIs. + // + IoWrite32 ((UINTN) (ABase + R_ACPI_IO_SMI_EN), SmiEnSave); + + ReleaseSpiBar0 (SpiInstance); + + return Status; +} + +/** + Read data from the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor. + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle. + @param[out] Buffer The Pointer to caller-allocated buffer c= ontaining the dada received. + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolFlashRead ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + IN UINT32 Address, + IN UINT32 ByteCount, + OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + FlashRegionType, + FlashCycleRead, + Address, + ByteCount, + Buffer + ); + return Status; +} + +/** + Write data to the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor. + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle. + @param[in] Buffer Pointer to caller-allocated buffer conta= ining the data sent during the SPI cycle. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolFlashWrite ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + IN UINT32 Address, + IN UINT32 ByteCount, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + FlashRegionType, + FlashCycleWrite, + Address, + ByteCount, + Buffer + ); + return Status; +} + +/** + Erase some area on the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] FlashRegionType The Flash Region type for flash cycle wh= ich is listed in the Descriptor. + @param[in] Address The Flash Linear Address must fall withi= n a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of t= he SPI cycle. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolFlashErase ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + IN UINT32 Address, + IN UINT32 ByteCount + ) +{ + EFI_STATUS Status; + + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + FlashRegionType, + FlashCycleErase, + Address, + ByteCount, + NULL + ); + return Status; +} + +/** + Read SFDP data from the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] ComponentNumber The Componen Number for chip select + @param[in] Address The starting byte address for SFDP data = read. + @param[in] ByteCount Number of bytes in SFDP data portion of = the SPI cycle + @param[out] SfdpData The Pointer to caller-allocated buffer c= ontaining the SFDP data received + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolFlashReadSfdp ( + IN PCH_SPI_PROTOCOL *This, + IN UINT8 ComponentNumber, + IN UINT32 Address, + IN UINT32 ByteCount, + OUT UINT8 *SfdpData + ) +{ + SPI_INSTANCE *SpiInstance; + EFI_STATUS Status; + UINT32 FlashAddress; + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + Status =3D EFI_SUCCESS; + + if (ComponentNumber > SpiInstance->NumberOfComponents) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + FlashAddress =3D 0; + if (ComponentNumber =3D=3D FlashComponent1) { + FlashAddress =3D SpiInstance->Component1StartAddr; + } + FlashAddress +=3D Address; + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + FlashRegionAll, + FlashCycleReadSfdp, + FlashAddress, + ByteCount, + SfdpData + ); + return Status; +} + +/** + Read Jedec Id from the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] ComponentNumber The Componen Number for chip select + @param[in] ByteCount Number of bytes in JedecId data portion = of the SPI cycle, the data size is 3 typically + @param[out] JedecId The Pointer to caller-allocated buffer c= ontaining JEDEC ID received + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolFlashReadJedecId ( + IN PCH_SPI_PROTOCOL *This, + IN UINT8 ComponentNumber, + IN UINT32 ByteCount, + OUT UINT8 *JedecId + ) +{ + SPI_INSTANCE *SpiInstance; + EFI_STATUS Status; + UINT32 Address; + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + Status =3D EFI_SUCCESS; + + if (ComponentNumber > SpiInstance->NumberOfComponents) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Address =3D 0; + if (ComponentNumber =3D=3D FlashComponent1) { + Address =3D SpiInstance->Component1StartAddr; + } + + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + FlashRegionAll, + FlashCycleReadJedecId, + Address, + ByteCount, + JedecId + ); + return Status; +} + +/** + Write the status register in the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] ByteCount Number of bytes in Status data portion o= f the SPI cycle, the data size is 1 typically + @param[in] StatusValue The Pointer to caller-allocated buffer c= ontaining the value of Status register writing + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolFlashWriteStatus ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 ByteCount, + IN UINT8 *StatusValue + ) +{ + EFI_STATUS Status; + + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + FlashRegionAll, + FlashCycleWriteStatus, + 0, + ByteCount, + StatusValue + ); + return Status; +} + +/** + Read status register in the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] ByteCount Number of bytes in Status data portion o= f the SPI cycle, the data size is 1 typically + @param[out] StatusValue The Pointer to caller-allocated buffer c= ontaining the value of Status register received. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolFlashReadStatus ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 ByteCount, + OUT UINT8 *StatusValue + ) +{ + EFI_STATUS Status; + + // + // Sends the command to the SPI interface to execute. + // + Status =3D SendSpiCmd ( + This, + FlashRegionAll, + FlashCycleReadStatus, + 0, + ByteCount, + StatusValue + ); + return Status; +} + +/** + Get the SPI region base and size, based on the enum type + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] FlashRegionType The Flash Region type for for the base a= ddress which is listed in the Descriptor. + @param[out] BaseAddress The Flash Linear Address for the Region = 'n' Base + @param[out] RegionSize The size for the Region 'n' + + @retval EFI_SUCCESS Read success + @retval EFI_INVALID_PARAMETER Invalid region type given + @retval EFI_DEVICE_ERROR The region is not used +**/ +EFI_STATUS +EFIAPI +SpiProtocolGetRegionAddress ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + OUT UINT32 *BaseAddress, + OUT UINT32 *RegionSize + ) +{ + SPI_INSTANCE *SpiInstance; + UINTN PchSpiBar0; + UINT32 ReadValue; + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + + if (FlashRegionType >=3D FlashRegionMax) { + return EFI_INVALID_PARAMETER; + } + + if (FlashRegionType =3D=3D FlashRegionAll) { + *BaseAddress =3D 0; + *RegionSize =3D SpiInstance->TotalFlashSize; + return EFI_SUCCESS; + } + + PchSpiBar0 =3D AcquireSpiBar0 (SpiInstance); + ReadValue =3D MmioRead32 (PchSpiBar0 + (R_SPI_MEM_FREG0_FLASHD + (S_SPI_= MEM_FREGX * ((UINT32) FlashRegionType)))); + ReleaseSpiBar0 (SpiInstance); + + // + // If the region is not used, the Region Base is 7FFFh and Region Limit = is 0000h + // + if (ReadValue =3D=3D B_SPI_MEM_FREGX_BASE_MASK) { + return EFI_DEVICE_ERROR; + } + *BaseAddress =3D ((ReadValue & B_SPI_MEM_FREGX_BASE_MASK) >> N_SPI_MEM_F= REGX_BASE) << + N_SPI_MEM_FREGX_BASE_REPR; + // + // Region limit address Bits[11:0] are assumed to be FFFh + // + *RegionSize =3D ((((ReadValue & B_SPI_MEM_FREGX_LIMIT_MASK) >> N_SPI_MEM= _FREGX_LIMIT) + 1) << + N_SPI_MEM_FREGX_LIMIT_REPR) - *BaseAddress; + + return EFI_SUCCESS; +} + +/** + Read PCH Soft Strap Values + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA= . + @param[in] ByteCount Number of bytes in SoftStrap data portio= n of the SPI cycle + @param[out] SoftStrapValue The Pointer to caller-allocated buffer c= ontaining PCH Soft Strap Value. + If the value of ByteCount is 0, the data= type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Sof= t Strap Length + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolReadPchSoftStrap ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 SoftStrapAddr, + IN UINT32 ByteCount, + OUT VOID *SoftStrapValue + ) +{ + SPI_INSTANCE *SpiInstance; + UINT32 StrapFlashAddr; + EFI_STATUS Status; + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + + if (ByteCount =3D=3D 0) { + *(UINT16 *) SoftStrapValue =3D SpiInstance->PchStrapSize; + return EFI_SUCCESS; + } + + if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->PchStrapSize) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // PCH Strap Flash Address =3D FPSBA + RamAddr + // + StrapFlashAddr =3D SpiInstance->PchStrapBaseAddr + SoftStrapAddr; + + // + // Read PCH Soft straps from using execute command + // + Status =3D SendSpiCmd ( + This, + FlashRegionDescriptor, + FlashCycleRead, + StrapFlashAddr, + ByteCount, + SoftStrapValue + ); + return Status; +} + +/** + Read CPU Soft Strap Values + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance= . + @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUS= BA. + @param[in] ByteCount Number of bytes in SoftStrap data portio= n of the SPI cycle. + @param[out] SoftStrapValue The Pointer to caller-allocated buffer c= ontaining CPU Soft Strap Value. + If the value of ByteCount is 0, the data= type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Sof= t Strap Length + It is the caller's responsibility to mak= e sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolReadCpuSoftStrap ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 SoftStrapAddr, + IN UINT32 ByteCount, + OUT VOID *SoftStrapValue + ) +{ + SPI_INSTANCE *SpiInstance; + UINT32 StrapFlashAddr; + EFI_STATUS Status; + + SpiInstance =3D SPI_INSTANCE_FROM_SPIPROTOCOL (This); + + if (ByteCount =3D=3D 0) { + *(UINT16 *) SoftStrapValue =3D SpiInstance->CpuStrapSize; + return EFI_SUCCESS; + } + + if ((SoftStrapAddr + ByteCount) > (UINT32) SpiInstance->CpuStrapSize) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // CPU Strap Flash Address =3D FCPUSBA + RamAddr + // + StrapFlashAddr =3D SpiInstance->CpuStrapBaseAddr + SoftStrapAddr; + + // + // Read Cpu Soft straps from using execute command + // + Status =3D SendSpiCmd ( + This, + FlashRegionDescriptor, + FlashCycleRead, + StrapFlashAddr, + ByteCount, + SoftStrapValue + ); + return Status; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiS= cheduleResetLib/BaseSiScheduleResetLib.c b/Silicon/Intel/CoffeelakeSiliconP= kg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLib.c new file mode 100644 index 0000000000..dfc49d9bf6 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiSchedule= ResetLib/BaseSiScheduleResetLib.c @@ -0,0 +1,70 @@ +/** @file + Reset scheduling library services + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + This function returns SiScheduleResetHob for library use +**/ +SI_SCHEDULE_RESET_HOB * +SiScheduleGetResetData ( + VOID + ); + +/** + This function performs reset based on SiScheduleResetHob + + @retval BOOLEAN The function returns FALSE if no reset is requ= ired +**/ +BOOLEAN +SiScheduleResetPerformReset ( + VOID + ) +{ + UINTN DataSize; + SI_SCHEDULE_RESET_HOB *SiScheduleResetHob; + + if (!SiScheduleResetIsRequired ()) { + return FALSE; + } + SiScheduleResetHob =3D SiScheduleGetResetData (); + + if (SiScheduleResetHob =3D=3D NULL) { + return TRUE; + } + + DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type =3D 0x%x\n= ", SiScheduleResetHob->ResetType)); + switch (SiScheduleResetHob->ResetType) { + case EfiResetWarm: + ResetWarm (); + break; + + case EfiResetCold: + ResetCold (); + break; + + case EfiResetShutdown: + ResetShutdown (); + break; + + case EfiResetPlatformSpecific: + DataSize =3D sizeof (PCH_RESET_DATA); + ResetPlatformSpecific (DataSize, &SiScheduleResetHob->ResetData); + break; + } + // Code should never reach here + ASSERT (FALSE); + return TRUE; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiS= cheduleResetLib/BaseSiScheduleResetLibCommon.c b/Silicon/Intel/CoffeelakeSi= liconPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibC= ommon.c new file mode 100644 index 0000000000..e1d783b2e2 --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiSchedule= ResetLib/BaseSiScheduleResetLibCommon.c @@ -0,0 +1,125 @@ +/** @file + Reset scheduling library services + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include + +/** + This function returns SiScheduleResetHob for library use +**/ +SI_SCHEDULE_RESET_HOB * +SiScheduleGetResetData ( + VOID + ) +{ + STATIC SI_SCHEDULE_RESET_HOB *SiScheduleResetHob =3D NULL; + SI_SCHEDULE_RESET_HOB *SiScheduleResetHobTemp; + VOID *HobPtr; + + if (SiScheduleResetHob !=3D NULL) { + return SiScheduleResetHob; + } + + HobPtr =3D GetFirstGuidHob (&gSiScheduleResetHobGuid); + if (HobPtr =3D=3D NULL) { + SiScheduleResetHobTemp =3D BuildGuidHob (&gSiScheduleResetHobGuid, siz= eof (SI_SCHEDULE_RESET_HOB)); + if (SiScheduleResetHobTemp =3D=3D NULL) { + ASSERT (FALSE); + return SiScheduleResetHobTemp; + } + SiScheduleResetHobTemp->ResetType =3D 0xFF; + DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Init SiScheduleResetHob\= n")); + } else { + SiScheduleResetHobTemp =3D (SI_SCHEDULE_RESET_HOB*) GET_GUID_HOB_DATA = (HobPtr); + } + SiScheduleResetHob =3D SiScheduleResetHobTemp; + return SiScheduleResetHobTemp; +} + +/** + This function updates the reset information in SiScheduleResetHob + @param[in] ResetType UEFI defined reset type. + @param[in] ResetData Optional element used to introduce a platfor= m specific reset. + The exact type of the reset is defined by t= he EFI_GUID that follows + the Null-terminated Unicode string. +**/ +VOID +SiScheduleResetSetType ( + IN EFI_RESET_TYPE ResetType, + IN PCH_RESET_DATA *ResetData OPTIONAL + ) +{ + SI_SCHEDULE_RESET_HOB *SiScheduleResetHob; + if (ResetType > EfiResetPlatformSpecific) { + DEBUG ((DEBUG_INFO, "Unsupported Reset Type Requested\n")); + return; + } + SiScheduleResetHob =3D SiScheduleGetResetData (); + if (SiScheduleResetHob =3D=3D NULL) { + return; + } + DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : Current Reset Type =3D 0x%= x\n", SiScheduleResetHob->ResetType)); + if (SiScheduleResetHob->ResetType =3D=3D ResetType) { + DEBUG ((DEBUG_INFO, "Current Reset Type is same as requested Reset Typ= e\n")); + return; + } + if (SiScheduleResetHob->ResetType =3D=3D 0xFF) { + // + // Init Reset Type to lowest ResetType + // + SiScheduleResetHob->ResetType =3D EfiResetWarm; + } + // + // ResetType Priority set as : ResetPlatformSpecific(3) > ResetShutdown(= 2) > ResetCold(0) > ResetWarm(1) + // + switch (ResetType) { + case EfiResetWarm: + break; + + case EfiResetCold: + if (SiScheduleResetHob->ResetType =3D=3D EfiResetWarm) { + SiScheduleResetHob->ResetType =3D ResetType; + } + break; + + case EfiResetShutdown: + if (SiScheduleResetHob->ResetType < ResetType) + SiScheduleResetHob->ResetType =3D ResetType; + break; + + case EfiResetPlatformSpecific: + SiScheduleResetHob->ResetType =3D ResetType; + SiScheduleResetHob->ResetData =3D *ResetData; + break; + } + DEBUG ((DEBUG_INFO, "SiScheduleResetSetType : New Reset Type =3D 0x%x\n"= , SiScheduleResetHob->ResetType)); +} + +/** + This function returns TRUE or FALSE depending on whether a reset is requ= ired based on SiScheduleResetHob + + @retval BOOLEAN The function returns FALSE if no reset is requ= ired +**/ +BOOLEAN +SiScheduleResetIsRequired ( + VOID + ) +{ + VOID *HobPtr; + + HobPtr =3D NULL; + HobPtr =3D GetFirstGuidHob (&gSiScheduleResetHobGuid); + if (HobPtr =3D=3D NULL) { + return FALSE; + } + return TRUE; +} diff --git a/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiS= cheduleResetLib/BaseSiScheduleResetLibFsp.c b/Silicon/Intel/CoffeelakeSilic= onPkg/Pch/Library/Private/BaseSiScheduleResetLib/BaseSiScheduleResetLibFsp.= c new file mode 100644 index 0000000000..15ac61a21b --- /dev/null +++ b/Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/Private/BaseSiSchedule= ResetLib/BaseSiScheduleResetLibFsp.c @@ -0,0 +1,61 @@ +/** @file + Reset scheduling library services + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + This function returns SiScheduleResetHob for library use +**/ +SI_SCHEDULE_RESET_HOB * +SiScheduleGetResetData ( + VOID + ); + +/** + This function performs reset based on SiScheduleResetHob + + @retval BOOLEAN The function returns FALSE if no reset is requ= ired +**/ +BOOLEAN +SiScheduleResetPerformReset ( + VOID + ) +{ + UINTN DataSize; + SI_SCHEDULE_RESET_HOB *SiScheduleResetHob; + + if (!SiScheduleResetIsRequired ()) { + return FALSE; + } + SiScheduleResetHob =3D SiScheduleGetResetData (); + + if (SiScheduleResetHob =3D=3D NULL) { + return TRUE; + } + + DEBUG ((DEBUG_INFO, "SiScheduleResetPerformReset : Reset Type =3D 0x%x\n= ", SiScheduleResetHob->ResetType)); + if (SiScheduleResetHob->ResetType =3D=3D EfiResetPlatformSpecific) { + DataSize =3D sizeof (PCH_RESET_DATA); + (*GetPeiServicesTablePointer ())->ResetSystem2 (SiScheduleResetHob->Re= setType, EFI_SUCCESS, DataSize, &SiScheduleResetHob->ResetData); + } else { + (*GetPeiServicesTablePointer ())->ResetSystem2 (SiScheduleResetHob->Re= setType, EFI_SUCCESS, 0, NULL); + } + // + // Code should never reach here + // + ASSERT (FALSE); + return TRUE; +} --=20 2.16.2.windows.1