Zheng Bao | eb75f65 | 2010-04-23 17:32:48 +0000 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2010 Advanced Micro Devices, Inc. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | */ |
| 19 | |
| 20 | #include "mct_d.h" |
| 21 | |
| 22 | static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr); |
| 23 | static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType); |
| 24 | |
| 25 | void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, |
| 26 | struct DCTStatStruc *pDCTstatA) |
| 27 | { |
| 28 | /* BSP only. Set the fixed MTRRs for common legacy ranges. |
| 29 | * Set TOP_MEM and TOM2. |
| 30 | * Set some variable MTRRs with WB Uncacheable type. |
| 31 | */ |
| 32 | |
| 33 | u32 Bottom32bIO, Bottom40bIO, Cache32bTOP; |
| 34 | u32 val; |
| 35 | u32 addr; |
| 36 | u32 lo, hi; |
| 37 | |
| 38 | /* Set temporary top of memory from Node structure data. |
Zheng Bao | 53b52f3 | 2010-10-09 07:18:50 +0000 | [diff] [blame^] | 39 | * Adjust temp top of memory down to accommodate 32-bit IO space. |
Zheng Bao | eb75f65 | 2010-04-23 17:32:48 +0000 | [diff] [blame] | 40 | * Bottom40bIO=top of memory, right justified 8 bits |
| 41 | * (defines dram versus IO space type) |
| 42 | * Bottom32bIO=sub 4GB top of memory, right justified 8 bits |
| 43 | * (defines dram versus IO space type) |
| 44 | * Cache32bTOP=sub 4GB top of WB cacheable memory, |
| 45 | * right justified 8 bits |
| 46 | */ |
| 47 | |
| 48 | val = mctGet_NVbits(NV_BottomIO); |
| 49 | if(val == 0) |
| 50 | val++; |
| 51 | |
| 52 | Bottom32bIO = val << (24-8); |
| 53 | |
| 54 | val = pMCTstat->SysLimit + 1; |
| 55 | if(val <= _4GB_RJ8) { |
| 56 | Bottom40bIO = 0; |
| 57 | if(Bottom32bIO >= val) |
| 58 | Bottom32bIO = val; |
| 59 | } else { |
| 60 | Bottom40bIO = val; |
| 61 | } |
| 62 | |
| 63 | Cache32bTOP = Bottom32bIO; |
| 64 | |
| 65 | /*====================================================================== |
| 66 | Set default values for CPU registers |
| 67 | ======================================================================*/ |
| 68 | |
| 69 | /* NOTE : For coreboot, we don't need to set mtrr enables here because |
| 70 | they are still enable from cache_as_ram.inc */ |
| 71 | |
| 72 | addr = 0x250; |
| 73 | lo = 0x1E1E1E1E; |
| 74 | hi = lo; |
| 75 | _WRMSR(addr, lo, hi); /* 0 - 512K = WB Mem */ |
| 76 | addr = 0x258; |
| 77 | _WRMSR(addr, lo, hi); /* 512K - 640K = WB Mem */ |
| 78 | |
| 79 | /*====================================================================== |
| 80 | Set variable MTRR values |
| 81 | ======================================================================*/ |
| 82 | /* NOTE: for coreboot change from 0x200 to 0x204: coreboot is using |
| 83 | 0x200, 0x201 for [1M, CONFIG_TOP_MEM) |
| 84 | 0x202, 0x203 for ROM Caching |
| 85 | */ |
| 86 | addr = 0x204; /* MTRR phys base 2*/ |
| 87 | /* use TOP_MEM as limit*/ |
| 88 | /* Limit=TOP_MEM|TOM2*/ |
| 89 | /* Base=0*/ |
| 90 | printk(BIOS_DEBUG, "\t CPUMemTyping: Cache32bTOP:%x\n", Cache32bTOP); |
| 91 | SetMTRRrangeWB_D(0, &Cache32bTOP, &addr); |
| 92 | /* Base */ |
| 93 | /* Limit */ |
| 94 | /* MtrrAddr */ |
| 95 | if(addr == -1) /* ran out of MTRRs?*/ |
| 96 | pMCTstat->GStatus |= 1<<GSB_MTRRshort; |
| 97 | |
| 98 | pMCTstat->Sub4GCacheTop = Cache32bTOP<<8; |
| 99 | |
| 100 | /*====================================================================== |
| 101 | Set TOP_MEM and TOM2 CPU registers |
| 102 | ======================================================================*/ |
| 103 | addr = TOP_MEM; |
| 104 | lo = Bottom32bIO<<8; |
| 105 | hi = Bottom32bIO>>24; |
| 106 | _WRMSR(addr, lo, hi); |
| 107 | printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom32bIO:%x\n", Bottom32bIO); |
| 108 | printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom40bIO:%x\n", Bottom40bIO); |
| 109 | if(Bottom40bIO) { |
| 110 | hi = Bottom40bIO >> 24; |
| 111 | lo = Bottom40bIO << 8; |
| 112 | addr += 3; /* TOM2 */ |
| 113 | _WRMSR(addr, lo, hi); |
| 114 | } |
| 115 | addr = 0xC0010010; /* SYS_CFG */ |
| 116 | _RDMSR(addr, &lo, &hi); |
| 117 | if(Bottom40bIO) { |
| 118 | lo |= (1<<21); /* MtrrTom2En=1 */ |
| 119 | lo |= (1<<22); /* Tom2ForceMemTypeWB */ |
| 120 | } else { |
| 121 | lo &= ~(1<<21); /* MtrrTom2En=0 */ |
| 122 | lo &= ~(1<<22); /* Tom2ForceMemTypeWB */ |
| 123 | } |
| 124 | _WRMSR(addr, lo, hi); |
| 125 | } |
| 126 | |
| 127 | static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr) |
| 128 | { |
| 129 | /*set WB type*/ |
| 130 | SetMTRRrange_D(Base, pLimit, pMtrrAddr, 6); |
| 131 | } |
| 132 | |
| 133 | static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType) |
| 134 | { |
| 135 | /* Program MTRRs to describe given range as given cache type. |
| 136 | * Use MTRR pairs starting with the given MTRRphys Base address, |
| 137 | * and use as many as is required up to (excluding) MSR 020C, which |
| 138 | * is reserved for OS. |
| 139 | * |
| 140 | * "Limit" in the context of this procedure is not the numerically |
| 141 | * correct limit, but rather the Last address+1, for purposes of coding |
| 142 | * efficiency and readability. Size of a region is then Limit-Base. |
| 143 | * |
| 144 | * 1. Size of each range must be a power of two |
| 145 | * 2. Each range must be naturally aligned (Base is same as size) |
| 146 | * |
| 147 | * There are two code paths: the ascending path and descending path |
Zheng Bao | 53b52f3 | 2010-10-09 07:18:50 +0000 | [diff] [blame^] | 148 | * (analogous to bsf and bsr), where the next limit is a function of the |
Zheng Bao | eb75f65 | 2010-04-23 17:32:48 +0000 | [diff] [blame] | 149 | * next set bit in a forward or backward sequence of bits (as a function |
| 150 | * of the Limit). We start with the ascending path, to ensure that |
| 151 | * regions are naturally aligned, then we switch to the descending path |
| 152 | * to maximize MTRR usage efficiency. Base=0 is a special case where we |
| 153 | * start with the descending path. Correct Mask for region is |
| 154 | * 2comp(Size-1)-1, which is 2comp(Limit-Base-1)-1 |
| 155 | */ |
| 156 | |
| 157 | u32 curBase, curLimit, curSize; |
| 158 | u32 val, valx; |
| 159 | u32 addr; |
| 160 | |
| 161 | val = curBase = Base; |
| 162 | curLimit = *pLimit; |
| 163 | addr = *pMtrrAddr; |
| 164 | while((addr >= 0x200) && (addr < 0x20C) && (val < *pLimit)) { |
| 165 | /* start with "ascending" code path */ |
| 166 | /* alignment (largest block size)*/ |
| 167 | valx = 1 << bsf(curBase); |
| 168 | curSize = valx; |
| 169 | |
| 170 | /* largest legal limit, given current non-zero range Base*/ |
| 171 | valx += curBase; |
| 172 | if((curBase == 0) || (*pLimit < valx)) { |
| 173 | /* flop direction to "descending" code path*/ |
| 174 | valx = 1<<bsr(*pLimit - curBase); |
| 175 | curSize = valx; |
| 176 | valx += curBase; |
| 177 | } |
| 178 | curLimit = valx; /*eax=curBase, edx=curLimit*/ |
| 179 | valx = val>>24; |
| 180 | val <<= 8; |
| 181 | |
| 182 | /* now program the MTRR */ |
| 183 | val |= MtrrType; /* set cache type (UC or WB)*/ |
| 184 | _WRMSR(addr, val, valx); /* prog. MTRR with current region Base*/ |
| 185 | val = ((~(curSize - 1))+1) - 1; /* Size-1*/ /*Mask=2comp(Size-1)-1*/ |
| 186 | valx = (val >> 24) | (0xff00); /* GH have 48 bits addr */ |
| 187 | val <<= 8; |
| 188 | val |= ( 1 << 11); /* set MTRR valid*/ |
| 189 | addr++; |
| 190 | _WRMSR(addr, val, valx); /* prog. MTRR with current region Mask*/ |
| 191 | val = curLimit; |
| 192 | curBase = val; /* next Base = current Limit (loop exit)*/ |
| 193 | addr++; /* next MTRR pair addr */ |
| 194 | } |
| 195 | if(val < *pLimit) { |
| 196 | *pLimit = val; |
| 197 | addr = -1; |
| 198 | } |
| 199 | *pMtrrAddr = addr; |
| 200 | } |
| 201 | |
| 202 | void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) |
| 203 | { |
| 204 | /* UMA memory size may need splitting the MTRR configuration into two |
| 205 | Before training use NB_BottomIO or the physical memory size to set the MTRRs. |
| 206 | After training, add UMAMemTyping function to reconfigure the MTRRs based on |
| 207 | NV_BottomUMA (for UMA systems only). |
| 208 | This two-step process allows all memory to be cached for training |
| 209 | */ |
| 210 | u32 Bottom32bIO, Cache32bTOP; |
| 211 | u32 val; |
| 212 | u32 addr; |
| 213 | u32 lo, hi; |
| 214 | |
| 215 | /*====================================================================== |
Zheng Bao | 53b52f3 | 2010-10-09 07:18:50 +0000 | [diff] [blame^] | 216 | * Adjust temp top of memory down to accommodate UMA memory start |
Zheng Bao | eb75f65 | 2010-04-23 17:32:48 +0000 | [diff] [blame] | 217 | *======================================================================*/ |
| 218 | /* Bottom32bIO=sub 4GB top of memory, right justified 8 bits |
| 219 | * (defines dram versus IO space type) |
| 220 | * Cache32bTOP=sub 4GB top of WB cacheable memory, right justified 8 bits */ |
| 221 | |
| 222 | Bottom32bIO = pMCTstat->Sub4GCacheTop >> 8; |
| 223 | |
| 224 | val = mctGet_NVbits(NV_BottomUMA); |
| 225 | if (val == 0) |
| 226 | val++; |
| 227 | |
| 228 | val <<= (24-8); |
| 229 | if (val < Bottom32bIO) { |
| 230 | Cache32bTOP = val; |
| 231 | pMCTstat->Sub4GCacheTop = val; |
| 232 | |
| 233 | /*====================================================================== |
| 234 | * Clear variable MTRR values |
| 235 | *======================================================================*/ |
| 236 | addr = 0x200; |
| 237 | lo = 0; |
| 238 | hi = lo; |
| 239 | while( addr < 0x20C) { |
| 240 | _WRMSR(addr, lo, hi); /* prog. MTRR with current region Mask */ |
| 241 | addr++; /* next MTRR pair addr */ |
| 242 | } |
| 243 | |
| 244 | /*====================================================================== |
| 245 | * Set variable MTRR values |
| 246 | *======================================================================*/ |
| 247 | printk(BIOS_DEBUG, "\t UMAMemTyping_D: Cache32bTOP:%x\n", Cache32bTOP); |
| 248 | SetMTRRrangeWB_D(0, &Cache32bTOP, &addr); |
| 249 | if(addr == -1) /* ran out of MTRRs?*/ |
| 250 | pMCTstat->GStatus |= 1<<GSB_MTRRshort; |
| 251 | } |
| 252 | } |