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