2 * This file is part of the coreboot project.
4 * Copyright (C) 2005-2007 Advanced Micro Devices, Inc.
5 * Copyright (C) 2008 Carl-Daniel Hailfinger
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #define CacheSize DCACHE_RAM_SIZE
22 #define CacheBase (0xd0000 - CacheSize)
24 /* leave some space for global variable to pass to RAM stage */
25 #define GlobalVarSize DCACHE_RAM_GLOBAL_VAR_SIZE
28 #define CacheSizeAPStack 0x400 /* 1K */
30 #define jmp_if_k8(x) comisd %xmm2, %xmm1; jb x
32 #define CPUID_MASK 0x0ff00f00
33 #define CPUID_VAL_FAM10_ROTATED 0x0f000010
35 #include <cpu/x86/mtrr.h>
36 #include <cpu/amd/mtrr.h>
40 xmm2: fam10 comparison value
44 /* Save the BIST result */
47 /*for normal part %ebx already contain cpu_init_detected from fallback call */
59 /* figure out cpu family */
63 /* base family is bits 8..11, extended family is bits 20..27 */
64 andl $CPUID_MASK, %eax
65 /* reorder bits for easier comparison by value */
68 movl $CPUID_VAL_FAM10_ROTATED, %eax
72 /* hope we can skip the double set for normal part */
73 #if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 1))
75 /* check if cpu_init_detected */
76 movl $MTRRdefType_MSR, %ecx
79 movl %eax, %ebx /* We store the status */
81 jmp_if_k8(CAR_FAM10_out_post_errata)
83 /* for GH, CAR need to set DRAM Base/Limit Registers to direct that to node0 */
85 /* Only BSP needed, for other nodes set during HT/memory init. */
86 /* So we need to check if it is BSP */
92 /* Enable RT tables on BSP */
93 movl $0x8000c06c, %eax
101 /* Setup temporary DRAM map: [0,16M) bit 0-23 */
102 movl $0x8000c144, %eax
109 movl $0x8000c140, %eax
118 /* Errata 193: Disable clean copybacks to L3 cache to allow cached ROM.
119 Re-enable it in after RAM is initialized and before CAR is disabled */
120 movl $0xc001102a, %ecx
125 CAR_FAM10_out_post_errata:
127 /* Set MtrrFixDramModEn for clear fixed mtrr */
128 enable_fixed_mtrr_dram_modify:
129 movl $SYSCFG_MSR, %ecx
131 andl $(~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrVarDramEn)), %eax
132 orl $SYSCFG_MSR_MtrrFixDramModEn, %eax
135 /* Clear all MTRRs */
137 movl $fixed_mtrr_msr, %esi
139 clear_fixed_var_mtrr:
142 jz clear_fixed_var_mtrr_out
148 jmp clear_fixed_var_mtrr
149 clear_fixed_var_mtrr_out:
151 /* 0x06 is the WB IO type for a given 4k segment.
152 * 0x1e is the MEM IO type for a given 4k segment (K10 and above).
153 * segs is the number of 4k segments in the area of the particular
154 * register we want to use for CAR.
155 * reg is the register where the IO type should be stored.
157 .macro extractmask segs, reg
159 /* The xorl here is superfluous because at the point of first execution
160 * of this macro, %eax and %edx are cleared. Later invocations of this
161 * macro will have a monotonically increasing segs parameter.
168 movl $0x1e000000, \reg /* WB MEM type */
170 movl $0x1e1e0000, \reg /* WB MEM type */
172 movl $0x1e1e1e00, \reg /* WB MEM type */
174 movl $0x1e1e1e1e, \reg /* WB MEM type */
179 movl $0x06000000, \reg /* WB IO type */
181 movl $0x06060000, \reg /* WB IO type */
183 movl $0x06060600, \reg /* WB IO type */
185 movl $0x06060606, \reg /* WB IO type */
188 .endif /* if \segs <= 0 */
191 /* size is the cache size in bytes we want to use for CAR.
192 * windowoffset is the 32k-aligned window into CAR size
194 .macro simplemask carsize, windowoffset
195 .set gas_bug_workaround,(((\carsize - \windowoffset) / 0x1000) - 4)
196 extractmask gas_bug_workaround, %eax
197 .set gas_bug_workaround,(((\carsize - \windowoffset) / 0x1000))
198 extractmask gas_bug_workaround, %edx
199 /* Without the gas bug workaround, the entire macro would consist only of the
201 extractmask (((\carsize - \windowoffset) / 0x1000) - 4), %eax
202 extractmask (((\carsize - \windowoffset) / 0x1000)), %edx
206 #if CacheSize > 0x10000
207 #error Invalid CAR size, must be at most 64k.
209 #if CacheSize < 0x1000
210 #error Invalid CAR size, must be at least 4k. This is a processor limitation.
212 #if (CacheSize & (0x1000 - 1))
213 #error Invalid CAR size, is not a multiple of 4k. This is a processor limitation.
216 #if CacheSize > 0x8000
217 /* enable caching for 32K-64K using fixed mtrr */
218 movl $0x268, %ecx /* fix4k_c0000*/
219 simplemask CacheSize, 0x8000
223 /* enable caching for 0-32K using fixed mtrr */
224 movl $0x269, %ecx /* fix4k_c8000*/
225 simplemask CacheSize, 0
228 /* enable memory access for first MBs using top_mem */
231 movl $(((CONFIG_LB_MEM_TOPK << 10) + TOP_MEM_MASK) & ~TOP_MEM_MASK) , %eax
233 #endif /* USE_FAILOVER_IMAGE == 1*/
236 #if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 0)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 0))
244 #if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
245 /* enable write base caching so we can do execute in place
250 movl $(XIP_ROM_BASE | MTRR_TYPE_WRBACK), %eax
254 movl $0xff, %edx /* (1 << (CPU_ADDR_BITS - 32)) - 1 for K8 (CPU_ADDR_BITS = 40) */
255 jmp_if_k8(wbcache_post_fam10_setup)
256 movl $0xffff, %edx /* (1 << (CPU_ADDR_BITS - 32)) - 1 for FAM10 (CPU_ADDR_BITS = 48) */
257 wbcache_post_fam10_setup:
258 movl $(~(XIP_ROM_SIZE - 1) | 0x800), %eax
260 #endif /* XIP_ROM_SIZE && XIP_ROM_BASE */
262 #if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 1))
263 /* Set the default memory type and enable fixed and variable MTRRs */
264 movl $MTRRdefType_MSR, %ecx
266 /* Enable Variable and Fixed MTRRs */
267 movl $0x00000c00, %eax
270 /* Enable the MTRRs and IORRs in SYSCFG */
271 movl $SYSCFG_MSR, %ecx
273 orl $(SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn), %eax
282 andl $0x9fffffff, %eax
286 jmp_if_k8(fam10_end_part1)
288 /* So we need to check if it is BSP */
298 #if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 1))
299 /* Read the range with lodsl*/
301 movl $CacheBase, %esi
302 movl $(CacheSize >> 2), %ecx
304 /* Clear the range */
305 movl $CacheBase, %edi
306 movl $(CacheSize >> 2), %ecx
310 #endif /*USE_FAILOVER_IMAGE == 1*/
312 /* set up the stack pointer */
313 movl $(CacheBase + CacheSize - GlobalVarSize), %eax
321 /* need to set stack pointer for AP */
322 /* it will be from CacheBase + (CacheSize - GlobalVarSize)/2 - (NodeID<<CoreIDbits + CoreID) * CacheSizeAPStack*/
323 /* So need to get the NodeID and CoreID at first */
324 /* If NB_CFG bit 54 is set just use initial apicid, otherwise need to reverse it */
326 /* store our init detected */
329 /* get the coreid bits at first */
330 movl $0x80000008, %eax
336 /* get the initial apic id */
341 /* get the nb cfg bit 54 */
342 movl $0xc001001f, %ecx /* NB_CFG_MSR */
344 movl %edi, %ecx /* CoreID bits */
350 /* calculate stack pointer */
351 movl $CacheSizeAPStack, %eax
353 movl $(CacheBase + (CacheSize - GlobalVarSize)/2), %esp
356 /* retrive init detected */
372 /* Restore the BIST result */
375 /* We need to set ebp ? No need */
377 pushl %ebx /* init detected */
378 pushl %eax /* bist */
379 call cache_as_ram_main
380 /* We will not go back */
382 movb $0xAF, %al /* Should never see this postcode */
386 .long 0x250, 0x258, 0x259
387 .long 0x268, 0x269, 0x26A
388 .long 0x26B, 0x26C, 0x26D
391 .long 0x200, 0x201, 0x202, 0x203
392 .long 0x204, 0x205, 0x206, 0x207
393 .long 0x208, 0x209, 0x20A, 0x20B
394 .long 0x20C, 0x20D, 0x20E, 0x20F
396 .long 0xC0010016, 0xC0010017, 0xC0010018, 0xC0010019
398 .long 0xC001001A, 0xC001001D
399 .long 0x000 /* NULL, end of table */
401 cache_as_ram_setup_out: