From eb75f652d392d2f4f257194e112f3f0db7479145 Mon Sep 17 00:00:00 2001 From: Zheng Bao Date: Fri, 23 Apr 2010 17:32:48 +0000 Subject: DDR3 support for AMD Fam10. Signed-off-by: Zheng Bao Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5481 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c | 252 +++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c') diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c new file mode 100644 index 0000000000..947da43ef2 --- /dev/null +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c @@ -0,0 +1,252 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 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 + */ + +#include "mct_d.h" + +static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr); +static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType); + +void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, + struct DCTStatStruc *pDCTstatA) +{ + /* BSP only. Set the fixed MTRRs for common legacy ranges. + * Set TOP_MEM and TOM2. + * Set some variable MTRRs with WB Uncacheable type. + */ + + u32 Bottom32bIO, Bottom40bIO, Cache32bTOP; + u32 val; + u32 addr; + u32 lo, hi; + + /* Set temporary top of memory from Node structure data. + * Adjust temp top of memory down to accomodate 32-bit IO space. + * Bottom40bIO=top of memory, right justified 8 bits + * (defines dram versus IO space type) + * Bottom32bIO=sub 4GB top of memory, right justified 8 bits + * (defines dram versus IO space type) + * Cache32bTOP=sub 4GB top of WB cacheable memory, + * right justified 8 bits + */ + + val = mctGet_NVbits(NV_BottomIO); + if(val == 0) + val++; + + Bottom32bIO = val << (24-8); + + val = pMCTstat->SysLimit + 1; + if(val <= _4GB_RJ8) { + Bottom40bIO = 0; + if(Bottom32bIO >= val) + Bottom32bIO = val; + } else { + Bottom40bIO = val; + } + + Cache32bTOP = Bottom32bIO; + + /*====================================================================== + Set default values for CPU registers + ======================================================================*/ + + /* NOTE : For coreboot, we don't need to set mtrr enables here because + they are still enable from cache_as_ram.inc */ + + addr = 0x250; + lo = 0x1E1E1E1E; + hi = lo; + _WRMSR(addr, lo, hi); /* 0 - 512K = WB Mem */ + addr = 0x258; + _WRMSR(addr, lo, hi); /* 512K - 640K = WB Mem */ + + /*====================================================================== + Set variable MTRR values + ======================================================================*/ + /* NOTE: for coreboot change from 0x200 to 0x204: coreboot is using + 0x200, 0x201 for [1M, CONFIG_TOP_MEM) + 0x202, 0x203 for ROM Caching + */ + addr = 0x204; /* MTRR phys base 2*/ + /* use TOP_MEM as limit*/ + /* Limit=TOP_MEM|TOM2*/ + /* Base=0*/ + printk(BIOS_DEBUG, "\t CPUMemTyping: Cache32bTOP:%x\n", Cache32bTOP); + SetMTRRrangeWB_D(0, &Cache32bTOP, &addr); + /* Base */ + /* Limit */ + /* MtrrAddr */ + if(addr == -1) /* ran out of MTRRs?*/ + pMCTstat->GStatus |= 1<Sub4GCacheTop = Cache32bTOP<<8; + + /*====================================================================== + Set TOP_MEM and TOM2 CPU registers + ======================================================================*/ + addr = TOP_MEM; + lo = Bottom32bIO<<8; + hi = Bottom32bIO>>24; + _WRMSR(addr, lo, hi); + printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom32bIO:%x\n", Bottom32bIO); + printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom40bIO:%x\n", Bottom40bIO); + if(Bottom40bIO) { + hi = Bottom40bIO >> 24; + lo = Bottom40bIO << 8; + addr += 3; /* TOM2 */ + _WRMSR(addr, lo, hi); + } + addr = 0xC0010010; /* SYS_CFG */ + _RDMSR(addr, &lo, &hi); + if(Bottom40bIO) { + lo |= (1<<21); /* MtrrTom2En=1 */ + lo |= (1<<22); /* Tom2ForceMemTypeWB */ + } else { + lo &= ~(1<<21); /* MtrrTom2En=0 */ + lo &= ~(1<<22); /* Tom2ForceMemTypeWB */ + } + _WRMSR(addr, lo, hi); +} + +static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr) +{ + /*set WB type*/ + SetMTRRrange_D(Base, pLimit, pMtrrAddr, 6); +} + +static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType) +{ + /* Program MTRRs to describe given range as given cache type. + * Use MTRR pairs starting with the given MTRRphys Base address, + * and use as many as is required up to (excluding) MSR 020C, which + * is reserved for OS. + * + * "Limit" in the context of this procedure is not the numerically + * correct limit, but rather the Last address+1, for purposes of coding + * efficiency and readability. Size of a region is then Limit-Base. + * + * 1. Size of each range must be a power of two + * 2. Each range must be naturally aligned (Base is same as size) + * + * There are two code paths: the ascending path and descending path + * (analogous to bsf and bsr), where the next limit is a funtion of the + * next set bit in a forward or backward sequence of bits (as a function + * of the Limit). We start with the ascending path, to ensure that + * regions are naturally aligned, then we switch to the descending path + * to maximize MTRR usage efficiency. Base=0 is a special case where we + * start with the descending path. Correct Mask for region is + * 2comp(Size-1)-1, which is 2comp(Limit-Base-1)-1 + */ + + u32 curBase, curLimit, curSize; + u32 val, valx; + u32 addr; + + val = curBase = Base; + curLimit = *pLimit; + addr = *pMtrrAddr; + while((addr >= 0x200) && (addr < 0x20C) && (val < *pLimit)) { + /* start with "ascending" code path */ + /* alignment (largest block size)*/ + valx = 1 << bsf(curBase); + curSize = valx; + + /* largest legal limit, given current non-zero range Base*/ + valx += curBase; + if((curBase == 0) || (*pLimit < valx)) { + /* flop direction to "descending" code path*/ + valx = 1<>24; + val <<= 8; + + /* now program the MTRR */ + val |= MtrrType; /* set cache type (UC or WB)*/ + _WRMSR(addr, val, valx); /* prog. MTRR with current region Base*/ + val = ((~(curSize - 1))+1) - 1; /* Size-1*/ /*Mask=2comp(Size-1)-1*/ + valx = (val >> 24) | (0xff00); /* GH have 48 bits addr */ + val <<= 8; + val |= ( 1 << 11); /* set MTRR valid*/ + addr++; + _WRMSR(addr, val, valx); /* prog. MTRR with current region Mask*/ + val = curLimit; + curBase = val; /* next Base = current Limit (loop exit)*/ + addr++; /* next MTRR pair addr */ + } + if(val < *pLimit) { + *pLimit = val; + addr = -1; + } + *pMtrrAddr = addr; +} + +void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) +{ +/* UMA memory size may need splitting the MTRR configuration into two + Before training use NB_BottomIO or the physical memory size to set the MTRRs. + After training, add UMAMemTyping function to reconfigure the MTRRs based on + NV_BottomUMA (for UMA systems only). + This two-step process allows all memory to be cached for training +*/ + u32 Bottom32bIO, Cache32bTOP; + u32 val; + u32 addr; + u32 lo, hi; + + /*====================================================================== + * Adjust temp top of memory down to accomodate UMA memory start + *======================================================================*/ + /* Bottom32bIO=sub 4GB top of memory, right justified 8 bits + * (defines dram versus IO space type) + * Cache32bTOP=sub 4GB top of WB cacheable memory, right justified 8 bits */ + + Bottom32bIO = pMCTstat->Sub4GCacheTop >> 8; + + val = mctGet_NVbits(NV_BottomUMA); + if (val == 0) + val++; + + val <<= (24-8); + if (val < Bottom32bIO) { + Cache32bTOP = val; + pMCTstat->Sub4GCacheTop = val; + + /*====================================================================== + * Clear variable MTRR values + *======================================================================*/ + addr = 0x200; + lo = 0; + hi = lo; + while( addr < 0x20C) { + _WRMSR(addr, lo, hi); /* prog. MTRR with current region Mask */ + addr++; /* next MTRR pair addr */ + } + + /*====================================================================== + * Set variable MTRR values + *======================================================================*/ + printk(BIOS_DEBUG, "\t UMAMemTyping_D: Cache32bTOP:%x\n", Cache32bTOP); + SetMTRRrangeWB_D(0, &Cache32bTOP, &addr); + if(addr == -1) /* ran out of MTRRs?*/ + pMCTstat->GStatus |= 1<