diff options
author | Marc Jones <marc.jones@amd.com> | 2007-12-19 01:32:08 +0000 |
---|---|---|
committer | Marc Jones <marc.jones@amd.com> | 2007-12-19 01:32:08 +0000 |
commit | 8ae8c8822068ef1722c08073ffa4ecc25633cbee (patch) | |
tree | 8c7bbf2f7b791081e486439a9b7ffb2fd6e649ac /src/northbridge/amd/amdht/comlib.c | |
parent | 2006b38fed2f5f3680de1736f7fc878823f2f93b (diff) | |
download | coreboot-8ae8c8822068ef1722c08073ffa4ecc25633cbee.tar.xz |
Initial AMD Barcelona support for rev Bx.
These are the core files for HyperTransport, DDR2 Memory, and multi-core initialization.
Signed-off-by: Marc Jones <marc.jones@amd.com>
Reviewed-by: Jordan Crouse <jordan.crouse@amd.com>
Acked-by: Myles Watson <myles@pel.cs.byu.edu>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3014 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/amd/amdht/comlib.c')
-rw-r--r-- | src/northbridge/amd/amdht/comlib.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/src/northbridge/amd/amdht/comlib.c b/src/northbridge/amd/amdht/comlib.c new file mode 100644 index 0000000000..47c538b19e --- /dev/null +++ b/src/northbridge/amd/amdht/comlib.c @@ -0,0 +1,290 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#undef FILECODE +#define FILECODE 0xCCCC +#include "comlib.h" + +/* + *--------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *--------------------------------------------------------------------------- + */ + +void CALLCONV AmdPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue) +{ + ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); + + AmdPCIRead(loc, pValue); + *pValue = *pValue >> lowbit; /* Shift */ + + /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */ + if ((highbit-lowbit) != 31) + *pValue &= (((u32)1 << (highbit-lowbit+1))-1); +} + + +void CALLCONV AmdPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue) +{ + u32 temp, mask; + + ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); + + /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */ + if ((highbit-lowbit) != 31) + mask = (((u32)1 << (highbit-lowbit+1))-1); + else + mask = (u32)0xFFFFFFFF; + + AmdPCIRead(loc, &temp); + temp &= ~(mask << lowbit); + temp |= (*pValue & mask) << lowbit; + AmdPCIWrite(loc, &temp); +} + + +/* + * Given a SBDFO this routine will find the next PCI capabilities list entry. + * If the end of the list of reached, or if a problem is detected, then + * ILLEGAL_SBDFO is returned. + * + * To start a new search from the beginning of head of the list, specify a + * SBDFO with a offset of zero. + */ +void CALLCONV AmdPCIFindNextCap(SBDFO *pCurrent) +{ + SBDFO base; + u32 offset; + u32 temp; + + if (*pCurrent == ILLEGAL_SBDFO) + return; + + offset = SBDFO_OFF(*pCurrent); + base = *pCurrent - offset; + *pCurrent = ILLEGAL_SBDFO; + + /* Verify that the SBDFO points to a valid PCI device SANITY CHECK */ + AmdPCIRead(base, &temp); + if (temp == 0xFFFFFFFF) + return; /* There is no device at this address */ + + /* Verify that the device supports a capability list */ + AmdPCIReadBits(base + 0x04, 20, 20, &temp); + if (temp == 0) + return; /* This PCI device does not support capability lists */ + + if (offset != 0) + { + /* If we are continuing on an existing list */ + AmdPCIReadBits(base + offset, 15, 8, &temp); + } + else + { + /* We are starting on a new list */ + AmdPCIReadBits(base + 0x34, 7, 0, &temp); + } + + if (temp == 0) + return; /* We have reached the end of the capabilties list */ + + /* Error detection and recovery- The statement below protects against + PCI devices with broken PCI capabilities lists. Detect a pointer + that is not u32 aligned, points into the first 64 reserved DWORDs + or points back to itself. + */ + if (((temp & 3) != 0) || (temp == offset) || (temp < 0x40)) + return; + + *pCurrent = base + temp; + return; +} + + +void CALLCONV Amdmemcpy(void *pDst, const void *pSrc, u32 length) +{ + ASSERT(length <= 32768); + ASSERT(pDst != NULL); + ASSERT(pSrc != NULL); + + while (length--){ + // *(((u8*)pDst)++) = *(((u8*)pSrc)++); + *((u8*)pDst) = *((u8*)pSrc); + pDst++; + pSrc++; + } +} + + +void CALLCONV Amdmemset(void *pBuf, u8 val, u32 length) +{ + ASSERT(length <= 32768); + ASSERT(pBuf != NULL); + + while (length--){ + //*(((u8*)pBuf)++) = val; + *(((u8*)pBuf)) = val; + pBuf++; + } +} + + +u8 CALLCONV AmdBitScanReverse(u32 value) +{ + u8 i; + + for (i = 31; i != 0xFF; i--) + { + if (value & ((u32)1 << i)) + break; + } + + return i; +} + + +u32 CALLCONV AmdRotateRight(u32 value, u8 size, u32 count) +{ + u32 msb, mask; + ASSERT(size > 0 && size <= 32); + + msb = (u32)1 << (size-1); + mask = ((msb-1) << 1) + 1; + + value = value & mask; + + while (count--) + { + if (value & 1) + value = (value >> 1) | msb; + else + value = value >> 1; + } + + return value; +} + + +u32 CALLCONV AmdRotateLeft(u32 value, u8 size, u32 count) +{ + u32 msb, mask; + ASSERT(size > 0 && size <= 32); + + msb = (u32)1 << (size-1); + mask = ((msb-1) << 1) + 1; + + value = value & mask; + + while (count--) + { + if (value & msb) + value = ((value << 1) & mask) | (u32)1; + else + value = ((value << 1) & mask); + } + + return value; +} + + +void CALLCONV AmdPCIRead(SBDFO loc, u32 *Value) +{ + /* Use LinuxBIOS PCI functions */ + *Value = pci_read_config32((loc & 0xFFFFF000), SBDFO_OFF(loc)); +} + + +void CALLCONV AmdPCIWrite(SBDFO loc, u32 *Value) +{ + /* Use LinuxBIOS PCI functions */ + pci_write_config32((loc & 0xFFFFF000), SBDFO_OFF(loc), *Value); +} + + +void CALLCONV AmdMSRRead(uint32 Address, uint64 *Value) +{ + msr_t msr; + + msr = rdmsr(Address); + Value->lo = msr.lo; + Value->hi = msr.hi; +} + + +void CALLCONV AmdMSRWrite(uint32 Address, uint64 *Value) +{ + msr_t msr; + + msr.lo = Value->lo; + msr.hi = Value->hi; + wrmsr(Address, msr); +} + + +void ErrorStop(u32 value) +{ + printk_debug("Error: %08x ", value); + +} + +/*;---------------------------------------------------------------------------- +; void __pascal ErrorStop(DWORD Value); +; +; This implementation provides a rotating display of the error code on the +; a port 80h POST display card. The rotation is used to make it easier to +; view the error on both a 16-bit as well as a 32-bit display card. +; +; For use with SimNow the unrotated error code is also written to port 84h +ErrorStop PROC FAR PASCAL PUBLIC Value:DWORD + pushad + mov eax, Value + mov bx, 0DEADh + out 84h, eax + +ErrorStopTop: + out 80h, eax + + mov cx, 4 ; Rotate the display by one nibble +@@: + bt bx, 15 + rcl eax, 1 + rcl bx, 1 + loop @B + + + push eax ; Delay a few hundred milliseconds + push ebx + mov ecx, 10h ; TSC + db 00Fh, 032h ; RDMSR + mov ebx, eax +@@: + db 00Fh, 032h ; RDMSR + sub eax, ebx + cmp eax, 500000000 + jb @B + pop ebx + pop eax + + jmp ErrorStopTop + + popad + ret +ErrorStop ENDP +*/ |