xref: /openbmc/u-boot/arch/x86/cpu/intel_common/cpu.c (revision e8f80a5a)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2016 Google, Inc
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <asm/cpu_common.h>
10 #include <asm/intel_regs.h>
11 #include <asm/lapic.h>
12 #include <asm/lpc_common.h>
13 #include <asm/msr.h>
14 #include <asm/mtrr.h>
15 #include <asm/post.h>
16 #include <asm/microcode.h>
17 
18 DECLARE_GLOBAL_DATA_PTR;
19 
report_bist_failure(void)20 static int report_bist_failure(void)
21 {
22 	if (gd->arch.bist != 0) {
23 		post_code(POST_BIST_FAILURE);
24 		printf("BIST failed: %08x\n", gd->arch.bist);
25 		return -EFAULT;
26 	}
27 
28 	return 0;
29 }
30 
cpu_common_init(void)31 int cpu_common_init(void)
32 {
33 	struct udevice *dev, *lpc;
34 	int ret;
35 
36 	/* Halt if there was a built in self test failure */
37 	ret = report_bist_failure();
38 	if (ret)
39 		return ret;
40 
41 	enable_lapic();
42 
43 	ret = microcode_update_intel();
44 	if (ret && ret != -EEXIST) {
45 		debug("%s: Microcode update failure (err=%d)\n", __func__, ret);
46 		return ret;
47 	}
48 
49 	/* Enable upper 128bytes of CMOS */
50 	writel(1 << 2, RCB_REG(RC));
51 
52 	/* Early chipset init required before RAM init can work */
53 	uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
54 
55 	ret = uclass_first_device(UCLASS_LPC, &lpc);
56 	if (ret)
57 		return ret;
58 	if (!lpc)
59 		return -ENODEV;
60 
61 	/* Cause the SATA device to do its early init */
62 	uclass_first_device(UCLASS_AHCI, &dev);
63 
64 	return 0;
65 }
66 
cpu_set_flex_ratio_to_tdp_nominal(void)67 int cpu_set_flex_ratio_to_tdp_nominal(void)
68 {
69 	msr_t flex_ratio, msr;
70 	u8 nominal_ratio;
71 
72 	/* Check for Flex Ratio support */
73 	flex_ratio = msr_read(MSR_FLEX_RATIO);
74 	if (!(flex_ratio.lo & FLEX_RATIO_EN))
75 		return -EINVAL;
76 
77 	/* Check for >0 configurable TDPs */
78 	msr = msr_read(MSR_PLATFORM_INFO);
79 	if (((msr.hi >> 1) & 3) == 0)
80 		return -EINVAL;
81 
82 	/* Use nominal TDP ratio for flex ratio */
83 	msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
84 	nominal_ratio = msr.lo & 0xff;
85 
86 	/* See if flex ratio is already set to nominal TDP ratio */
87 	if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
88 		return 0;
89 
90 	/* Set flex ratio to nominal TDP ratio */
91 	flex_ratio.lo &= ~0xff00;
92 	flex_ratio.lo |= nominal_ratio << 8;
93 	flex_ratio.lo |= FLEX_RATIO_LOCK;
94 	msr_write(MSR_FLEX_RATIO, flex_ratio);
95 
96 	/* Set flex ratio in soft reset data register bits 11:6 */
97 	clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
98 			(nominal_ratio & 0x3f) << 6);
99 
100 	debug("CPU: Soft reset to set up flex ratio\n");
101 
102 	/* Set soft reset control to use register value */
103 	setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
104 
105 	/* Issue warm reset, will be "CPU only" due to soft reset data */
106 	outb(0x0, IO_PORT_RESET);
107 	outb(SYS_RST | RST_CPU, IO_PORT_RESET);
108 	cpu_hlt();
109 
110 	/* Not reached */
111 	return -EINVAL;
112 }
113