Merge git://git.denx.de/u-boot-x86

This commit is contained in:
Tom Rini 2015-01-13 13:39:25 -05:00
commit 5f88ed5cde
58 changed files with 1412 additions and 711 deletions

View File

@ -47,13 +47,10 @@ config RAMBASE
hex
default 0x100000
config RAMTOP
hex
default 0x200000
config XIP_ROM_SIZE
hex
default 0x10000
depends on X86_RESET_VECTOR
default ROM_SIZE
config CPU_ADDR_BITS
int
@ -70,6 +67,15 @@ config SMM_TSEG
config SMM_TSEG_SIZE
hex
config X86_RESET_VECTOR
bool
default n
config SYS_X86_START16
hex
depends on X86_RESET_VECTOR
default 0xfffff800
config BOARD_ROMSIZE_KB_512
bool
config BOARD_ROMSIZE_KB_1024
@ -85,6 +91,7 @@ config BOARD_ROMSIZE_KB_16384
choice
prompt "ROM chip size"
depends on X86_RESET_VECTOR
default UBOOT_ROMSIZE_KB_512 if BOARD_ROMSIZE_KB_512
default UBOOT_ROMSIZE_KB_1024 if BOARD_ROMSIZE_KB_1024
default UBOOT_ROMSIZE_KB_2048 if BOARD_ROMSIZE_KB_2048
@ -317,6 +324,28 @@ config FRAMEBUFFER_VESA_MODE
endmenu
config TSC_CALIBRATION_BYPASS
bool "Bypass Time-Stamp Counter (TSC) calibration"
default n
help
By default U-Boot automatically calibrates Time-Stamp Counter (TSC)
running frequency via Model-Specific Register (MSR) and Programmable
Interval Timer (PIT). If the calibration does not work on your board,
select this option and provide a hardcoded TSC running frequency with
CONFIG_TSC_FREQ_IN_MHZ below.
Normally this option should be turned on in a simulation environment
like qemu.
config TSC_FREQ_IN_MHZ
int "Time-Stamp Counter (TSC) running frequency in MHz"
depends on TSC_CALIBRATION_BYPASS
default 1000
help
The running frequency in MHz of Time-Stamp Counter (TSC).
source "arch/x86/cpu/coreboot/Kconfig"
source "arch/x86/cpu/ivybridge/Kconfig"
source "arch/x86/cpu/queensbay/Kconfig"

View File

@ -17,5 +17,6 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-y += lapic.o
obj-y += mtrr.o
obj-$(CONFIG_PCI) += pci.o
obj-y += turbo.o

View File

@ -0,0 +1,15 @@
if TARGET_COREBOOT
config SYS_COREBOOT
bool
default y
config CBMEM_CONSOLE
bool
default y
config VIDEO_COREBOOT
bool
default y
endif

View File

@ -15,6 +15,7 @@
#include <asm/cache.h>
#include <asm/cpu.h>
#include <asm/io.h>
#include <asm/mtrr.h>
#include <asm/arch/tables.h>
#include <asm/arch/sysinfo.h>
#include <asm/arch/timestamp.h>
@ -64,11 +65,6 @@ int board_eth_init(bd_t *bis)
return pci_eth_init(bis);
}
#define MTRR_TYPE_WP 5
#define MTRRcap_MSR 0xfe
#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
void board_final_cleanup(void)
{
/* Un-cache the ROM so the kernel has one
@ -77,15 +73,17 @@ void board_final_cleanup(void)
* Coreboot should have assigned this to the
* top available variable MTRR.
*/
u8 top_mtrr = (native_read_msr(MTRRcap_MSR) & 0xff) - 1;
u8 top_type = native_read_msr(MTRRphysBase_MSR(top_mtrr)) & 0xff;
u8 top_mtrr = (native_read_msr(MTRR_CAP_MSR) & 0xff) - 1;
u8 top_type = native_read_msr(MTRR_PHYS_BASE_MSR(top_mtrr)) & 0xff;
/* Make sure this MTRR is the correct Write-Protected type */
if (top_type == MTRR_TYPE_WP) {
disable_caches();
wrmsrl(MTRRphysBase_MSR(top_mtrr), 0);
wrmsrl(MTRRphysMask_MSR(top_mtrr), 0);
enable_caches();
if (top_type == MTRR_TYPE_WRPROT) {
struct mtrr_state state;
mtrr_open(&state);
wrmsrl(MTRR_PHYS_BASE_MSR(top_mtrr), 0);
wrmsrl(MTRR_PHYS_MASK_MSR(top_mtrr), 0);
mtrr_close(&state);
}
/* Issue SMI to Coreboot to lock down ME and registers */

View File

@ -13,6 +13,8 @@
#include <pci.h>
#include <asm/pci.h>
DECLARE_GLOBAL_DATA_PTR;
static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev,
struct pci_config_table *table)
{
@ -35,7 +37,31 @@ void board_pci_setup_hose(struct pci_controller *hose)
hose->first_busno = 0;
hose->last_busno = 0;
pci_set_region(hose->regions + 0, 0x0, 0x0, 0xffffffff,
/* PCI memory space */
pci_set_region(hose->regions + 0,
CONFIG_PCI_MEM_BUS,
CONFIG_PCI_MEM_PHYS,
CONFIG_PCI_MEM_SIZE,
PCI_REGION_MEM);
hose->region_count = 1;
/* PCI IO space */
pci_set_region(hose->regions + 1,
CONFIG_PCI_IO_BUS,
CONFIG_PCI_IO_PHYS,
CONFIG_PCI_IO_SIZE,
PCI_REGION_IO);
pci_set_region(hose->regions + 2,
CONFIG_PCI_PREF_BUS,
CONFIG_PCI_PREF_PHYS,
CONFIG_PCI_PREF_SIZE,
PCI_REGION_PREFETCH);
pci_set_region(hose->regions + 3,
0,
0,
gd->ram_size,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
hose->region_count = 4;
}

View File

@ -3,18 +3,7 @@
*
* Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
@ -38,9 +27,27 @@ static struct timestamp_table *ts_table __attribute__((section(".data")));
void timestamp_init(void)
{
#ifdef CONFIG_SYS_X86_TSC_TIMER
uint64_t base_time;
#endif
ts_table = lib_sysinfo.tstamp_table;
#ifdef CONFIG_SYS_X86_TSC_TIMER
timer_set_base(ts_table->base_time);
/*
* If coreboot is built with CONFIG_COLLECT_TIMESTAMPS, use the value
* of base_time in coreboot's timestamp table as our timer base,
* otherwise TSC counter value will be used.
*
* Sometimes even coreboot is built with CONFIG_COLLECT_TIMESTAMPS,
* the value of base_time in the timestamp table is still zero, so
* we must exclude this case too (this is currently seen on booting
* coreboot in qemu)
*/
if (ts_table && ts_table->base_time)
base_time = ts_table->base_time;
else
base_time = rdtsc();
timer_set_base(base_time);
#endif
timestamp_add_now(TS_U_BOOT_INITTED);
}

View File

@ -12,9 +12,11 @@
*/
#include <common.h>
#include <asm/msr-index.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor-flags.h>
#include <asm/arch/microcode.h>
#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
@ -45,6 +47,14 @@ car_init:
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
@ -61,7 +71,7 @@ clear_mtrrs:
post_code(POST_CAR_MTRR)
/* Configure the default memory type to uncacheable */
movl $MTRRdefType_MSR, %ecx
movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
andl $(~0x00000cff), %eax
wrmsr
@ -76,16 +86,16 @@ clear_mtrrs:
post_code(POST_CAR_BASE_ADDRESS)
/* Set Cache-as-RAM mask */
movl $(MTRR_PHYS_MASK_MSR(0)), %ecx
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
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 $MTRRdefType_MSR, %ecx
movl $MTRR_DEF_TYPE_MSR, %ecx
rdmsr
orl $MTRRdefTypeEn, %eax
orl $MTRR_DEF_TYPE_EN, %eax
wrmsr
/* Enable cache (CR0.CD = 0, CR0.NW = 0) */
@ -130,7 +140,7 @@ clear_mtrrs:
movl $MTRR_PHYS_MASK_MSR(1), %ecx
movl $CPU_PHYSMASK_HI, %edx
movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
wrmsr
post_code(POST_CAR_ROM_CACHE)
@ -141,7 +151,7 @@ clear_mtrrs:
xorl %edx, %edx
wrmsr
movl $MTRR_PHYS_MASK_MSR(2), %ecx
movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax
movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax
movl $CPU_PHYSMASK_HI, %edx
wrmsr
#endif
@ -163,6 +173,52 @@ 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
@ -176,3 +232,9 @@ mtrr_table:
.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 */
.long 0 /* microcode base */
.long 0 /* microcode size */

View File

@ -49,27 +49,6 @@ static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
}
static void set_var_mtrr(
unsigned reg, unsigned base, unsigned size, unsigned type)
{
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
/* FIXME: It only support 4G less range */
wrmsr(MTRRphysBase_MSR(reg), base | type, 0);
wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid,
(1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1);
}
static void enable_rom_caching(void)
{
disable_caches();
set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT);
enable_caches();
/* Enable Variable MTRRs */
wrmsr(MTRRdefType_MSR, 0x800, 0);
}
static int set_flex_ratio_to_tdp_nominal(void)
{
msr_t flex_ratio, msr;
@ -165,10 +144,6 @@ int arch_cpu_init(void)
/* This is already done in start.S, but let's do it in C */
enable_port80_on_lpc(hose, PCH_LPC_DEV);
/* already done in car.S */
if (false)
enable_rom_caching();
set_spi_speed();
/*
@ -288,7 +263,7 @@ int print_cpuinfo(void)
enable_lapic();
ret = microcode_update_intel();
if (ret && ret != -ENOENT && ret != -EEXIST)
if (ret)
return ret;
/* Enable upper 128bytes of CMOS */

View File

@ -12,9 +12,11 @@
#include <fdtdec.h>
#include <pci_rom.h>
#include <asm/io.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/pch.h>
#include <asm/arch/sandybridge.h>
#include <linux/kconfig.h>
struct gt_powermeter {
u16 reg;
@ -730,7 +732,11 @@ static int int15_handler(void)
int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
const void *blob, int node)
{
#ifdef CONFIG_VIDEO
ulong start;
#endif
void *gtt_bar;
ulong base;
u32 reg32;
int ret;
@ -739,14 +745,22 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
pci_write_config32(dev, PCI_COMMAND, reg32);
/* Use write-combining for the graphics memory, 256MB */
base = pci_read_bar32(hose, dev, 2);
mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20);
mtrr_commit(true);
gtt_bar = (void *)pci_read_bar32(pci_bus_to_hose(0), dev, 0);
debug("GT bar %p\n", gtt_bar);
ret = gma_pm_init_pre_vbios(gtt_bar);
if (ret)
return ret;
#ifdef CONFIG_VIDEO
start = get_timer(0);
ret = pci_run_vga_bios(dev, int15_handler, false);
debug("BIOS ran in %lums\n", get_timer(start));
#endif
/* Post VBIOS init */
ret = gma_pm_init_post_vbios(gtt_bar, blob, node);
if (ret)

View File

@ -13,7 +13,9 @@
#include <libfdt.h>
#include <asm/cpu.h>
#include <asm/msr.h>
#include <asm/msr-index.h>
#include <asm/processor.h>
#include <asm/arch/microcode.h>
/**
* struct microcode_update - standard microcode header from Intel
@ -40,8 +42,8 @@ static int microcode_decode_node(const void *blob, int node,
update->data = fdt_getprop(blob, node, "data", &update->size);
if (!update->data)
return -EINVAL;
update->data += 48;
update->size -= 48;
update->data += UCODE_HEADER_LEN;
update->size -= UCODE_HEADER_LEN;
update->header_version = fdtdec_get_int(blob, node,
"intel,header-version", 0);
@ -71,15 +73,16 @@ static inline uint32_t microcode_read_rev(void)
asm volatile (
"xorl %%eax, %%eax\n"
"xorl %%edx, %%edx\n"
"movl $0x8b, %%ecx\n"
"movl %2, %%ecx\n"
"wrmsr\n"
"movl $0x01, %%eax\n"
"cpuid\n"
"movl $0x8b, %%ecx\n"
"movl %2, %%ecx\n"
"rdmsr\n"
: /* outputs */
"=a" (low), "=d" (high)
: /* inputs */
"i" (MSR_IA32_UCODE_REV)
: /* clobbers */
"ebx", "ecx"
);
@ -94,9 +97,9 @@ static void microcode_read_cpu(struct microcode_update *cpu)
struct cpuid_result result;
uint32_t low, high;
wrmsr(0x8b, 0, 0);
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
result = cpuid(1);
rdmsr(0x8b, low, cpu->update_revision);
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;
@ -120,6 +123,7 @@ int microcode_update_intel(void)
int count;
int node;
int ret;
int rev;
microcode_read_cpu(&cpu);
node = 0;
@ -147,12 +151,16 @@ int microcode_update_intel(void)
skipped++;
continue;
}
ret = microcode_read_rev();
wrmsr(0x79, (ulong)update.data, 0);
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",
microcode_read_rev(), update.date_code & 0xffff,
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);
}

View File

@ -17,6 +17,7 @@
#include <asm/processor.h>
#include <asm/gpio.h>
#include <asm/global_data.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/me.h>
#include <asm/arch/pei_data.h>
@ -430,6 +431,15 @@ static int sdram_find(pci_dev_t dev)
add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28);
add_memory_area(info, (4 << 28) + (2 << 20), tseg_base);
add_memory_area(info, 1ULL << 32, touud);
/* Add MTRRs for memory */
mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30);
mtrr_add_request(MTRR_TYPE_WRBACK, 2ULL << 30, 512 << 20);
mtrr_add_request(MTRR_TYPE_WRBACK, 0xaULL << 28, 256 << 20);
mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base, 16 << 20);
mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base + (16 << 20),
32 << 20);
/*
* If >= 4GB installed then memory from TOLUD to 4GB
* is remapped above TOM, TOUUD will account for both

81
arch/x86/cpu/mtrr.c Normal file
View File

@ -0,0 +1,81 @@
/*
* (C) Copyright 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*
* Memory Type Range Regsters - these are used to tell the CPU whether
* memory is cacheable and if so the cache write mode to use.
*
* These can speed up booting. See the mtrr command.
*
* Reference: Intel Architecture Software Developer's Manual, Volume 3:
* System Programming
*/
#include <common.h>
#include <asm/io.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
/* Prepare to adjust MTRRs */
void mtrr_open(struct mtrr_state *state)
{
state->enable_cache = dcache_status();
if (state->enable_cache)
disable_caches();
state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
}
/* Clean up after adjusting MTRRs, and enable them */
void mtrr_close(struct mtrr_state *state)
{
wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
if (state->enable_cache)
enable_caches();
}
int mtrr_commit(bool do_caches)
{
struct mtrr_request *req = gd->arch.mtrr_req;
struct mtrr_state state;
uint64_t mask;
int i;
mtrr_open(&state);
for (i = 0; i < gd->arch.mtrr_req_count; i++, req++) {
mask = ~(req->size - 1);
mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
wrmsrl(MTRR_PHYS_BASE_MSR(i), req->start | req->type);
wrmsrl(MTRR_PHYS_MASK_MSR(i), mask | MTRR_PHYS_MASK_VALID);
}
/* Clear the ones that are unused */
for (; i < MTRR_COUNT; i++)
wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
mtrr_close(&state);
return 0;
}
int mtrr_add_request(int type, uint64_t start, uint64_t size)
{
struct mtrr_request *req;
uint64_t mask;
if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
return -ENOSPC;
req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
req->type = type;
req->start = start;
req->size = size;
debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1,
req->type, req->start, req->size);
mask = ~(req->size - 1);
mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
mask |= MTRR_PHYS_MASK_VALID;
debug(" %016llx %016llx\n", req->start | req->type, mask);
return 0;
}

View File

@ -15,6 +15,8 @@
#include <pci.h>
#include <asm/pci.h>
DECLARE_GLOBAL_DATA_PTR;
static struct pci_controller x86_hose;
int pci_early_init_hose(struct pci_controller **hosep)
@ -27,7 +29,8 @@ int pci_early_init_hose(struct pci_controller **hosep)
board_pci_setup_hose(hose);
pci_setup_type1(hose);
gd->arch.hose = hose;
hose->last_busno = pci_hose_scan(hose);
gd->hose = hose;
*hosep = hose;
return 0;
@ -48,7 +51,7 @@ void pci_init_board(void)
struct pci_controller *hose = &x86_hose;
/* Stop using the early hose */
gd->arch.hose = NULL;
gd->hose = NULL;
board_pci_setup_hose(hose);
pci_setup_type1(hose);
@ -61,8 +64,8 @@ void pci_init_board(void)
static struct pci_controller *get_hose(void)
{
if (gd->arch.hose)
return gd->arch.hose;
if (gd->hose)
return gd->hose;
return pci_bus_to_hose(0);
}

View File

@ -231,26 +231,28 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
u32 fsp_get_usable_lowmem_top(const void *hob_list)
{
union hob_pointers hob;
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u32 top;
/* Get the HOB list for processing */
hob.raw = (void *)hob_list;
hdr = hob_list;
/* * Collect memory ranges */
top = FSP_LOWMEM_BASE;
while (!end_of_hob(hob)) {
if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
if (hob.res_desc->type == RES_SYS_MEM) {
phys_start = hob.res_desc->phys_start;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_SYS_MEM) {
phys_start = res_desc->phys_start;
/* Need memory above 1MB to be collected here */
if (phys_start >= FSP_LOWMEM_BASE &&
phys_start < (phys_addr_t)FSP_HIGHMEM_BASE)
top += (u32)(hob.res_desc->len);
top += (u32)(res_desc->len);
}
}
hob.raw = get_next_hob(hob);
hdr = get_next_hob(hdr);
}
return top;
@ -258,25 +260,27 @@ u32 fsp_get_usable_lowmem_top(const void *hob_list)
u64 fsp_get_usable_highmem_top(const void *hob_list)
{
union hob_pointers hob;
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
phys_addr_t phys_start;
u64 top;
/* Get the HOB list for processing */
hob.raw = (void *)hob_list;
hdr = hob_list;
/* Collect memory ranges */
top = FSP_HIGHMEM_BASE;
while (!end_of_hob(hob)) {
if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
if (hob.res_desc->type == RES_SYS_MEM) {
phys_start = hob.res_desc->phys_start;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_SYS_MEM) {
phys_start = res_desc->phys_start;
/* Need memory above 1MB to be collected here */
if (phys_start >= (phys_addr_t)FSP_HIGHMEM_BASE)
top += (u32)(hob.res_desc->len);
top += (u32)(res_desc->len);
}
}
hob.raw = get_next_hob(hob);
hdr = get_next_hob(hdr);
}
return top;
@ -285,24 +289,26 @@ u64 fsp_get_usable_highmem_top(const void *hob_list)
u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len,
struct efi_guid *guid)
{
union hob_pointers hob;
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
/* Get the HOB list for processing */
hob.raw = (void *)hob_list;
hdr = hob_list;
/* Collect memory ranges */
while (!end_of_hob(hob)) {
if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
if (hob.res_desc->type == RES_MEM_RESERVED) {
if (compare_guid(&hob.res_desc->owner, guid)) {
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_MEM_RESERVED) {
if (compare_guid(&res_desc->owner, guid)) {
if (len)
*len = (u32)(hob.res_desc->len);
*len = (u32)(res_desc->len);
return (u64)(hob.res_desc->phys_start);
return (u64)(res_desc->phys_start);
}
}
}
hob.raw = get_next_hob(hob);
hdr = get_next_hob(hdr);
}
return 0;
@ -336,44 +342,45 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len)
return base;
}
void *fsp_get_next_hob(u16 type, const void *hob_list)
const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list)
{
union hob_pointers hob;
const struct hob_header *hdr;
assert(hob_list != NULL);
hob.raw = (u8 *)hob_list;
hdr = hob_list;
/* Parse the HOB list until end of list or matching type is found */
while (!end_of_hob(hob)) {
if (get_hob_type(hob) == type)
return hob.raw;
while (!end_of_hob(hdr)) {
if (hdr->type == type)
return hdr;
hob.raw = get_next_hob(hob);
hdr = get_next_hob(hdr);
}
return NULL;
}
void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list)
const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
const void *hob_list)
{
union hob_pointers hob;
const struct hob_header *hdr;
struct hob_guid *guid_hob;
hob.raw = (u8 *)hob_list;
while ((hob.raw = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
hob.raw)) != NULL) {
if (compare_guid(guid, &hob.guid->name))
hdr = hob_list;
while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
hdr)) != NULL) {
guid_hob = (struct hob_guid *)hdr;
if (compare_guid(guid, &(guid_hob->name)))
break;
hob.raw = get_next_hob(hob);
hdr = get_next_hob(hdr);
}
return hob.raw;
return hdr;
}
void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
struct efi_guid *guid)
{
u8 *guid_hob;
const struct hob_header *guid_hob;
guid_hob = fsp_get_next_guid_hob(guid, hob_list);
if (guid_hob == NULL) {

View File

@ -14,17 +14,19 @@ DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
phys_size_t ram_size = 0;
union hob_pointers hob;
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
hob.raw = gd->arch.hob_list;
while (!end_of_hob(hob)) {
if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
if (hob.res_desc->type == RES_SYS_MEM ||
hob.res_desc->type == RES_MEM_RESERVED) {
ram_size += hob.res_desc->len;
hdr = gd->arch.hob_list;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
if (res_desc->type == RES_SYS_MEM ||
res_desc->type == RES_MEM_RESERVED) {
ram_size += res_desc->len;
}
}
hob.raw = get_next_hob(hob);
hdr = get_next_hob(hdr);
}
gd->ram_size = ram_size;
@ -55,22 +57,23 @@ ulong board_get_usable_ram_top(ulong total_size)
unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
{
unsigned num_entries = 0;
const struct hob_header *hdr;
struct hob_res_desc *res_desc;
union hob_pointers hob;
hdr = gd->arch.hob_list;
hob.raw = gd->arch.hob_list;
while (!end_of_hob(hdr)) {
if (hdr->type == HOB_TYPE_RES_DESC) {
res_desc = (struct hob_res_desc *)hdr;
entries[num_entries].addr = res_desc->phys_start;
entries[num_entries].size = res_desc->len;
while (!end_of_hob(hob)) {
if (get_hob_type(hob) == HOB_TYPE_RES_DESC) {
entries[num_entries].addr = hob.res_desc->phys_start;
entries[num_entries].size = hob.res_desc->len;
if (hob.res_desc->type == RES_SYS_MEM)
if (res_desc->type == RES_SYS_MEM)
entries[num_entries].type = E820_RAM;
else if (hob.res_desc->type == RES_MEM_RESERVED)
else if (res_desc->type == RES_MEM_RESERVED)
entries[num_entries].type = E820_RESERVED;
}
hob.raw = get_next_hob(hob);
hdr = get_next_hob(hdr);
num_entries++;
}

View File

@ -205,6 +205,14 @@ board_init_f_r_trampoline:
/* Setup global descriptor table so gd->xyz works */
call setup_gdt
/* Set if we need to disable CAR */
.weak car_uninit
movl $car_uninit, %eax
cmpl $0, %eax
jz 1f
call car_uninit
1:
/* Re-enter U-Boot by calling board_init_f_r */
call board_init_f_r

View File

@ -1,6 +1,4 @@
dtb-y += link.dtb \
chromebook_link.dtb \
alex.dtb \
dtb-y += chromebook_link.dtb \
crownbay.dtb
targets += $(dtb-y)

View File

@ -1,24 +0,0 @@
/dts-v1/;
/include/ "coreboot.dtsi"
/ {
#address-cells = <1>;
#size-cells = <1>;
model = "Google Alex";
compatible = "google,alex", "intel,atom-pineview";
config {
silent_console = <0>;
};
gpio: gpio {};
serial {
reg = <0x3f8 8>;
clock-frequency = <115200>;
};
chosen { };
memory { device_type = "memory"; reg = <0 0>; };
};

View File

@ -1 +0,0 @@
link.dts

View File

@ -0,0 +1,216 @@
/dts-v1/;
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/ {
model = "Google Link";
compatible = "google,link", "intel,celeron-ivybridge";
config {
silent_console = <0>;
};
gpioa {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0 0x10>;
bank-name = "A";
};
gpiob {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x30 0x10>;
bank-name = "B";
};
gpioc {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x40 0x10>;
bank-name = "C";
};
chosen {
stdout-path = "/serial";
};
spd {
compatible = "memory-spd";
#address-cells = <1>;
#size-cells = <0>;
elpida_4Gb_1600_x16 {
reg = <0>;
data = [92 10 0b 03 04 19 02 02
03 52 01 08 0a 00 fe 00
69 78 69 3c 69 11 18 81
20 08 3c 3c 01 40 83 81
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0f 11 42 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 02 fe 00
11 52 00 00 00 07 7f 37
45 42 4a 32 30 55 47 36
45 42 55 30 2d 47 4e 2d
46 20 30 20 02 fe 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00];
};
samsung_4Gb_1600_1.35v_x16 {
reg = <1>;
data = [92 11 0b 03 04 19 02 02
03 11 01 08 0a 00 fe 00
69 78 69 3c 69 11 18 81
f0 0a 3c 3c 01 40 83 01
00 80 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0f 11 02 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 80 ce 01
00 00 00 00 00 00 6a 04
4d 34 37 31 42 35 36 37
34 42 48 30 2d 59 4b 30
20 20 00 00 80 ce 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00];
};
micron_4Gb_1600_1.35v_x16 {
reg = <2>;
data = [92 11 0b 03 04 19 02 02
03 11 01 08 0a 00 fe 00
69 78 69 3c 69 11 18 81
20 08 3c 3c 01 40 83 05
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0f 01 02 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 80 2c 00
00 00 00 00 00 00 ad 75
34 4b 54 46 32 35 36 36
34 48 5a 2d 31 47 36 45
31 20 45 31 80 2c 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff];
};
};
spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich9";
spi-flash@0 {
reg = <0>;
compatible = "winbond,w25q64", "spi-flash";
memory-map = <0xff800000 0x00800000>;
};
};
pci {
sata {
compatible = "intel,pantherpoint-ahci";
intel,sata-mode = "ahci";
intel,sata-port-map = <1>;
intel,sata-port0-gen3-tx = <0x00880a7f>;
};
gma {
compatible = "intel,gma";
intel,dp_hotplug = <0 0 0x06>;
intel,panel-port-select = <1>;
intel,panel-power-cycle-delay = <6>;
intel,panel-power-up-delay = <2000>;
intel,panel-power-down-delay = <500>;
intel,panel-power-backlight-on-delay = <2000>;
intel,panel-power-backlight-off-delay = <2000>;
intel,cpu-backlight = <0x00000200>;
intel,pch-backlight = <0x04000000>;
};
lpc {
compatible = "intel,lpc";
#address-cells = <1>;
#size-cells = <1>;
gen-dec = <0x800 0xfc 0x900 0xfc>;
intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b
0x80 0x80 0x80 0x80>;
intel,gpi-routing = <0 0 0 0 0 0 0 2
1 0 0 0 0 0 0 0>;
/* Enable EC SMI source */
intel,alt-gp-smi-enable = <0x0100>;
cros-ec@200 {
compatible = "google,cros-ec";
reg = <0x204 1 0x200 1 0x880 0x80>;
/* Describes the flash memory within the EC */
#address-cells = <1>;
#size-cells = <1>;
flash@8000000 {
reg = <0x08000000 0x20000>;
erase-value = <0xff>;
};
};
};
};
microcode {
update@0 {
#include "microcode/m12306a9_0000001b.dtsi"
};
};
};

View File

@ -1,17 +0,0 @@
/include/ "skeleton.dtsi"
/ {
chosen {
stdout-path = "/serial";
};
serial {
compatible = "x86-uart";
reg = <0x3f8 0x10>;
reg-shift = <0>;
io-mapped = <1>;
multiplier = <1>;
baudrate = <115200>;
status = "disabled";
};
};

View File

@ -6,11 +6,10 @@
/dts-v1/;
/include/ "coreboot.dtsi"
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/ {
#address-cells = <1>;
#size-cells = <1>;
model = "Intel Crown Bay";
compatible = "intel,crownbay", "intel,queensbay";
@ -32,14 +31,18 @@
bank-name = "B";
};
serial {
reg = <0x3f8 8>;
clock-frequency = <115200>;
chosen {
/*
* By default the legacy superio serial port is used as the
* U-Boot serial console. If we want to use UART from Topcliff
* PCH as the console, change this property to &pciuart#.
*
* For example, stdout-path = &pciuart0 will use the first
* UART on Topcliff PCH.
*/
stdout-path = "/serial";
};
chosen { };
memory { device_type = "memory"; reg = <0 0>; };
spi {
#address-cells = <1>;
#size-cells = <0>;
@ -57,4 +60,77 @@
};
};
pci {
#address-cells = <3>;
#size-cells = <2>;
compatible = "intel,pci";
device_type = "pci";
pcie@17,0 {
#address-cells = <3>;
#size-cells = <2>;
compatible = "intel,pci";
device_type = "pci";
topcliff@0,0 {
#address-cells = <3>;
#size-cells = <2>;
compatible = "intel,pci";
device_type = "pci";
pciuart0: uart@a,1 {
compatible = "pci8086,8811.00",
"pci8086,8811",
"pciclass,070002",
"pciclass,0700",
"x86-uart";
reg = <0x00025100 0x0 0x0 0x0 0x0
0x01025110 0x0 0x0 0x0 0x0>;
reg-shift = <0>;
clock-frequency = <1843200>;
current-speed = <115200>;
};
pciuart1: uart@a,2 {
compatible = "pci8086,8812.00",
"pci8086,8812",
"pciclass,070002",
"pciclass,0700",
"x86-uart";
reg = <0x00025200 0x0 0x0 0x0 0x0
0x01025210 0x0 0x0 0x0 0x0>;
reg-shift = <0>;
clock-frequency = <1843200>;
current-speed = <115200>;
};
pciuart2: uart@a,3 {
compatible = "pci8086,8813.00",
"pci8086,8813",
"pciclass,070002",
"pciclass,0700",
"x86-uart";
reg = <0x00025300 0x0 0x0 0x0 0x0
0x01025310 0x0 0x0 0x0 0x0>;
reg-shift = <0>;
clock-frequency = <1843200>;
current-speed = <115200>;
};
pciuart3: uart@a,4 {
compatible = "pci8086,8814.00",
"pci8086,8814",
"pciclass,070002",
"pciclass,0700",
"x86-uart";
reg = <0x00025400 0x0 0x0 0x0 0x0
0x01025410 0x0 0x0 0x0 0x0>;
reg-shift = <0>;
clock-frequency = <1843200>;
current-speed = <115200>;
};
};
};
};
};

View File

@ -1,224 +0,0 @@
/dts-v1/;
/include/ "coreboot.dtsi"
/ {
#address-cells = <1>;
#size-cells = <1>;
model = "Google Link";
compatible = "google,link", "intel,celeron-ivybridge";
config {
silent_console = <0>;
};
gpioa {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0 0x10>;
bank-name = "A";
};
gpiob {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x30 0x10>;
bank-name = "B";
};
gpioc {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
reg = <0x40 0x10>;
bank-name = "C";
};
serial {
reg = <0x3f8 8>;
clock-frequency = <115200>;
};
chosen { };
memory { device_type = "memory"; reg = <0 0>; };
spd {
compatible = "memory-spd";
#address-cells = <1>;
#size-cells = <0>;
elpida_4Gb_1600_x16 {
reg = <0>;
data = [92 10 0b 03 04 19 02 02
03 52 01 08 0a 00 fe 00
69 78 69 3c 69 11 18 81
20 08 3c 3c 01 40 83 81
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0f 11 42 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 02 fe 00
11 52 00 00 00 07 7f 37
45 42 4a 32 30 55 47 36
45 42 55 30 2d 47 4e 2d
46 20 30 20 02 fe 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00];
};
samsung_4Gb_1600_1.35v_x16 {
reg = <1>;
data = [92 11 0b 03 04 19 02 02
03 11 01 08 0a 00 fe 00
69 78 69 3c 69 11 18 81
f0 0a 3c 3c 01 40 83 01
00 80 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0f 11 02 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 80 ce 01
00 00 00 00 00 00 6a 04
4d 34 37 31 42 35 36 37
34 42 48 30 2d 59 4b 30
20 20 00 00 80 ce 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00];
};
micron_4Gb_1600_1.35v_x16 {
reg = <2>;
data = [92 11 0b 03 04 19 02 02
03 11 01 08 0a 00 fe 00
69 78 69 3c 69 11 18 81
20 08 3c 3c 01 40 83 05
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0f 01 02 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 80 2c 00
00 00 00 00 00 00 ad 75
34 4b 54 46 32 35 36 36
34 48 5a 2d 31 47 36 45
31 20 45 31 80 2c 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff
ff ff ff ff ff ff ff ff];
};
};
spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich9";
spi-flash@0 {
reg = <0>;
compatible = "winbond,w25q64", "spi-flash";
memory-map = <0xff800000 0x00800000>;
};
};
pci {
sata {
compatible = "intel,pantherpoint-ahci";
intel,sata-mode = "ahci";
intel,sata-port-map = <1>;
intel,sata-port0-gen3-tx = <0x00880a7f>;
};
gma {
compatible = "intel,gma";
intel,dp_hotplug = <0 0 0x06>;
intel,panel-port-select = <1>;
intel,panel-power-cycle-delay = <6>;
intel,panel-power-up-delay = <2000>;
intel,panel-power-down-delay = <500>;
intel,panel-power-backlight-on-delay = <2000>;
intel,panel-power-backlight-off-delay = <2000>;
intel,cpu-backlight = <0x00000200>;
intel,pch-backlight = <0x04000000>;
};
lpc {
compatible = "intel,lpc";
#address-cells = <1>;
#size-cells = <1>;
gen-dec = <0x800 0xfc 0x900 0xfc>;
intel,gen-dec = <0x800 0xfc 0x900 0xfc>;
intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b
0x80 0x80 0x80 0x80>;
intel,gpi-routing = <0 0 0 0 0 0 0 2
1 0 0 0 0 0 0 0>;
/* Enable EC SMI source */
intel,alt-gp-smi-enable = <0x0100>;
cros-ec@200 {
compatible = "google,cros-ec";
reg = <0x204 1 0x200 1 0x880 0x80>;
/* Describes the flash memory within the EC */
#address-cells = <1>;
#size-cells = <1>;
flash@8000000 {
reg = <0x08000000 0x20000>;
erase-value = <0xff>;
};
};
};
};
microcode {
update@0 {
#include "microcode/m12206a7_00000029.dtsi"
};
update@1 {
#include "microcode/m12306a9_0000001b.dtsi"
};
};
};

9
arch/x86/dts/serial.dtsi Normal file
View File

@ -0,0 +1,9 @@
/ {
serial {
compatible = "x86-uart";
reg = <0x3f8 8>;
reg-shift = <0>;
clock-frequency = <1843200>;
current-speed = <115200>;
};
};

View File

@ -7,6 +7,11 @@
#ifndef __ASM_ARCH_MICROCODE_H
#define __ASM_ARCH_MICROCODE_H
/* Length of the public header on Intel microcode blobs */
#define UCODE_HEADER_LEN 0x30
#ifndef __ASSEMBLY__
/**
* microcode_update_intel() - Apply microcode updates
*
@ -16,5 +21,6 @@
* not updates were found, -EINVAL if an update was invalid
*/
int microcode_update_intel(void);
#endif /* __ASSEMBLY__ */
#endif

View File

@ -182,58 +182,19 @@ struct hob_guid {
/* GUID specific data goes here */
};
/* Union of all the possible HOB Types */
union hob_pointers {
struct hob_header *hdr;
struct hob_mem_alloc *mem_alloc;
struct hob_res_desc *res_desc;
struct hob_guid *guid;
u8 *raw;
};
/**
* get_hob_type() - return the type of a HOB
*
* This macro returns the type field from the HOB header for the
* HOB specified by hob.
*
* @hob: A pointer to a HOB.
*
* @return: HOB type.
*/
static inline u16 get_hob_type(union hob_pointers hob)
{
return hob.hdr->type;
}
/**
* get_hob_length() - return the length, in bytes, of a HOB
*
* This macro returns the len field from the HOB header for the
* HOB specified by hob.
*
* @hob: A pointer to a HOB.
*
* @return: HOB length.
*/
static inline u16 get_hob_length(union hob_pointers hob)
{
return hob.hdr->len;
}
/**
* get_next_hob() - return a pointer to the next HOB in the HOB list
*
* This macro returns a pointer to HOB that follows the HOB specified by hob
* in the HOB List.
*
* @hob: A pointer to a HOB.
* @hdr: A pointer to a HOB.
*
* @return: A pointer to the next HOB in the HOB list.
*/
static inline void *get_next_hob(union hob_pointers hob)
static inline const struct hob_header *get_next_hob(const struct hob_header *hdr)
{
return (void *)(*(u8 **)&(hob) + get_hob_length(hob));
return (const struct hob_header *)((u32)hdr + hdr->len);
}
/**
@ -243,14 +204,14 @@ static inline void *get_next_hob(union hob_pointers hob)
* HOB list. If hob is last HOB in the HOB list, then true is returned.
* Otherwise, false is returned.
*
* @hob: A pointer to a HOB.
* @hdr: A pointer to a HOB.
*
* @retval true: The HOB specified by hob is the last HOB in the HOB list.
* @retval false: The HOB specified by hob is not the last HOB in the HOB list.
* @retval true: The HOB specified by hdr is the last HOB in the HOB list.
* @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
*/
static inline bool end_of_hob(union hob_pointers hob)
static inline bool end_of_hob(const struct hob_header *hdr)
{
return get_hob_type(hob) == HOB_TYPE_EOH;
return hdr->type == HOB_TYPE_EOH;
}
/**
@ -260,13 +221,13 @@ static inline bool end_of_hob(union hob_pointers hob)
* This macro returns a pointer to the data buffer in a HOB specified by hob.
* hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
*
* @hob: A pointer to a HOB.
* @hdr: A pointer to a HOB.
*
* @return: A pointer to the data buffer in a HOB.
*/
static inline void *get_guid_hob_data(u8 *hob)
static inline void *get_guid_hob_data(const struct hob_header *hdr)
{
return (void *)(hob + sizeof(struct hob_guid));
return (void *)((u32)hdr + sizeof(struct hob_guid));
}
/**
@ -276,14 +237,13 @@ static inline void *get_guid_hob_data(u8 *hob)
* This macro returns the size, in bytes, of the data buffer in a HOB
* specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
*
* @hob: A pointer to a HOB.
* @hdr: A pointer to a HOB.
*
* @return: The size of the data buffer.
*/
static inline u16 get_guid_hob_data_size(u8 *hob)
static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
{
union hob_pointers hob_p = *(union hob_pointers *)hob;
return get_hob_length(hob_p) - sizeof(struct hob_guid);
return hdr->len - sizeof(struct hob_guid);
}
/* FSP specific GUID HOB definitions */

View File

@ -145,7 +145,7 @@ u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len);
*
* @retval: A HOB object with matching type; Otherwise NULL.
*/
void *fsp_get_next_hob(u16 type, const void *hob_list);
const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list);
/**
* Returns the next instance of the matched GUID HOB from the starting HOB.
@ -155,7 +155,8 @@ void *fsp_get_next_hob(u16 type, const void *hob_list);
*
* @retval: A HOB object with matching GUID; Otherwise NULL.
*/
void *fsp_get_next_guid_hob(const struct efi_guid *guid, const void *hob_list);
const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
const void *hob_list);
/**
* This function retrieves a GUID HOB data buffer and size.

View File

@ -29,6 +29,19 @@ struct memory_info {
struct memory_area area[CONFIG_NR_DRAM_BANKS];
};
#define MAX_MTRR_REQUESTS 8
/**
* A request for a memory region to be set up in a particular way. These
* requests are processed before board_init_r() is called. They are generally
* optional and can be ignored with some performance impact.
*/
struct mtrr_request {
int type; /* MTRR_TYPE_... */
uint64_t start;
uint64_t size;
};
/* Architecture-specific global data */
struct arch_global_data {
struct global_data *gd_addr; /* Location of Global Data */
@ -43,13 +56,14 @@ struct arch_global_data {
uint32_t tsc_mhz; /* TSC frequency in MHz */
void *new_fdt; /* Relocated FDT */
uint32_t bist; /* Built-in self test value */
struct pci_controller *hose; /* PCI hose for early use */
enum pei_boot_mode_t pei_boot_mode;
const struct pch_gpio_map *gpio_map; /* board GPIO map */
struct memory_info meminfo; /* Memory information */
#ifdef CONFIG_HAVE_FSP
void *hob_list; /* FSP HOB list */
#endif
struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
int mtrr_req_count;
};
#endif

View File

@ -9,99 +9,86 @@
#ifndef _ASM_MTRR_H
#define _ASM_MTRR_H
/* These are the region types */
#define MTRR_TYPE_UNCACHEABLE 0
#define MTRR_TYPE_WRCOMB 1
/*#define MTRR_TYPE_ 2*/
/*#define MTRR_TYPE_ 3*/
#define MTRR_TYPE_WRTHROUGH 4
#define MTRR_TYPE_WRPROT 5
#define MTRR_TYPE_WRBACK 6
#define MTRR_NUM_TYPES 7
/* MTRR region types */
#define MTRR_TYPE_UNCACHEABLE 0
#define MTRR_TYPE_WRCOMB 1
#define MTRR_TYPE_WRTHROUGH 4
#define MTRR_TYPE_WRPROT 5
#define MTRR_TYPE_WRBACK 6
#define MTRRcap_MSR 0x0fe
#define MTRRdefType_MSR 0x2ff
#define MTRR_TYPE_COUNT 7
#define MTRRdefTypeEn (1 << 11)
#define MTRRdefTypeFixEn (1 << 10)
#define MTRR_CAP_MSR 0x0fe
#define MTRR_DEF_TYPE_MSR 0x2ff
#define SMRRphysBase_MSR 0x1f2
#define SMRRphysMask_MSR 0x1f3
#define MTRR_DEF_TYPE_EN (1 << 11)
#define MTRR_DEF_TYPE_FIX_EN (1 << 10)
#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
#define MTRRphysMaskValid (1 << 11)
#define MTRR_PHYS_MASK_VALID (1 << 11)
#define NUM_FIXED_RANGES 88
#define RANGES_PER_FIXED_MTRR 8
#define MTRRfix64K_00000_MSR 0x250
#define MTRRfix16K_80000_MSR 0x258
#define MTRRfix16K_A0000_MSR 0x259
#define MTRRfix4K_C0000_MSR 0x268
#define MTRRfix4K_C8000_MSR 0x269
#define MTRRfix4K_D0000_MSR 0x26a
#define MTRRfix4K_D8000_MSR 0x26b
#define MTRRfix4K_E0000_MSR 0x26c
#define MTRRfix4K_E8000_MSR 0x26d
#define MTRRfix4K_F0000_MSR 0x26e
#define MTRRfix4K_F8000_MSR 0x26f
#define MTRR_BASE_TYPE_MASK 0x7
/* Number of MTRRs supported */
#define MTRR_COUNT 8
#if !defined(__ASSEMBLER__)
/*
* The MTRR code has some side effects that the callers should be aware for.
* 1. The call sequence matters. x86_setup_mtrrs() calls
* x86_setup_fixed_mtrrs_no_enable() then enable_fixed_mtrrs() (equivalent
* of x86_setup_fixed_mtrrs()) then x86_setup_var_mtrrs(). If the callers
* want to call the components of x86_setup_mtrrs() because of other
* rquirements the ordering should still preserved.
* 2. enable_fixed_mtrr() will enable both variable and fixed MTRRs because
* of the nature of the global MTRR enable flag. Therefore, all direct
* or indirect callers of enable_fixed_mtrr() should ensure that the
* variable MTRR MSRs do not contain bad ranges.
* 3. If CONFIG_CACHE_ROM is selected an MTRR is allocated for enabling
* the caching of the ROM. However, it is set to uncacheable (UC). It
* is the responsiblity of the caller to enable it by calling
* x86_mtrr_enable_rom_caching().
/**
* Information about the previous MTRR state, set up by mtrr_open()
*
* @deftype: Previous value of MTRR_DEF_TYPE_MSR
* @enable_cache: true if cache was enabled
*/
void x86_setup_mtrrs(void);
/*
* x86_setup_var_mtrrs() parameters:
* address_bits - number of physical address bits supported by cpu
* above4gb - 2 means dynamically detect number of variable MTRRs available.
* non-zero means handle memory ranges above 4GiB.
* 0 means ignore memory ranges above 4GiB
struct mtrr_state {
uint64_t deftype;
bool enable_cache;
};
/**
* mtrr_open() - Prepare to adjust MTRRs
*
* Use mtrr_open() passing in a structure - this function will init it. Then
* when done, pass the same structure to mtrr_close() to re-enable MTRRs and
* possibly the cache.
*
* @state: Empty structure to pass in to hold settings
*/
void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb);
void enable_fixed_mtrr(void);
void x86_setup_fixed_mtrrs(void);
/* Set up fixed MTRRs but do not enable them. */
void x86_setup_fixed_mtrrs_no_enable(void);
int x86_mtrr_check(void);
/* ROM caching can be used after variable MTRRs are set up. Beware that
* enabling CONFIG_CACHE_ROM will eat through quite a few MTRRs based on
* one's IO hole size and WRCOMB resources. Be sure to check the console
* log when enabling CONFIG_CACHE_ROM or adding WRCOMB resources. Beware that
* on CPUs with core-scoped MTRR registers such as hyperthreaded CPUs the
* rom caching will be disabled if all threads run the MTRR code. Therefore,
* one needs to call x86_mtrr_enable_rom_caching() after all threads of the
* same core have run the MTRR code. */
#if CONFIG_CACHE_ROM
void x86_mtrr_enable_rom_caching(void);
void x86_mtrr_disable_rom_caching(void);
/* Return the variable range MTRR index of the ROM cache. */
long x86_mtrr_rom_cache_var_index(void);
#else
static inline void x86_mtrr_enable_rom_caching(void) {}
static inline void x86_mtrr_disable_rom_caching(void) {}
static inline long x86_mtrr_rom_cache_var_index(void) { return -1; }
#endif /* CONFIG_CACHE_ROM */
void mtrr_open(struct mtrr_state *state);
#endif
/**
* mtrr_open() - Clean up after adjusting MTRRs, and enable them
*
* This uses the structure containing information returned from mtrr_open().
*
* @state: Structure from mtrr_open()
*/
/* */
void mtrr_close(struct mtrr_state *state);
/**
* mtrr_add_request() - Add a new MTRR request
*
* This adds a request for a memory region to be set up in a particular way.
*
* @type: Requested type (MTRR_TYPE_)
* @start: Start address
* @size: Size
*/
int mtrr_add_request(int type, uint64_t start, uint64_t size);
/**
* mtrr_commit() - set up the MTRR registers based on current requests
*
* This sets up MTRRs for the available DRAM and the requests received so far.
* It must be called with caches disabled.
*
* @do_caches: true if caches are currently on
*/
int mtrr_commit(bool do_caches);
#if !defined(CONFIG_RAMTOP)
# error "CONFIG_RAMTOP not defined"
#endif
#if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)
@ -114,8 +101,4 @@ static inline long x86_mtrr_rom_cache_var_index(void) { return -1; }
#define CACHE_ROM_BASE (((1 << 20) - (CONFIG_CACHE_ROM_SIZE >> 12)) << 12)
#if (CONFIG_RAMTOP & (CONFIG_RAMTOP - 1)) != 0
# error "CONFIG_RAMTOP must be a power of 2"
#endif
#endif

View File

@ -29,7 +29,7 @@ void board_pci_setup_hose(struct pci_controller *hose);
* pci_early_init_hose() - Set up PCI host before relocation
*
* This allocates memory for, sets up and returns the PCI hose. It can be
* called before relocation. The hose will be stored in gd->arch.hose for
* called before relocation. The hose will be stored in gd->hose for
* later use, but will become invalid one DRAM is available.
*/
int pci_early_init_hose(struct pci_controller **hosep);

View File

@ -14,6 +14,7 @@ obj-$(CONFIG_HAVE_FSP) += cmd_hob.o
obj-y += gcc.o
obj-y += init_helpers.o
obj-y += interrupts.o
obj-y += cmd_mtrr.o
obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o
obj-$(CONFIG_PCI) += pci_type1.o

View File

@ -207,12 +207,14 @@ static u8 vbe_get_mode_info(struct vbe_mode_info *mi)
static u8 vbe_set_mode(struct vbe_mode_info *mi)
{
debug("VBE: Setting VESA mode %#04x\n", mi->video_mode);
int video_mode = mi->video_mode;
debug("VBE: Setting VESA mode %#04x\n", video_mode);
/* request linear framebuffer mode */
mi->video_mode |= (1 << 14);
/* request clearing of framebuffer */
mi->video_mode &= ~(1 << 15);
realmode_interrupt(0x10, VESA_SET_MODE, mi->video_mode,
video_mode |= (1 << 14);
/* don't clear the framebuffer, we do that later */
video_mode |= (1 << 15);
realmode_interrupt(0x10, VESA_SET_MODE, video_mode,
0x0000, 0x0000, 0x0000, 0x0000);
return 0;
@ -236,6 +238,7 @@ static void vbe_set_graphics(int vesa_mode, struct vbe_mode_info *mode_info)
return;
}
mode_info->video_mode &= 0x3ff;
vbe_set_mode(mode_info);
}
@ -262,7 +265,6 @@ void bios_run_on_x86(pci_dev_t pcidev, unsigned long addr, int vesa_mode,
/* Make sure the code is placed. */
setup_realmode_code();
disable_caches();
debug("Calling Option ROM at %lx, pci device %#x...", addr, num_dev);
/* Option ROM entry point is at OPROM start + 3 */

View File

@ -28,20 +28,20 @@ static char *hob_type[] = {
int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
union hob_pointers hob;
u16 type;
const struct hob_header *hdr;
uint type;
char *desc;
int i = 0;
hob.raw = (u8 *)gd->arch.hob_list;
hdr = gd->arch.hob_list;
printf("HOB list address: 0x%08x\n\n", (unsigned int)hob.raw);
printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
printf("No. | Address | Type | Length in Bytes\n");
printf("----|----------|---------------------|----------------\n");
while (!end_of_hob(hob)) {
printf("%-3d | %08x | ", i, (unsigned int)hob.raw);
type = get_hob_type(hob);
while (!end_of_hob(hdr)) {
printf("%-3d | %08x | ", i, (unsigned int)hdr);
type = hdr->type;
if (type == HOB_TYPE_UNUSED)
desc = "*Unused*";
else if (type == HOB_TYPE_EOH)
@ -50,8 +50,8 @@ int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
desc = hob_type[type];
else
desc = "*Invalid Type*";
printf("%-19s | %-15d\n", desc, get_hob_length(hob));
hob.raw = get_next_hob(hob);
printf("%-19s | %-15d\n", desc, hdr->len);
hdr = get_next_hob(hdr);
i++;
}

138
arch/x86/lib/cmd_mtrr.c Normal file
View File

@ -0,0 +1,138 @@
/*
* (C) Copyright 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
"Uncacheable",
"Combine",
"2",
"3",
"Through",
"Protect",
"Back",
};
static int do_mtrr_list(void)
{
int i;
printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||",
"Mask ||", "Size ||");
for (i = 0; i < MTRR_COUNT; i++) {
const char *type = "Invalid";
uint64_t base, mask, size;
bool valid;
base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
size |= (1 << 12) - 1;
size += 1;
valid = mask & MTRR_PHYS_MASK_VALID;
type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
valid ? "Y" : "N", type, base, mask, size);
}
return 0;
}
static int do_mtrr_set(uint reg, int argc, char * const argv[])
{
const char *typename = argv[0];
struct mtrr_state state;
uint32_t start, size;
uint64_t base, mask;
int i, type = -1;
bool valid;
if (argc < 3)
return CMD_RET_USAGE;
for (i = 0; i < MTRR_TYPE_COUNT; i++) {
if (*typename == *mtrr_type_name[i])
type = i;
}
if (type == -1) {
printf("Invalid type name %s\n", typename);
return CMD_RET_USAGE;
}
start = simple_strtoul(argv[1], NULL, 16);
size = simple_strtoul(argv[2], NULL, 16);
base = start | type;
valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
mask = ~((uint64_t)size - 1);
mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
if (valid)
mask |= MTRR_PHYS_MASK_VALID;
printf("base=%llx, mask=%llx\n", base, mask);
mtrr_open(&state);
wrmsrl(MTRR_PHYS_BASE_MSR(reg), base);
wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
mtrr_close(&state);
return 0;
}
static int mtrr_set_valid(int reg, bool valid)
{
struct mtrr_state state;
uint64_t mask;
mtrr_open(&state);
mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg));
if (valid)
mask |= MTRR_PHYS_MASK_VALID;
else
mask &= ~MTRR_PHYS_MASK_VALID;
wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask);
mtrr_close(&state);
return 0;
}
static int do_mtrr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
const char *cmd;
uint reg;
cmd = argv[1];
if (argc < 2 || *cmd == 'l')
return do_mtrr_list();
argc -= 2;
argv += 2;
if (argc <= 0)
return CMD_RET_USAGE;
reg = simple_strtoul(argv[0], NULL, 16);
if (reg >= MTRR_COUNT) {
printf("Invalid register number\n");
return CMD_RET_USAGE;
}
if (*cmd == 'e')
return mtrr_set_valid(reg, true);
else if (*cmd == 'd')
return mtrr_set_valid(reg, false);
else if (*cmd == 's')
return do_mtrr_set(reg, argc - 1, argv + 1);
else
return CMD_RET_USAGE;
return 0;
}
U_BOOT_CMD(
mtrr, 6, 1, do_mtrr,
"Use x86 memory type range registers (32-bit only)",
"[list] - list current registers\n"
"set <reg> <type> <start> <size> - set a register\n"
"\t<type> is Uncacheable, Combine, Through, Protect, Back\n"
"disable <reg> - disable a register\n"
"ensable <reg> - enable a register"
);

View File

@ -7,6 +7,7 @@
#include <common.h>
#include <fdtdec.h>
#include <spi.h>
#include <asm/mtrr.h>
#include <asm/sections.h>
DECLARE_GLOBAL_DATA_PTR;
@ -66,6 +67,13 @@ int calculate_relocation_address(void)
int init_cache_f_r(void)
{
#if defined(CONFIG_X86_RESET_VECTOR) & !defined(CONFIG_HAVE_FSP)
int ret;
ret = mtrr_commit(false);
if (ret)
return ret;
#endif
/* Initialise the CPU cache(s) */
return init_cache();
}

View File

@ -78,7 +78,7 @@ static int match_cpu(u8 family, u8 model)
*
* Returns the calibration value or 0 if MSR calibration failed.
*/
static unsigned long try_msr_calibrate_tsc(void)
static unsigned long __maybe_unused try_msr_calibrate_tsc(void)
{
u32 lo, hi, ratio, freq_id, freq;
unsigned long res;
@ -199,7 +199,7 @@ static inline int pit_expect_msb(unsigned char val, u64 *tscp,
#define MAX_QUICK_PIT_MS 50
#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
static unsigned long quick_pit_calibrate(void)
static unsigned long __maybe_unused quick_pit_calibrate(void)
{
int i;
u64 tsc, delta;
@ -306,6 +306,9 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
if (gd->arch.tsc_mhz)
return gd->arch.tsc_mhz;
#ifdef CONFIG_TSC_CALIBRATION_BYPASS
fast_calibrate = CONFIG_TSC_FREQ_IN_MHZ;
#else
fast_calibrate = try_msr_calibrate_tsc();
if (!fast_calibrate) {
@ -313,6 +316,7 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
if (!fast_calibrate)
panic("TSC frequency is ZERO");
}
#endif
gd->arch.tsc_mhz = fast_calibrate;
return fast_calibrate;

View File

@ -9,7 +9,32 @@ config SYS_VENDOR
config SYS_SOC
default "coreboot"
comment "coreboot-specific options"
config SYS_CONFIG_NAME
default "coreboot"
string "Board configuration file"
default "chromebook_link"
help
This option selects the board configuration file in include/configs/
directory to be used to build U-Boot for coreboot.
config DEFAULT_DEVICE_TREE
string "Board Device Tree Source (dts) file"
default "chromebook_link"
help
This option selects the board Device Tree Source (dts) file in
arch/x86/dts/ directory to be used to build U-Boot for coreboot.
config SYS_CAR_ADDR
hex "Board specific Cache-As-RAM (CAR) address"
default 0x19200000
help
This option specifies the board specific Cache-As-RAM (CAR) address.
config SYS_CAR_SIZE
hex "Board specific Cache-As-RAM (CAR) size"
default 0x4000
help
This option specifies the board specific Cache-As-RAM (CAR) size.
endif

View File

@ -2,5 +2,5 @@ COREBOOT BOARD
M: Simon Glass <sjg@chromium.org>
S: Maintained
F: board/coreboot/coreboot/
F: include/configs/coreboot.h
F: include/configs/chromebook_link.h
F: configs/coreboot-x86_defconfig

View File

@ -10,8 +10,10 @@
int arch_early_init_r(void)
{
#ifdef CONFIG_CROS_EC
if (cros_ec_board_init())
return -1;
#endif
return 0;
}

View File

@ -14,6 +14,7 @@ config SYS_CONFIG_NAME
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select X86_RESET_VECTOR
select CPU_INTEL_SOCKET_RPGA989
select NORTHBRIDGE_INTEL_IVYBRIDGE
select SOUTHBRIDGE_INTEL_C216
@ -29,4 +30,12 @@ config EARLY_POST_CROS_EC
bool "Enable early post to Chrome OS EC"
default y
config SYS_CAR_ADDR
hex
default 0xff7e0000
config SYS_CAR_SIZE
hex
default 0x20000
endif

View File

@ -14,6 +14,7 @@ config SYS_CONFIG_NAME
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select X86_RESET_VECTOR
select INTEL_QUEENSBAY
select BOARD_ROMSIZE_KB_1024

View File

@ -985,6 +985,11 @@ static init_fnc_t init_sequence_f[] = {
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
setup_reloc,
#ifdef CONFIG_X86
copy_uboot_to_ram,
clear_bss,
do_elf_reloc_fixups,
#endif
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
jump_to_copy,
#endif
@ -1044,9 +1049,6 @@ void board_init_f(ulong boot_flags)
*/
static init_fnc_t init_sequence_f_r[] = {
init_cache_f_r,
copy_uboot_to_ram,
clear_bss,
do_elf_reloc_fixups,
NULL,
};

View File

@ -6,5 +6,6 @@ CONFIG_OF_SEPARATE=y
CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
CONFIG_HAVE_MRC=y
CONFIG_SMM_TSEG_SIZE=0x800000
CONFIG_VIDEO_X86=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_FRAMEBUFFER_VESA_MODE_11A=y

View File

@ -2,4 +2,3 @@ CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0x01110000"
CONFIG_X86=y
CONFIG_TARGET_COREBOOT=y
CONFIG_OF_CONTROL=y
CONFIG_DEFAULT_DEVICE_TREE="link"

View File

@ -32,6 +32,21 @@ on other architectures, like below:
$ make coreboot-x86_defconfig
$ make all
Note this default configuration will build a U-Boot payload for the Link board.
To build a coreboot payload against another board, you can change the build
configuration during the 'make menuconfig' process.
x86 architecture --->
...
(chromebook_link) Board configuration file
(chromebook_link) Board Device Tree Source (dts) file
(0x19200000) Board specific Cache-As-RAM (CAR) address
(0x4000) Board specific Cache-As-RAM (CAR) size
Change the 'Board configuration file' and 'Board Device Tree Source (dts) file'
to point to a new board. You can also change the Cache-As-RAM (CAR) related
settings here if the default values do not fit your new board.
Building ROM version of U-Boot (hereafter referred to as u-boot.rom) is a
little bit tricky, as generally it requires several binary blobs which are not
shipped in the U-Boot source tree. Due to this reason, the u-boot.rom build is
@ -88,11 +103,31 @@ in this FSP package too.
Rename the first one to fsp.bin and second one to cmc.bin and put them in the
board directory.
Now you can build U-Boot and obtaim u-boot.rom
Now you can build U-Boot and obtain u-boot.rom
$ make crownbay_defconfig
$ make all
Test with coreboot
------------------
For testing U-Boot as the coreboot payload, there are things that need be paid
attention to. coreboot supports loading an ELF executable and a 32-bit plain
binary, as well as other supported payloads. With the default configuration,
U-Boot is set up to use a separate Device Tree Blob (dtb). As of today, the
generated u-boot-dtb.bin needs to be packaged by the cbfstool utility (a tool
provided by coreboot) manually as coreboot's 'make menuconfig' does not provide
this capability yet. The command is as follows:
# in the coreboot root directory
$ ./build/util/cbfstool/cbfstool build/coreboot.rom add-flat-binary \
-f u-boot-dtb.bin -n fallback/payload -c lzma -l 0x1110000 -e 0x1110015
Make sure 0x1110000 matches CONFIG_SYS_TEXT_BASE and 0x1110015 matches the
symbol address of _start (in arch/x86/cpu/start.S).
If you want to use ELF as the coreboot payload, change U-Boot configuration to
use CONFIG_OF_EMBED.
CPU Microcode
-------------
Modern CPU usually requires a special bit stream called microcode [5] to be
@ -106,13 +141,29 @@ x86 has been converted to use driver model for serial and GPIO.
Device Tree
-----------
x86 uses device tree to configure the board thus requires CONFIG_OF_CONTROL to
be turned on. Not every device on the board is configured via devie tree, but
be turned on. Not every device on the board is configured via device tree, but
more and more devices will be added as time goes by. Check out the directory
arch/x86/dts/ for these device tree source files.
Useful Commands
---------------
In keeping with the U-Boot philosophy of providing functions to check and
adjust internal settings, there are several x86-specific commands that may be
useful:
hob - Display information about Firmware Support Package (FSP) Hand-off
Block. This is only available on platforms which use FSP, mostly
Atom.
iod - Display I/O memory
iow - Write I/O memory
mtrr - List and set the Memory Type Range Registers (MTRR). These are used to
tell the CPU whether memory is cacheable and if so the cache write
mode to use. U-Boot sets up some reasonable values but you can
adjust then with this command.
TODO List
---------
- MTRR support (for performance)
- Audio
- Chrome OS verified boot
- SMI and ACPI support, to provide platform info and facilities to Linux

View File

@ -19,6 +19,8 @@
#include <asm/io.h>
#include <pci.h>
DECLARE_GLOBAL_DATA_PTR;
#define PCI_HOSE_OP(rw, size, type) \
int pci_hose_##rw##_config_##size(struct pci_controller *hose, \
pci_dev_t dev, \
@ -123,6 +125,14 @@ void *pci_map_bar(pci_dev_t pdev, int bar, int flags)
static struct pci_controller* hose_head;
struct pci_controller *pci_get_hose_head(void)
{
if (gd->hose)
return gd->hose;
return hose_head;
}
void pci_register_hose(struct pci_controller* hose)
{
struct pci_controller **phose = &hose_head;
@ -139,7 +149,7 @@ struct pci_controller *pci_bus_to_hose(int bus)
{
struct pci_controller *hose;
for (hose = hose_head; hose; hose = hose->next) {
for (hose = pci_get_hose_head(); hose; hose = hose->next) {
if (bus >= hose->first_busno && bus <= hose->last_busno)
return hose;
}
@ -152,7 +162,7 @@ struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr)
{
struct pci_controller *hose;
for (hose = hose_head; hose; hose = hose->next) {
for (hose = pci_get_hose_head(); hose; hose = hose->next) {
if (hose->cfg_addr == cfg_addr)
return hose;
}
@ -162,7 +172,7 @@ struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr)
int pci_last_busno(void)
{
struct pci_controller *hose = hose_head;
struct pci_controller *hose = pci_get_hose_head();
if (!hose)
return -1;
@ -181,7 +191,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
pci_dev_t bdf;
int i, bus, found_multi = 0;
for (hose = hose_head; hose; hose = hose->next) {
for (hose = pci_get_hose_head(); hose; hose = hose->next) {
#ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
for (bus = hose->last_busno; bus >= hose->first_busno; bus--)
#else
@ -233,7 +243,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
{
static struct pci_device_id ids[2] = {{}, {0, 0}};
struct pci_device_id ids[2] = { {}, {0, 0} };
ids[0].vendor = vendor;
ids[0].device = device;
@ -709,11 +719,10 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus)
int pci_hose_scan(struct pci_controller *hose)
{
#if defined(CONFIG_PCI_BOOTDELAY)
static int pcidelay_done;
char *s;
int i;
if (!pcidelay_done) {
if (!gd->pcidelay_done) {
/* wait "pcidelay" ms (if defined)... */
s = getenv("pcidelay");
if (s) {
@ -721,7 +730,7 @@ int pci_hose_scan(struct pci_controller *hose)
for (i = 0; i < val; i++)
udelay(1000);
}
pcidelay_done = 1;
gd->pcidelay_done = 1;
}
#endif /* CONFIG_PCI_BOOTDELAY */

View File

@ -156,6 +156,8 @@ int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header,
target = (void *)PCI_VGA_RAM_IMAGE_START;
if (target != rom_header) {
ulong start = get_timer(0);
debug("Copying VGA ROM Image from %p to %p, 0x%x bytes\n",
rom_header, target, rom_size);
memcpy(target, rom_header, rom_size);
@ -163,6 +165,7 @@ int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header,
printf("VGA ROM copy failed\n");
return -EFAULT;
}
debug("Copy took %lums\n", get_timer(start));
}
*ram_headerp = target;
@ -205,7 +208,7 @@ int vbe_get_video_info(struct graphic_device *gdev)
gdev->vprBase = vesa->phys_base_ptr;
gdev->cprBase = vesa->phys_base_ptr;
return 0;
return gdev->winSizeX ? 0 : -ENOSYS;
#else
return -ENOSYS;
#endif
@ -244,7 +247,7 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
defined(CONFIG_FRAMEBUFFER_VESA_MODE)
vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
#endif
debug("Selected vesa mode %d\b", vesa_mode);
debug("Selected vesa mode %#x\n", vesa_mode);
if (emulate) {
#ifdef CONFIG_BIOSEMU
BE_VGAInfo *info;
@ -272,7 +275,7 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate)
return -ENOSYS;
#endif
}
debug("Final vesa mode %d\n", mode_info.video_mode);
debug("Final vesa mode %#x\n", mode_info.video_mode);
return 0;
}

View File

@ -458,6 +458,7 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node,
unsigned int *index,
unsigned int *lanes)
{
struct fdt_pci_addr addr;
pci_dev_t bdf;
int err;
@ -469,7 +470,7 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node,
*lanes = err;
err = fdtdec_pci_get_bdf(fdt, node, &bdf);
err = fdtdec_get_pci_bdf(fdt, node, &addr, &bdf);
if (err < 0) {
error("failed to parse \"reg\" property");
return err;

View File

@ -289,7 +289,38 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
struct ns16550_platdata *plat = dev->platdata;
fdt_addr_t addr;
/* try Processor Local Bus device first */
addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg");
#ifdef CONFIG_PCI
if (addr == FDT_ADDR_T_NONE) {
/* then try pci device */
struct fdt_pci_addr pci_addr;
u32 bar;
int ret;
/* we prefer to use a memory-mapped register */
ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset,
FDT_PCI_SPACE_MEM32, "reg",
&pci_addr);
if (ret) {
/* try if there is any i/o-mapped register */
ret = fdtdec_get_pci_addr(gd->fdt_blob,
dev->of_offset,
FDT_PCI_SPACE_IO,
"reg", &pci_addr);
if (ret)
return ret;
}
ret = fdtdec_get_pci_bar32(gd->fdt_blob, dev->of_offset,
&pci_addr, &bar);
if (ret)
return ret;
addr = bar;
}
#endif
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;

View File

@ -6,9 +6,12 @@
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <ns16550.h>
#include <serial.h>
DECLARE_GLOBAL_DATA_PTR;
static const struct udevice_id x86_serial_ids[] = {
{ .compatible = "x86-uart" },
{ }
@ -22,10 +25,13 @@ static int x86_serial_ofdata_to_platdata(struct udevice *dev)
ret = ns16550_serial_ofdata_to_platdata(dev);
if (ret)
return ret;
plat->clock = 1843200;
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"clock-frequency", 1843200);
return 0;
}
U_BOOT_DRIVER(serial_ns16550) = {
.name = "serial_x86",
.id = UCLASS_SERIAL,

View File

@ -0,0 +1,8 @@
config VIDEO_X86
bool "Enable x86 video driver support"
depends on X86
default n
help
Turn on this option to enable a very simple driver which uses vesa
to discover the video mode and then provides a frame buffer for use
by U-Boot.

View File

@ -32,6 +32,7 @@ void *video_hw_init(void)
sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
bits_per_pixel);
printf("%s\n", gdev->modeIdent);
debug("Frame buffer at %x\n", gdev->frameAdrs);
return (void *)gdev;
}

View File

@ -90,6 +90,12 @@ typedef struct global_data {
unsigned long malloc_base; /* base address of early malloc() */
unsigned long malloc_limit; /* limit address */
unsigned long malloc_ptr; /* current address */
#endif
#ifdef CONFIG_PCI
struct pci_controller *hose; /* PCI hose for early use */
#endif
#ifdef CONFIG_PCI_BOOTDELAY
int pcidelay_done;
#endif
struct udevice *cur_serial_dev; /* current serial device */
struct arch_global_data arch; /* architecture-specific data */

View File

@ -15,15 +15,12 @@
#include <configs/x86-common.h>
#define CONFIG_SYS_CAR_ADDR 0xff7e0000
#define CONFIG_SYS_CAR_SIZE (128 * 1024)
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000
#define CONFIG_SYS_X86_START16 0xfffff800
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_X86_RESET_VECTOR
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_NR_DRAM_BANKS 8
#define CONFIG_X86_MRC_ADDR 0xfffa0000
#define CONFIG_CACHE_MRC_SIZE_KB 512
@ -41,7 +38,6 @@
#define CONFIG_X86_OPTION_ROM_FILE pci8086,0166.bin
#define CONFIG_X86_OPTION_ROM_ADDR 0xfff90000
#define CONFIG_VIDEO_X86
#define CONFIG_PCI_MEM_BUS 0xe0000000
#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS

View File

@ -1,75 +0,0 @@
/*
* Copyright (c) 2011 The Chromium OS Authors.
* (C) Copyright 2008
* Graeme Russ, graeme.russ@gmail.com.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* board/config.h - configuration options, board specific
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <configs/x86-common.h>
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_SYS_COREBOOT
#define CONFIG_LAST_STAGE_INIT
#define CONFIG_SYS_EARLY_PCI_INIT
#define CONFIG_SYS_CAR_ADDR 0x19200000
#define CONFIG_SYS_CAR_SIZE (16 * 1024)
#define CONFIG_SYS_MONITOR_LEN (256 * 1024)
#define CONFIG_TRACE_EARLY_SIZE (8 << 20)
#define CONFIG_TRACE_EARLY
#define CONFIG_TRACE_EARLY_ADDR 0x01400000
#define CONFIG_BOOTSTAGE
#define CONFIG_BOOTSTAGE_REPORT
#define CONFIG_BOOTSTAGE_FDT
#define CONFIG_CMD_BOOTSTAGE
/* Place to stash bootstage data from first-stage U-Boot */
#define CONFIG_BOOTSTAGE_STASH 0x0110f000
#define CONFIG_BOOTSTAGE_STASH_SIZE 0x7fc
#define CONFIG_BOOTSTAGE_USER_COUNT 60
#define CONFIG_SCSI_DEV_LIST {PCI_VENDOR_ID_INTEL, \
PCI_DEVICE_ID_INTEL_NM10_AHCI}, \
{PCI_VENDOR_ID_INTEL, \
PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_MOBILE}, \
{PCI_VENDOR_ID_INTEL, \
PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_SERIES6}, \
{PCI_VENDOR_ID_INTEL, \
PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}
#define CONFIG_X86_SERIAL
#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \
"stdout=vga,serial,cbmem\0" \
"stderr=vga,serial,cbmem\0"
#define CONFIG_CBMEM_CONSOLE
#define CONFIG_VIDEO_COREBOOT
#define CONFIG_NR_DRAM_BANKS 4
#define CONFIG_TRACE
#define CONFIG_CMD_TRACE
#define CONFIG_TRACE_BUFFER_SIZE (16 << 20)
#define CONFIG_BOOTDELAY 2
#define CONFIG_CROS_EC
#define CONFIG_CROS_EC_LPC
#define CONFIG_CMD_CROS_EC
#define CONFIG_ARCH_EARLY_INIT_R
#endif /* __CONFIG_H */

View File

@ -14,10 +14,8 @@
#include <configs/x86-common.h>
#define CONFIG_SYS_MONITOR_LEN (1 << 20)
#define CONFIG_SYS_X86_START16 0xfffff800
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_X86_RESET_VECTOR
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_X86_SERIAL

View File

@ -15,6 +15,7 @@
*/
#include <libfdt.h>
#include <pci.h>
/*
* A typedef for a physical address. Note that fdt data is always big
@ -50,6 +51,49 @@ struct fdt_resource {
fdt_addr_t end;
};
enum fdt_pci_space {
FDT_PCI_SPACE_CONFIG = 0,
FDT_PCI_SPACE_IO = 0x01000000,
FDT_PCI_SPACE_MEM32 = 0x02000000,
FDT_PCI_SPACE_MEM64 = 0x03000000,
FDT_PCI_SPACE_MEM32_PREF = 0x42000000,
FDT_PCI_SPACE_MEM64_PREF = 0x43000000,
};
#define FDT_PCI_ADDR_CELLS 3
#define FDT_PCI_SIZE_CELLS 2
#define FDT_PCI_REG_SIZE \
((FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS) * sizeof(u32))
/*
* The Open Firmware spec defines PCI physical address as follows:
*
* bits# 31 .... 24 23 .... 16 15 .... 08 07 .... 00
*
* phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr
* phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh
* phys.lo cell: llllllll llllllll llllllll llllllll
*
* where:
*
* n: is 0 if the address is relocatable, 1 otherwise
* p: is 1 if addressable region is prefetchable, 0 otherwise
* t: is 1 if the address is aliased (for non-relocatable I/O) below 1MB
* (for Memory), or below 64KB (for relocatable I/O)
* ss: is the space code, denoting the address space
* bbbbbbbb: is the 8-bit Bus Number
* ddddd: is the 5-bit Device Number
* fff: is the 3-bit Function Number
* rrrrrrrr: is the 8-bit Register Number
* hhhhhhhh: is a 32-bit unsigned number
* llllllll: is a 32-bit unsigned number
*/
struct fdt_pci_addr {
u32 phys_hi;
u32 phys_mid;
u32 phys_lo;
};
/**
* Compute the size of a resource.
*
@ -257,6 +301,60 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node,
fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
const char *prop_name, fdt_size_t *sizep);
/**
* Look at an address property in a node and return the pci address which
* corresponds to the given type in the form of fdt_pci_addr.
* The property must hold one fdt_pci_addr with a lengh.
*
* @param blob FDT blob
* @param node node to examine
* @param type pci address type (FDT_PCI_SPACE_xxx)
* @param prop_name name of property to find
* @param addr returns pci address in the form of fdt_pci_addr
* @return 0 if ok, negative on error
*/
int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
const char *prop_name, struct fdt_pci_addr *addr);
/**
* Look at the compatible property of a device node that represents a PCI
* device and extract pci vendor id and device id from it.
*
* @param blob FDT blob
* @param node node to examine
* @param vendor vendor id of the pci device
* @param device device id of the pci device
* @return 0 if ok, negative on error
*/
int fdtdec_get_pci_vendev(const void *blob, int node,
u16 *vendor, u16 *device);
/**
* Look at the pci address of a device node that represents a PCI device
* and parse the bus, device and function number from it.
*
* @param blob FDT blob
* @param node node to examine
* @param addr pci address in the form of fdt_pci_addr
* @param bdf returns bus, device, function triplet
* @return 0 if ok, negative on error
*/
int fdtdec_get_pci_bdf(const void *blob, int node,
struct fdt_pci_addr *addr, pci_dev_t *bdf);
/**
* Look at the pci address of a device node that represents a PCI device
* and return base address of the pci device's registers.
*
* @param blob FDT blob
* @param node node to examine
* @param addr pci address in the form of fdt_pci_addr
* @param bar returns base address of the pci device's registers
* @return 0 if ok, negative on error
*/
int fdtdec_get_pci_bar32(const void *blob, int node,
struct fdt_pci_addr *addr, u32 *bar);
/**
* Look up a 32-bit integer property in a node and return it. The property
* must have at least 4 bytes of data. The value of the first cell is
@ -682,17 +780,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
const char *prop_names, const char *name,
struct fdt_resource *res);
/**
* Look at the reg property of a device node that represents a PCI device
* and parse the bus, device and function number from it.
*
* @param fdt FDT blob
* @param node node to examine
* @param bdf returns bus, device, function triplet
* @return 0 if ok, negative on error
*/
int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf);
/**
* Decode a named region within a memory bank of a given type.
*

View File

@ -126,6 +126,163 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node,
return fdtdec_get_addr_size(blob, node, prop_name, NULL);
}
#ifdef CONFIG_PCI
int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
const char *prop_name, struct fdt_pci_addr *addr)
{
const u32 *cell;
int len;
int ret = -ENOENT;
debug("%s: %s: ", __func__, prop_name);
/*
* If we follow the pci bus bindings strictly, we should check
* the value of the node's parent node's #address-cells and
* #size-cells. They need to be 3 and 2 accordingly. However,
* for simplicity we skip the check here.
*/
cell = fdt_getprop(blob, node, prop_name, &len);
if (!cell)
goto fail;
if ((len % FDT_PCI_REG_SIZE) == 0) {
int num = len / FDT_PCI_REG_SIZE;
int i;
for (i = 0; i < num; i++) {
debug("pci address #%d: %08lx %08lx %08lx\n", i,
(ulong)fdt_addr_to_cpu(cell[0]),
(ulong)fdt_addr_to_cpu(cell[1]),
(ulong)fdt_addr_to_cpu(cell[2]));
if ((fdt_addr_to_cpu(*cell) & type) == type) {
addr->phys_hi = fdt_addr_to_cpu(cell[0]);
addr->phys_mid = fdt_addr_to_cpu(cell[1]);
addr->phys_lo = fdt_addr_to_cpu(cell[2]);
break;
} else {
cell += (FDT_PCI_ADDR_CELLS +
FDT_PCI_SIZE_CELLS);
}
}
if (i == num)
goto fail;
return 0;
} else {
ret = -EINVAL;
}
fail:
debug("(not found)\n");
return ret;
}
int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device)
{
const char *list, *end;
int len;
list = fdt_getprop(blob, node, "compatible", &len);
if (!list)
return -ENOENT;
end = list + len;
while (list < end) {
char *s;
len = strlen(list);
if (len >= strlen("pciVVVV,DDDD")) {
s = strstr(list, "pci");
/*
* check if the string is something like pciVVVV,DDDD.RR
* or just pciVVVV,DDDD
*/
if (s && s[7] == ',' &&
(s[12] == '.' || s[12] == 0)) {
s += 3;
*vendor = simple_strtol(s, NULL, 16);
s += 5;
*device = simple_strtol(s, NULL, 16);
return 0;
}
} else {
list += (len + 1);
}
}
return -ENOENT;
}
int fdtdec_get_pci_bdf(const void *blob, int node,
struct fdt_pci_addr *addr, pci_dev_t *bdf)
{
u16 dt_vendor, dt_device, vendor, device;
int ret;
/* get vendor id & device id from the compatible string */
ret = fdtdec_get_pci_vendev(blob, node, &dt_vendor, &dt_device);
if (ret)
return ret;
/* extract the bdf from fdt_pci_addr */
*bdf = addr->phys_hi & 0xffff00;
/* read vendor id & device id based on bdf */
pci_read_config_word(*bdf, PCI_VENDOR_ID, &vendor);
pci_read_config_word(*bdf, PCI_DEVICE_ID, &device);
/*
* Note there are two places in the device tree to fully describe
* a pci device: one is via compatible string with a format of
* "pciVVVV,DDDD" and the other one is the bdf numbers encoded in
* the device node's reg address property. We read the vendor id
* and device id based on bdf and compare the values with the
* "VVVV,DDDD". If they are the same, then we are good to use bdf
* to read device's bar. But if they are different, we have to rely
* on the vendor id and device id extracted from the compatible
* string and locate the real bdf by pci_find_device(). This is
* because normally we may only know device's device number and
* function number when writing device tree. The bus number is
* dynamically assigned during the pci enumeration process.
*/
if ((dt_vendor != vendor) || (dt_device != device)) {
*bdf = pci_find_device(dt_vendor, dt_device, 0);
if (*bdf == -1)
return -ENODEV;
}
return 0;
}
int fdtdec_get_pci_bar32(const void *blob, int node,
struct fdt_pci_addr *addr, u32 *bar)
{
pci_dev_t bdf;
int barnum;
int ret;
/* get pci devices's bdf */
ret = fdtdec_get_pci_bdf(blob, node, addr, &bdf);
if (ret)
return ret;
/* extract the bar number from fdt_pci_addr */
barnum = addr->phys_hi & 0xff;
if ((barnum < PCI_BASE_ADDRESS_0) || (barnum > PCI_CARDBUS_CIS))
return -EINVAL;
barnum = (barnum - PCI_BASE_ADDRESS_0) / 4;
*bar = pci_read_bar32(pci_bus_to_hose(PCI_BUS(bdf)), bdf, barnum);
return 0;
}
#endif
uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
uint64_t default_val)
{
@ -795,20 +952,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
return fdt_get_resource(fdt, node, property, index, res);
}
int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf)
{
const fdt32_t *prop;
int len;
prop = fdt_getprop(fdt, node, "reg", &len);
if (!prop)
return len;
*bdf = fdt32_to_cpu(*prop) & 0xffffff;
return 0;
}
int fdtdec_decode_memory_region(const void *blob, int config_node,
const char *mem_type, const char *suffix,
fdt_addr_t *basep, fdt_size_t *sizep)

View File

@ -788,9 +788,9 @@ static int write_uboot(char *image, int size, struct input_file *uboot,
fdt_strerror(data_size));
return -ENOENT;
}
offset = ucode_ptr - uboot->addr;
offset = (uint32_t)(ucode_ptr + size);
ptr = (void *)image + offset;
ptr[0] = uboot->addr + (data - image);
ptr[0] = (data - image) - size;
ptr[1] = data_size;
debug("Wrote microcode pointer at %x: addr=%x, size=%x\n",
ucode_ptr, ptr[0], ptr[1]);