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