xref: /OK3568_Linux_fs/u-boot/arch/x86/cpu/intel_common/car.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/*
2*4882a593Smuzhiyun * Copyright (c) 2014 Google, Inc
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * From Coreboot file cpu/intel/model_206ax/cache_as_ram.inc
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
7*4882a593Smuzhiyun * Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan)
8*4882a593Smuzhiyun * Copyright (C) 2007-2008 coresystems GmbH
9*4882a593Smuzhiyun * Copyright (C) 2012 Kyösti Mälkki <kyosti.malkki@gmail.com>
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * SPDX-License-Identifier:	GPL-2.0
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun#include <common.h>
15*4882a593Smuzhiyun#include <asm/microcode.h>
16*4882a593Smuzhiyun#include <asm/msr-index.h>
17*4882a593Smuzhiyun#include <asm/mtrr.h>
18*4882a593Smuzhiyun#include <asm/post.h>
19*4882a593Smuzhiyun#include <asm/processor.h>
20*4882a593Smuzhiyun#include <asm/processor-flags.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
23*4882a593Smuzhiyun#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun#define CACHE_AS_RAM_SIZE	CONFIG_DCACHE_RAM_SIZE
26*4882a593Smuzhiyun#define CACHE_AS_RAM_BASE	CONFIG_DCACHE_RAM_BASE
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun/* Cache 4GB - MRC_SIZE_KB for MRC */
29*4882a593Smuzhiyun#define CACHE_MRC_BYTES	((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1)
30*4882a593Smuzhiyun#define CACHE_MRC_BASE		(0xFFFFFFFF - CACHE_MRC_BYTES)
31*4882a593Smuzhiyun#define CACHE_MRC_MASK		(~CACHE_MRC_BYTES)
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun#define CPU_PHYSMASK_HI	(1 << (CONFIG_CPU_ADDR_BITS - 32) - 1)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun#define NOEVICTMOD_MSR	0x2e0
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun	/*
38*4882a593Smuzhiyun	 * Note: ebp must not be touched in this code as it holds the BIST
39*4882a593Smuzhiyun	 * value (built-in self test). We preserve this value until it can
40*4882a593Smuzhiyun	 * be written to global_data when CAR is ready for use.
41*4882a593Smuzhiyun	 */
42*4882a593Smuzhiyun.globl car_init
43*4882a593Smuzhiyuncar_init:
44*4882a593Smuzhiyun	post_code(POST_CAR_START)
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun	/* Send INIT IPI to all excluding ourself */
47*4882a593Smuzhiyun	movl	$0x000C4500, %eax
48*4882a593Smuzhiyun	movl	$0xFEE00300, %esi
49*4882a593Smuzhiyun	movl	%eax, (%esi)
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun	/* TODO: Load microcode later - the 'no eviction' mode breaks this */
52*4882a593Smuzhiyun	movl	$MSR_IA32_UCODE_WRITE, %ecx
53*4882a593Smuzhiyun	xorl	%edx, %edx
54*4882a593Smuzhiyun	movl	$_dt_ucode_base_size, %eax
55*4882a593Smuzhiyun	movl	(%eax), %eax
56*4882a593Smuzhiyun	addl	$UCODE_HEADER_LEN, %eax
57*4882a593Smuzhiyun	wrmsr
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun	post_code(POST_CAR_SIPI)
60*4882a593Smuzhiyun	/* Zero out all fixed range and variable range MTRRs */
61*4882a593Smuzhiyun	movl	$mtrr_table, %esi
62*4882a593Smuzhiyun	movl	$((mtrr_table_end - mtrr_table) / 2), %edi
63*4882a593Smuzhiyun	xorl	%eax, %eax
64*4882a593Smuzhiyun	xorl	%edx, %edx
65*4882a593Smuzhiyunclear_mtrrs:
66*4882a593Smuzhiyun	movw	(%esi), %bx
67*4882a593Smuzhiyun	movzx	%bx, %ecx
68*4882a593Smuzhiyun	wrmsr
69*4882a593Smuzhiyun	add	$2, %esi
70*4882a593Smuzhiyun	dec	%edi
71*4882a593Smuzhiyun	jnz	clear_mtrrs
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun	post_code(POST_CAR_MTRR)
74*4882a593Smuzhiyun	/* Configure the default memory type to uncacheable */
75*4882a593Smuzhiyun	movl	$MTRR_DEF_TYPE_MSR, %ecx
76*4882a593Smuzhiyun	rdmsr
77*4882a593Smuzhiyun	andl	$(~0x00000cff), %eax
78*4882a593Smuzhiyun	wrmsr
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun	post_code(POST_CAR_UNCACHEABLE)
81*4882a593Smuzhiyun	/* Set Cache-as-RAM base address */
82*4882a593Smuzhiyun	movl	$(MTRR_PHYS_BASE_MSR(0)), %ecx
83*4882a593Smuzhiyun	movl	$(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
84*4882a593Smuzhiyun	xorl	%edx, %edx
85*4882a593Smuzhiyun	wrmsr
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun	post_code(POST_CAR_BASE_ADDRESS)
88*4882a593Smuzhiyun	/* Set Cache-as-RAM mask */
89*4882a593Smuzhiyun	movl	$(MTRR_PHYS_MASK_MSR(0)), %ecx
90*4882a593Smuzhiyun	movl	$(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
91*4882a593Smuzhiyun	movl	$CPU_PHYSMASK_HI, %edx
92*4882a593Smuzhiyun	wrmsr
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun	post_code(POST_CAR_MASK)
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun	/* Enable MTRR */
97*4882a593Smuzhiyun	movl	$MTRR_DEF_TYPE_MSR, %ecx
98*4882a593Smuzhiyun	rdmsr
99*4882a593Smuzhiyun	orl	$MTRR_DEF_TYPE_EN, %eax
100*4882a593Smuzhiyun	wrmsr
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun	/* Enable cache (CR0.CD = 0, CR0.NW = 0) */
103*4882a593Smuzhiyun        movl	%cr0, %eax
104*4882a593Smuzhiyun	andl	$(~(X86_CR0_CD | X86_CR0_NW)), %eax
105*4882a593Smuzhiyun	invd
106*4882a593Smuzhiyun	movl	%eax, %cr0
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun	/* enable the 'no eviction' mode */
109*4882a593Smuzhiyun	movl    $NOEVICTMOD_MSR, %ecx
110*4882a593Smuzhiyun	rdmsr
111*4882a593Smuzhiyun	orl     $1, %eax
112*4882a593Smuzhiyun	andl    $~2, %eax
113*4882a593Smuzhiyun	wrmsr
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun       /* Clear the cache memory region. This will also fill up the cache */
116*4882a593Smuzhiyun	movl	$CACHE_AS_RAM_BASE, %esi
117*4882a593Smuzhiyun	movl	%esi, %edi
118*4882a593Smuzhiyun	movl	$(CACHE_AS_RAM_SIZE / 4), %ecx
119*4882a593Smuzhiyun	xorl	%eax, %eax
120*4882a593Smuzhiyun	rep	stosl
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun	/* enable the 'no eviction run' state */
123*4882a593Smuzhiyun	movl    $NOEVICTMOD_MSR, %ecx
124*4882a593Smuzhiyun	rdmsr
125*4882a593Smuzhiyun	orl     $3, %eax
126*4882a593Smuzhiyun	wrmsr
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun	post_code(POST_CAR_FILL)
129*4882a593Smuzhiyun	/* Enable Cache-as-RAM mode by disabling cache */
130*4882a593Smuzhiyun	movl	%cr0, %eax
131*4882a593Smuzhiyun	orl	$X86_CR0_CD, %eax
132*4882a593Smuzhiyun	movl	%eax, %cr0
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun	/* Enable cache for our code in Flash because we do XIP here */
135*4882a593Smuzhiyun	movl	$MTRR_PHYS_BASE_MSR(1), %ecx
136*4882a593Smuzhiyun	xorl	%edx, %edx
137*4882a593Smuzhiyun	movl    $car_init_ret, %eax
138*4882a593Smuzhiyun	andl    $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax
139*4882a593Smuzhiyun	orl	$MTRR_TYPE_WRPROT, %eax
140*4882a593Smuzhiyun	wrmsr
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun	movl	$MTRR_PHYS_MASK_MSR(1), %ecx
143*4882a593Smuzhiyun	movl	$CPU_PHYSMASK_HI, %edx
144*4882a593Smuzhiyun	movl	$(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
145*4882a593Smuzhiyun	wrmsr
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun	post_code(POST_CAR_ROM_CACHE)
148*4882a593Smuzhiyun#ifdef CONFIG_CACHE_MRC_BIN
149*4882a593Smuzhiyun	/* Enable caching for ram init code to run faster */
150*4882a593Smuzhiyun	movl	$MTRR_PHYS_BASE_MSR(2), %ecx
151*4882a593Smuzhiyun	movl	$(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
152*4882a593Smuzhiyun	xorl	%edx, %edx
153*4882a593Smuzhiyun	wrmsr
154*4882a593Smuzhiyun	movl	$MTRR_PHYS_MASK_MSR(2), %ecx
155*4882a593Smuzhiyun	movl	$(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax
156*4882a593Smuzhiyun	movl	$CPU_PHYSMASK_HI, %edx
157*4882a593Smuzhiyun	wrmsr
158*4882a593Smuzhiyun#endif
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun	post_code(POST_CAR_MRC_CACHE)
161*4882a593Smuzhiyun	/* Enable cache */
162*4882a593Smuzhiyun	movl	%cr0, %eax
163*4882a593Smuzhiyun	andl	$(~(X86_CR0_CD | X86_CR0_NW)), %eax
164*4882a593Smuzhiyun	movl	%eax, %cr0
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun	post_code(POST_CAR_CPU_CACHE)
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun	/* All CPUs need to be in Wait for SIPI state */
169*4882a593Smuzhiyunwait_for_sipi:
170*4882a593Smuzhiyun	movl	(%esi), %eax
171*4882a593Smuzhiyun	bt	$12, %eax
172*4882a593Smuzhiyun	jc	wait_for_sipi
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun	/* return */
175*4882a593Smuzhiyun	jmp	car_init_ret
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun.globl car_uninit
178*4882a593Smuzhiyuncar_uninit:
179*4882a593Smuzhiyun	/* Disable cache */
180*4882a593Smuzhiyun	movl	%cr0, %eax
181*4882a593Smuzhiyun	orl	$X86_CR0_CD, %eax
182*4882a593Smuzhiyun	movl	%eax, %cr0
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun	/* Disable MTRRs */
185*4882a593Smuzhiyun	movl	$MTRR_DEF_TYPE_MSR, %ecx
186*4882a593Smuzhiyun	rdmsr
187*4882a593Smuzhiyun	andl	$(~MTRR_DEF_TYPE_EN), %eax
188*4882a593Smuzhiyun	wrmsr
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun	/* Disable the no-eviction run state */
191*4882a593Smuzhiyun	movl    $NOEVICTMOD_MSR, %ecx
192*4882a593Smuzhiyun	rdmsr
193*4882a593Smuzhiyun	andl    $~2, %eax
194*4882a593Smuzhiyun	wrmsr
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun	invd
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun	/* Disable the no-eviction mode */
199*4882a593Smuzhiyun	rdmsr
200*4882a593Smuzhiyun	andl    $~1, %eax
201*4882a593Smuzhiyun	wrmsr
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun#ifdef CONFIG_CACHE_MRC_BIN
204*4882a593Smuzhiyun	/* Clear the MTRR that was used to cache MRC */
205*4882a593Smuzhiyun	xorl	%eax, %eax
206*4882a593Smuzhiyun	xorl	%edx, %edx
207*4882a593Smuzhiyun	movl	$MTRR_PHYS_BASE_MSR(2), %ecx
208*4882a593Smuzhiyun	wrmsr
209*4882a593Smuzhiyun	movl	$MTRR_PHYS_MASK_MSR(2), %ecx
210*4882a593Smuzhiyun	wrmsr
211*4882a593Smuzhiyun#endif
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun	/* Enable MTRRs */
214*4882a593Smuzhiyun	movl	$MTRR_DEF_TYPE_MSR, %ecx
215*4882a593Smuzhiyun	rdmsr
216*4882a593Smuzhiyun	orl	$MTRR_DEF_TYPE_EN, %eax
217*4882a593Smuzhiyun	wrmsr
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun	invd
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun	ret
222*4882a593Smuzhiyun
223*4882a593Smuzhiyunmtrr_table:
224*4882a593Smuzhiyun	/* Fixed MTRRs */
225*4882a593Smuzhiyun	.word 0x250, 0x258, 0x259
226*4882a593Smuzhiyun	.word 0x268, 0x269, 0x26A
227*4882a593Smuzhiyun	.word 0x26B, 0x26C, 0x26D
228*4882a593Smuzhiyun	.word 0x26E, 0x26F
229*4882a593Smuzhiyun	/* Variable MTRRs */
230*4882a593Smuzhiyun	.word 0x200, 0x201, 0x202, 0x203
231*4882a593Smuzhiyun	.word 0x204, 0x205, 0x206, 0x207
232*4882a593Smuzhiyun	.word 0x208, 0x209, 0x20A, 0x20B
233*4882a593Smuzhiyun	.word 0x20C, 0x20D, 0x20E, 0x20F
234*4882a593Smuzhiyun	.word 0x210, 0x211, 0x212, 0x213
235*4882a593Smuzhiyunmtrr_table_end:
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun	.align 4
238*4882a593Smuzhiyun_dt_ucode_base_size:
239*4882a593Smuzhiyun	/* These next two fields are filled in by ifdtool */
240*4882a593Smuzhiyun.globl ucode_base
241*4882a593Smuzhiyunucode_base:	/* Declared in microcode.h */
242*4882a593Smuzhiyun	.long	0			/* microcode base */
243*4882a593Smuzhiyun	.long	0			/* microcode size */
244