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