blob: c00687a20af27005cbf656240cc559f345c9ce89 [file] [log] [blame]
Simon Glassd8d9fec2014-10-10 08:21:52 -06001/*
2 * Copyright (c) 2014 The Chromium OS Authors.
3 *
Bin Meng035c1d22014-11-09 22:18:56 +08004 * Part of this file is adapted from coreboot
5 * src/arch/x86/include/arch/cpu.h and
6 * src/arch/x86/lib/cpu.c
7 *
Simon Glassd8d9fec2014-10-10 08:21:52 -06008 * SPDX-License-Identifier: GPL-2.0+
9 */
Bin Meng035c1d22014-11-09 22:18:56 +080010
11#ifndef _ASM_CPU_H
12#define _ASM_CPU_H
13
14enum {
15 X86_VENDOR_INVALID = 0,
16 X86_VENDOR_INTEL,
17 X86_VENDOR_CYRIX,
18 X86_VENDOR_AMD,
19 X86_VENDOR_UMC,
20 X86_VENDOR_NEXGEN,
21 X86_VENDOR_CENTAUR,
22 X86_VENDOR_RISE,
23 X86_VENDOR_TRANSMETA,
24 X86_VENDOR_NSC,
25 X86_VENDOR_SIS,
26 X86_VENDOR_ANY = 0xfe,
27 X86_VENDOR_UNKNOWN = 0xff
28};
29
Simon Glassd360b2f2015-08-04 12:33:54 -060030/* Global descriptor table (GDT) bits */
31enum {
32 GDT_4KB = 1ULL << 55,
33 GDT_32BIT = 1ULL << 54,
34 GDT_LONG = 1ULL << 53,
35 GDT_PRESENT = 1ULL << 47,
36 GDT_NOTSYS = 1ULL << 44,
37 GDT_CODE = 1ULL << 43,
38 GDT_LIMIT_LOW_SHIFT = 0,
39 GDT_LIMIT_LOW_MASK = 0xffff,
40 GDT_LIMIT_HIGH_SHIFT = 48,
41 GDT_LIMIT_HIGH_MASK = 0xf,
42 GDT_BASE_LOW_SHIFT = 16,
43 GDT_BASE_LOW_MASK = 0xffff,
44 GDT_BASE_HIGH_SHIFT = 56,
45 GDT_BASE_HIGH_MASK = 0xf,
46};
47
Simon Glass43a50342016-01-17 16:11:58 -070048/*
49 * System controllers in an x86 system. We mostly need to just find these and
Simon Glassa75abeb2016-01-17 16:11:59 -070050 * use them on PCI. At some point these might have their own uclass (e.g.
51 * UCLASS_VIDEO for the GMA device).
Simon Glass43a50342016-01-17 16:11:58 -070052 */
53enum {
54 X86_NONE,
55 X86_SYSCON_ME, /* Intel Management Engine */
Simon Glass11cd6312016-03-11 22:07:13 -070056 X86_SYSCON_PINCONF, /* Intel x86 pin configuration */
Andy Shevchenko7d2c2012017-04-01 16:21:34 +030057 X86_SYSCON_PMU, /* Power Management Unit */
Felipe Balbiee2e85f2017-04-01 16:21:33 +030058 X86_SYSCON_SCU, /* System Controller Unit */
Simon Glass43a50342016-01-17 16:11:58 -070059};
60
Bin Meng035c1d22014-11-09 22:18:56 +080061struct cpuid_result {
62 uint32_t eax;
63 uint32_t ebx;
64 uint32_t ecx;
65 uint32_t edx;
66};
67
68/*
69 * Generic CPUID function
70 */
71static inline struct cpuid_result cpuid(int op)
72{
73 struct cpuid_result result;
74 asm volatile(
75 "mov %%ebx, %%edi;"
76 "cpuid;"
77 "mov %%ebx, %%esi;"
78 "mov %%edi, %%ebx;"
79 : "=a" (result.eax),
80 "=S" (result.ebx),
81 "=c" (result.ecx),
82 "=d" (result.edx)
83 : "0" (op)
84 : "edi");
85 return result;
86}
87
88/*
89 * Generic Extended CPUID function
90 */
91static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
92{
93 struct cpuid_result result;
94 asm volatile(
95 "mov %%ebx, %%edi;"
96 "cpuid;"
97 "mov %%ebx, %%esi;"
98 "mov %%edi, %%ebx;"
99 : "=a" (result.eax),
100 "=S" (result.ebx),
101 "=c" (result.ecx),
102 "=d" (result.edx)
103 : "0" (op), "2" (ecx)
104 : "edi");
105 return result;
106}
107
108/*
109 * CPUID functions returning a single datum
110 */
111static inline unsigned int cpuid_eax(unsigned int op)
112{
113 unsigned int eax;
114
115 __asm__("mov %%ebx, %%edi;"
116 "cpuid;"
117 "mov %%edi, %%ebx;"
118 : "=a" (eax)
119 : "0" (op)
120 : "ecx", "edx", "edi");
121 return eax;
122}
123
124static inline unsigned int cpuid_ebx(unsigned int op)
125{
126 unsigned int eax, ebx;
127
128 __asm__("mov %%ebx, %%edi;"
129 "cpuid;"
130 "mov %%ebx, %%esi;"
131 "mov %%edi, %%ebx;"
132 : "=a" (eax), "=S" (ebx)
133 : "0" (op)
134 : "ecx", "edx", "edi");
135 return ebx;
136}
137
138static inline unsigned int cpuid_ecx(unsigned int op)
139{
140 unsigned int eax, ecx;
Simon Glassd8d9fec2014-10-10 08:21:52 -0600141
Bin Meng035c1d22014-11-09 22:18:56 +0800142 __asm__("mov %%ebx, %%edi;"
143 "cpuid;"
144 "mov %%edi, %%ebx;"
145 : "=a" (eax), "=c" (ecx)
146 : "0" (op)
147 : "edx", "edi");
148 return ecx;
149}
Simon Glassd8d9fec2014-10-10 08:21:52 -0600150
Bin Meng035c1d22014-11-09 22:18:56 +0800151static inline unsigned int cpuid_edx(unsigned int op)
152{
153 unsigned int eax, edx;
154
155 __asm__("mov %%ebx, %%edi;"
156 "cpuid;"
157 "mov %%edi, %%ebx;"
158 : "=a" (eax), "=d" (edx)
159 : "0" (op)
160 : "ecx", "edi");
161 return edx;
162}
163
Simon Glass249da612017-01-16 07:04:05 -0700164#if !CONFIG_IS_ENABLED(X86_64)
165
Bin Meng035c1d22014-11-09 22:18:56 +0800166/* Standard macro to see if a specific flag is changeable */
167static inline int flag_is_changeable_p(uint32_t flag)
168{
169 uint32_t f1, f2;
170
171 asm(
172 "pushfl\n\t"
173 "pushfl\n\t"
174 "popl %0\n\t"
175 "movl %0,%1\n\t"
176 "xorl %2,%0\n\t"
177 "pushl %0\n\t"
178 "popfl\n\t"
179 "pushfl\n\t"
180 "popl %0\n\t"
181 "popfl\n\t"
182 : "=&r" (f1), "=&r" (f2)
183 : "ir" (flag));
184 return ((f1^f2) & flag) != 0;
185}
Simon Glass249da612017-01-16 07:04:05 -0700186#endif
Bin Meng035c1d22014-11-09 22:18:56 +0800187
Simon Glassdb139ab2015-04-28 20:25:14 -0600188static inline void mfence(void)
189{
190 __asm__ __volatile__("mfence" : : : "memory");
191}
192
Bin Meng035c1d22014-11-09 22:18:56 +0800193/**
Simon Glassd8d9fec2014-10-10 08:21:52 -0600194 * cpu_enable_paging_pae() - Enable PAE-paging
195 *
Bin Meng035c1d22014-11-09 22:18:56 +0800196 * @cr3: Value to set in cr3 (PDPT or PML4T)
Simon Glassd8d9fec2014-10-10 08:21:52 -0600197 */
198void cpu_enable_paging_pae(ulong cr3);
199
200/**
201 * cpu_disable_paging_pae() - Disable paging and PAE
202 */
203void cpu_disable_paging_pae(void);
204
Simon Glass2f2efbc2014-10-10 08:21:54 -0600205/**
206 * cpu_has_64bit() - Check if the CPU has 64-bit support
207 *
208 * @return 1 if this CPU supports long mode (64-bit), 0 if not
209 */
210int cpu_has_64bit(void);
211
Simon Glass463fac22014-10-10 08:21:55 -0600212/**
Bin Meng035c1d22014-11-09 22:18:56 +0800213 * cpu_vendor_name() - Get CPU vendor name
214 *
215 * @vendor: CPU vendor enumeration number
216 *
217 * @return: Address to hold the CPU vendor name string
218 */
219const char *cpu_vendor_name(int vendor);
220
Simon Glass543bb142014-11-10 18:00:26 -0700221#define CPU_MAX_NAME_LEN 49
222
Bin Meng035c1d22014-11-09 22:18:56 +0800223/**
Simon Glass543bb142014-11-10 18:00:26 -0700224 * cpu_get_name() - Get the name of the current cpu
Bin Meng035c1d22014-11-09 22:18:56 +0800225 *
Simon Glass543bb142014-11-10 18:00:26 -0700226 * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including
227 * @return pointer to name, which will likely be a few bytes after the start
228 * of @name
229 * \0 terminator
Bin Meng035c1d22014-11-09 22:18:56 +0800230 */
Simon Glass543bb142014-11-10 18:00:26 -0700231char *cpu_get_name(char *name);
Bin Meng035c1d22014-11-09 22:18:56 +0800232
233/**
Simon Glass463fac22014-10-10 08:21:55 -0600234 * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
235 *
236 * The kernel is uncompressed and the 64-bit entry point is expected to be
237 * at @target.
238 *
239 * This function is used internally - see cpu_jump_to_64bit() for a more
240 * useful function.
241 *
242 * @pgtable: Address of 24KB area containing the page table
243 * @setup_base: Pointer to the setup.bin information for the kernel
244 * @target: Pointer to the start of the kernel image
245 */
246void cpu_call64(ulong pgtable, ulong setup_base, ulong target);
247
248/**
Simon Glassbae81c72015-08-04 12:33:55 -0600249 * cpu_call32() - Jump to a 32-bit entry point
250 *
251 * @code_seg32: 32-bit code segment to use (GDT offset, e.g. 0x20)
252 * @target: Pointer to the start of the 32-bit U-Boot image/entry point
253 * @table: Pointer to start of info table to pass to U-Boot
254 */
255void cpu_call32(ulong code_seg32, ulong target, ulong table);
256
257/**
Simon Glass463fac22014-10-10 08:21:55 -0600258 * cpu_jump_to_64bit() - Jump to a 64-bit Linux kernel
259 *
260 * The kernel is uncompressed and the 64-bit entry point is expected to be
261 * at @target.
262 *
263 * @setup_base: Pointer to the setup.bin information for the kernel
264 * @target: Pointer to the start of the kernel image
265 */
266int cpu_jump_to_64bit(ulong setup_base, ulong target);
267
Simon Glass2f462fd2016-03-11 22:06:52 -0700268/**
Simon Glass1e32ede2017-01-16 07:04:15 -0700269 * cpu_jump_to_64bit_uboot() - special function to jump from SPL to U-Boot
270 *
271 * This handles calling from 32-bit SPL to 64-bit U-Boot.
272 *
273 * @target: Address of U-Boot in RAM
274 */
275int cpu_jump_to_64bit_uboot(ulong target);
276
277/**
Simon Glass2f462fd2016-03-11 22:06:52 -0700278 * cpu_get_family_model() - Get the family and model for the CPU
279 *
280 * @return the CPU ID masked with 0x0fff0ff0
281 */
282u32 cpu_get_family_model(void);
283
284/**
285 * cpu_get_stepping() - Get the stepping value for the CPU
286 *
287 * @return the CPU ID masked with 0xf
288 */
289u32 cpu_get_stepping(void);
290
Simon Glassecae7fd2016-03-11 22:07:16 -0700291/**
292 * cpu_run_reference_code() - Run the platform reference code
293 *
294 * Some platforms require a binary blob to be executed once SDRAM is
295 * available. This is used to set up various platform features, such as the
296 * platform controller hub (PCH). This function should be implemented by the
297 * CPU-specific code.
298 *
299 * @return 0 on success, -ve on failure
300 */
301int cpu_run_reference_code(void);
302
Simon Glassd8d9fec2014-10-10 08:21:52 -0600303#endif