1*50dd3da0SSimon Glass /* 2*50dd3da0SSimon Glass * Copyright (c) 2016 Google, Inc 3*50dd3da0SSimon Glass * 4*50dd3da0SSimon Glass * SPDX-License-Identifier: GPL-2.0 5*50dd3da0SSimon Glass */ 6*50dd3da0SSimon Glass 7*50dd3da0SSimon Glass #include <common.h> 8*50dd3da0SSimon Glass #include <dm.h> 9*50dd3da0SSimon Glass #include <errno.h> 10*50dd3da0SSimon Glass #include <asm/cpu_common.h> 11*50dd3da0SSimon Glass #include <asm/intel_regs.h> 12*50dd3da0SSimon Glass #include <asm/lapic.h> 13*50dd3da0SSimon Glass #include <asm/lpc_common.h> 14*50dd3da0SSimon Glass #include <asm/msr.h> 15*50dd3da0SSimon Glass #include <asm/mtrr.h> 16*50dd3da0SSimon Glass #include <asm/post.h> 17*50dd3da0SSimon Glass #include <asm/microcode.h> 18*50dd3da0SSimon Glass 19*50dd3da0SSimon Glass DECLARE_GLOBAL_DATA_PTR; 20*50dd3da0SSimon Glass 21*50dd3da0SSimon Glass static int report_bist_failure(void) 22*50dd3da0SSimon Glass { 23*50dd3da0SSimon Glass if (gd->arch.bist != 0) { 24*50dd3da0SSimon Glass post_code(POST_BIST_FAILURE); 25*50dd3da0SSimon Glass printf("BIST failed: %08x\n", gd->arch.bist); 26*50dd3da0SSimon Glass return -EFAULT; 27*50dd3da0SSimon Glass } 28*50dd3da0SSimon Glass 29*50dd3da0SSimon Glass return 0; 30*50dd3da0SSimon Glass } 31*50dd3da0SSimon Glass 32*50dd3da0SSimon Glass int cpu_common_init(void) 33*50dd3da0SSimon Glass { 34*50dd3da0SSimon Glass struct udevice *dev, *lpc; 35*50dd3da0SSimon Glass int ret; 36*50dd3da0SSimon Glass 37*50dd3da0SSimon Glass /* Halt if there was a built in self test failure */ 38*50dd3da0SSimon Glass ret = report_bist_failure(); 39*50dd3da0SSimon Glass if (ret) 40*50dd3da0SSimon Glass return ret; 41*50dd3da0SSimon Glass 42*50dd3da0SSimon Glass enable_lapic(); 43*50dd3da0SSimon Glass 44*50dd3da0SSimon Glass ret = microcode_update_intel(); 45*50dd3da0SSimon Glass if (ret && ret != -EEXIST) 46*50dd3da0SSimon Glass return ret; 47*50dd3da0SSimon Glass 48*50dd3da0SSimon Glass /* Enable upper 128bytes of CMOS */ 49*50dd3da0SSimon Glass writel(1 << 2, RCB_REG(RC)); 50*50dd3da0SSimon Glass 51*50dd3da0SSimon Glass /* Early chipset init required before RAM init can work */ 52*50dd3da0SSimon Glass uclass_first_device(UCLASS_NORTHBRIDGE, &dev); 53*50dd3da0SSimon Glass 54*50dd3da0SSimon Glass ret = uclass_first_device(UCLASS_LPC, &lpc); 55*50dd3da0SSimon Glass if (ret) 56*50dd3da0SSimon Glass return ret; 57*50dd3da0SSimon Glass if (!lpc) 58*50dd3da0SSimon Glass return -ENODEV; 59*50dd3da0SSimon Glass 60*50dd3da0SSimon Glass /* Cause the SATA device to do its early init */ 61*50dd3da0SSimon Glass uclass_first_device(UCLASS_DISK, &dev); 62*50dd3da0SSimon Glass 63*50dd3da0SSimon Glass return 0; 64*50dd3da0SSimon Glass } 65*50dd3da0SSimon Glass 66*50dd3da0SSimon Glass int cpu_set_flex_ratio_to_tdp_nominal(void) 67*50dd3da0SSimon Glass { 68*50dd3da0SSimon Glass msr_t flex_ratio, msr; 69*50dd3da0SSimon Glass u8 nominal_ratio; 70*50dd3da0SSimon Glass 71*50dd3da0SSimon Glass /* Check for Flex Ratio support */ 72*50dd3da0SSimon Glass flex_ratio = msr_read(MSR_FLEX_RATIO); 73*50dd3da0SSimon Glass if (!(flex_ratio.lo & FLEX_RATIO_EN)) 74*50dd3da0SSimon Glass return -EINVAL; 75*50dd3da0SSimon Glass 76*50dd3da0SSimon Glass /* Check for >0 configurable TDPs */ 77*50dd3da0SSimon Glass msr = msr_read(MSR_PLATFORM_INFO); 78*50dd3da0SSimon Glass if (((msr.hi >> 1) & 3) == 0) 79*50dd3da0SSimon Glass return -EINVAL; 80*50dd3da0SSimon Glass 81*50dd3da0SSimon Glass /* Use nominal TDP ratio for flex ratio */ 82*50dd3da0SSimon Glass msr = msr_read(MSR_CONFIG_TDP_NOMINAL); 83*50dd3da0SSimon Glass nominal_ratio = msr.lo & 0xff; 84*50dd3da0SSimon Glass 85*50dd3da0SSimon Glass /* See if flex ratio is already set to nominal TDP ratio */ 86*50dd3da0SSimon Glass if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio) 87*50dd3da0SSimon Glass return 0; 88*50dd3da0SSimon Glass 89*50dd3da0SSimon Glass /* Set flex ratio to nominal TDP ratio */ 90*50dd3da0SSimon Glass flex_ratio.lo &= ~0xff00; 91*50dd3da0SSimon Glass flex_ratio.lo |= nominal_ratio << 8; 92*50dd3da0SSimon Glass flex_ratio.lo |= FLEX_RATIO_LOCK; 93*50dd3da0SSimon Glass msr_write(MSR_FLEX_RATIO, flex_ratio); 94*50dd3da0SSimon Glass 95*50dd3da0SSimon Glass /* Set flex ratio in soft reset data register bits 11:6 */ 96*50dd3da0SSimon Glass clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6, 97*50dd3da0SSimon Glass (nominal_ratio & 0x3f) << 6); 98*50dd3da0SSimon Glass 99*50dd3da0SSimon Glass debug("CPU: Soft reset to set up flex ratio\n"); 100*50dd3da0SSimon Glass 101*50dd3da0SSimon Glass /* Set soft reset control to use register value */ 102*50dd3da0SSimon Glass setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1); 103*50dd3da0SSimon Glass 104*50dd3da0SSimon Glass /* Issue warm reset, will be "CPU only" due to soft reset data */ 105*50dd3da0SSimon Glass outb(0x0, PORT_RESET); 106*50dd3da0SSimon Glass outb(SYS_RST | RST_CPU, PORT_RESET); 107*50dd3da0SSimon Glass cpu_hlt(); 108*50dd3da0SSimon Glass 109*50dd3da0SSimon Glass /* Not reached */ 110*50dd3da0SSimon Glass return -EINVAL; 111*50dd3da0SSimon Glass } 112