avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
16
u-boot/arch/x86/cpu/intel_common/Makefile
Normal file
16
u-boot/arch/x86/cpu/intel_common/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2016 Google, Inc
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-$(CONFIG_HAVE_MRC) += car.o
|
||||
obj-y += cpu.o
|
||||
obj-y += lpc.o
|
||||
obj-$(CONFIG_HAVE_MRC) += me_status.o
|
||||
ifndef CONFIG_TARGET_EFI
|
||||
obj-y += microcode.o
|
||||
endif
|
||||
obj-y += pch.o
|
||||
obj-$(CONFIG_HAVE_MRC) += report_platform.o
|
||||
obj-$(CONFIG_HAVE_MRC) += mrc.o
|
||||
243
u-boot/arch/x86/cpu/intel_common/car.S
Normal file
243
u-boot/arch/x86/cpu/intel_common/car.S
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
*
|
||||
* From Coreboot file cpu/intel/model_206ax/cache_as_ram.inc
|
||||
*
|
||||
* Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
|
||||
* Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan)
|
||||
* Copyright (C) 2007-2008 coresystems GmbH
|
||||
* Copyright (C) 2012 Kyösti Mälkki <kyosti.malkki@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/msr-index.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/post.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/processor-flags.h>
|
||||
|
||||
#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
|
||||
#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
|
||||
|
||||
#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE
|
||||
#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE
|
||||
|
||||
/* Cache 4GB - MRC_SIZE_KB for MRC */
|
||||
#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1)
|
||||
#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES)
|
||||
#define CACHE_MRC_MASK (~CACHE_MRC_BYTES)
|
||||
|
||||
#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1)
|
||||
|
||||
#define NOEVICTMOD_MSR 0x2e0
|
||||
|
||||
/*
|
||||
* Note: ebp must not be touched in this code as it holds the BIST
|
||||
* value (built-in self test). We preserve this value until it can
|
||||
* be written to global_data when CAR is ready for use.
|
||||
*/
|
||||
.globl car_init
|
||||
car_init:
|
||||
post_code(POST_CAR_START)
|
||||
|
||||
/* Send INIT IPI to all excluding ourself */
|
||||
movl $0x000C4500, %eax
|
||||
movl $0xFEE00300, %esi
|
||||
movl %eax, (%esi)
|
||||
|
||||
/* TODO: Load microcode later - the 'no eviction' mode breaks this */
|
||||
movl $MSR_IA32_UCODE_WRITE, %ecx
|
||||
xorl %edx, %edx
|
||||
movl $_dt_ucode_base_size, %eax
|
||||
movl (%eax), %eax
|
||||
addl $UCODE_HEADER_LEN, %eax
|
||||
wrmsr
|
||||
|
||||
post_code(POST_CAR_SIPI)
|
||||
/* Zero out all fixed range and variable range MTRRs */
|
||||
movl $mtrr_table, %esi
|
||||
movl $((mtrr_table_end - mtrr_table) / 2), %edi
|
||||
xorl %eax, %eax
|
||||
xorl %edx, %edx
|
||||
clear_mtrrs:
|
||||
movw (%esi), %bx
|
||||
movzx %bx, %ecx
|
||||
wrmsr
|
||||
add $2, %esi
|
||||
dec %edi
|
||||
jnz clear_mtrrs
|
||||
|
||||
post_code(POST_CAR_MTRR)
|
||||
/* Configure the default memory type to uncacheable */
|
||||
movl $MTRR_DEF_TYPE_MSR, %ecx
|
||||
rdmsr
|
||||
andl $(~0x00000cff), %eax
|
||||
wrmsr
|
||||
|
||||
post_code(POST_CAR_UNCACHEABLE)
|
||||
/* Set Cache-as-RAM base address */
|
||||
movl $(MTRR_PHYS_BASE_MSR(0)), %ecx
|
||||
movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
|
||||
xorl %edx, %edx
|
||||
wrmsr
|
||||
|
||||
post_code(POST_CAR_BASE_ADDRESS)
|
||||
/* Set Cache-as-RAM mask */
|
||||
movl $(MTRR_PHYS_MASK_MSR(0)), %ecx
|
||||
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
|
||||
movl $CPU_PHYSMASK_HI, %edx
|
||||
wrmsr
|
||||
|
||||
post_code(POST_CAR_MASK)
|
||||
|
||||
/* Enable MTRR */
|
||||
movl $MTRR_DEF_TYPE_MSR, %ecx
|
||||
rdmsr
|
||||
orl $MTRR_DEF_TYPE_EN, %eax
|
||||
wrmsr
|
||||
|
||||
/* Enable cache (CR0.CD = 0, CR0.NW = 0) */
|
||||
movl %cr0, %eax
|
||||
andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax
|
||||
invd
|
||||
movl %eax, %cr0
|
||||
|
||||
/* enable the 'no eviction' mode */
|
||||
movl $NOEVICTMOD_MSR, %ecx
|
||||
rdmsr
|
||||
orl $1, %eax
|
||||
andl $~2, %eax
|
||||
wrmsr
|
||||
|
||||
/* Clear the cache memory region. This will also fill up the cache */
|
||||
movl $CACHE_AS_RAM_BASE, %esi
|
||||
movl %esi, %edi
|
||||
movl $(CACHE_AS_RAM_SIZE / 4), %ecx
|
||||
xorl %eax, %eax
|
||||
rep stosl
|
||||
|
||||
/* enable the 'no eviction run' state */
|
||||
movl $NOEVICTMOD_MSR, %ecx
|
||||
rdmsr
|
||||
orl $3, %eax
|
||||
wrmsr
|
||||
|
||||
post_code(POST_CAR_FILL)
|
||||
/* Enable Cache-as-RAM mode by disabling cache */
|
||||
movl %cr0, %eax
|
||||
orl $X86_CR0_CD, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Enable cache for our code in Flash because we do XIP here */
|
||||
movl $MTRR_PHYS_BASE_MSR(1), %ecx
|
||||
xorl %edx, %edx
|
||||
movl $car_init_ret, %eax
|
||||
andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax
|
||||
orl $MTRR_TYPE_WRPROT, %eax
|
||||
wrmsr
|
||||
|
||||
movl $MTRR_PHYS_MASK_MSR(1), %ecx
|
||||
movl $CPU_PHYSMASK_HI, %edx
|
||||
movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
|
||||
wrmsr
|
||||
|
||||
post_code(POST_CAR_ROM_CACHE)
|
||||
#ifdef CONFIG_CACHE_MRC_BIN
|
||||
/* Enable caching for ram init code to run faster */
|
||||
movl $MTRR_PHYS_BASE_MSR(2), %ecx
|
||||
movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
|
||||
xorl %edx, %edx
|
||||
wrmsr
|
||||
movl $MTRR_PHYS_MASK_MSR(2), %ecx
|
||||
movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax
|
||||
movl $CPU_PHYSMASK_HI, %edx
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
post_code(POST_CAR_MRC_CACHE)
|
||||
/* Enable cache */
|
||||
movl %cr0, %eax
|
||||
andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
post_code(POST_CAR_CPU_CACHE)
|
||||
|
||||
/* All CPUs need to be in Wait for SIPI state */
|
||||
wait_for_sipi:
|
||||
movl (%esi), %eax
|
||||
bt $12, %eax
|
||||
jc wait_for_sipi
|
||||
|
||||
/* return */
|
||||
jmp car_init_ret
|
||||
|
||||
.globl car_uninit
|
||||
car_uninit:
|
||||
/* Disable cache */
|
||||
movl %cr0, %eax
|
||||
orl $X86_CR0_CD, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Disable MTRRs */
|
||||
movl $MTRR_DEF_TYPE_MSR, %ecx
|
||||
rdmsr
|
||||
andl $(~MTRR_DEF_TYPE_EN), %eax
|
||||
wrmsr
|
||||
|
||||
/* Disable the no-eviction run state */
|
||||
movl $NOEVICTMOD_MSR, %ecx
|
||||
rdmsr
|
||||
andl $~2, %eax
|
||||
wrmsr
|
||||
|
||||
invd
|
||||
|
||||
/* Disable the no-eviction mode */
|
||||
rdmsr
|
||||
andl $~1, %eax
|
||||
wrmsr
|
||||
|
||||
#ifdef CONFIG_CACHE_MRC_BIN
|
||||
/* Clear the MTRR that was used to cache MRC */
|
||||
xorl %eax, %eax
|
||||
xorl %edx, %edx
|
||||
movl $MTRR_PHYS_BASE_MSR(2), %ecx
|
||||
wrmsr
|
||||
movl $MTRR_PHYS_MASK_MSR(2), %ecx
|
||||
wrmsr
|
||||
#endif
|
||||
|
||||
/* Enable MTRRs */
|
||||
movl $MTRR_DEF_TYPE_MSR, %ecx
|
||||
rdmsr
|
||||
orl $MTRR_DEF_TYPE_EN, %eax
|
||||
wrmsr
|
||||
|
||||
invd
|
||||
|
||||
ret
|
||||
|
||||
mtrr_table:
|
||||
/* Fixed MTRRs */
|
||||
.word 0x250, 0x258, 0x259
|
||||
.word 0x268, 0x269, 0x26A
|
||||
.word 0x26B, 0x26C, 0x26D
|
||||
.word 0x26E, 0x26F
|
||||
/* Variable MTRRs */
|
||||
.word 0x200, 0x201, 0x202, 0x203
|
||||
.word 0x204, 0x205, 0x206, 0x207
|
||||
.word 0x208, 0x209, 0x20A, 0x20B
|
||||
.word 0x20C, 0x20D, 0x20E, 0x20F
|
||||
.word 0x210, 0x211, 0x212, 0x213
|
||||
mtrr_table_end:
|
||||
|
||||
.align 4
|
||||
_dt_ucode_base_size:
|
||||
/* These next two fields are filled in by ifdtool */
|
||||
.globl ucode_base
|
||||
ucode_base: /* Declared in microcode.h */
|
||||
.long 0 /* microcode base */
|
||||
.long 0 /* microcode size */
|
||||
111
u-boot/arch/x86/cpu/intel_common/cpu.c
Normal file
111
u-boot/arch/x86/cpu/intel_common/cpu.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <asm/cpu_common.h>
|
||||
#include <asm/intel_regs.h>
|
||||
#include <asm/lapic.h>
|
||||
#include <asm/lpc_common.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/post.h>
|
||||
#include <asm/microcode.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int report_bist_failure(void)
|
||||
{
|
||||
if (gd->arch.bist != 0) {
|
||||
post_code(POST_BIST_FAILURE);
|
||||
printf("BIST failed: %08x\n", gd->arch.bist);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_common_init(void)
|
||||
{
|
||||
struct udevice *dev, *lpc;
|
||||
int ret;
|
||||
|
||||
/* Halt if there was a built in self test failure */
|
||||
ret = report_bist_failure();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
enable_lapic();
|
||||
|
||||
ret = microcode_update_intel();
|
||||
if (ret && ret != -EEXIST)
|
||||
return ret;
|
||||
|
||||
/* Enable upper 128bytes of CMOS */
|
||||
writel(1 << 2, RCB_REG(RC));
|
||||
|
||||
/* Early chipset init required before RAM init can work */
|
||||
uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
|
||||
|
||||
ret = uclass_first_device(UCLASS_LPC, &lpc);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!lpc)
|
||||
return -ENODEV;
|
||||
|
||||
/* Cause the SATA device to do its early init */
|
||||
uclass_first_device(UCLASS_AHCI, &dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_set_flex_ratio_to_tdp_nominal(void)
|
||||
{
|
||||
msr_t flex_ratio, msr;
|
||||
u8 nominal_ratio;
|
||||
|
||||
/* Check for Flex Ratio support */
|
||||
flex_ratio = msr_read(MSR_FLEX_RATIO);
|
||||
if (!(flex_ratio.lo & FLEX_RATIO_EN))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check for >0 configurable TDPs */
|
||||
msr = msr_read(MSR_PLATFORM_INFO);
|
||||
if (((msr.hi >> 1) & 3) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Use nominal TDP ratio for flex ratio */
|
||||
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
||||
nominal_ratio = msr.lo & 0xff;
|
||||
|
||||
/* See if flex ratio is already set to nominal TDP ratio */
|
||||
if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
|
||||
return 0;
|
||||
|
||||
/* Set flex ratio to nominal TDP ratio */
|
||||
flex_ratio.lo &= ~0xff00;
|
||||
flex_ratio.lo |= nominal_ratio << 8;
|
||||
flex_ratio.lo |= FLEX_RATIO_LOCK;
|
||||
msr_write(MSR_FLEX_RATIO, flex_ratio);
|
||||
|
||||
/* Set flex ratio in soft reset data register bits 11:6 */
|
||||
clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
|
||||
(nominal_ratio & 0x3f) << 6);
|
||||
|
||||
debug("CPU: Soft reset to set up flex ratio\n");
|
||||
|
||||
/* Set soft reset control to use register value */
|
||||
setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
|
||||
|
||||
/* Issue warm reset, will be "CPU only" due to soft reset data */
|
||||
outb(0x0, IO_PORT_RESET);
|
||||
outb(SYS_RST | RST_CPU, IO_PORT_RESET);
|
||||
cpu_hlt();
|
||||
|
||||
/* Not reached */
|
||||
return -EINVAL;
|
||||
}
|
||||
100
u-boot/arch/x86/cpu/intel_common/lpc.c
Normal file
100
u-boot/arch/x86/cpu/intel_common/lpc.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <pch.h>
|
||||
#include <pci.h>
|
||||
#include <asm/intel_regs.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/lpc_common.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* Enable Prefetching and Caching */
|
||||
static void enable_spi_prefetch(struct udevice *pch)
|
||||
{
|
||||
u8 reg8;
|
||||
|
||||
dm_pci_read_config8(pch, 0xdc, ®8);
|
||||
reg8 &= ~(3 << 2);
|
||||
reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
|
||||
dm_pci_write_config8(pch, 0xdc, reg8);
|
||||
}
|
||||
|
||||
static void enable_port80_on_lpc(struct udevice *pch)
|
||||
{
|
||||
/* Enable port 80 POST on LPC */
|
||||
dm_pci_write_config32(pch, PCH_RCBA_BASE, RCB_BASE_ADDRESS | 1);
|
||||
clrbits_le32(RCB_REG(GCS), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpc_early_init() - set up LPC serial ports and other early things
|
||||
*
|
||||
* @dev: LPC device
|
||||
* @return 0 if OK, -ve on error
|
||||
*/
|
||||
int lpc_common_early_init(struct udevice *dev)
|
||||
{
|
||||
struct udevice *pch = dev->parent;
|
||||
struct reg_info {
|
||||
u32 base;
|
||||
u32 size;
|
||||
} values[4], *ptr;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
count = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset,
|
||||
"intel,gen-dec", (u32 *)values,
|
||||
sizeof(values) / sizeof(u32));
|
||||
if (count < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set COM1/COM2 decode range */
|
||||
dm_pci_write_config16(pch, LPC_IO_DEC, 0x0010);
|
||||
|
||||
/* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */
|
||||
dm_pci_write_config16(pch, LPC_EN, KBC_LPC_EN | MC_LPC_EN |
|
||||
GAMEL_LPC_EN | COMA_LPC_EN);
|
||||
|
||||
/* Write all registers but use 0 if we run out of data */
|
||||
count = count * sizeof(u32) / sizeof(values[0]);
|
||||
for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) {
|
||||
u32 reg = 0;
|
||||
|
||||
if (i < count)
|
||||
reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16);
|
||||
dm_pci_write_config32(pch, LPC_GENX_DEC(i), reg);
|
||||
}
|
||||
|
||||
enable_spi_prefetch(pch);
|
||||
|
||||
/* This is already done in start.S, but let's do it in C */
|
||||
enable_port80_on_lpc(pch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lpc_set_spi_protect(struct udevice *dev, int bios_ctrl, bool protect)
|
||||
{
|
||||
uint8_t bios_cntl;
|
||||
|
||||
/* Adjust the BIOS write protect and SMM BIOS Write Protect Disable */
|
||||
dm_pci_read_config8(dev, bios_ctrl, &bios_cntl);
|
||||
if (protect) {
|
||||
bios_cntl &= ~BIOS_CTRL_BIOSWE;
|
||||
bios_cntl |= BIT(5);
|
||||
} else {
|
||||
bios_cntl |= BIOS_CTRL_BIOSWE;
|
||||
bios_cntl &= ~BIT(5);
|
||||
}
|
||||
dm_pci_write_config8(dev, bios_ctrl, bios_cntl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
213
u-boot/arch/x86/cpu/intel_common/me_status.c
Normal file
213
u-boot/arch/x86/cpu/intel_common/me_status.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* From Coreboot src/southbridge/intel/bd82x6x/me_status.c
|
||||
*
|
||||
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/me.h>
|
||||
|
||||
/* HFS1[3:0] Current Working State Values */
|
||||
static const char *const me_cws_values[] = {
|
||||
[ME_HFS_CWS_RESET] = "Reset",
|
||||
[ME_HFS_CWS_INIT] = "Initializing",
|
||||
[ME_HFS_CWS_REC] = "Recovery",
|
||||
[ME_HFS_CWS_NORMAL] = "Normal",
|
||||
[ME_HFS_CWS_WAIT] = "Platform Disable Wait",
|
||||
[ME_HFS_CWS_TRANS] = "OP State Transition",
|
||||
[ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In"
|
||||
};
|
||||
|
||||
/* HFS1[8:6] Current Operation State Values */
|
||||
static const char *const me_opstate_values[] = {
|
||||
[ME_HFS_STATE_PREBOOT] = "Preboot",
|
||||
[ME_HFS_STATE_M0_UMA] = "M0 with UMA",
|
||||
[ME_HFS_STATE_M3] = "M3 without UMA",
|
||||
[ME_HFS_STATE_M0] = "M0 without UMA",
|
||||
[ME_HFS_STATE_BRINGUP] = "Bring up",
|
||||
[ME_HFS_STATE_ERROR] = "M0 without UMA but with error"
|
||||
};
|
||||
|
||||
/* HFS[19:16] Current Operation Mode Values */
|
||||
static const char *const me_opmode_values[] = {
|
||||
[ME_HFS_MODE_NORMAL] = "Normal",
|
||||
[ME_HFS_MODE_DEBUG] = "Debug",
|
||||
[ME_HFS_MODE_DIS] = "Soft Temporary Disable",
|
||||
[ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper",
|
||||
[ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message"
|
||||
};
|
||||
|
||||
/* HFS[15:12] Error Code Values */
|
||||
static const char *const me_error_values[] = {
|
||||
[ME_HFS_ERROR_NONE] = "No Error",
|
||||
[ME_HFS_ERROR_UNCAT] = "Uncategorized Failure",
|
||||
[ME_HFS_ERROR_IMAGE] = "Image Failure",
|
||||
[ME_HFS_ERROR_DEBUG] = "Debug Failure"
|
||||
};
|
||||
|
||||
/* GMES[31:28] ME Progress Code */
|
||||
static const char *const me_progress_values[] = {
|
||||
[ME_GMES_PHASE_ROM] = "ROM Phase",
|
||||
[ME_GMES_PHASE_BUP] = "BUP Phase",
|
||||
[ME_GMES_PHASE_UKERNEL] = "uKernel Phase",
|
||||
[ME_GMES_PHASE_POLICY] = "Policy Module",
|
||||
[ME_GMES_PHASE_MODULE] = "Module Loading",
|
||||
[ME_GMES_PHASE_UNKNOWN] = "Unknown",
|
||||
[ME_GMES_PHASE_HOST] = "Host Communication"
|
||||
};
|
||||
|
||||
/* GMES[27:24] Power Management Event */
|
||||
static const char *const me_pmevent_values[] = {
|
||||
[0x00] = "Clean Moff->Mx wake",
|
||||
[0x01] = "Moff->Mx wake after an error",
|
||||
[0x02] = "Clean global reset",
|
||||
[0x03] = "Global reset after an error",
|
||||
[0x04] = "Clean Intel ME reset",
|
||||
[0x05] = "Intel ME reset due to exception",
|
||||
[0x06] = "Pseudo-global reset",
|
||||
[0x07] = "S0/M0->Sx/M3",
|
||||
[0x08] = "Sx/M3->S0/M0",
|
||||
[0x09] = "Non-power cycle reset",
|
||||
[0x0a] = "Power cycle reset through M3",
|
||||
[0x0b] = "Power cycle reset through Moff",
|
||||
[0x0c] = "Sx/Mx->Sx/Moff"
|
||||
};
|
||||
|
||||
/* Progress Code 0 states */
|
||||
static const char *const me_progress_rom_values[] = {
|
||||
[0x00] = "BEGIN",
|
||||
[0x06] = "DISABLE"
|
||||
};
|
||||
|
||||
/* Progress Code 1 states */
|
||||
static const char *const me_progress_bup_values[] = {
|
||||
[0x00] = "Initialization starts",
|
||||
[0x01] = "Disable the host wake event",
|
||||
[0x04] = "Flow determination start process",
|
||||
[0x08] = "Error reading/matching the VSCC table in the descriptor",
|
||||
[0x0a] = "Check to see if straps say ME DISABLED",
|
||||
[0x0b] = "Timeout waiting for PWROK",
|
||||
[0x0d] = "Possibly handle BUP manufacturing override strap",
|
||||
[0x11] = "Bringup in M3",
|
||||
[0x12] = "Bringup in M0",
|
||||
[0x13] = "Flow detection error",
|
||||
[0x15] = "M3 clock switching error",
|
||||
[0x18] = "M3 kernel load",
|
||||
[0x1c] = "T34 missing - cannot program ICC",
|
||||
[0x1f] = "Waiting for DID BIOS message",
|
||||
[0x20] = "Waiting for DID BIOS message failure",
|
||||
[0x21] = "DID reported an error",
|
||||
[0x22] = "Enabling UMA",
|
||||
[0x23] = "Enabling UMA error",
|
||||
[0x24] = "Sending DID Ack to BIOS",
|
||||
[0x25] = "Sending DID Ack to BIOS error",
|
||||
[0x26] = "Switching clocks in M0",
|
||||
[0x27] = "Switching clocks in M0 error",
|
||||
[0x28] = "ME in temp disable",
|
||||
[0x32] = "M0 kernel load",
|
||||
};
|
||||
|
||||
/* Progress Code 3 states */
|
||||
static const char *const me_progress_policy_values[] = {
|
||||
[0x00] = "Entery into Policy Module",
|
||||
[0x03] = "Received S3 entry",
|
||||
[0x04] = "Received S4 entry",
|
||||
[0x05] = "Received S5 entry",
|
||||
[0x06] = "Received UPD entry",
|
||||
[0x07] = "Received PCR entry",
|
||||
[0x08] = "Received NPCR entry",
|
||||
[0x09] = "Received host wake",
|
||||
[0x0a] = "Received AC<>DC switch",
|
||||
[0x0b] = "Received DRAM Init Done",
|
||||
[0x0c] = "VSCC Data not found for flash device",
|
||||
[0x0d] = "VSCC Table is not valid",
|
||||
[0x0e] = "Flash Partition Boundary is outside address space",
|
||||
[0x0f] = "ME cannot access the chipset descriptor region",
|
||||
[0x10] = "Required VSCC values for flash parts do not match",
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* _intel_me_status() - Check Intel Management Engine status
|
||||
*
|
||||
* struct hfs: Firmware status
|
||||
* struct gmes: Management engine status
|
||||
*/
|
||||
static void _intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes)
|
||||
{
|
||||
/* Check Current States */
|
||||
debug("ME: FW Partition Table : %s\n",
|
||||
hfs->fpt_bad ? "BAD" : "OK");
|
||||
debug("ME: Bringup Loader Failure : %s\n",
|
||||
hfs->ft_bup_ld_flr ? "YES" : "NO");
|
||||
debug("ME: Firmware Init Complete : %s\n",
|
||||
hfs->fw_init_complete ? "YES" : "NO");
|
||||
debug("ME: Manufacturing Mode : %s\n",
|
||||
hfs->mfg_mode ? "YES" : "NO");
|
||||
debug("ME: Boot Options Present : %s\n",
|
||||
hfs->boot_options_present ? "YES" : "NO");
|
||||
debug("ME: Update In Progress : %s\n",
|
||||
hfs->update_in_progress ? "YES" : "NO");
|
||||
debug("ME: Current Working State : %s\n",
|
||||
me_cws_values[hfs->working_state]);
|
||||
debug("ME: Current Operation State : %s\n",
|
||||
me_opstate_values[hfs->operation_state]);
|
||||
debug("ME: Current Operation Mode : %s\n",
|
||||
me_opmode_values[hfs->operation_mode]);
|
||||
debug("ME: Error Code : %s\n",
|
||||
me_error_values[hfs->error_code]);
|
||||
debug("ME: Progress Phase : %s\n",
|
||||
me_progress_values[gmes->progress_code]);
|
||||
debug("ME: Power Management Event : %s\n",
|
||||
me_pmevent_values[gmes->current_pmevent]);
|
||||
|
||||
debug("ME: Progress Phase State : ");
|
||||
switch (gmes->progress_code) {
|
||||
case ME_GMES_PHASE_ROM: /* ROM Phase */
|
||||
debug("%s", me_progress_rom_values[gmes->current_state]);
|
||||
break;
|
||||
|
||||
case ME_GMES_PHASE_BUP: /* Bringup Phase */
|
||||
if (gmes->current_state < ARRAY_SIZE(me_progress_bup_values) &&
|
||||
me_progress_bup_values[gmes->current_state])
|
||||
debug("%s",
|
||||
me_progress_bup_values[gmes->current_state]);
|
||||
else
|
||||
debug("0x%02x", gmes->current_state);
|
||||
break;
|
||||
|
||||
case ME_GMES_PHASE_POLICY: /* Policy Module Phase */
|
||||
if (gmes->current_state <
|
||||
ARRAY_SIZE(me_progress_policy_values) &&
|
||||
me_progress_policy_values[gmes->current_state])
|
||||
debug("%s",
|
||||
me_progress_policy_values[gmes->current_state]);
|
||||
else
|
||||
debug("0x%02x", gmes->current_state);
|
||||
break;
|
||||
|
||||
case ME_GMES_PHASE_HOST: /* Host Communication Phase */
|
||||
if (!gmes->current_state)
|
||||
debug("Host communication established");
|
||||
else
|
||||
debug("0x%02x", gmes->current_state);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Unknown 0x%02x", gmes->current_state);
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
void intel_me_status(struct udevice *me_dev)
|
||||
{
|
||||
struct me_hfs hfs;
|
||||
struct me_gmes gmes;
|
||||
|
||||
pci_read_dword_ptr(me_dev, &hfs, PCI_ME_HFS);
|
||||
pci_read_dword_ptr(me_dev, &gmes, PCI_ME_GMES);
|
||||
|
||||
_intel_me_status(&hfs, &gmes);
|
||||
}
|
||||
173
u-boot/arch/x86/cpu/intel_common/microcode.c
Normal file
173
u-boot/arch/x86/cpu/intel_common/microcode.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Google, Inc
|
||||
* Copyright (C) 2000 Ronald G. Minnich
|
||||
*
|
||||
* Microcode update for Intel PIII and later CPUs
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <libfdt.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/msr-index.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* struct microcode_update - standard microcode header from Intel
|
||||
*
|
||||
* We read this information out of the device tree and use it to determine
|
||||
* whether the update is applicable or not. We also use the same structure
|
||||
* to read information from the CPU.
|
||||
*/
|
||||
struct microcode_update {
|
||||
uint header_version;
|
||||
uint update_revision;
|
||||
uint date_code;
|
||||
uint processor_signature;
|
||||
uint checksum;
|
||||
uint loader_revision;
|
||||
uint processor_flags;
|
||||
const void *data;
|
||||
int size;
|
||||
};
|
||||
|
||||
static int microcode_decode_node(const void *blob, int node,
|
||||
struct microcode_update *update)
|
||||
{
|
||||
update->data = fdt_getprop(blob, node, "data", &update->size);
|
||||
if (!update->data)
|
||||
return -EINVAL;
|
||||
update->data += UCODE_HEADER_LEN;
|
||||
update->size -= UCODE_HEADER_LEN;
|
||||
|
||||
update->header_version = fdtdec_get_int(blob, node,
|
||||
"intel,header-version", 0);
|
||||
update->update_revision = fdtdec_get_int(blob, node,
|
||||
"intel,update-revision", 0);
|
||||
update->date_code = fdtdec_get_int(blob, node,
|
||||
"intel,date-code", 0);
|
||||
update->processor_signature = fdtdec_get_int(blob, node,
|
||||
"intel,processor-signature", 0);
|
||||
update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0);
|
||||
update->loader_revision = fdtdec_get_int(blob, node,
|
||||
"intel,loader-revision", 0);
|
||||
update->processor_flags = fdtdec_get_int(blob, node,
|
||||
"intel,processor-flags", 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int microcode_read_rev(void)
|
||||
{
|
||||
/* Quark does not have microcode MSRs */
|
||||
#ifdef CONFIG_INTEL_QUARK
|
||||
return 0;
|
||||
#else
|
||||
/*
|
||||
* Some Intel CPUs can be very finicky about the CPUID sequence used.
|
||||
* So this is implemented in assembly so that it works reliably.
|
||||
*/
|
||||
uint32_t low, high;
|
||||
|
||||
asm volatile (
|
||||
"xorl %%eax, %%eax\n"
|
||||
"xorl %%edx, %%edx\n"
|
||||
"movl %2, %%ecx\n"
|
||||
"wrmsr\n"
|
||||
"movl $0x01, %%eax\n"
|
||||
"cpuid\n"
|
||||
"movl %2, %%ecx\n"
|
||||
"rdmsr\n"
|
||||
: /* outputs */
|
||||
"=a" (low), "=d" (high)
|
||||
: /* inputs */
|
||||
"i" (MSR_IA32_UCODE_REV)
|
||||
: /* clobbers */
|
||||
"ebx", "ecx"
|
||||
);
|
||||
|
||||
return high;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void microcode_read_cpu(struct microcode_update *cpu)
|
||||
{
|
||||
/* CPUID sets MSR 0x8B iff a microcode update has been loaded. */
|
||||
unsigned int x86_model, x86_family;
|
||||
struct cpuid_result result;
|
||||
uint32_t low, high;
|
||||
|
||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
||||
result = cpuid(1);
|
||||
rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision);
|
||||
x86_model = (result.eax >> 4) & 0x0f;
|
||||
x86_family = (result.eax >> 8) & 0x0f;
|
||||
cpu->processor_signature = result.eax;
|
||||
|
||||
cpu->processor_flags = 0;
|
||||
if ((x86_model >= 5) || (x86_family > 6)) {
|
||||
rdmsr(0x17, low, high);
|
||||
cpu->processor_flags = 1 << ((high >> 18) & 7);
|
||||
}
|
||||
debug("microcode: sig=%#x pf=%#x revision=%#x\n",
|
||||
cpu->processor_signature, cpu->processor_flags,
|
||||
cpu->update_revision);
|
||||
}
|
||||
|
||||
/* Get a microcode update from the device tree and apply it */
|
||||
int microcode_update_intel(void)
|
||||
{
|
||||
struct microcode_update cpu, update;
|
||||
const void *blob = gd->fdt_blob;
|
||||
int skipped;
|
||||
int count;
|
||||
int node;
|
||||
int ret;
|
||||
int rev;
|
||||
|
||||
microcode_read_cpu(&cpu);
|
||||
node = 0;
|
||||
count = 0;
|
||||
skipped = 0;
|
||||
do {
|
||||
node = fdtdec_next_compatible(blob, node,
|
||||
COMPAT_INTEL_MICROCODE);
|
||||
if (node < 0) {
|
||||
debug("%s: Found %d updates\n", __func__, count);
|
||||
return count ? 0 : skipped ? -EEXIST : -ENOENT;
|
||||
}
|
||||
|
||||
ret = microcode_decode_node(blob, node, &update);
|
||||
if (ret) {
|
||||
debug("%s: Unable to decode update: %d\n", __func__,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
if (!(update.processor_signature == cpu.processor_signature &&
|
||||
(update.processor_flags & cpu.processor_flags))) {
|
||||
debug("%s: Skipping non-matching update, sig=%x, pf=%x\n",
|
||||
__func__, update.processor_signature,
|
||||
update.processor_flags);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0);
|
||||
rev = microcode_read_rev();
|
||||
debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
|
||||
rev, update.date_code & 0xffff,
|
||||
(update.date_code >> 24) & 0xff,
|
||||
(update.date_code >> 16) & 0xff);
|
||||
if (update.update_revision != rev) {
|
||||
printf("Microcode update failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
count++;
|
||||
} while (1);
|
||||
}
|
||||
271
u-boot/arch/x86/cpu/intel_common/mrc.c
Normal file
271
u-boot/arch/x86/cpu/intel_common/mrc.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <syscon.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/intel_regs.h>
|
||||
#include <asm/mrc_common.h>
|
||||
#include <asm/pch_common.h>
|
||||
#include <asm/post.h>
|
||||
#include <asm/arch/me.h>
|
||||
#include <asm/report_platform.h>
|
||||
|
||||
static const char *const ecc_decoder[] = {
|
||||
"inactive",
|
||||
"active on IO",
|
||||
"disabled on IO",
|
||||
"active"
|
||||
};
|
||||
|
||||
ulong mrc_common_board_get_usable_ram_top(ulong total_size)
|
||||
{
|
||||
struct memory_info *info = &gd->arch.meminfo;
|
||||
uintptr_t dest_addr = 0;
|
||||
struct memory_area *largest = NULL;
|
||||
int i;
|
||||
|
||||
/* Find largest area of memory below 4GB */
|
||||
|
||||
for (i = 0; i < info->num_areas; i++) {
|
||||
struct memory_area *area = &info->area[i];
|
||||
|
||||
if (area->start >= 1ULL << 32)
|
||||
continue;
|
||||
if (!largest || area->size > largest->size)
|
||||
largest = area;
|
||||
}
|
||||
|
||||
/* If no suitable area was found, return an error. */
|
||||
assert(largest);
|
||||
if (!largest || largest->size < (2 << 20))
|
||||
panic("No available memory found for relocation");
|
||||
|
||||
dest_addr = largest->start + largest->size;
|
||||
|
||||
return (ulong)dest_addr;
|
||||
}
|
||||
|
||||
void mrc_common_dram_init_banksize(void)
|
||||
{
|
||||
struct memory_info *info = &gd->arch.meminfo;
|
||||
int num_banks;
|
||||
int i;
|
||||
|
||||
for (i = 0, num_banks = 0; i < info->num_areas; i++) {
|
||||
struct memory_area *area = &info->area[i];
|
||||
|
||||
if (area->start >= 1ULL << 32)
|
||||
continue;
|
||||
gd->bd->bi_dram[num_banks].start = area->start;
|
||||
gd->bd->bi_dram[num_banks].size = area->size;
|
||||
num_banks++;
|
||||
}
|
||||
}
|
||||
|
||||
int mrc_add_memory_area(struct memory_info *info, uint64_t start,
|
||||
uint64_t end)
|
||||
{
|
||||
struct memory_area *ptr;
|
||||
|
||||
if (info->num_areas == CONFIG_NR_DRAM_BANKS)
|
||||
return -ENOSPC;
|
||||
|
||||
ptr = &info->area[info->num_areas];
|
||||
ptr->start = start;
|
||||
ptr->size = end - start;
|
||||
info->total_memory += ptr->size;
|
||||
if (ptr->start < (1ULL << 32))
|
||||
info->total_32bit_memory += ptr->size;
|
||||
debug("%d: memory %llx size %llx, total now %llx / %llx\n",
|
||||
info->num_areas, ptr->start, ptr->size,
|
||||
info->total_32bit_memory, info->total_memory);
|
||||
info->num_areas++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump in the log memory controller configuration as read from the memory
|
||||
* controller registers.
|
||||
*/
|
||||
void report_memory_config(void)
|
||||
{
|
||||
u32 addr_decoder_common, addr_decode_ch[2];
|
||||
int i;
|
||||
|
||||
addr_decoder_common = readl(MCHBAR_REG(0x5000));
|
||||
addr_decode_ch[0] = readl(MCHBAR_REG(0x5004));
|
||||
addr_decode_ch[1] = readl(MCHBAR_REG(0x5008));
|
||||
|
||||
debug("memcfg DDR3 clock %d MHz\n",
|
||||
(readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100);
|
||||
debug("memcfg channel assignment: A: %d, B % d, C % d\n",
|
||||
addr_decoder_common & 3,
|
||||
(addr_decoder_common >> 2) & 3,
|
||||
(addr_decoder_common >> 4) & 3);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
|
||||
u32 ch_conf = addr_decode_ch[i];
|
||||
debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf);
|
||||
debug(" ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]);
|
||||
debug(" enhanced interleave mode %s\n",
|
||||
((ch_conf >> 22) & 1) ? "on" : "off");
|
||||
debug(" rank interleave %s\n",
|
||||
((ch_conf >> 21) & 1) ? "on" : "off");
|
||||
debug(" DIMMA %d MB width x%d %s rank%s\n",
|
||||
((ch_conf >> 0) & 0xff) * 256,
|
||||
((ch_conf >> 19) & 1) ? 16 : 8,
|
||||
((ch_conf >> 17) & 1) ? "dual" : "single",
|
||||
((ch_conf >> 16) & 1) ? "" : ", selected");
|
||||
debug(" DIMMB %d MB width x%d %s rank%s\n",
|
||||
((ch_conf >> 8) & 0xff) * 256,
|
||||
((ch_conf >> 20) & 1) ? 16 : 8,
|
||||
((ch_conf >> 18) & 1) ? "dual" : "single",
|
||||
((ch_conf >> 16) & 1) ? ", selected" : "");
|
||||
}
|
||||
}
|
||||
|
||||
int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap)
|
||||
{
|
||||
const void *blob = gd->fdt_blob;
|
||||
int spd_index;
|
||||
struct gpio_desc desc[4];
|
||||
int spd_node;
|
||||
int node;
|
||||
int ret;
|
||||
|
||||
ret = gpio_request_list_by_name(dev, "board-id-gpios", desc,
|
||||
ARRAY_SIZE(desc), GPIOD_IS_IN);
|
||||
if (ret < 0) {
|
||||
debug("%s: gpio ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
spd_index = dm_gpio_get_values_as_int(desc, ret);
|
||||
debug("spd index %d\n", spd_index);
|
||||
|
||||
node = fdt_first_subnode(blob, dev->of_offset);
|
||||
if (node < 0)
|
||||
return -EINVAL;
|
||||
for (spd_node = fdt_first_subnode(blob, node);
|
||||
spd_node > 0;
|
||||
spd_node = fdt_next_subnode(blob, spd_node)) {
|
||||
int len;
|
||||
|
||||
if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index)
|
||||
continue;
|
||||
*spd_datap = fdt_getprop(blob, spd_node, "data", &len);
|
||||
if (len < size) {
|
||||
printf("Missing SPD data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
debug("Using SDRAM SPD data for '%s'\n",
|
||||
fdt_get_name(blob, spd_node, NULL));
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("No SPD data found for index %d\n", spd_index);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
asmlinkage void sdram_console_tx_byte(unsigned char byte)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
putc(byte);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the PEI executable in the ROM and execute it.
|
||||
*
|
||||
* @me_dev: Management Engine device
|
||||
* @pei_data: configuration data for UEFI PEI reference code
|
||||
*/
|
||||
static int sdram_initialise(struct udevice *dev, struct udevice *me_dev,
|
||||
void *pei_data, bool use_asm_linkage)
|
||||
{
|
||||
unsigned version;
|
||||
const char *data;
|
||||
|
||||
report_platform_info(dev);
|
||||
debug("Starting UEFI PEI System Agent\n");
|
||||
|
||||
debug("PEI data at %p:\n", pei_data);
|
||||
|
||||
data = (char *)CONFIG_X86_MRC_ADDR;
|
||||
if (data) {
|
||||
int rv;
|
||||
ulong start;
|
||||
|
||||
debug("Calling MRC at %p\n", data);
|
||||
post_code(POST_PRE_MRC);
|
||||
start = get_timer(0);
|
||||
if (use_asm_linkage) {
|
||||
asmlinkage int (*func)(void *);
|
||||
|
||||
func = (asmlinkage int (*)(void *))data;
|
||||
rv = func(pei_data);
|
||||
} else {
|
||||
int (*func)(void *);
|
||||
|
||||
func = (int (*)(void *))data;
|
||||
rv = func(pei_data);
|
||||
}
|
||||
post_code(POST_MRC);
|
||||
if (rv) {
|
||||
switch (rv) {
|
||||
case -1:
|
||||
printf("PEI version mismatch.\n");
|
||||
break;
|
||||
case -2:
|
||||
printf("Invalid memory frequency.\n");
|
||||
break;
|
||||
default:
|
||||
printf("MRC returned %x.\n", rv);
|
||||
}
|
||||
printf("Nonzero MRC return value.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
debug("MRC execution time %lu ms\n", get_timer(start));
|
||||
} else {
|
||||
printf("UEFI PEI System Agent not found.\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
version = readl(MCHBAR_REG(MCHBAR_PEI_VERSION));
|
||||
debug("System Agent Version %d.%d.%d Build %d\n",
|
||||
version >> 24 , (version >> 16) & 0xff,
|
||||
(version >> 8) & 0xff, version & 0xff);
|
||||
|
||||
#if CONFIG_USBDEBUG
|
||||
/* mrc.bin reconfigures USB, so reinit it to have debug */
|
||||
early_usbdebug_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mrc_common_init(struct udevice *dev, void *pei_data, bool use_asm_linkage)
|
||||
{
|
||||
struct udevice *me_dev;
|
||||
int ret;
|
||||
|
||||
ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sdram_initialise(dev, me_dev, pei_data, use_asm_linkage);
|
||||
if (ret)
|
||||
return ret;
|
||||
quick_ram_check();
|
||||
post_code(POST_DRAM);
|
||||
report_memory_config();
|
||||
|
||||
return 0;
|
||||
}
|
||||
25
u-boot/arch/x86/cpu/intel_common/pch.c
Normal file
25
u-boot/arch/x86/cpu/intel_common/pch.c
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/pch_common.h>
|
||||
|
||||
u32 pch_common_sir_read(struct udevice *dev, int idx)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
dm_pci_write_config32(dev, SATA_SIRI, idx);
|
||||
dm_pci_read_config32(dev, SATA_SIRD, &data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void pch_common_sir_write(struct udevice *dev, int idx, u32 value)
|
||||
{
|
||||
dm_pci_write_config32(dev, SATA_SIRI, idx);
|
||||
dm_pci_write_config32(dev, SATA_SIRD, value);
|
||||
}
|
||||
90
u-boot/arch/x86/cpu/intel_common/report_platform.c
Normal file
90
u-boot/arch/x86/cpu/intel_common/report_platform.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* From Coreboot src/northbridge/intel/sandybridge/report_platform.c
|
||||
*
|
||||
* Copyright (C) 2012 Google Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/pci.h>
|
||||
#include <asm/report_platform.h>
|
||||
#include <asm/arch/pch.h>
|
||||
|
||||
static void report_cpu_info(void)
|
||||
{
|
||||
char cpu_string[CPU_MAX_NAME_LEN], *cpu_name;
|
||||
const char *mode[] = {"NOT ", ""};
|
||||
struct cpuid_result cpuidr;
|
||||
int vt, txt, aes;
|
||||
u32 index;
|
||||
|
||||
index = 0x80000000;
|
||||
cpuidr = cpuid(index);
|
||||
if (cpuidr.eax < 0x80000004) {
|
||||
strcpy(cpu_string, "Platform info not available");
|
||||
cpu_name = cpu_string;
|
||||
} else {
|
||||
cpu_name = cpu_get_name(cpu_string);
|
||||
}
|
||||
|
||||
cpuidr = cpuid(1);
|
||||
debug("CPU id(%x): %s\n", cpuidr.eax, cpu_name);
|
||||
aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0;
|
||||
txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0;
|
||||
vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0;
|
||||
debug("AES %ssupported, TXT %ssupported, VT %ssupported\n",
|
||||
mode[aes], mode[txt], mode[vt]);
|
||||
}
|
||||
|
||||
/* The PCI id name match comes from Intel document 472178 */
|
||||
static struct {
|
||||
u16 dev_id;
|
||||
const char *dev_name;
|
||||
} pch_table[] = {
|
||||
{0x1E41, "Desktop Sample"},
|
||||
{0x1E42, "Mobile Sample"},
|
||||
{0x1E43, "SFF Sample"},
|
||||
{0x1E44, "Z77"},
|
||||
{0x1E45, "H71"},
|
||||
{0x1E46, "Z75"},
|
||||
{0x1E47, "Q77"},
|
||||
{0x1E48, "Q75"},
|
||||
{0x1E49, "B75"},
|
||||
{0x1E4A, "H77"},
|
||||
{0x1E53, "C216"},
|
||||
{0x1E55, "QM77"},
|
||||
{0x1E56, "QS77"},
|
||||
{0x1E58, "UM77"},
|
||||
{0x1E57, "HM77"},
|
||||
{0x1E59, "HM76"},
|
||||
{0x1E5D, "HM75"},
|
||||
{0x1E5E, "HM70"},
|
||||
{0x1E5F, "NM70"},
|
||||
};
|
||||
|
||||
static void report_pch_info(struct udevice *dev)
|
||||
{
|
||||
const char *pch_type = "Unknown";
|
||||
int i;
|
||||
u16 dev_id;
|
||||
uint8_t rev_id;
|
||||
|
||||
dm_pci_read_config16(dev, 2, &dev_id);
|
||||
for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
|
||||
if (pch_table[i].dev_id == dev_id) {
|
||||
pch_type = pch_table[i].dev_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dm_pci_read_config8(dev, 8, &rev_id);
|
||||
debug("PCH type: %s, device id: %x, rev id %x\n", pch_type, dev_id,
|
||||
rev_id);
|
||||
}
|
||||
|
||||
void report_platform_info(struct udevice *dev)
|
||||
{
|
||||
report_cpu_info();
|
||||
report_pch_info(dev);
|
||||
}
|
||||
Reference in New Issue
Block a user