/* $NoKeywords:$ */ /** * @file * * PCIe late post initialization. * * * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: GNB * @e \$Revision: 86584 $ @e \$Date: 2013-01-23 12:34:28 -0600 (Wed, 23 Jan 2013) $ * */ /* ***************************************************************************** * * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Advanced Micro Devices, Inc. nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************** * */ /*---------------------------------------------------------------------------------------- * M O D U L E S U S E D *---------------------------------------------------------------------------------------- */ #include "AGESA.h" #include "Ids.h" #include "amdlib.h" #include "heapManager.h" #include "Gnb.h" #include "GnbGfx.h" #include "GnbCommonLib.h" #include "GnbTable.h" #include "GnbPcieConfig.h" #include "GnbRegisterAccKB.h" #include "cpuFamilyTranslation.h" #include "GnbRegistersKB.h" #include "GfxLibKB.h" #include "GfxSamuInitKB.h" #include "GnbSamuPatchKB.h" #include "OptionGnb.h" #include "Filecode.h" #define FILECODE PROC_GNB_MODULES_GNBINITKB_GFXSAMUINITKB_FILECODE /*---------------------------------------------------------------------------------------- * D E F I N I T I O N S A N D M A C R O S *---------------------------------------------------------------------------------------- */ extern GNB_BUILD_OPTIONS GnbBuildOptions; /*---------------------------------------------------------------------------------------- * T Y P E D E F S A N D S T R U C T U R E S *---------------------------------------------------------------------------------------- */ #define LENGTH_1MBYTE 0x0100000ul #define MASK_1MBYTE 0x0FFFFFul #define SAM_IND_INDEX 0x22000ul #define SAM_IND_DATA 0x22004ul #define SAM_SAB_IND_INDEX 0x22008ul #define SAM_SAB_IND_DATA 0x2200Cul #define SMU_TOOLS_INDEX 0x238ul #define SMU_TOOLS_DATA 0x23Cul typedef struct { UINT32 BootControl; ///< UINT32 KeySelect; ///< UINT32 KernelAddrLo; ///< UINT32 KernelAddrHi; ///< UINT32 TweakSelect; ///< } SAMU_BOOT_CONTROL; /*---------------------------------------------------------------------------------------- * P R O T O T Y P E S O F L O C A L F U N C T I O N S *---------------------------------------------------------------------------------------- */ /*----------------------------------------------------------------------------------------*/ /** * Initialize GMC * * * * @param[in] Gfx Pointer to global GFX configuration * */ AGESA_STATUS GfxSamuInit ( IN GFX_PLATFORM_CONFIG *Gfx ) { UINT32 D0F0xBC_xC00C0000; GNB_HANDLE *GnbHandle; VOID *ControlXBuffer; VOID *AlignedControlXBuffer; VOID *PatchYBuffer; VOID *AlignedPatchYBuffer; SAMU_BOOT_CONTROL *SamuBootControl; UINT32 D0F0xBC_x800000A4; UINT32 GMMx22000; UINT32 GMMx22004; UINT32 GMMx22008; UINT32 GMMx2200C; UINT32 LoopCount; BOOLEAN SamuUseF1dPatch; BOOLEAN SamuPatchEnabled; IDS_HDT_CONSOLE (GNB_TRACE, "GnbSamuInit Enter\n"); GnbHandle = GnbGetHandle (GnbLibGetHeader (Gfx)); ASSERT (GnbHandle != NULL); GnbRegisterReadKB (GnbHandle, 0x4, 0xc00c0000, &D0F0xBC_xC00C0000, 0, GnbLibGetHeader (Gfx)); SamuPatchEnabled = GnbBuildOptions.CfgSamuPatchEnabled; IDS_OPTION_HOOK (IDS_GNB_LOAD_SAMU_PATCH, &SamuPatchEnabled, GnbLibGetHeader (Gfx)); if ((((D0F0xBC_xC00C0000) & BIT24) == 0) && (SamuPatchEnabled == TRUE)) { // Decide which version of the patch to use SamuUseF1dPatch = TRUE; GMMx22008 = 0x29; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22008, &GMMx22008, 0, GnbLibGetHeader (Gfx)); GnbRegisterReadKB (GnbHandle, 0x12, 0x2200C, &GMMx2200C, 0, GnbLibGetHeader (Gfx)); IDS_HDT_CONSOLE (GNB_TRACE, " SAMSAB:29=%08x\n", GMMx2200C); if (GMMx2200C == 0x80000001) { SamuUseF1dPatch = FALSE; } ControlXBuffer = GnbAllocateHeapBufferAndClear (AMD_GNB_SAMU_BOOT_CONTROL_HANDLE, 2 * LENGTH_1MBYTE, GnbLibGetHeader (Gfx)); ASSERT (ControlXBuffer != NULL); if (ControlXBuffer == NULL) { return AGESA_ERROR; } AlignedControlXBuffer = (VOID *) (((UINTN)ControlXBuffer + LENGTH_1MBYTE) & (~MASK_1MBYTE)); PatchYBuffer = GnbAllocateHeapBuffer (AMD_GNB_SAMU_PATCH_HANDLE, 2 * LENGTH_1MBYTE, GnbLibGetHeader (Gfx)); ASSERT (PatchYBuffer != NULL); if (PatchYBuffer == NULL) { return AGESA_ERROR; } AlignedPatchYBuffer = (VOID *) (((UINTN)PatchYBuffer + LENGTH_1MBYTE) & (~MASK_1MBYTE)); // Copy samu firmware patch to PatchYBuffer if (SamuUseF1dPatch == TRUE) { LibAmdMemCopy (AlignedPatchYBuffer, &SamuPatchKB[0], SamuPatchKBHeader[1], GnbLibGetHeader (Gfx)); } else { LibAmdMemCopy (AlignedPatchYBuffer, &SamuPatchKBUnf1[0], SamuPatchKBHeaderUnf1[1], GnbLibGetHeader (Gfx)); } // WBINVD LibAmdWriteBackInvalidateCache (); // Load boot control structure SamuBootControl = (SAMU_BOOT_CONTROL *)AlignedControlXBuffer; SamuBootControl->BootControl = 0x3; SamuBootControl->KernelAddrLo = (UINTN)AlignedPatchYBuffer; SamuBootControl->KernelAddrHi = ((((UINT64)(UINTN)AlignedPatchYBuffer) >> 32) & 0xFF); if (SamuUseF1dPatch == TRUE) { SamuBootControl->TweakSelect = 0xBB027E1F; SamuBootControl->KeySelect = 0x8E174F83; } else { SamuBootControl->TweakSelect = 0x0; SamuBootControl->KeySelect = 0x0; } // Write 0x0 to SAM_CGC_HOST_CTRL to release the clock-gating of SAMU GMMx22000 = 0x3; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22000, &GMMx22000, 0, GnbLibGetHeader (Gfx)); GMMx22004 = 0x0; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22004, &GMMx22004, 0, GnbLibGetHeader (Gfx)); // Write (physical address of boot control structure)>>8 into SAM_SAB_INIT_TLB_CONFIG (Location X >> 8) GMMx22008 = 0x4; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22008, &GMMx22008, 0, GnbLibGetHeader (Gfx)); GMMx2200C = ((UINTN) AlignedControlXBuffer) >> 8; GnbRegisterWriteKB (GnbHandle, 0x12, 0x2200C, &GMMx2200C, 0, GnbLibGetHeader (Gfx)); // Write 0x0 to SAM_RST_HOST_SOFT_RESET GMMx22000 = 0x1; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22000, &GMMx22000, 0, GnbLibGetHeader (Gfx)); GMMx22004 = 0x0; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22004, &GMMx22004, 0, GnbLibGetHeader (Gfx)); // Write 0x2 to SAM_SCRATCH_0 to start the firmware boot GMMx22000 = 0x38; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22000, &GMMx22000, 0, GnbLibGetHeader (Gfx)); GMMx22004 = 0x2; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22004, &GMMx22004, 0, GnbLibGetHeader (Gfx)); // Poll SAM_RST_HOST_SOFT_RST_RDY and wait for HOST_RDY do { // Write 0x2 to SAM_SCRATCH_0 to start the firmware boot GMMx22000 = 0x51; GnbRegisterWriteKB (GnbHandle, 0x12, 0x22000, &GMMx22000, 0, GnbLibGetHeader (Gfx)); GnbRegisterReadKB (GnbHandle, 0x12, 0x22004, &GMMx22004, 0, GnbLibGetHeader (Gfx)); } while ((GMMx22004 & BIT0) == 0); // Clear the allocated memory ranges, locations X and Y (write 0), issue WBINVD LibAmdMemFill (ControlXBuffer, 0, 2 * LENGTH_1MBYTE, GnbLibGetHeader (Gfx)); LibAmdMemFill (PatchYBuffer, 0, 2 * LENGTH_1MBYTE, GnbLibGetHeader (Gfx)); LibAmdWriteBackInvalidateCache (); // Confirm read of SMC_DRAM_ACCESS_CNTL is 0x1 D0F0xBC_x800000A4 = 0; for (LoopCount = 0; LoopCount < 0x00FFFFFF; LoopCount++) { GnbRegisterReadKB (GnbHandle, 0x4, 0x800000A4, &D0F0xBC_x800000A4, 0, GnbLibGetHeader (Gfx)); if ((D0F0xBC_x800000A4 & BIT0) != 0) { break; } } ASSERT ((D0F0xBC_x800000A4 & BIT0) != 0); } IDS_HDT_CONSOLE (GNB_TRACE, "GnbSamuInit Exit\n"); return AGESA_SUCCESS; }