diff options
author | efdesign98 <efdesign98@gmail.com> | 2011-06-16 16:39:30 -0700 |
---|---|---|
committer | Marc Jones <marcj303@gmail.com> | 2011-06-21 22:38:39 +0200 |
commit | ee39ea7e7edf9699f1bae1b2708ad6816f054817 (patch) | |
tree | e2de6cd600b1b8d4a657202962d8bc2e348ec67f /src/vendorcode/amd/cimx/sb900/Sata.c | |
parent | b0969d65e675f7c7a3004fc3f6fc154f22e73d44 (diff) |
Add AMD SB900 CIMx code
This code is added to support the AMD SB900 southbridge.
Change-Id: I7dc5e13a53ffd479dcea4e05e8c8631096e2ba91
Signed-off-by: Frank Vibrans <frank.vibrans@amd.com>
Signed-off-by: efdesign98 <efdesign98@gmail.com>
Reviewed-on: http://review.coreboot.org/41
Tested-by: build bot (Jenkins)
Reviewed-by: Marc Jones <marcj303@gmail.com>
Diffstat (limited to 'src/vendorcode/amd/cimx/sb900/Sata.c')
-rwxr-xr-x | src/vendorcode/amd/cimx/sb900/Sata.c | 1042 |
1 files changed, 1042 insertions, 0 deletions
diff --git a/src/vendorcode/amd/cimx/sb900/Sata.c b/src/vendorcode/amd/cimx/sb900/Sata.c new file mode 100755 index 0000000000..9a7cf5389c --- /dev/null +++ b/src/vendorcode/amd/cimx/sb900/Sata.c @@ -0,0 +1,1042 @@ + +/** + * @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)) { + // RIAD 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, them 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); + } +} + + |