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