/** * @file * * Config Southbridge SATA controller * * Init SATA features. * * @xrefitem bom "File Content Label" "Release Content" * @e project: CIMx-SB * @e sub-project: * @e \$Revision:$ @e \$Date:$ * */ /* ***************************************************************************** * * Copyright (c) 2011, 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. * **************************************************************************** */ #include "SbPlatform.h" #include "cbtypes.h" #include "AmdSbLib.h" // // Declaration of local functions // VOID sataSetIrqIntResource (IN AMDSBCFG* pConfig); VOID sataBar5setting (IN AMDSBCFG* pConfig, IN UINT32 *pBar5); #ifdef SATA_BUS_DEV_FUN_FPGA VOID sataBar5settingFpga (IN AMDSBCFG* pConfig, IN UINT32 *pBar5); #endif VOID shutdownUnconnectedSataPortClock (IN AMDSBCFG* pConfig, IN UINT32 ddBar5); VOID CaculateAhciPortNumber (IN AMDSBCFG* pConfig, IN UINT32 ddBar5); VOID sataDriveDetection (IN AMDSBCFG* pConfig, IN UINT32 *pBar5); #ifdef SATA_BUS_DEV_FUN_FPGA VOID sataDriveDetectionFpga (IN AMDSBCFG* pConfig, IN UINT32 *pBar5); #endif VOID sataGpioPorcedure (IN AMDSBCFG* pConfig); /** * sataSetIrqIntResource - Config SATA IRQ/INT# resource * * * - Private function * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID sataSetIrqIntResource ( IN AMDSBCFG* pConfig ) { UINT8 dbValue; // IRQ14/IRQ15 come from IDE or SATA dbValue = 0x08; WriteIO (SB_IOMAP_REGC00, AccWidthUint8, &dbValue); ReadIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue); dbValue = dbValue & 0x0F; if (pConfig->SataClass == 3) { dbValue = dbValue | 0x50; } else { if (pConfig->SataIdeMode == 1) { // Both IDE & SATA set to Native mode dbValue = dbValue | 0xF0; } } WriteIO (SB_IOMAP_REGC01, AccWidthUint8, &dbValue); } /** * sataBar5setting - Config SATA BAR5 * * - Private function * * @param[in] pConfig - Southbridge configuration structure pointer. * @param[in] *pBar5 - SATA BAR5 buffer. * */ VOID sataBar5setting ( IN AMDSBCFG* pConfig, IN UINT32 *pBar5 ) { //Get BAR5 value ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5); //Assign temporary BAR if is not already assigned if ( (*pBar5 == 0) || (*pBar5 == - 1) ) { //assign temporary BAR5 if ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == - 1) ) { *pBar5 = 0xFEC01000; } else { *pBar5 = pConfig->TempMMIO; } WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG24), AccWidthUint32, pBar5); } //Clear Bits 9:0 *pBar5 = *pBar5 & 0xFFFFFC00; } #ifdef SATA_BUS_DEV_FUN_FPGA VOID sataBar5settingFpga ( IN AMDSBCFG* pConfig, IN UINT32 *pBar5 ) { UINT8 dbValue; //Get BAR5 value ReadPCI (((SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG24), AccWidthUint32, pBar5); //Assign temporary BAR if is not already assigned if ( (*pBar5 == 0) || (*pBar5 == - 1) ) { //assign temporary BAR5 if ( (pConfig->TempMMIO == 0) || (pConfig->TempMMIO == - 1) ) { *pBar5 = 0xFEC01000; } else { *pBar5 = pConfig->TempMMIO; } WritePCI (((SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG24), AccWidthUint32, pBar5); } //Clear Bits 9:0 *pBar5 = *pBar5 & 0xFFFFFC00; dbValue = 0x07; WritePCI (((SATA_BUS_DEV_FUN_FPGA << 16) + 0x04), AccWidthUint8, &dbValue); WritePCI (((PCIB_BUS_DEV_FUN << 16) + 0x04), AccWidthUint8, &dbValue); } #endif /** * shutdownUnconnectedSataPortClock - Shutdown unconnected Sata port clock * * - Private function * * @param[in] pConfig Southbridge configuration structure pointer. * @param[in] ddBar5 Sata BAR5 base address. * */ VOID shutdownUnconnectedSataPortClock ( IN AMDSBCFG* pConfig, IN UINT32 ddBar5 ) { UINT8 dbPortNum; UINT32 ddPortSataStatus; UINT8 cimSataClkAutoOff; cimSataClkAutoOff = (UINT8) pConfig->SataClkAutoOff; #if SB_CIMx_PARAMETER == 0 cimSataClkAutoOff = cimSataClkAutoOffDefault; #endif if ( cimSataClkAutoOff == TRUE ) { //ENH225976 Enable SATA auto clock control by default ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) ) { for ( dbPortNum = 0; dbPortNum < 8; dbPortNum++ ) { ReadMEM (ddBar5 + SB_SATA_BAR5_REG128 + (dbPortNum * 0x80), AccWidthUint32, &ddPortSataStatus); // Shutdown the clock for the port and do the necessary port reporting changes. // ?? Error port status should be 1 not 3 ddPortSataStatus &= 0x00000F0F; if ( (!((ddPortSataStatus == 0x601) || (ddPortSataStatus == 0x201) || (ddPortSataStatus == 0x103))) && (! ((pConfig->SATAESPPORT.SataPortReg) & (1 << dbPortNum))) ) { TRACE ((DMSG_SB_TRACE, "Shutting down clock for SATA port %X \n", dbPortNum)); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, 0xFF, (1 << dbPortNum)); } } //end of for (dbPortNum=0;dbPortNum<6;dbPortNum++) } //end of SataClkAuto Off option } /** * CaculateAhciPortNumber - Caculat AHCI Port Number * * - Private function * * @param[in] pConfig Southbridge configuration structure pointer. * @param[in] ddBar5 Sata BAR5 base address. * */ VOID CaculateAhciPortNumber ( IN AMDSBCFG* pConfig, IN UINT32 ddBar5 ) { UINT8 dbPortNum; UINT8 dbPortSataStatus; UINT8 NumOfPorts; UINT8 MaxPortNum; NumOfPorts = 0; MaxPortNum = 4; if ( (pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED ) { MaxPortNum = 6; } else if ( (pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == ENABLED ) { MaxPortNum = 8; } ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8, &dbPortSataStatus); for ( dbPortNum = 0; dbPortNum < MaxPortNum; dbPortNum++ ) { if ( dbPortSataStatus & (1 << dbPortNum) ) { RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, ~(1 << dbPortNum), 00); } } ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus); //if all ports are in disabled state, report atleast one port if ( (dbPortSataStatus & 0xFF) == 0) { RWMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, (UINT32) ~(0xFF), 01); } ReadMEM (ddBar5 + SB_SATA_BAR5_REG0C, AccWidthUint8, &dbPortSataStatus); for (dbPortNum = 0; dbPortNum < MaxPortNum; dbPortNum ++) { if (dbPortSataStatus & (1 << dbPortNum)) { NumOfPorts++; } } if ( NumOfPorts == 0) { NumOfPorts = 0x01; } RWMEM (ddBar5 + SB_SATA_BAR5_REG00, AccWidthUint8, 0xE0, NumOfPorts - 1); } /** * sataGpioPorcedure - Sata GPIO function Procedure * * - Private function * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID sataGpioPorcedure ( IN AMDSBCFG* pConfig ) { UINT32 ddBar5; UINT32 ddData; UINT32 eMb; UINT32 ddTempVariable; UINT8 cimSataSgpio0; ddBar5 = 0; eMb = 0; cimSataSgpio0 = (UINT8) pConfig->SataSgpio0; #if SB_CIMx_PARAMETER == 0 cimSataSgpio0 = cimSataSgpio0Default; #endif sataBar5setting (pConfig, &ddBar5); ReadMEM (ddBar5 + SB_SATA_BAR5_REG1C , AccWidthUint32 | S3_SAVE, &ddData); eMb = (ddBar5 + (( ddData & 0xFFFF0000) >> 14)); if ( eMb ) { ddTempVariable = 0x03040C00; WriteMEM ( ddBar5 + eMb, AccWidthUint32 | S3_SAVE, &ddTempVariable); ddTempVariable = 0x00C08240; WriteMEM ( ddBar5 + eMb + 4, AccWidthUint32 | S3_SAVE, &ddTempVariable); ddTempVariable = 0x00000001; WriteMEM ( ddBar5 + eMb + 8, AccWidthUint32 | S3_SAVE, &ddTempVariable); if ( cimSataSgpio0 ) { ddTempVariable = 0x00000060; } else { ddTempVariable = 0x00000061; } WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable); RWMEM ((ddBar5 + SB_SATA_BAR5_REG20), AccWidthUint16 | S3_SAVE, ~(BIT8), BIT8); do { ReadMEM (ddBar5 + SB_SATA_BAR5_REG20 , AccWidthUint32 | S3_SAVE, &ddData); ddData = ddData & BIT8; } while ( ddData != 0 ); ddTempVariable = 0x03040F00; WriteMEM ( ddBar5 + eMb, AccWidthUint32 | S3_SAVE, &ddTempVariable); ddTempVariable = 0x00008240; WriteMEM ( ddBar5 + eMb + 4, AccWidthUint32 | S3_SAVE, &ddTempVariable); ddTempVariable = 0x00000002; WriteMEM ( ddBar5 + eMb + 8, AccWidthUint32 | S3_SAVE, &ddTempVariable); ddTempVariable = 0x00800000; WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable); ddTempVariable = 0x0F003700; WriteMEM ( ddBar5 + eMb + 0x0C, AccWidthUint32 | S3_SAVE, &ddTempVariable); RWMEM ((ddBar5 + SB_SATA_BAR5_REG20), AccWidthUint16 | S3_SAVE, ~(BIT8), BIT8); do { ReadMEM (ddBar5 + SB_SATA_BAR5_REG20 , AccWidthUint32 | S3_SAVE, &ddData); ddData = ddData & BIT8; } while ( ddData != 0 ); } } /** * Table for class code of SATA Controller in different modes * * * * */ UINT32 sataIfCodeTable[] = { 0x01018F40, //sata class ID of IDE 0x01040040, //sata class ID of RAID 0x01060140, //sata class ID of AHCI 0x01018A40, //sata class ID of Legacy IDE 0x01018F40, //sata class ID of IDE to AHCI mode }; /** * Table for device id of SATA Controller in different modes * * * * */ UINT16 sataDeviceIDTable[] = { SB_SATA_DID, //sata device ID of IDE SB_SATA_RAID_DID, //sata device ID of RAID SB_SATA_AHCI_DID, //sata class ID of AHCI SB_SATA_DID, //sata device ID of Legacy IDE SB_SATA_DID, //sata device ID of IDE->AHCI mode }; /** * Table for Sata Phy Fine Setting * * * * */ SATAPHYSETTING sataPhyTable[] = { //Gen3 {0x0030, 0x0057A607}, {0x0031, 0x0057A607}, {0x0032, 0x0057A407}, {0x0033, 0x0057A407}, {0x0034, 0x0057A607}, {0x0035, 0x0057A607}, {0x0036, 0x0057A403}, {0x0037, 0x0057A403}, //Gen2 {0x0120, 0x00071302}, //Gen1 {0x0110, 0x00174101} }; /** * sataInitBeforePciEnum - Config SATA controller before PCI emulation * * * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID sataInitBeforePciEnum ( IN AMDSBCFG* pConfig ) { UINT32 ddTempVar; UINT32 ddValue; UINT32 *tempptr; UINT16 *pDeviceIdptr; UINT32 dwDeviceId; UINT8 dbValue; UINT8 pValue; UINT8 dbChannel; UINT16 i; SATAPHYSETTING *pPhyTable; pConfig->SATAPORTPOWER.SataPortPowerReg = \ + pConfig->SATAPORTPOWER.SataPortPower.PORT0 \ + (pConfig->SATAPORTPOWER.SataPortPower.PORT1 << 1) \ + (pConfig->SATAPORTPOWER.SataPortPower.PORT2 << 2) \ + (pConfig->SATAPORTPOWER.SataPortPower.PORT3 << 3) \ + (pConfig->SATAPORTPOWER.SataPortPower.PORT4 << 4) \ + (pConfig->SATAPORTPOWER.SataPortPower.PORT5 << 5) \ + (pConfig->SATAPORTPOWER.SataPortPower.PORT6 << 6) \ + (pConfig->SATAPORTPOWER.SataPortPower.PORT7 << 7); // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting SATA PCI register 40h // BIT4:disable fast boot //? RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0 + BIT4); // BIT0 Enable write access to PCI header (reg 08h-0Bh) by setting IDE PCI register 40h RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0); // RPR Enable IDE DMA read enhancement RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8 | S3_SAVE, 0xff, BIT7); // RPR Unused SATA Ports Disabled RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 2), AccWidthUint8 | S3_SAVE, 0, pConfig->SATAPORTPOWER.SataPortPowerReg); dbValue = (UINT8)pConfig->SataClass; if (dbValue == AHCI_MODE_7804) { dbValue = AHCI_MODE; } if (dbValue == IDE_TO_AHCI_MODE_7804) { dbValue = IDE_TO_AHCI_MODE; } // Disable PATA MSI RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG34), AccWidthUint8 | S3_SAVE, 0x00, 0x00); RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG06), AccWidthUint8 | S3_SAVE, 0xEF, 0x00); if ( (pConfig->SataClass == 3) | (pConfig->SataClass == 0)) { dbChannel = 0x00; ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8, &dbChannel); dbChannel &= 0xCF; if ( pConfig->SataDisUnusedIdePChannel ) { dbChannel |= 0x10; } if ( pConfig->SataDisUnusedIdeSChannel ) { dbChannel |= 0x20; } WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48 + 3), AccWidthUint8, &dbChannel); } if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED ) { ReadPCI (((IDE_BUS_DEV_FUN << 16) + SB_SATA_REG40 + 11), AccWidthUint8, &dbChannel); dbChannel &= 0xCF; if ( pConfig->IdeDisUnusedIdePChannel ) { dbChannel |= 0x10; } if ( pConfig->IdeDisUnusedIdeSChannel ) { dbChannel |= 0x20; } WritePCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40 + 11), AccWidthUint8, &dbChannel); } // Get the appropriate class code from the table and write it to PCI register 08h-0Bh // Set the appropriate SATA class based on the input parameters // SATA IDE Controller Class ID & SSID tempptr = (UINT32 *) FIXUP_PTR (&sataIfCodeTable[0]); if ( (pConfig->SataIdeMode == 1) && (pConfig->SataClass != 3) ) { ddValue = tempptr[0]; // Write the class code to IDE PCI register 08h-0Bh RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue); } ddValue = tempptr[dbValue]; // Write the class code to SATA PCI register 08h-0Bh RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, ddValue); if ( pConfig->SataClass == LEGACY_IDE_MODE ) { //Set PATA controller to native mode RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG09), AccWidthUint8 | S3_SAVE, 0x00, 0x08F); } if (pConfig->BuildParameters.IdeSsid != NULL ) { RWPCI ((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG2C, AccWidthUint32 | S3_SAVE, 0x00, pConfig->BuildParameters.IdeSsid); } // SATA Controller Class ID & SSID pDeviceIdptr = (UINT16 *) FIXUP_PTR (&sataDeviceIDTable[0]); ddTempVar = pConfig->BuildParameters.SataIDESsid; dwDeviceId = pDeviceIdptr[dbValue]; if ( pConfig->SataClass == RAID_MODE) { ddTempVar = pConfig->BuildParameters.SataRAID5Ssid; dwDeviceId = SB_SATA_RAID5_DID; pValue = SATA_EFUSE_LOCATION; getEfuseStatus (&pValue); if (( pValue & SATA_EFUSE_BIT ) || ( pConfig->SataForceRaid == 1 )) { dwDeviceId = SB_SATA_RAID_DID; ddTempVar = pConfig->BuildParameters.SataRAIDSsid; } } if ( ((pConfig->SataClass) == AHCI_MODE) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE) || ((pConfig->SataClass) == AHCI_MODE_7804) || ((pConfig->SataClass) == IDE_TO_AHCI_MODE_7804) ) { ddTempVar = pConfig->BuildParameters.SataAHCISsid; } RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, dwDeviceId); RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG2C, AccWidthUint32 | S3_SAVE, 0x00, ddTempVar); // SATA IRQ Resource sataSetIrqIntResource (pConfig); // RPR 9.5 SATA PHY Programming Sequence pPhyTable = (SATAPHYSETTING*)FIXUP_PTR (&sataPhyTable[0]); for (i = 0; i < (sizeof (sataPhyTable) / sizeof (SATAPHYSETTING)); i++) { RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, pPhyTable->wPhyCoreControl); RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG98, AccWidthUint32 | S3_SAVE, 0x00, pPhyTable->dwPhyFineTune); ++pPhyTable; } RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, 0x110); RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG9C, AccWidthUint32 | S3_SAVE, (UINT32) (~(0x7 << 4)), (UINT32) (0x2 << 4)); RWPCI ((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80, AccWidthUint16 | S3_SAVE, 0x00, 0x10); RWPCI (((IDE_BUS_DEV_FUN << 16) + SB_IDE_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0); // Disable write access to PCI header RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0); if ( IsSbA12Plus () ) { //SATA PCI Config 0x4C[31:26] program 111111b (six 1's) //SATA PCI Config 0x48[11] program 1 //SATA PCI Config 0x84[31] program 0 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x3f << 26)), (UINT32) (0x3f << 26)); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 11)), (UINT32) (0x01 << 11)); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG84), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 31)), (UINT32) (0x00 << 31)); } //SATA PCI config register 0x4C [20] =1 //SATA PCI config register 0x4C [21] =1 //SATA PCI config register 0x4C [18] =1 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, ~ (BIT18 + BIT20 + BIT21), (BIT18 + BIT20 + BIT21)); } /** * sataInitAfterPciEnum - Config SATA controller after PCI emulation * * * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID sataInitAfterPciEnum ( IN AMDSBCFG* pConfig ) { UINT32 ddAndMask; UINT32 ddOrMask; UINT32 ddBar5; UINT8 dbVar; UINT8 dbPortNum; UINT8 dbEfuse; UINT8 dbPortMode; UINT16 SataPortMode; UINT8 cimSataAggrLinkPmCap; UINT8 cimSataPortMultCap; UINT8 cimSataPscCap; UINT8 cimSataSscCap; UINT8 cimSataFisBasedSwitching; UINT8 cimSataCccSupport; UINT8 cimSataMsiCapability; UINT8 cimSataTargetSupport8Device; UINT8 cimSataDisableGenericMode; UINT8 cimSataAhciEnclosureManagement; UINT8 cimSataSgpio0; UINT8 cimSataSgpio1; UINT8 cimSataHotRemovelEnh; UINT8 cimSataPhyPllShutDown; UINT8 dbCccInt; cimSataAggrLinkPmCap = (UINT8) pConfig->SataAggrLinkPmCap; cimSataPortMultCap = (UINT8) pConfig->SataPortMultCap; cimSataPscCap = (UINT8) pConfig->SataPscCap; cimSataSscCap = (UINT8) pConfig->SataSscCap; cimSataFisBasedSwitching = (UINT8) pConfig->SataFisBasedSwitching; cimSataCccSupport = (UINT8) pConfig->SataCccSupport; cimSataMsiCapability = (UINT8) pConfig->SataMsiCapability; cimSataTargetSupport8Device = (UINT8) pConfig->SataTargetSupport8Device; cimSataDisableGenericMode = (UINT8) pConfig->SataDisableGenericMode; cimSataAhciEnclosureManagement = (UINT8) pConfig->SataAhciEnclosureManagement; cimSataSgpio0 = (UINT8) pConfig->SataSgpio0; cimSataSgpio1 = (UINT8) pConfig->SataSgpio1; cimSataHotRemovelEnh = (UINT8) pConfig->SataHotRemoveEnh; cimSataPhyPllShutDown = (UINT8) pConfig->SataPhyPllShutDown; #if SB_CIMx_PARAMETER == 0 cimSataAggrLinkPmCap = cimSataAggrLinkPmCapDefault; cimSataPortMultCap = cimSataPortMultCapDefault; cimSataPscCap = cimSataPscCapDefault; cimSataSscCap = cimSataSscCapDefault; cimSataFisBasedSwitching = cimSataFisBasedSwitchingDefault; cimSataCccSupport = cimSataCccSupportDefault; cimSataMsiCapability = cimSataMsiCapabilityDefault; cimSataTargetSupport8Device = cimSataTargetSupport8DeviceDefault; cimSataDisableGenericMode = cimSataDisableGenericModeDefault; cimSataAhciEnclosureManagement = cimSataAhciEnclosureManagementDefault; cimSataSgpio0 = cimSataSgpio0Default; cimSataSgpio1 = cimSataSgpio1Default; cimSataHotRemovelEnh = cimSataHotRemoveEnhDefault; cimSataPhyPllShutDown = cimSataPhyPllShutDownDefault; #endif ddAndMask = 0; ddOrMask = 0; ddBar5 = 0; if ( pConfig->SATAMODE.SataMode.SataController == 0 ) { return; //return if SATA controller is disabled. } //Enable write access to pci header, pm capabilities RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xFF, BIT0); sataBar5setting (pConfig, &ddBar5); ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03); //memory and io access enable dbEfuse = SATA_FIS_BASE_EFUSE_LOC; getEfuseStatus (&dbEfuse); if ( !cimSataPortMultCap ) { ddAndMask |= BIT12; } if ( cimSataAggrLinkPmCap ) { ddOrMask |= BIT11; } else { ddAndMask |= BIT11; } if ( cimSataPscCap ) { ddOrMask |= BIT1; } else { ddAndMask |= BIT1; } if ( cimSataSscCap ) { ddOrMask |= BIT26; } else { ddAndMask |= BIT26; } if ( cimSataFisBasedSwitching ) { if (dbEfuse & BIT1) { ddAndMask |= BIT10; } else { ddOrMask |= BIT10; } } else { ddAndMask |= BIT10; } // RPR 8.10 Disabling CCC (Command Completion Coalescing) support. if ( cimSataCccSupport ) { ddOrMask |= BIT19; } else { ddAndMask |= BIT19; } if ( cimSataAhciEnclosureManagement ) { ddOrMask |= BIT27; } else { ddAndMask |= BIT27; } RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~ddAndMask, ddOrMask); // SATA ESP port setting // These config bits are set for SATA driver to identify which ports are external SATA ports and need to // support hotplug. If a port is set as an external SATA port and need to support hotplug, then driver will // not enable power management (HIPM & DIPM) for these ports. pConfig->SATAESPPORT.SataPortReg = \ + pConfig->SATAESPPORT.SataEspPort.PORT0 \ + (pConfig->SATAESPPORT.SataEspPort.PORT1 << 1) \ + (pConfig->SATAESPPORT.SataEspPort.PORT2 << 2) \ + (pConfig->SATAESPPORT.SataEspPort.PORT3 << 3) \ + (pConfig->SATAESPPORT.SataEspPort.PORT4 << 4) \ + (pConfig->SATAESPPORT.SataEspPort.PORT5 << 5) \ + (pConfig->SATAESPPORT.SataEspPort.PORT6 << 6) \ + (pConfig->SATAESPPORT.SataEspPort.PORT7 << 7); if ( pConfig->SATAESPPORT.SataPortReg != 0 ) { RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, ~(pConfig->SATAESPPORT.SataPortReg), 0); RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0xFF00FF00, (pConfig->SATAESPPORT.SataPortReg << 16)); // RPR 8.7 External SATA Port Indication Registers // If any of the ports was programmed as an external port, HCAP.SXS should also be set RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), BIT20); } else { // RPR 8.7 External SATA Port Indication Registers // If any of the ports was programmed as an external port, HCAP.SXS should also be set (Clear for no ESP port) RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0xFF00FF00, 0x00); RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint32 | S3_SAVE, ~(BIT20), 0x00); } if ( cimSataFisBasedSwitching ) { if (dbEfuse & BIT1) { RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0x00); } else { RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0xFF000000); } } else { RWMEM ((ddBar5 + SB_SATA_BAR5_REGF8), AccWidthUint32 | S3_SAVE, 0x00FFFFFF, 0x00); } //SB02712 Turn off MSI for SATA IDE mode. if ((pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE)) { cimSataMsiCapability = 0; } //Enabled SATA MSI capability // RPR 8.11 SATA MSI and D3 Power State Capability if (IsSbA12Plus ()) { if ( cimSataMsiCapability ) { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x50); } else { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x70); } } else { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG34), AccWidthUint8 | S3_SAVE, 0, 0x70); } if (((pConfig->SataClass) != NATIVE_IDE_MODE) && ((pConfig->SataClass) != LEGACY_IDE_MODE)) { // RAID or AHCI if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED) { // IDE2 Controller is enabled if ((pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED) { // 6 AHCI mode RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0x3F); RWMEM ((ddBar5 + SB_SATA_BAR5_REG00), AccWidthUint8 | S3_SAVE, ~(BIT2 + BIT1 + BIT0), BIT2 + BIT0); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1); RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint8, 0x07, 0x30); } else { RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0x0F); if ( pConfig->SataCccSupport ) { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1); } else { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2); } } } else { // IDE2 Controller is disabled RWMEM ((ddBar5 + SB_SATA_BAR5_REG00), AccWidthUint8 | S3_SAVE, ~(BIT2 + BIT1 + BIT0), BIT2 + BIT1 + BIT0); RWMEM ((ddBar5 + SB_SATA_BAR5_REG0C), AccWidthUint8 | S3_SAVE, 0x00, 0xFF); if ( pConfig->SataCccSupport ) { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT3); } else { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG50 + 2), AccWidthUint8, ~(BIT3 + BIT2 + BIT1), BIT2 + BIT1); } } } if ( pConfig->BIOSOSHandoff == 1 ) { RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, BIT0); } else { RWMEM ((ddBar5 + SB_SATA_BAR5_REG24), AccWidthUint8 | S3_SAVE, ~BIT0, 0x00); } pConfig->SATAPORTMODE.SataPortMode = \ pConfig->SATAPORTMODE.SataPortMd.PORT0 \ + (pConfig->SATAPORTMODE.SataPortMd.PORT1 << 2) \ + (pConfig->SATAPORTMODE.SataPortMd.PORT2 << 4) \ + (pConfig->SATAPORTMODE.SataPortMd.PORT3 << 6) \ + (pConfig->SATAPORTMODE.SataPortMd.PORT4 << 8) \ + (pConfig->SATAPORTMODE.SataPortMd.PORT5 << 10) \ + (pConfig->SATAPORTMODE.SataPortMd.PORT6 << 12) \ + (pConfig->SATAPORTMODE.SataPortMd.PORT7 << 14); SataPortMode = (UINT16)pConfig->SATAPORTMODE.SataPortMode; dbPortNum = 0; while ( dbPortNum < 8 ) { dbPortMode = (UINT8) (SataPortMode & 3); if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) { if ( dbPortMode == BIT0 ) { // set GEN 1 RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x10); } if ( dbPortMode == BIT1 ) { // set GEN2 (default is GEN3) RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0x0F, 0x20); } RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFF, 0x01); cimSbStall (1000); RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00); } SataPortMode >>= 2; dbPortNum ++; } SbStall (1000); SataPortMode = (UINT16)pConfig->SATAPORTMODE.SataPortMode; dbPortNum = 0; while ( dbPortNum < 8 ) { dbPortMode = (UINT8) (SataPortMode & 3); if ( (dbPortMode == BIT0) || (dbPortMode == BIT1) ) { RWMEM (ddBar5 + SB_SATA_BAR5_REG12C + dbPortNum * 0x80, AccWidthUint8, 0xFE, 0x00); } dbPortNum ++; SataPortMode >>= 2; } if ( cimSataTargetSupport8Device ) { RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT12, BIT12); } else { RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT12, 0x00); } if ( cimSataDisableGenericMode ) { RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT13, BIT13); } else { RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint16, ~BIT13, 0x00); } // 9.19 Optionally Disable Hot-removal Detection Enhancement if ( cimSataHotRemovelEnh ) { RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80), AccWidthUint16 | S3_SAVE, ~BIT8, BIT8 ); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REGA8), AccWidthUint16 | S3_SAVE, ~BIT0, BIT0); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG80), AccWidthUint16 | S3_SAVE, ~BIT8, 0 ); } if ( cimSataSgpio0 ) { sataGpioPorcedure (pConfig); } if ( cimSataSgpio1 ) { sataGpioPorcedure (pConfig); } if ( IsSbA11 () ) { if ( cimSataPhyPllShutDown ) { RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6 + BIT7), BIT6 + BIT7); } else { RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6 + BIT7), 0x00); } } else { if ( cimSataPhyPllShutDown ) { RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6), BIT6); } else { RWPCI (((SATA_BUS_DEV_FUN << 16) + 0x87), AccWidthUint8 | S3_SAVE, ~(BIT6), 0x00); } } if ( IsSbA12Plus () ) { //SATA PCI Config 0x4C[31:26] program 111111b (six 1's) //SATA PCI Config 0x48[11] program 1 //SATA PCI Config 0x84[31] program 0 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG4C), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x3f << 26)), (UINT32) (0x3f << 26)); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG48), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 11)), (UINT32) (0x01 << 11)); RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG84), AccWidthUint32 | S3_SAVE, (UINT32) (~ (0x01 << 31)), (UINT32) (0x00 << 31)); } // RPR 9.18 CCC Interrupt dbCccInt = 4; if ((pConfig->SATAMODE.SataMode.SataIdeCombinedMode) == DISABLED) { if ((pConfig->SATAMODE.SataMode.SataIdeCombMdPriSecOpt) == ENABLED) { dbCccInt = 6; } } else { dbCccInt = 8; } RWMEM ((ddBar5 + SB_SATA_BAR5_REGFC), AccWidthUint8, 0x07, (dbCccInt << 3)); shutdownUnconnectedSataPortClock (pConfig, ddBar5); WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar); // RPR 9.13 Disable SATA FLR Capability // SATA_PCI_config 0x70 [15:8] = 0x00 RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG70), AccWidthUint32 | S3_SAVE, 0xFFFF00FF, 0x00); //Disable write access to pci header, pm capabilities RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0); } /** * sataInitMidPost - Config SATA controller in Middle POST. * * * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID sataInitMidPost ( IN AMDSBCFG* pConfig ) { UINT32 ddBar5; sataBar5setting (pConfig, &ddBar5); //If this is not S3 resume and also if SATA set to one of IDE mode, then implement drive detection workaround. if ( ! (pConfig->S3Resume) && ( ((pConfig->SataClass) != AHCI_MODE) && ((pConfig->SataClass) != RAID_MODE) ) ) { sataDriveDetection (pConfig, &ddBar5); } #ifdef SATA_BUS_DEV_FUN_FPGA sataBar5settingFpga (pConfig, &ddBar5); sataDriveDetectionFpga (pConfig, &ddBar5); #endif } /** * sataDriveDetection - Sata drive detection * * * @param[in] pConfig Southbridge configuration structure pointer. * @param[in] *pBar5 Sata BAR5 base address. * */ VOID sataDriveDetection ( IN AMDSBCFG* pConfig, IN UINT32 *pBar5 ) { UINT32 ddVar0; UINT8 dbPortNum; UINT8 dbVar0; UINT16 dwIoBase; UINT32 ddVar1; TRACE ((DMSG_SB_TRACE, "CIMx - Entering sata drive detection procedure\n\n")); TRACE ((DMSG_SB_TRACE, "SATA BAR5 is %X \n", *pBar5)); if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE) ) { for ( dbPortNum = 0; dbPortNum < 4; dbPortNum++ ) { ReadMEM (*pBar5 + SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0); if ( ( ddVar0 & 0x0F ) == 0x03 ) { if ( dbPortNum & BIT0 ) { //this port belongs to secondary channel ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase); } else { //this port belongs to primary channel ReadPCI (((UINT32) (SATA_BUS_DEV_FUN << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase); } //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them if ( pConfig->SataClass == LEGACY_IDE_MODE ) { dwIoBase = ( (0x170) | ((UINT16) ( (~((UINT8) (dbPortNum & BIT0) << 7)) & 0x80 )) ); } if ( dbPortNum & BIT1 ) { //this port is slave dbVar0 = 0xB0; } else { //this port is master dbVar0 = 0xA0; } dwIoBase &= 0xFFF8; WriteIO (dwIoBase + 6, AccWidthUint8, &dbVar0); //Wait in loop for 30s for the drive to become ready for ( ddVar1 = 0; ddVar1 < 300000; ddVar1++ ) { ReadIO (dwIoBase + 7, AccWidthUint8, &dbVar0); if ( (dbVar0 & 0x88) == 0 ) { break; } SbStall (100); } } //end of if ( ( ddVar0 & 0x0F ) == 0x03) } //for (dbPortNum = 0; dbPortNum < 4; dbPortNum++) } //if ( (pConfig->SataClass == NATIVE_IDE_MODE) || (pConfig->SataClass == LEGACY_IDE_MODE) || (pConfig->SataClass == IDE_TO_AHCI_MODE)) } #ifdef SATA_BUS_DEV_FUN_FPGA VOID sataDriveDetectionFpga ( IN AMDSBCFG* pConfig, IN UINT32 *pBar5 ) { UINT32 ddVar0; UINT8 dbPortNum; UINT8 dbVar0; UINT16 dwIoBase; UINT32 ddVar1; TRACE ((DMSG_SB_TRACE, "CIMx - Entering sata drive detection procedure\n\n")); TRACE ((DMSG_SB_TRACE, "SATA BAR5 is %X \n", *pBar5)); for ( dbPortNum = 0; dbPortNum < 4; dbPortNum++ ) { ReadMEM (*pBar5 + SB_SATA_BAR5_REG128 + dbPortNum * 0x80, AccWidthUint32, &ddVar0); if ( ( ddVar0 & 0x0F ) == 0x03 ) { if ( dbPortNum & BIT0 ) { //this port belongs to secondary channel ReadPCI (((UINT32) (SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG18), AccWidthUint16, &dwIoBase); } else { //this port belongs to primary channel ReadPCI (((UINT32) (SATA_BUS_DEV_FUN_FPGA << 16) + SB_SATA_REG10), AccWidthUint16, &dwIoBase); } //if legacy ide mode, then the bar registers don't contain the correct values. So we need to hardcode them if ( pConfig->SataClass == LEGACY_IDE_MODE ) { dwIoBase = ( (0x170) | ((UINT16) ( (~((UINT8) (dbPortNum & BIT0) << 7)) & 0x80 )) ); } if ( dbPortNum & BIT1 ) { //this port is slave dbVar0 = 0xB0; } else { //this port is master dbVar0 = 0xA0; } dwIoBase &= 0xFFF8; WriteIO (dwIoBase + 6, AccWidthUint8, &dbVar0); //Wait in loop for 30s for the drive to become ready for ( ddVar1 = 0; ddVar1 < 300000; ddVar1++ ) { ReadIO (dwIoBase + 7, AccWidthUint8, &dbVar0); if ( (dbVar0 & 0x88) == 0 ) { break; } SbStall (100); } } //end of if ( ( ddVar0 & 0x0F ) == 0x03) } //for (dbPortNum = 0; dbPortNum < 4; dbPortNum++) } #endif /** * sataInitLatePost - Prepare SATA controller to boot to OS. * * - Set class ID to AHCI (if set to AHCI * Mode) * - Enable AHCI interrupt * * @param[in] pConfig Southbridge configuration structure pointer. * */ VOID sataInitLatePost ( IN AMDSBCFG* pConfig ) { UINT32 ddBar5; UINT8 dbVar; UINT8 dbPortNum; //Return immediately is sata controller is not enabled if ( pConfig->SATAMODE.SataMode.SataController == 0 ) { return; } //Enable write access to pci header, pm capabilities RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, 0xff, BIT0); sataBar5setting (pConfig, &ddBar5); ReadPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar); //Enable memory and io access RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, 0xFF, 0x03); if (( pConfig->SataClass == IDE_TO_AHCI_MODE) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 )) { //program the AHCI class code RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG08), AccWidthUint32 | S3_SAVE, 0, 0x01060100); //Set interrupt enable bit RWMEM ((ddBar5 + 0x04), AccWidthUint8, (UINT32)~0, BIT1); //program the correct device id for AHCI mode RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, SB_SATA_AHCI_DID); } if (( pConfig->SataClass == AHCI_MODE_7804 ) || ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 )) { //program the correct device id for AHCI 7804 mode RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG02), AccWidthUint16 | S3_SAVE, 0, SB_SATA_AMDAHCI_DID); } // OBS236459 IDE controller not shown in device manager when Os installed on IDE mode port //if ( pConfig->SataClass == IDE_TO_AHCI_MODE_7804 ) { //Disable IDE2 and Enable 8 channel for IDE-AHCI mode //RWMEM (ACPI_MMIO_BASE + PMIO_BASE + SB_PMIOA_REGDA, AccWidthUint8, ~BIT1, BIT3); //} //Clear error status RWMEM ((ddBar5 + SB_SATA_BAR5_REG130), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); RWMEM ((ddBar5 + SB_SATA_BAR5_REG1B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); RWMEM ((ddBar5 + SB_SATA_BAR5_REG230), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); RWMEM ((ddBar5 + SB_SATA_BAR5_REG2B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); RWMEM ((ddBar5 + SB_SATA_BAR5_REG330), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); RWMEM ((ddBar5 + SB_SATA_BAR5_REG3B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); RWMEM ((ddBar5 + SB_SATA_BAR5_REG430), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); RWMEM ((ddBar5 + SB_SATA_BAR5_REG4B0), AccWidthUint32 | S3_SAVE, 0xFFFFFFFF, 0xFFFFFFFF); CaculateAhciPortNumber (pConfig, ddBar5); //Restore memory and io access bits WritePCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG04), AccWidthUint8, &dbVar ); //Disable write access to pci header and pm capabilities RWPCI (((SATA_BUS_DEV_FUN << 16) + SB_SATA_REG40), AccWidthUint8 | S3_SAVE, ~BIT0, 0); for ( dbPortNum = 0; dbPortNum < 6; dbPortNum++ ) { RWMEM ((ddBar5 + 0x110 + (dbPortNum * 0x80)), AccWidthUint32, 0xFFFFFFFF, 0x00); } }