xref: /rk3399_rockchip-uboot/arch/x86/cpu/intel_common/cpu.c (revision a219639d4216e59a0c55f0b7d2c8a21f9cb0bb06)
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 
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 
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();
4550dd3da0SSimon Glass 	if (ret && ret != -EEXIST)
4650dd3da0SSimon Glass 		return ret;
4750dd3da0SSimon Glass 
4850dd3da0SSimon Glass 	/* Enable upper 128bytes of CMOS */
4950dd3da0SSimon Glass 	writel(1 << 2, RCB_REG(RC));
5050dd3da0SSimon Glass 
5150dd3da0SSimon Glass 	/* Early chipset init required before RAM init can work */
5250dd3da0SSimon Glass 	uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
5350dd3da0SSimon Glass 
5450dd3da0SSimon Glass 	ret = uclass_first_device(UCLASS_LPC, &lpc);
5550dd3da0SSimon Glass 	if (ret)
5650dd3da0SSimon Glass 		return ret;
5750dd3da0SSimon Glass 	if (!lpc)
5850dd3da0SSimon Glass 		return -ENODEV;
5950dd3da0SSimon Glass 
6050dd3da0SSimon Glass 	/* Cause the SATA device to do its early init */
61*a219639dSSimon Glass 	uclass_first_device(UCLASS_AHCI, &dev);
6250dd3da0SSimon Glass 
6350dd3da0SSimon Glass 	return 0;
6450dd3da0SSimon Glass }
6550dd3da0SSimon Glass 
6650dd3da0SSimon Glass int cpu_set_flex_ratio_to_tdp_nominal(void)
6750dd3da0SSimon Glass {
6850dd3da0SSimon Glass 	msr_t flex_ratio, msr;
6950dd3da0SSimon Glass 	u8 nominal_ratio;
7050dd3da0SSimon Glass 
7150dd3da0SSimon Glass 	/* Check for Flex Ratio support */
7250dd3da0SSimon Glass 	flex_ratio = msr_read(MSR_FLEX_RATIO);
7350dd3da0SSimon Glass 	if (!(flex_ratio.lo & FLEX_RATIO_EN))
7450dd3da0SSimon Glass 		return -EINVAL;
7550dd3da0SSimon Glass 
7650dd3da0SSimon Glass 	/* Check for >0 configurable TDPs */
7750dd3da0SSimon Glass 	msr = msr_read(MSR_PLATFORM_INFO);
7850dd3da0SSimon Glass 	if (((msr.hi >> 1) & 3) == 0)
7950dd3da0SSimon Glass 		return -EINVAL;
8050dd3da0SSimon Glass 
8150dd3da0SSimon Glass 	/* Use nominal TDP ratio for flex ratio */
8250dd3da0SSimon Glass 	msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
8350dd3da0SSimon Glass 	nominal_ratio = msr.lo & 0xff;
8450dd3da0SSimon Glass 
8550dd3da0SSimon Glass 	/* See if flex ratio is already set to nominal TDP ratio */
8650dd3da0SSimon Glass 	if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
8750dd3da0SSimon Glass 		return 0;
8850dd3da0SSimon Glass 
8950dd3da0SSimon Glass 	/* Set flex ratio to nominal TDP ratio */
9050dd3da0SSimon Glass 	flex_ratio.lo &= ~0xff00;
9150dd3da0SSimon Glass 	flex_ratio.lo |= nominal_ratio << 8;
9250dd3da0SSimon Glass 	flex_ratio.lo |= FLEX_RATIO_LOCK;
9350dd3da0SSimon Glass 	msr_write(MSR_FLEX_RATIO, flex_ratio);
9450dd3da0SSimon Glass 
9550dd3da0SSimon Glass 	/* Set flex ratio in soft reset data register bits 11:6 */
9650dd3da0SSimon Glass 	clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
9750dd3da0SSimon Glass 			(nominal_ratio & 0x3f) << 6);
9850dd3da0SSimon Glass 
9950dd3da0SSimon Glass 	debug("CPU: Soft reset to set up flex ratio\n");
10050dd3da0SSimon Glass 
10150dd3da0SSimon Glass 	/* Set soft reset control to use register value */
10250dd3da0SSimon Glass 	setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
10350dd3da0SSimon Glass 
10450dd3da0SSimon Glass 	/* Issue warm reset, will be "CPU only" due to soft reset data */
1052a605d4dSSimon Glass 	outb(0x0, IO_PORT_RESET);
1062a605d4dSSimon Glass 	outb(SYS_RST | RST_CPU, IO_PORT_RESET);
10750dd3da0SSimon Glass 	cpu_hlt();
10850dd3da0SSimon Glass 
10950dd3da0SSimon Glass 	/* Not reached */
11050dd3da0SSimon Glass 	return -EINVAL;
11150dd3da0SSimon Glass }
112