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