2 * This file is part of the coreboot project.
4 * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
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.
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.
17 #include <cpu/amd/mtrr.h>
18 #include <cpu/x86/mtrr.h>
20 static void SetMTRRrangeWB_D(u32 Base
, u32
*pLimit
, u32
*pMtrrAddr
);
21 static void SetMTRRrange_D(u32 Base
, u32
*pLimit
, u32
*pMtrrAddr
, u16 MtrrType
);
23 void CPUMemTyping_D(struct MCTStatStruc
*pMCTstat
,
24 struct DCTStatStruc
*pDCTstatA
)
26 /* BSP only. Set the fixed MTRRs for common legacy ranges.
27 * Set TOP_MEM and TOM2.
28 * Set some variable MTRRs with WB Uncacheable type.
31 u32 Bottom32bIO
, Bottom40bIO
, Cache32bTOP
;
36 /* Set temporary top of memory from Node structure data.
37 * Adjust temp top of memory down to accommodate 32-bit IO space.
38 * Bottom40bIO = top of memory, right justified 8 bits
39 * (defines dram versus IO space type)
40 * Bottom32bIO = sub 4GB top of memory, right justified 8 bits
41 * (defines dram versus IO space type)
42 * Cache32bTOP = sub 4GB top of WB cacheable memory,
43 * right justified 8 bits
46 val
= mctGet_NVbits(NV_BottomIO
);
50 Bottom32bIO
= val
<< (24-8);
52 val
= pMCTstat
->SysLimit
+ 1;
53 if (val
<= _4GB_RJ8
) {
55 if (Bottom32bIO
>= val
)
61 Cache32bTOP
= Bottom32bIO
;
63 /*======================================================================
64 Set default values for CPU registers
65 ======================================================================*/
67 /* NOTE : For coreboot, we don't need to set mtrr enables here because
68 they are still enable from cache_as_ram.inc */
70 addr
= MTRR_FIX_64K_00000
;
73 _WRMSR(addr
, lo
, hi
); /* 0 - 512K = WB Mem */
74 addr
= MTRR_FIX_16K_80000
;
75 _WRMSR(addr
, lo
, hi
); /* 512K - 640K = WB Mem */
77 /*======================================================================
78 Set variable MTRR values
79 ======================================================================*/
80 /* NOTE: for coreboot change from 0x200 to 0x204: coreboot is using
81 0x200, 0x201 for [1M, CONFIG_TOP_MEM)
82 0x202, 0x203 for ROM Caching
84 addr
= MTRR_PHYS_BASE(2); /* MTRR phys base 2*/
85 /* use TOP_MEM as limit*/
86 /* Limit = TOP_MEM|TOM2*/
88 print_tx("\t CPUMemTyping: Cache32bTOP:", Cache32bTOP
);
89 SetMTRRrangeWB_D(0, &Cache32bTOP
, &addr
);
93 if (addr
== -1) /* ran out of MTRRs?*/
94 pMCTstat
->GStatus
|= 1<<GSB_MTRRshort
;
96 pMCTstat
->Sub4GCacheTop
= Cache32bTOP
<<8;
98 /*======================================================================
99 Set TOP_MEM and TOM2 CPU registers
100 ======================================================================*/
103 hi
= Bottom32bIO
>>24;
104 _WRMSR(addr
, lo
, hi
);
105 print_tx("\t CPUMemTyping: Bottom32bIO:", Bottom32bIO
);
106 print_tx("\t CPUMemTyping: Bottom40bIO:", Bottom40bIO
);
108 hi
= Bottom40bIO
>> 24;
109 lo
= Bottom40bIO
<< 8;
110 if (mctSetNodeBoundary_D())
112 addr
+= 3; /* TOM2 */
113 _WRMSR(addr
, lo
, hi
);
115 addr
= SYSCFG_MSR
; /* SYS_CFG */
116 _RDMSR(addr
, &lo
, &hi
);
118 lo
|= SYSCFG_MSR_TOM2En
; /* MtrrTom2En = 1 */
119 lo
|= SYSCFG_MSR_TOM2WB
; /* Tom2ForceMemTypeWB */
121 lo
&= ~SYSCFG_MSR_TOM2En
; /* MtrrTom2En = 0 */
122 lo
&= ~SYSCFG_MSR_TOM2WB
; /* Tom2ForceMemTypeWB */
124 _WRMSR(addr
, lo
, hi
);
128 static void SetMTRRrangeWB_D(u32 Base
, u32
*pLimit
, u32
*pMtrrAddr
)
131 SetMTRRrange_D(Base
, pLimit
, pMtrrAddr
, 6);
135 static void SetMTRRrange_D(u32 Base
, u32
*pLimit
, u32
*pMtrrAddr
, u16 MtrrType
)
137 /* Program MTRRs to describe given range as given cache type.
138 * Use MTRR pairs starting with the given MTRRphys Base address,
139 * and use as many as is required up to (excluding) MSR 020C, which
140 * is reserved for OS.
142 * "Limit" in the context of this procedure is not the numerically
143 * correct limit, but rather the Last address+1, for purposes of coding
144 * efficiency and readability. Size of a region is then Limit-Base.
146 * 1. Size of each range must be a power of two
147 * 2. Each range must be naturally aligned (Base is same as size)
149 * There are two code paths: the ascending path and descending path
150 * (analogous to bsf and bsr), where the next limit is a function of the
151 * next set bit in a forward or backward sequence of bits (as a function
152 * of the Limit). We start with the ascending path, to ensure that
153 * regions are naturally aligned, then we switch to the descending path
154 * to maximize MTRR usage efficiency. Base = 0 is a special case where we
155 * start with the descending path. Correct Mask for region is
156 * 2comp(Size-1)-1, which is 2comp(Limit-Base-1)-1
159 u32 curBase
, curLimit
, curSize
;
163 val
= curBase
= Base
;
166 while ((addr
>= 0x200) && (addr
< 0x20C) && (val
< *pLimit
)) {
167 /* start with "ascending" code path */
168 /* alignment (largest block size)*/
169 valx
= 1 << bsf(curBase
);
172 /* largest legal limit, given current non-zero range Base*/
174 if ((curBase
== 0) || (*pLimit
< valx
)) {
175 /* flop direction to "descending" code path*/
176 valx
= 1<<bsr(*pLimit
- curBase
);
180 curLimit
= valx
; /*eax = curBase, edx = curLimit*/
184 /* now program the MTRR */
185 val
|= MtrrType
; /* set cache type (UC or WB)*/
186 _WRMSR(addr
, val
, valx
); /* prog. MTRR with current region Base*/
187 val
= ((~(curSize
- 1))+1) - 1; /* Size-1*/ /*Mask = 2comp(Size-1)-1*/
188 valx
= (val
>> 24) | (0xff00); /* GH have 48 bits addr */
190 val
|= (1 << 11); /* set MTRR valid*/
192 _WRMSR(addr
, val
, valx
); /* prog. MTRR with current region Mask*/
194 curBase
= val
; /* next Base = current Limit (loop exit)*/
195 addr
++; /* next MTRR pair addr */
204 void UMAMemTyping_D(struct MCTStatStruc
*pMCTstat
, struct DCTStatStruc
*pDCTstatA
)
206 /* UMA memory size may need splitting the MTRR configuration into two
207 Before training use NB_BottomIO or the physical memory size to set the MTRRs.
208 After training, add UMAMemTyping function to reconfigure the MTRRs based on
209 NV_BottomUMA (for UMA systems only).
210 This two-step process allows all memory to be cached for training
212 u32 Bottom32bIO
, Cache32bTOP
;
217 /*======================================================================
218 * Adjust temp top of memory down to accommodate UMA memory start
219 *======================================================================*/
220 /* Bottom32bIO = sub 4GB top of memory, right justified 8 bits
221 * (defines dram versus IO space type)
222 * Cache32bTOP = sub 4GB top of WB cacheable memory, right justified 8 bits */
224 Bottom32bIO
= pMCTstat
->Sub4GCacheTop
>> 8;
226 val
= mctGet_NVbits(NV_BottomUMA
);
231 if (val
< Bottom32bIO
) {
233 pMCTstat
->Sub4GCacheTop
= val
;
235 /*======================================================================
236 * Clear variable MTRR values
237 *======================================================================*/
238 addr
= MTRR_PHYS_BASE(0);
241 while (addr
< MTRR_PHYS_BASE(6)) {
242 _WRMSR(addr
, lo
, hi
); /* prog. MTRR with current region Mask */
243 addr
++; /* next MTRR pair addr */
246 /*======================================================================
247 * Set variable MTRR values
248 *======================================================================*/
249 print_tx("\t UMAMemTyping_D: Cache32bTOP:", Cache32bTOP
);
250 SetMTRRrangeWB_D(0, &Cache32bTOP
, &addr
);
251 if (addr
== -1) /* ran out of MTRRs?*/
252 pMCTstat
->GStatus
|= 1<<GSB_MTRRshort
;