/* $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); }