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