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