/***************************************************************************** * * Copyright (C) 2012 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 "Platform.h" VOID ReadIO ( IN UINT16 Address, IN UINT8 OpFlag, IN VOID* Value ) { OpFlag = OpFlag & 0x7f; switch ( OpFlag ) { case AccWidthUint8: *(UINT8*)Value = ReadIo8 (Address); break; case AccWidthUint16: *(UINT16*)Value = ReadIo16 (Address); break; case AccWidthUint32: *(UINT32*)Value = ReadIo32 (Address); break; default: break; } } VOID WriteIO ( IN UINT16 Address, IN UINT8 OpFlag, IN VOID* Value ) { OpFlag = OpFlag & 0x7f; switch ( OpFlag ) { case AccWidthUint8: WriteIo8 (Address, *(UINT8*)Value); break; case AccWidthUint16: WriteIo16 (Address, *(UINT16*)Value); break; case AccWidthUint32: WriteIo32 (Address, *(UINT32*)Value); break; default: break; } } VOID RWIO ( IN UINT16 Address, IN UINT8 OpFlag, IN UINT32 Mask, IN UINT32 Data ) { UINT32 Result; ReadIO (Address, OpFlag, &Result); Result = (Result & Mask) | Data; WriteIO (Address, OpFlag, &Result); } VOID ReadPCI ( IN UINT32 Address, IN UINT8 OpFlag, IN VOID* Value ) { OpFlag = OpFlag & 0x7f; if ( (UINT16)Address < 0xff ) { //Normal Config Access UINT32 AddrCf8; AddrCf8 = (1 << 31) + ((Address >> 8) & 0x0FFFF00) + (Address & 0xFC); WriteIO (0xCf8, AccWidthUint32, &AddrCf8); ReadIO ((UINT16) (0xCfC + (Address & 0x3)), OpFlag, Value); } } VOID WritePCI ( IN UINT32 Address, IN UINT8 OpFlag, IN VOID* Value ) { OpFlag = OpFlag & 0x7f; if ( (UINT16)Address < 0xff ) { //Normal Config Access UINT32 AddrCf8; AddrCf8 = (1 << 31) + ((Address >> 8)&0x0FFFF00) + (Address & 0xFC); WriteIO (0xCf8, AccWidthUint32, &AddrCf8); WriteIO ((UINT16) (0xCfC + (Address & 0x3)), OpFlag, Value); } } VOID RWPCI ( IN UINT32 Address, IN UINT8 OpFlag, IN UINT32 Mask, IN UINT32 Data ) { UINT32 Result; Result = 0; OpFlag = OpFlag & 0x7f; ReadPCI (Address, OpFlag, &Result); Result = (Result & Mask) | Data; WritePCI (Address, OpFlag, &Result); } void ReadIndexPCI32 ( UINT32 PciAddress, UINT32 IndexAddress, void* Value ) { WritePCI(PciAddress,AccWidthUint32,&IndexAddress); ReadPCI(PciAddress+4,AccWidthUint32,Value); } void WriteIndexPCI32 ( UINT32 PciAddress, UINT32 IndexAddress, UINT8 OpFlag, void* Value ) { WritePCI(PciAddress,AccWidthUint32 | (OpFlag & 0x80),&IndexAddress); WritePCI(PciAddress+4,AccWidthUint32 | (OpFlag & 0x80) ,Value); } void RWIndexPCI32 ( UINT32 PciAddress, UINT32 IndexAddress, UINT8 OpFlag, UINT32 Mask, UINT32 Data ) { UINT32 Result; ReadIndexPCI32(PciAddress,IndexAddress,&Result); Result = (Result & Mask)| Data; WriteIndexPCI32(PciAddress,IndexAddress,(OpFlag & 0x80),&Result); } void ReadMEM ( UINTN Address, UINT8 OpFlag, void* Value ) { OpFlag = OpFlag & 0x7f; switch (OpFlag){ case AccWidthUint8 : *((UINT8*)Value)=*((UINT8*)Address);break; case AccWidthUint16: *((UINT16*)Value)=*((UINT16*)Address);break; case AccWidthUint32: *((UINT32*)Value)=*((UINT32*)Address);break; } } void WriteMEM ( UINTN Address, UINT8 OpFlag, void* Value ) { OpFlag = OpFlag & 0x7f; switch (OpFlag){ case AccWidthUint8 : *((UINT8*)Address)=*((UINT8*)Value);break; case AccWidthUint16: *((UINT16*)Address)=*((UINT16*)Value);break; case AccWidthUint32: *((UINT32*)Address)=*((UINT32*)Value);break; } } void RWMEM ( UINTN Address, UINT8 OpFlag, UINT32 Mask, UINT32 Data ) { UINT32 Result; ReadMEM(Address,OpFlag,&Result); Result = (Result & Mask)| Data; WriteMEM(Address,OpFlag,&Result); } void RWMSR( UINT32 Address, UINT64 Mask, UINT64 Value ) { MsrWrite(Address,(MsrRead(Address)& Mask)|Value); } UINT32 IsFamily10() { CPUID_DATA Cpuid; CpuidRead(0x1,(CPUID_DATA *)&Cpuid); return Cpuid.REG_EAX & 0xff00000; } UINT8 GetNumberOfCpuCores(void) { UINT8 Result=1; Result=ReadNumberOfCpuCores(); return Result; } void Stall( UINT32 uSec ) { UINT16 timerAddr; UINT32 startTime, elapsedTime; ReadPMIO(SB_PMIO_REG24, AccWidthUint16, &timerAddr); if (timerAddr ==0){ uSec = uSec/2; while (uSec!=0){ ReadIO(0x80,AccWidthUint8,(UINT8 *)(&startTime)); uSec--; } } else{ ReadIO(timerAddr, AccWidthUint32,&startTime); while (1){ ReadIO(timerAddr, AccWidthUint32,&elapsedTime); if (elapsedTime < startTime) elapsedTime = elapsedTime+0xFFFFFFFF-startTime; else elapsedTime = elapsedTime-startTime; if ((elapsedTime*28/100)>uSec) break; } } } void Reset( ) { RWIO(0xcf9,AccWidthUint8,0x0,0x06); } CIM_STATUS RWSMBUSBlock( UINT8 Controller, UINT8 Address, UINT8 Offset, UINT8 BufferSize, UINT8* BufferPrt ) { UINT16 SmbusPort; UINT8 i; UINT8 Status; ReadPCI(PCI_ADDRESS(0,0x14,0,Controller?0x58:0x10),AccWidthUint16,&SmbusPort); SmbusPort &= 0xfffe; RWIO(SmbusPort + 0,AccWidthUint8,0x0,0xff); RWIO(SmbusPort + 4,AccWidthUint8,0x0,Address); RWIO(SmbusPort + 3,AccWidthUint8,0x0,Offset); RWIO(SmbusPort + 2,AccWidthUint8,0x0,0x14); RWIO(SmbusPort + 5,AccWidthUint8,0x0,BufferSize); if(!(Address & 0x1)){ for (i = 0 ;i < BufferSize;i++){ WriteIO(SmbusPort + 7,AccWidthUint8,&BufferPrt[i]); } } RWIO(SmbusPort + 2,AccWidthUint8,0x0,0x54); do{ ReadIO(SmbusPort + 0,AccWidthUint8,&Status); if (Status & 0x1C) return CIM_ERROR; if (Status & 0x02) break; }while(!(Status & 0x1)); do{ ReadIO(SmbusPort + 0,AccWidthUint8,&Status); }while(Status & 0x1); if(Address & 0x1){ for (i = 0 ;i < BufferSize;i++){ ReadIO(SmbusPort + 7,AccWidthUint8,&BufferPrt[i]); } } return CIM_SUCCESS; } void outPort80(UINT32 pcode) { WriteIO(0x80, AccWidthUint8, &pcode); return; } UINT8 GetByteSum( void* pData, UINT32 Length ) { UINT32 i; UINT8 Checksum = 0; for (i = 0;i < Length;i++){ Checksum += *((UINT8*)pData+i); } return Checksum; } UINT32 readAlink( UINT32 Index ){ UINT32 Data; WriteIO(ALINK_ACCESS_INDEX, AccWidthUint32, &Index); ReadIO(ALINK_ACCESS_DATA, AccWidthUint32, &Data); //Clear Index Index=0; WriteIO(ALINK_ACCESS_INDEX, AccWidthUint32, &Index); return Data; } void writeAlink( UINT32 Index, UINT32 Data ){ WriteIO(ALINK_ACCESS_INDEX, AccWidthUint32, &Index); WriteIO(ALINK_ACCESS_DATA, AccWidthUint32, &Data); //Clear Index Index=0; WriteIO(ALINK_ACCESS_INDEX, AccWidthUint32, &Index); } /** * * IsServer - Determine if southbridge type is SP5100 (server) or SB7x0 (non-server) * * A SP5100 is determined when both following two items are true: * 1) Revision >= A14; * 2) A server north bridge chipset is detected; * * A list of server north bridge chipset: * * Family DeviceID * ---------------------- * SR5690 0x5A10 * SR5670 0x5A12 * SR5650 0x5A13 * */ UINT8 IsServer (void){ UINT16 DevID; if (getRevisionID () < SB700_A14) { return 0; } ReadPCI ((NB_BDF << 16) + 2, AccWidthUint16, &DevID); return ((DevID == 0x5a10) || (DevID == 0x5a12) || (DevID == 0x5a13))? 1: 0; } /** * * IsLS2Mode - Determine if LS2 mode is enabled or not in northbridge. * */ UINT8 IsLs2Mode (void) { UINT32 HT3LinkTraining0; ReadPCI ((NB_BDF << 16) + 0xAC, AccWidthUint32, &HT3LinkTraining0); return ( HT3LinkTraining0 & 0x100 )? 1: 0; }