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