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