Home | History | Annotate | Download | only in cpu
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2008-2011
      4  * Graeme Russ, <graeme.russ (at) gmail.com>
      5  *
      6  * (C) Copyright 2002
      7  * Daniel Engstrm, Omicron Ceti AB, <daniel (at) omicron.se>
      8  *
      9  * (C) Copyright 2002
     10  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
     11  * Marius Groeger <mgroeger (at) sysgo.de>
     12  *
     13  * (C) Copyright 2002
     14  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
     15  * Alex Zuepke <azu (at) sysgo.de>
     16  *
     17  * Part of this file is adapted from coreboot
     18  * src/arch/x86/lib/cpu.c
     19  */
     20 
     21 #include <common.h>
     22 #include <command.h>
     23 #include <dm.h>
     24 #include <errno.h>
     25 #include <malloc.h>
     26 #include <syscon.h>
     27 #include <asm/acpi_s3.h>
     28 #include <asm/acpi_table.h>
     29 #include <asm/control_regs.h>
     30 #include <asm/coreboot_tables.h>
     31 #include <asm/cpu.h>
     32 #include <asm/lapic.h>
     33 #include <asm/microcode.h>
     34 #include <asm/mp.h>
     35 #include <asm/mrccache.h>
     36 #include <asm/msr.h>
     37 #include <asm/mtrr.h>
     38 #include <asm/post.h>
     39 #include <asm/processor.h>
     40 #include <asm/processor-flags.h>
     41 #include <asm/interrupt.h>
     42 #include <asm/tables.h>
     43 #include <linux/compiler.h>
     44 
     45 DECLARE_GLOBAL_DATA_PTR;
     46 
     47 static const char *const x86_vendor_name[] = {
     48 	[X86_VENDOR_INTEL]     = "Intel",
     49 	[X86_VENDOR_CYRIX]     = "Cyrix",
     50 	[X86_VENDOR_AMD]       = "AMD",
     51 	[X86_VENDOR_UMC]       = "UMC",
     52 	[X86_VENDOR_NEXGEN]    = "NexGen",
     53 	[X86_VENDOR_CENTAUR]   = "Centaur",
     54 	[X86_VENDOR_RISE]      = "Rise",
     55 	[X86_VENDOR_TRANSMETA] = "Transmeta",
     56 	[X86_VENDOR_NSC]       = "NSC",
     57 	[X86_VENDOR_SIS]       = "SiS",
     58 };
     59 
     60 int __weak x86_cleanup_before_linux(void)
     61 {
     62 #ifdef CONFIG_BOOTSTAGE_STASH
     63 	bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
     64 			CONFIG_BOOTSTAGE_STASH_SIZE);
     65 #endif
     66 
     67 	return 0;
     68 }
     69 
     70 int x86_init_cache(void)
     71 {
     72 	enable_caches();
     73 
     74 	return 0;
     75 }
     76 int init_cache(void) __attribute__((weak, alias("x86_init_cache")));
     77 
     78 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
     79 {
     80 	printf("resetting ...\n");
     81 
     82 	/* wait 50 ms */
     83 	udelay(50000);
     84 	disable_interrupts();
     85 	reset_cpu(0);
     86 
     87 	/*NOTREACHED*/
     88 	return 0;
     89 }
     90 
     91 void  flush_cache(unsigned long dummy1, unsigned long dummy2)
     92 {
     93 	asm("wbinvd\n");
     94 }
     95 
     96 __weak void reset_cpu(ulong addr)
     97 {
     98 	/* Do a hard reset through the chipset's reset control register */
     99 	outb(SYS_RST | RST_CPU, IO_PORT_RESET);
    100 	for (;;)
    101 		cpu_hlt();
    102 }
    103 
    104 void x86_full_reset(void)
    105 {
    106 	outb(FULL_RST | SYS_RST | RST_CPU, IO_PORT_RESET);
    107 }
    108 
    109 /* Define these functions to allow ehch-hcd to function */
    110 void flush_dcache_range(unsigned long start, unsigned long stop)
    111 {
    112 }
    113 
    114 void invalidate_dcache_range(unsigned long start, unsigned long stop)
    115 {
    116 }
    117 
    118 void dcache_enable(void)
    119 {
    120 	enable_caches();
    121 }
    122 
    123 void dcache_disable(void)
    124 {
    125 	disable_caches();
    126 }
    127 
    128 void icache_enable(void)
    129 {
    130 }
    131 
    132 void icache_disable(void)
    133 {
    134 }
    135 
    136 int icache_status(void)
    137 {
    138 	return 1;
    139 }
    140 
    141 const char *cpu_vendor_name(int vendor)
    142 {
    143 	const char *name;
    144 	name = "<invalid cpu vendor>";
    145 	if (vendor < ARRAY_SIZE(x86_vendor_name) &&
    146 	    x86_vendor_name[vendor])
    147 		name = x86_vendor_name[vendor];
    148 
    149 	return name;
    150 }
    151 
    152 char *cpu_get_name(char *name)
    153 {
    154 	unsigned int *name_as_ints = (unsigned int *)name;
    155 	struct cpuid_result regs;
    156 	char *ptr;
    157 	int i;
    158 
    159 	/* This bit adds up to 48 bytes */
    160 	for (i = 0; i < 3; i++) {
    161 		regs = cpuid(0x80000002 + i);
    162 		name_as_ints[i * 4 + 0] = regs.eax;
    163 		name_as_ints[i * 4 + 1] = regs.ebx;
    164 		name_as_ints[i * 4 + 2] = regs.ecx;
    165 		name_as_ints[i * 4 + 3] = regs.edx;
    166 	}
    167 	name[CPU_MAX_NAME_LEN - 1] = '\0';
    168 
    169 	/* Skip leading spaces. */
    170 	ptr = name;
    171 	while (*ptr == ' ')
    172 		ptr++;
    173 
    174 	return ptr;
    175 }
    176 
    177 int default_print_cpuinfo(void)
    178 {
    179 	printf("CPU: %s, vendor %s, device %xh\n",
    180 	       cpu_has_64bit() ? "x86_64" : "x86",
    181 	       cpu_vendor_name(gd->arch.x86_vendor), gd->arch.x86_device);
    182 
    183 #ifdef CONFIG_HAVE_ACPI_RESUME
    184 	debug("ACPI previous sleep state: %s\n",
    185 	      acpi_ss_string(gd->arch.prev_sleep_state));
    186 #endif
    187 
    188 	return 0;
    189 }
    190 
    191 void show_boot_progress(int val)
    192 {
    193 	outb(val, POST_PORT);
    194 }
    195 
    196 #if !defined(CONFIG_SYS_COREBOOT) && !defined(CONFIG_EFI_STUB)
    197 /*
    198  * Implement a weak default function for boards that optionally
    199  * need to clean up the system before jumping to the kernel.
    200  */
    201 __weak void board_final_cleanup(void)
    202 {
    203 }
    204 
    205 int last_stage_init(void)
    206 {
    207 	board_final_cleanup();
    208 
    209 #if CONFIG_HAVE_ACPI_RESUME
    210 	struct acpi_fadt *fadt = acpi_find_fadt();
    211 
    212 	if (fadt != NULL && gd->arch.prev_sleep_state == ACPI_S3)
    213 		acpi_resume(fadt);
    214 #endif
    215 
    216 	write_tables();
    217 
    218 	return 0;
    219 }
    220 #endif
    221 
    222 static int x86_init_cpus(void)
    223 {
    224 #ifdef CONFIG_SMP
    225 	debug("Init additional CPUs\n");
    226 	x86_mp_init();
    227 #else
    228 	struct udevice *dev;
    229 
    230 	/*
    231 	 * This causes the cpu-x86 driver to be probed.
    232 	 * We don't check return value here as we want to allow boards
    233 	 * which have not been converted to use cpu uclass driver to boot.
    234 	 */
    235 	uclass_first_device(UCLASS_CPU, &dev);
    236 #endif
    237 
    238 	return 0;
    239 }
    240 
    241 int cpu_init_r(void)
    242 {
    243 	struct udevice *dev;
    244 	int ret;
    245 
    246 	if (!ll_boot_init())
    247 		return 0;
    248 
    249 	ret = x86_init_cpus();
    250 	if (ret)
    251 		return ret;
    252 
    253 	/*
    254 	 * Set up the northbridge, PCH and LPC if available. Note that these
    255 	 * may have had some limited pre-relocation init if they were probed
    256 	 * before relocation, but this is post relocation.
    257 	 */
    258 	uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
    259 	uclass_first_device(UCLASS_PCH, &dev);
    260 	uclass_first_device(UCLASS_LPC, &dev);
    261 
    262 	/* Set up pin control if available */
    263 	ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &dev);
    264 	debug("%s, pinctrl=%p, ret=%d\n", __func__, dev, ret);
    265 
    266 	return 0;
    267 }
    268 
    269 #ifndef CONFIG_EFI_STUB
    270 int reserve_arch(void)
    271 {
    272 #ifdef CONFIG_ENABLE_MRC_CACHE
    273 	mrccache_reserve();
    274 #endif
    275 
    276 #ifdef CONFIG_SEABIOS
    277 	high_table_reserve();
    278 #endif
    279 
    280 #ifdef CONFIG_HAVE_ACPI_RESUME
    281 	acpi_s3_reserve();
    282 
    283 #ifdef CONFIG_HAVE_FSP
    284 	/*
    285 	 * Save stack address to CMOS so that at next S3 boot,
    286 	 * we can use it as the stack address for fsp_contiue()
    287 	 */
    288 	fsp_save_s3_stack();
    289 #endif /* CONFIG_HAVE_FSP */
    290 #endif /* CONFIG_HAVE_ACPI_RESUME */
    291 
    292 	return 0;
    293 }
    294 #endif
    295