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