blob: f1f62b1b3f248063b588471031b40062f7080c44 [file] [log] [blame]
/* $NoKeywords:$ */
/**
* @file
*
* Config Fch Spi controller
*
* Init Spi Controller features (PEI phase).
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: AGESA
* @e sub-project: FCH
* @e \$Revision: 64064 $ @e \$Date: 2012-01-15 22:36:53 -0600 (Sun, 15 Jan 2012) $
*
*/
/*
*****************************************************************************
*
* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
*
* AMD is granting you permission to use this software (the Materials)
* pursuant to the terms and conditions of your Software License Agreement
* with AMD. This header does *NOT* give you permission to use the Materials
* or any rights under AMD's intellectual property. Your use of any portion
* of these Materials shall constitute your acceptance of those terms and
* conditions. If you do not agree to the terms and conditions of the Software
* License Agreement, please do not use any portion of these Materials.
*
* CONFIDENTIALITY: The Materials and all other information, identified as
* confidential and provided to you by AMD shall be kept confidential in
* accordance with the terms and conditions of the Software License Agreement.
*
* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
*
* AMD does not assume any responsibility for any errors which may appear in
* the Materials or any other related information provided to you by AMD, or
* result from use of the Materials or any related information.
*
* You agree that you will not reverse engineer or decompile the Materials.
*
* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
* further information, software, technical information, know-how, or show-how
* available to you. Additionally, AMD retains the right to modify the
* Materials at any time, without notice, and is not obligated to provide such
* modified Materials to you.
*
* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
* subject to the restrictions as set forth in FAR 52.227-14 and
* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
* Government constitutes acknowledgement of AMD's proprietary rights in them.
*
* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
* direct product thereof will be exported directly or indirectly, into any
* country prohibited by the United States Export Administration Act and the
* regulations thereunder, without the required authorization from the U.S.
* government nor will be used for any purpose prohibited by the same.
****************************************************************************
*/
#include "FchPlatform.h"
#define FILECODE PROC_FCH_SPI_SPIRESET_FILECODE
/**
* FchDummy2 - Dummy2
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
*
*/
VOID
FchDummy2 (
IN UINT32 SpiRomBase
);
VOID
FchDummy (
IN UINT32 SpiRomBase
);
VOID
FchSpiExecute (
IN UINT32 SpiRomBase
);
VOID
FchResetFifo (
IN UINT32 SpiRomBase
);
VOID
FchResetFifoToLast (
IN UINT32 SpiRomBase
);
UINT32
FchReadSpiId (
IN UINT32 SpiRomBase,
IN BOOLEAN Flag
);
BOOLEAN
FchReadSpiQe (
IN UINT32 SpiRomBase,
IN UINT32 DeviceID
);
VOID
FchWriteSpiQe (
IN UINT32 SpiRomBase,
IN UINT32 DeviceID
);
VOID
FchSetQualMode (
IN UINT32 SpiQualMode,
IN UINT32 SpiRomBase,
IN AMD_CONFIG_PARAMS *StdHeader
);
VOID
FchClearQualMode (
IN AMD_CONFIG_PARAMS *StdHeader
);
BOOLEAN
FchCheckSpiQe (
IN UINT32 SpiRomBase,
IN AMD_CONFIG_PARAMS *StdHeader
);
/**
* FchDummy - Dummy
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
*
*/
VOID
FchDummy (
IN UINT32 SpiRomBase
)
{
ACPIMMIO32 (SpiRomBase + FCH_SPI_MMIO_REG00);
}
/**
* FchSpiExecute - SPI Execute
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
*
*/
VOID
FchSpiExecute (
IN UINT32 SpiRomBase
)
{
UINT32 SpiReg00;
SpiReg00 = BIT31 + BIT16;
ACPIMMIO32 (SpiRomBase + FCH_SPI_MMIO_REG00) |= BIT16;
do {
SpiReg00 = ACPIMMIO32 (SpiRomBase + FCH_SPI_MMIO_REG00);
} while ((SpiReg00 & (BIT31 + BIT16)));
}
/**
* FchResetFifo - Reset SPI FIFO
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
*
*/
VOID
FchResetFifo (
IN UINT32 SpiRomBase
)
{
ACPIMMIO32 (SpiRomBase + FCH_SPI_MMIO_REG00) |= BIT20;
//ACPIMMIO32 (SpiRomBase + FCH_SPI_MMIO_REG00) |= BIT21;
}
/**
* FchResetFifoToLast - Reset SPI FIFO to last
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
*
*/
VOID
FchResetFifoToLast (
IN UINT32 SpiRomBase
)
{
ACPIMMIO32 (SpiRomBase + FCH_SPI_MMIO_REG00) |= BIT20;
}
/**
* FchReadSpiId - Read SPI ID
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
* @param[in] Flag - Read Flag.
*
*/
UINT32
FchReadSpiId (
IN UINT32 SpiRomBase,
IN BOOLEAN Flag
)
{
UINT32 DeviceID;
UINT8 i;
DeviceID = 0;
if (Flag) {
ACPIMMIO16 (SpiRomBase + FCH_SPI_MMIO_REG00) = 0x409F;
FchSpiExecute (SpiRomBase);
FchResetFifo (SpiRomBase);
for (i = 0; i < 3; i++) {
DeviceID |= ((UINT32) (ACPIMMIO8 (SpiRomBase + FCH_SPI_MMIO_REG0C)) << (i*8));
}
} else {
FchDummy (SpiRomBase);
FchDummy2 (SpiRomBase);
}
return DeviceID;
}
/**
* FchReadSpiQe - Read SPI Qual Enable
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
* @param[in] DeviceID - Devic ID.
*
*/
BOOLEAN
FchReadSpiQe (
IN UINT32 SpiRomBase,
IN UINT32 DeviceID
)
{
UINT8 StatusLen;
UINT8 dbStatus;
UINT8 dbStatus1;
UINT8 StatusRead;
UINT8 StatusWrite;
UINT8 QualEnable;
UINT8 QualEnable1;
StatusLen = 0x02;
StatusRead = 0x05;
StatusWrite = 0x01;
QualEnable = 0;
QualEnable1 = 0;
switch (DeviceID) {
case 0x0024C2: //Macronix_MX25L1633E
case 0x0025C2: //Macronix_MX25L1636E
case 0x005EC2: //Macronix_MX25L3235D
case 0x165EC2: //Macronix_MX25L3235D:tested
QualEnable = 0x40;
break;
case 0x0014ef: //Wnbond_W25X16= S25FL016K
case 0x004015: //Wnbond_W25Q16CV
StatusLen = 0x02;
StatusRead = 0x35;
QualEnable1 = 0x02;
break;
case 0x00861F: //Atmel_AT25DQ161
StatusRead = 0x3F;
StatusRead = 0x3E;
QualEnable = 0x80;
break;
default:
return FALSE;
}
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth16, 0, (StatusLen << 12) | StatusRead);
FchSpiExecute (SpiRomBase);
FchResetFifo (SpiRomBase);
ReadMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth8, &dbStatus);
ReadMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth8, &dbStatus);
ReadMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth8, &dbStatus1);
if ((dbStatus & QualEnable) || (dbStatus1 & QualEnable1) ) {
return TRUE;
}
return FALSE;
}
/**
* FchWriteSpiQe - Write SPI Qual Enable
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
* @param[in] DeviceID - Devic ID.
*
*/
VOID
FchWriteSpiQe (
IN UINT32 SpiRomBase,
IN UINT32 DeviceID
)
{
UINT8 StatusLen;
UINT8 StatusWriteLen;
UINT8 dbStatus;
UINT8 dbStatus1;
UINT8 StatusRead;
UINT8 StatusWrite;
UINT8 QualEnable;
UINT8 QualEnable1;
StatusLen = 0x02;
StatusRead = 0x05;
StatusWrite = 0x01;
StatusWriteLen = 0x01;
QualEnable = 0;
QualEnable1 = 0;
switch (DeviceID) {
case 0x0024C2: //Macronix_MX25L1633E
case 0x0025C2: //Macronix_MX25L1636E
case 0x005EC2: //Macronix_MX25L3235D
case 0x165EC2: //Macronix_MX25L3235D:tested
QualEnable = 0x40;
break;
case 0x0014ef: //Wnbond_W25X16= S25FL016K
case 0x004015: //Wnbond_W25Q16CV
StatusLen = 0x02;
StatusRead = 0x35;
QualEnable1 = 0x02;
break;
case 0x00861F: //Atmel_AT25DQ161
StatusRead = 0x3F;
StatusRead = 0x3E;
QualEnable = 0x80;
break;
default:
return ;
}
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth16, 0, (StatusLen << 12) | StatusRead);
FchSpiExecute (SpiRomBase);
FchResetFifo (SpiRomBase);
ReadMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth8, &dbStatus);
ReadMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth8, &dbStatus1);
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth16, 0, 0x0006);
FchSpiExecute (SpiRomBase);
FchResetFifo (SpiRomBase);
dbStatus |= QualEnable;
dbStatus1 |= QualEnable1;
WriteMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth8, &dbStatus);
WriteMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth8, &dbStatus1);
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth16, 0, (StatusWriteLen << 8) | StatusWrite);
FchSpiExecute (SpiRomBase);
}
/**
* FchSetQualMode - Set SPI Qual Mode
*
*
*
* @param[in] SpiQualMode- Spi Qual Mode.
* @param[in] SpiRomBase - Spi Rom Base.
* @param[in] StdHeader - Standard Header.
*
*/
VOID
FchSetQualMode (
IN UINT32 SpiQualMode,
IN UINT32 SpiRomBase,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
RwMem (ACPI_MMIO_BASE + GPIO_BASE + FCH_GEVENT_REG09, AccessWidth8, (UINT32)~BIT3, (UINT32)BIT3);
RwPci ((LPC_BUS_DEV_FUN << 16) + FCH_LPC_REGBB, AccessWidth8, (UINT32)~BIT0, (UINT32)BIT0, StdHeader);
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth32, (UINT32)~( BIT18 + BIT29 + BIT30), ((SpiQualMode & 1) << 18) + ((SpiQualMode & 6) << 28));
}
/**
* FchClearQualMode - Clear SPI Qual Mode
*
*
*
* @param[in] StdHeader - Standard Header.
*
*/
VOID
FchClearQualMode (
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT32 SpiRomBase;
//
// Get Spi ROM Base Address
//
ReadPci ((LPC_BUS_DEV_FUN << 16) + FCH_LPC_REGA0, AccessWidth32, &SpiRomBase, StdHeader);
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth32, (UINT32)~( BIT18 + BIT29 + BIT30), 0);
RwMem (ACPI_MMIO_BASE + GPIO_BASE + FCH_GEVENT_REG09, AccessWidth8, (UINT32)~BIT3, 0);
RwPci ((LPC_BUS_DEV_FUN << 16) + FCH_LPC_REGBB, AccessWidth8, (UINT32)~ BIT0, 0, StdHeader);
}
/**
* FchCheckSpiQe - Check SPI Qual Enable
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
* @param[in] StdHeader - Standard Header.
*
*/
BOOLEAN
FchCheckSpiQe (
IN UINT32 SpiRomBase,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT32 DeviceID;
//FchClearQualMode (SpiRomBase, StdHeader);
FchReadSpiId (SpiRomBase, FALSE);
DeviceID = FchReadSpiId (SpiRomBase, TRUE);
//if (DeviceID != 0x165EC2) FCH_DEADLOOP();
switch (DeviceID) {
case 0x0024C2: //Macronix_MX25L1633E
case 0x0025C2: //Macronix_MX25L1636E
case 0x005EC2: //Macronix_MX25L3235D
case 0x165EC2: //Macronix_MX25L3235D:tested
case 0x0014ef: //Wnbond_W25X16= S25FL016K
case 0x004015: //Wnbond_W25Q16CV
case 0x00861F: //Atmel_AT25DQ161
if (FchReadSpiQe (SpiRomBase, DeviceID)) {
return TRUE;
} else {
do {
FchWriteSpiQe (SpiRomBase, DeviceID);
if (FchReadSpiQe (SpiRomBase, DeviceID)) {
return TRUE;
}
} while (!FchReadSpiQe (SpiRomBase, DeviceID));
}
break;
}
return FALSE;
}
/**
* FchInitResetSpi - Config Spi controller during Power-On
*
*
*
* @param[in] FchDataPtr Fch configuration structure pointer.
*
*/
VOID
FchInitResetSpi (
IN VOID *FchDataPtr
)
{
UINT32 SpiModeByte;
UINT32 SpiRomBase;
FCH_RESET_DATA_BLOCK *LocalCfgPtr;
AMD_CONFIG_PARAMS *StdHeader;
LocalCfgPtr = (FCH_RESET_DATA_BLOCK *) FchDataPtr;
StdHeader = LocalCfgPtr->StdHeader;
SpiRomBase = UserOptions.FchBldCfg->CfgSpiRomBaseAddress;
//
// Set Spi ROM Base Address
//
RwPci ((LPC_BUS_DEV_FUN << 16) + FCH_LPC_REGA0, AccessWidth32, 0x001F, SpiRomBase, StdHeader);
//
// Spi Mode Initial
//
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth32, 0xFFFFFFFF, (BIT19 + BIT24 + BIT25 + BIT26));
RwMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth32, 0xFFC0FFFF, 0 );
if (LocalCfgPtr->SpiSpeed) {
RwMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth32, (UINT32)~(BIT13 + BIT12), ((LocalCfgPtr->SpiSpeed - 1 ) << 12));
}
if (LocalCfgPtr->FastSpeed) {
RwMem (SpiRomBase + FCH_SPI_MMIO_REG0C, AccessWidth32, (UINT32)~(BIT15 + BIT14), ((LocalCfgPtr->FastSpeed - 1 ) << 14));
}
RwMem (SpiRomBase + FCH_SPI_MMIO_REG1C, AccessWidth32, (UINT32)~(BIT10), ((LocalCfgPtr->BurstWrite) << 10));
SpiModeByte = LocalCfgPtr->Mode;
if (LocalCfgPtr->Mode) {
if ((SpiModeByte == FCH_SPI_MODE_QUAL_114) || (SpiModeByte == FCH_SPI_MODE_QUAL_144)) {
if (FchCheckSpiQe (SpiRomBase, StdHeader)) {
FchSetQualMode (SpiModeByte, SpiRomBase, StdHeader);
}
} else {
RwMem (SpiRomBase + FCH_SPI_MMIO_REG00, AccessWidth32, (UINT32)~( BIT18 + BIT29 + BIT30), ((LocalCfgPtr->Mode & 1) << 18) + ((LocalCfgPtr->Mode & 6) << 28));
}
} else {
if (FchCheckSpiQe (SpiRomBase, StdHeader)) {
SpiModeByte = FCH_SPI_MODE_QUAL_144;
//FchSetQualMode (SpiModeByte, SpiRomBase, StdHeader);
}
}
// Enabling SPI ROM Prefetch
// Set LPC cfg 0xBA bit 8
RwPci ((LPC_BUS_DEV_FUN << 16) + FCH_LPC_REGBA, AccessWidth16, 0xFFFF, BIT8, StdHeader);
// Enable SPI Prefetch for USB, set LPC cfg 0xBA bit 7 to 1.
RwPci ((LPC_BUS_DEV_FUN << 16) + FCH_LPC_REGBA, AccessWidth16, 0xFFFF, BIT7, StdHeader);
}
/**
* FchDummy2 - Dummy2
*
*
*
* @param[in] SpiRomBase - Spi Rom Base.
*
*/
VOID
FchDummy2 (
IN UINT32 SpiRomBase
)
{
ACPIMMIO32 (SpiRomBase + FCH_SPI_MMIO_REG00);
}