blob: aee94676e9a9fb04e48af787ef880b56b2c99aa6 [file] [log] [blame]
/* $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;
}