diff options
58 files changed, 1416 insertions, 715 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ebf72b3..90e828a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -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" diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 5033d2b..62e43c0 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -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 diff --git a/arch/x86/cpu/coreboot/Kconfig b/arch/x86/cpu/coreboot/Kconfig new file mode 100644 index 0000000..e0e3c64 --- /dev/null +++ b/arch/x86/cpu/coreboot/Kconfig @@ -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 diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index cfacc05..6d06d5a 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -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 */ diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c index 6a3dd93..c9983f1 100644 --- a/arch/x86/cpu/coreboot/pci.c +++ b/arch/x86/cpu/coreboot/pci.c @@ -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; } diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c index bd3558a..0edee6b 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -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); } diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index dca68e4..9441666 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -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 */ diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 969b07b..e925310 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -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 */ diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c index 3d7f740..6cf9654 100644 --- a/arch/x86/cpu/ivybridge/gma.c +++ b/arch/x86/cpu/ivybridge/gma.c @@ -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) diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c index 0817751..2440a97 100644 --- a/arch/x86/cpu/ivybridge/microcode_intel.c +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -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); } diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index b95e781..9504735 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -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 diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c new file mode 100644 index 0000000..d5a825d --- /dev/null +++ b/arch/x86/cpu/mtrr.c @@ -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; +} diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index f3492c3..ab1aaaa 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -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); } diff --git a/arch/x86/cpu/queensbay/fsp_support.c b/arch/x86/cpu/queensbay/fsp_support.c index ef1916b..aed3e2b 100644 --- a/arch/x86/cpu/queensbay/fsp_support.c +++ b/arch/x86/cpu/queensbay/fsp_support.c @@ -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; - - 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)) + const struct hob_header *hdr; + struct hob_guid *guid_hob; + + 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) { diff --git a/arch/x86/cpu/queensbay/tnc_dram.c b/arch/x86/cpu/queensbay/tnc_dram.c index 8e97c9b..df79a39 100644 --- a/arch/x86/cpu/queensbay/tnc_dram.c +++ b/arch/x86/cpu/queensbay/tnc_dram.c @@ -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++; } diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 125782c..f51f112 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -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 diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index 3b5d6da..97ed884 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -1,6 +1,4 @@ -dtb-y += link.dtb \ - chromebook_link.dtb \ - alex.dtb \ +dtb-y += chromebook_link.dtb \ crownbay.dtb targets += $(dtb-y) diff --git a/arch/x86/dts/alex.dts b/arch/x86/dts/alex.dts deleted file mode 100644 index 2f13544..0000000 --- a/arch/x86/dts/alex.dts +++ /dev/null @@ -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>; }; -}; diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts index 6f8c5cd..9490b16 120000..100644 --- a/arch/x86/dts/chromebook_link.dts +++ b/arch/x86/dts/chromebook_link.dts @@ -1 +1,216 @@ -link.dts
\ No newline at end of file +/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" + }; + }; + +}; diff --git a/arch/x86/dts/coreboot.dtsi b/arch/x86/dts/coreboot.dtsi deleted file mode 100644 index 65a93ac..0000000 --- a/arch/x86/dts/coreboot.dtsi +++ /dev/null @@ -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"; - }; -}; diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts index 3f43f3c..e81054e 100644 --- a/arch/x86/dts/crownbay.dts +++ b/arch/x86/dts/crownbay.dts @@ -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>; + }; + }; + }; + }; + }; diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts deleted file mode 100644 index a739080..0000000 --- a/arch/x86/dts/link.dts +++ /dev/null @@ -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" - }; - }; - -}; diff --git a/arch/x86/dts/serial.dtsi b/arch/x86/dts/serial.dtsi new file mode 100644 index 0000000..9b097f4 --- /dev/null +++ b/arch/x86/dts/serial.dtsi @@ -0,0 +1,9 @@ +/ { + serial { + compatible = "x86-uart"; + reg = <0x3f8 8>; + reg-shift = <0>; + clock-frequency = <1843200>; + current-speed = <115200>; + }; +}; diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h index bc9b87c..b868283 100644 --- a/arch/x86/include/asm/arch-ivybridge/microcode.h +++ b/arch/x86/include/asm/arch-ivybridge/microcode.h @@ -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 diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h index 380b64e..6cca7f5 100644 --- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_hob.h @@ -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 */ diff --git a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h index 3ae1b66..ebdbd03 100644 --- a/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h +++ b/arch/x86/include/asm/arch-queensbay/fsp/fsp_support.h @@ -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. diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 03d491a..24e3052 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -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 diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 5f05a48..3c11740 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -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 - -#define MTRRcap_MSR 0x0fe -#define MTRRdefType_MSR 0x2ff - -#define MTRRdefTypeEn (1 << 11) -#define MTRRdefTypeFixEn (1 << 10) - -#define SMRRphysBase_MSR 0x1f2 -#define SMRRphysMask_MSR 0x1f3 - -#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) -#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) - -#define MTRRphysMaskValid (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 +/* 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 MTRR_TYPE_COUNT 7 + +#define MTRR_CAP_MSR 0x0fe +#define MTRR_DEF_TYPE_MSR 0x2ff + +#define MTRR_DEF_TYPE_EN (1 << 11) +#define MTRR_DEF_TYPE_FIX_EN (1 << 10) + +#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg)) +#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1) + +#define MTRR_PHYS_MASK_VALID (1 << 11) + +#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 diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index ac1a808..c30dd4c 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -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); diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 73262d7..32d7b98 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -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 diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index d1f8933..1d75cfc 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -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 */ diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c index b552fe6..a0ef037 100644 --- a/arch/x86/lib/cmd_hob.c +++ b/arch/x86/lib/cmd_hob.c @@ -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++; } diff --git a/arch/x86/lib/cmd_mtrr.c b/arch/x86/lib/cmd_mtrr.c new file mode 100644 index 0000000..7e0506b --- /dev/null +++ b/arch/x86/lib/cmd_mtrr.c @@ -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" +); diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index be4eb12..fc211d9 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -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(); } diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c index fb9afed..7f5ba2c 100644 --- a/arch/x86/lib/tsc_timer.c +++ b/arch/x86/lib/tsc_timer.c @@ -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; diff --git a/board/coreboot/coreboot/Kconfig b/board/coreboot/coreboot/Kconfig index 6ca6ced..981de1f 100644 --- a/board/coreboot/coreboot/Kconfig +++ b/board/coreboot/coreboot/Kconfig @@ -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 diff --git a/board/coreboot/coreboot/MAINTAINERS b/board/coreboot/coreboot/MAINTAINERS index 6ce66f5..2736aa0 100644 --- a/board/coreboot/coreboot/MAINTAINERS +++ b/board/coreboot/coreboot/MAINTAINERS @@ -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 diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c index 154faf6..e076ea6 100644 --- a/board/coreboot/coreboot/coreboot.c +++ b/board/coreboot/coreboot/coreboot.c @@ -10,8 +10,10 @@ int arch_early_init_r(void) { +#ifdef CONFIG_CROS_EC if (cros_ec_board_init()) return -1; +#endif return 0; } diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig index 7f79fd2..33a31f3 100644 --- a/board/google/chromebook_link/Kconfig +++ b/board/google/chromebook_link/Kconfig @@ -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 diff --git a/board/intel/crownbay/Kconfig b/board/intel/crownbay/Kconfig index 4709f9b..762663a 100644 --- a/board/intel/crownbay/Kconfig +++ b/board/intel/crownbay/Kconfig @@ -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 diff --git a/common/board_f.c b/common/board_f.c index cfd77f8..3a4b32c 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -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, }; diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig index b83803e..e956835 100644 --- a/configs/chromebook_link_defconfig +++ b/configs/chromebook_link_defconfig @@ -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 diff --git a/configs/coreboot-x86_defconfig b/configs/coreboot-x86_defconfig index 6249db7..3cc034a 100644 --- a/configs/coreboot-x86_defconfig +++ b/configs/coreboot-x86_defconfig @@ -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" diff --git a/doc/README.x86 b/doc/README.x86 index 5fab044..7df8cc5 100644 --- a/doc/README.x86 +++ b/doc/README.x86 @@ -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 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3daf73c..83fd9a0 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -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 */ diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index af6a3ae..7d25cc9 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -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; } diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index a03ad5f..f9e05ad 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -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; diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index af5beba..70c9462 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -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; diff --git a/drivers/serial/serial_x86.c b/drivers/serial/serial_x86.c index e81e035..4bf6062 100644 --- a/drivers/serial/serial_x86.c +++ b/drivers/serial/serial_x86.c @@ -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, diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e69de29..fdbf3f6 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -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. diff --git a/drivers/video/x86_fb.c b/drivers/video/x86_fb.c index 8743a8c..6641033 100644 --- a/drivers/video/x86_fb.c +++ b/drivers/video/x86_fb.c @@ -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; } diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 9c5a1e1..3d14d5f 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -91,6 +91,12 @@ typedef struct global_data { 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 */ } gd_t; diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 8930210..7e6d239 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -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_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 diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h deleted file mode 100644 index 990a2d1..0000000 --- a/include/configs/coreboot.h +++ /dev/null @@ -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 */ diff --git a/include/configs/crownbay.h b/include/configs/crownbay.h index eadb339..b927b1c 100644 --- a/include/configs/crownbay.h +++ b/include/configs/crownbay.h @@ -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 diff --git a/include/fdtdec.h b/include/fdtdec.h index 5effa24..75af750 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -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. * @@ -258,6 +302,60 @@ 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 * returned. @@ -683,17 +781,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property, 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. * * This function handles selection of a memory region. The region is diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 745b390..487122e 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -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) diff --git a/tools/ifdtool.c b/tools/ifdtool.c index fe8366b..590ccc9 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -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]); |