xref: /rk3399_rockchip-uboot/arch/x86/cpu/intel_common/cpu.c (revision fda4fa8195bab36879272e92973a7ef39e759795)
150dd3da0SSimon Glass /*
250dd3da0SSimon Glass  * Copyright (c) 2016 Google, Inc
350dd3da0SSimon Glass  *
450dd3da0SSimon Glass  * SPDX-License-Identifier:	GPL-2.0
550dd3da0SSimon Glass  */
650dd3da0SSimon Glass 
750dd3da0SSimon Glass #include <common.h>
850dd3da0SSimon Glass #include <dm.h>
950dd3da0SSimon Glass #include <errno.h>
1050dd3da0SSimon Glass #include <asm/cpu_common.h>
1150dd3da0SSimon Glass #include <asm/intel_regs.h>
1250dd3da0SSimon Glass #include <asm/lapic.h>
1350dd3da0SSimon Glass #include <asm/lpc_common.h>
1450dd3da0SSimon Glass #include <asm/msr.h>
1550dd3da0SSimon Glass #include <asm/mtrr.h>
1650dd3da0SSimon Glass #include <asm/post.h>
1750dd3da0SSimon Glass #include <asm/microcode.h>
1850dd3da0SSimon Glass 
1950dd3da0SSimon Glass DECLARE_GLOBAL_DATA_PTR;
2050dd3da0SSimon Glass 
report_bist_failure(void)2150dd3da0SSimon Glass static int report_bist_failure(void)
2250dd3da0SSimon Glass {
2350dd3da0SSimon Glass 	if (gd->arch.bist != 0) {
2450dd3da0SSimon Glass 		post_code(POST_BIST_FAILURE);
2550dd3da0SSimon Glass 		printf("BIST failed: %08x\n", gd->arch.bist);
2650dd3da0SSimon Glass 		return -EFAULT;
2750dd3da0SSimon Glass 	}
2850dd3da0SSimon Glass 
2950dd3da0SSimon Glass 	return 0;
3050dd3da0SSimon Glass }
3150dd3da0SSimon Glass 
cpu_common_init(void)3250dd3da0SSimon Glass int cpu_common_init(void)
3350dd3da0SSimon Glass {
3450dd3da0SSimon Glass 	struct udevice *dev, *lpc;
3550dd3da0SSimon Glass 	int ret;
3650dd3da0SSimon Glass 
3750dd3da0SSimon Glass 	/* Halt if there was a built in self test failure */
3850dd3da0SSimon Glass 	ret = report_bist_failure();
3950dd3da0SSimon Glass 	if (ret)
4050dd3da0SSimon Glass 		return ret;
4150dd3da0SSimon Glass 
4250dd3da0SSimon Glass 	enable_lapic();
4350dd3da0SSimon Glass 
4450dd3da0SSimon Glass 	ret = microcode_update_intel();
45*fda4fa81SSimon Glass 	if (ret && ret != -EEXIST) {
46*fda4fa81SSimon Glass 		debug("%s: Microcode update failure (err=%d)\n", __func__, ret);
4750dd3da0SSimon Glass 		return ret;
48*fda4fa81SSimon Glass 	}
4950dd3da0SSimon Glass 
5050dd3da0SSimon Glass 	/* Enable upper 128bytes of CMOS */
5150dd3da0SSimon Glass 	writel(1 << 2, RCB_REG(RC));
5250dd3da0SSimon Glass 
5350dd3da0SSimon Glass 	/* Early chipset init required before RAM init can work */
5450dd3da0SSimon Glass 	uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
5550dd3da0SSimon Glass 
5650dd3da0SSimon Glass 	ret = uclass_first_device(UCLASS_LPC, &lpc);
5750dd3da0SSimon Glass 	if (ret)
5850dd3da0SSimon Glass 		return ret;
5950dd3da0SSimon Glass 	if (!lpc)
6050dd3da0SSimon Glass 		return -ENODEV;
6150dd3da0SSimon Glass 
6250dd3da0SSimon Glass 	/* Cause the SATA device to do its early init */
63a219639dSSimon Glass 	uclass_first_device(UCLASS_AHCI, &dev);
6450dd3da0SSimon Glass 
6550dd3da0SSimon Glass 	return 0;
6650dd3da0SSimon Glass }
6750dd3da0SSimon Glass 
cpu_set_flex_ratio_to_tdp_nominal(void)6850dd3da0SSimon Glass int cpu_set_flex_ratio_to_tdp_nominal(void)
6950dd3da0SSimon Glass {
7050dd3da0SSimon Glass 	msr_t flex_ratio, msr;
7150dd3da0SSimon Glass 	u8 nominal_ratio;
7250dd3da0SSimon Glass 
7350dd3da0SSimon Glass 	/* Check for Flex Ratio support */
7450dd3da0SSimon Glass 	flex_ratio = msr_read(MSR_FLEX_RATIO);
7550dd3da0SSimon Glass 	if (!(flex_ratio.lo & FLEX_RATIO_EN))
7650dd3da0SSimon Glass 		return -EINVAL;
7750dd3da0SSimon Glass 
7850dd3da0SSimon Glass 	/* Check for >0 configurable TDPs */
7950dd3da0SSimon Glass 	msr = msr_read(MSR_PLATFORM_INFO);
8050dd3da0SSimon Glass 	if (((msr.hi >> 1) & 3) == 0)
8150dd3da0SSimon Glass 		return -EINVAL;
8250dd3da0SSimon Glass 
8350dd3da0SSimon Glass 	/* Use nominal TDP ratio for flex ratio */
8450dd3da0SSimon Glass 	msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
8550dd3da0SSimon Glass 	nominal_ratio = msr.lo & 0xff;
8650dd3da0SSimon Glass 
8750dd3da0SSimon Glass 	/* See if flex ratio is already set to nominal TDP ratio */
8850dd3da0SSimon Glass 	if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
8950dd3da0SSimon Glass 		return 0;
9050dd3da0SSimon Glass 
9150dd3da0SSimon Glass 	/* Set flex ratio to nominal TDP ratio */
9250dd3da0SSimon Glass 	flex_ratio.lo &= ~0xff00;
9350dd3da0SSimon Glass 	flex_ratio.lo |= nominal_ratio << 8;
9450dd3da0SSimon Glass 	flex_ratio.lo |= FLEX_RATIO_LOCK;
9550dd3da0SSimon Glass 	msr_write(MSR_FLEX_RATIO, flex_ratio);
9650dd3da0SSimon Glass 
9750dd3da0SSimon Glass 	/* Set flex ratio in soft reset data register bits 11:6 */
9850dd3da0SSimon Glass 	clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
9950dd3da0SSimon Glass 			(nominal_ratio & 0x3f) << 6);
10050dd3da0SSimon Glass 
10150dd3da0SSimon Glass 	debug("CPU: Soft reset to set up flex ratio\n");
10250dd3da0SSimon Glass 
10350dd3da0SSimon Glass 	/* Set soft reset control to use register value */
10450dd3da0SSimon Glass 	setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
10550dd3da0SSimon Glass 
10650dd3da0SSimon Glass 	/* Issue warm reset, will be "CPU only" due to soft reset data */
1072a605d4dSSimon Glass 	outb(0x0, IO_PORT_RESET);
1082a605d4dSSimon Glass 	outb(SYS_RST | RST_CPU, IO_PORT_RESET);
10950dd3da0SSimon Glass 	cpu_hlt();
11050dd3da0SSimon Glass 
11150dd3da0SSimon Glass 	/* Not reached */
11250dd3da0SSimon Glass 	return -EINVAL;
11350dd3da0SSimon Glass }
114