diff options
author | Tom Rini <trini@ti.com> | 2012-12-07 06:43:40 -0700 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2012-12-07 08:47:59 -0700 |
commit | fd4d564b3c80b111f18c93adb14233a6a7ddb0e9 (patch) | |
tree | a42d63aae4f7c07f441321c18098a85cbcc45dee | |
parent | 13d43555a9154cf12255023c47e80d947d7d0604 (diff) | |
parent | ac426b7290e3a96c97fbc093f15cd0660e0edaf2 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-x86
44 files changed, 2347 insertions, 128 deletions
@@ -1414,6 +1414,13 @@ CBFS (Coreboot Filesystem) support boot. See the documentation file README.video for a description of this variable. + CONFIG_VIDEO_VGA + + Enable the VGA video / BIOS for x86. The alternative if you + are using coreboot is to use the coreboot frame buffer + driver. + + - Keyboard Support: CONFIG_KEYBOARD @@ -2205,6 +2212,14 @@ CBFS (Coreboot Filesystem) support HERMES, IP860, RPXlite, LWMON, FLAGADM, TQM8260 +- Access to physical memory region (> 4GB) + Some basic support is provided for operations on memory not + normally accessible to U-Boot - e.g. some architectures + support access to more than 4GB of memory on 32-bit + machines using physical address extension or similar. + Define CONFIG_PHYSMEM to access this basic support, which + currently only supports clearing the memory. + - Error Recovery: CONFIG_PANIC_HANG diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile index 2afd30cd52b..b1d3e959f8f 100644 --- a/arch/x86/cpu/coreboot/Makefile +++ b/arch/x86/cpu/coreboot/Makefile @@ -33,14 +33,14 @@ include $(TOPDIR)/config.mk LIB := $(obj)lib$(SOC).o +SOBJS-$(CONFIG_SYS_COREBOOT) += car.o COBJS-$(CONFIG_SYS_COREBOOT) += coreboot.o COBJS-$(CONFIG_SYS_COREBOOT) += tables.o COBJS-$(CONFIG_SYS_COREBOOT) += ipchecksum.o COBJS-$(CONFIG_SYS_COREBOOT) += sdram.o +COBJS-$(CONFIG_SYS_COREBOOT) += timestamp.o COBJS-$(CONFIG_PCI) += pci.o -SOBJS-$(CONFIG_SYS_COREBOOT) += coreboot_car.o - SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) diff --git a/arch/x86/cpu/coreboot/coreboot_car.S b/arch/x86/cpu/coreboot/car.S index 3cc25755fdb..3cc25755fdb 100644 --- a/arch/x86/cpu/coreboot/coreboot_car.S +++ b/arch/x86/cpu/coreboot/car.S diff --git a/arch/x86/cpu/coreboot/config.mk b/arch/x86/cpu/coreboot/config.mk new file mode 100644 index 00000000000..4858fc37284 --- /dev/null +++ b/arch/x86/cpu/coreboot/config.mk @@ -0,0 +1,23 @@ +# +# Copyright (c) 2012 The Chromium OS Authors. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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; either version 2 of +# the License, or (at your option) any later version. +# +# 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., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +CONFIG_ARCH_DEVICE_TREE := coreboot diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 22a643c9d6b..9c9431e0d9d 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -26,13 +26,15 @@ #include <asm/u-boot-x86.h> #include <flash.h> #include <netdev.h> +#include <asm/msr.h> +#include <asm/cache.h> +#include <asm/io.h> #include <asm/arch-coreboot/tables.h> #include <asm/arch-coreboot/sysinfo.h> +#include <asm/arch/timestamp.h> DECLARE_GLOBAL_DATA_PTR; -unsigned long monitor_flash_len = CONFIG_SYS_MONITOR_LEN; - /* * Miscellaneous platform dependent initializations */ @@ -41,6 +43,9 @@ int cpu_init_f(void) int ret = get_coreboot_info(&lib_sysinfo); if (ret != 0) printf("Failed to parse coreboot tables.\n"); + + timestamp_init(); + return ret; } @@ -62,8 +67,29 @@ int board_early_init_r(void) void show_boot_progress(int val) { -} +#if MIN_PORT80_KCLOCKS_DELAY + static uint32_t prev_stamp; + static uint32_t base; + + /* + * Scale the time counter reading to avoid using 64 bit arithmetics. + * Can't use get_timer() here becuase it could be not yet + * initialized or even implemented. + */ + if (!prev_stamp) { + base = rdtsc() / 1000; + prev_stamp = 0; + } else { + uint32_t now; + do { + now = rdtsc() / 1000 - base; + } while (now < (prev_stamp + MIN_PORT80_KCLOCKS_DELAY)); + prev_stamp = now; + } +#endif + outb(val, 0x80); +} int last_stage_init(void) { @@ -82,6 +108,33 @@ int board_eth_init(bd_t *bis) return pci_eth_init(bis); } -void setup_pcat_compatibility() +#define MTRR_TYPE_WP 5 +#define MTRRcap_MSR 0xfe +#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) +#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) + +int board_final_cleanup(void) { + /* Un-cache the ROM so the kernel has one + * more MTRR available. + * + * 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; + + /* 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(); + } + + /* Issue SMI to Coreboot to lock down ME and registers */ + printf("Finalizing Coreboot\n"); + outb(0xcb, 0xb2); + + return 0; } diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index f8fdac6319e..76274cb88e3 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -27,8 +27,9 @@ #include <asm/e820.h> #include <asm/u-boot-x86.h> #include <asm/global_data.h> -#include <asm/arch-coreboot/sysinfo.h> -#include <asm/arch-coreboot/tables.h> +#include <asm/processor.h> +#include <asm/arch/sysinfo.h> +#include <asm/arch/tables.h> DECLARE_GLOBAL_DATA_PTR; @@ -51,6 +52,58 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) return num_entries; } +/* + * This function looks for the highest region of memory lower than 4GB which + * has enough space for U-Boot where U-Boot is aligned on a page boundary. It + * overrides the default implementation found elsewhere which simply picks the + * end of ram, wherever that may be. The location of the stack, the relocation + * address, and how far U-Boot is moved by relocation are set in the global + * data structure. + */ +int calculate_relocation_address(void) +{ + const uint64_t uboot_size = (uintptr_t)&__bss_end - + (uintptr_t)&__text_start; + const uint64_t total_size = uboot_size + CONFIG_SYS_MALLOC_LEN + + CONFIG_SYS_STACK_SIZE; + uintptr_t dest_addr = 0; + int i; + + for (i = 0; i < lib_sysinfo.n_memranges; i++) { + struct memrange *memrange = &lib_sysinfo.memrange[i]; + /* Force U-Boot to relocate to a page aligned address. */ + uint64_t start = roundup(memrange->base, 1 << 12); + uint64_t end = memrange->base + memrange->size; + + /* Ignore non-memory regions. */ + if (memrange->type != CB_MEM_RAM) + continue; + + /* Filter memory over 4GB. */ + if (end > 0xffffffffULL) + end = 0x100000000ULL; + /* Skip this region if it's too small. */ + if (end - start < total_size) + continue; + + /* Use this address if it's the largest so far. */ + if (end - uboot_size > dest_addr) + dest_addr = end; + } + + /* If no suitable area was found, return an error. */ + if (!dest_addr) + return 1; + + dest_addr -= uboot_size; + dest_addr &= ~((1 << 12) - 1); + gd->relocaddr = dest_addr; + gd->reloc_off = dest_addr - (uintptr_t)&__text_start; + gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN; + + return 0; +} + int dram_init_f(void) { int i; @@ -71,5 +124,20 @@ int dram_init_f(void) int dram_init(void) { + int i, j; + + if (CONFIG_NR_DRAM_BANKS) { + for (i = 0, j = 0; i < lib_sysinfo.n_memranges; i++) { + struct memrange *memrange = &lib_sysinfo.memrange[i]; + + if (memrange->type == CB_MEM_RAM) { + gd->bd->bi_dram[j].start = memrange->base; + gd->bd->bi_dram[j].size = memrange->size; + j++; + if (j >= CONFIG_NR_DRAM_BANKS) + break; + } + } + } return 0; } diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c new file mode 100644 index 00000000000..2ca7a57bce5 --- /dev/null +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * 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 + */ + +#include <common.h> +#include <asm/arch/timestamp.h> +#include <asm/arch/sysinfo.h> +#include <linux/compiler.h> + +struct timestamp_entry { + uint32_t entry_id; + uint64_t entry_stamp; +} __packed; + +struct timestamp_table { + uint64_t base_time; + uint32_t max_entries; + uint32_t num_entries; + struct timestamp_entry entries[0]; /* Variable number of entries */ +} __packed; + +static struct timestamp_table *ts_table __attribute__((section(".data"))); + +void timestamp_init(void) +{ + ts_table = lib_sysinfo.tstamp_table; + timer_set_tsc_base(ts_table->base_time); + timestamp_add_now(TS_U_BOOT_INITTED); +} + +void timestamp_add(enum timestamp_id id, uint64_t ts_time) +{ + struct timestamp_entry *tse; + + if (!ts_table || (ts_table->num_entries == ts_table->max_entries)) + return; + + tse = &ts_table->entries[ts_table->num_entries++]; + tse->entry_id = id; + tse->entry_stamp = ts_time - ts_table->base_time; +} + +void timestamp_add_now(enum timestamp_id id) +{ + timestamp_add(id, rdtsc()); +} diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index fabfbd1bf7f..315e87afeb2 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -34,6 +34,7 @@ #include <common.h> #include <command.h> +#include <asm/control_regs.h> #include <asm/processor.h> #include <asm/processor-flags.h> #include <asm/interrupt.h> @@ -147,16 +148,27 @@ int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r"))); void x86_enable_caches(void) { - const u32 nw_cd_rst = ~(X86_CR0_NW | X86_CR0_CD); + unsigned long cr0; - /* turn on the cache and disable write through */ - asm("movl %%cr0, %%eax\n" - "andl %0, %%eax\n" - "movl %%eax, %%cr0\n" - "wbinvd\n" : : "i" (nw_cd_rst) : "eax"); + cr0 = read_cr0(); + cr0 &= ~(X86_CR0_NW | X86_CR0_CD); + write_cr0(cr0); + wbinvd(); } void enable_caches(void) __attribute__((weak, alias("x86_enable_caches"))); +void x86_disable_caches(void) +{ + unsigned long cr0; + + cr0 = read_cr0(); + cr0 |= X86_CR0_NW | X86_CR0_CD; + wbinvd(); + write_cr0(cr0); + wbinvd(); +} +void disable_caches(void) __attribute__((weak, alias("x86_disable_caches"))); + int x86_init_cache(void) { enable_caches(); @@ -200,3 +212,17 @@ void __reset_cpu(ulong addr) generate_gpf(); /* start the show */ } void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu"))); + +int dcache_status(void) +{ + return !(read_cr0() & 0x40000000); +} + +/* Define these functions to allow ehch-hcd to function */ +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index 43ec3f8b081..dd30a05a9dd 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -28,10 +28,14 @@ */ #include <common.h> +#include <asm/cache.h> +#include <asm/control_regs.h> #include <asm/interrupt.h> #include <asm/io.h> #include <asm/processor-flags.h> #include <linux/compiler.h> +#include <asm/msr.h> +#include <asm/u-boot-x86.h> #define DECLARE_INTERRUPT(x) \ ".globl irq_"#x"\n" \ @@ -41,72 +45,6 @@ "pushl $"#x"\n" \ "jmp irq_common_entry\n" -/* - * Volatile isn't enough to prevent the compiler from reordering the - * read/write functions for the control registers and messing everything up. - * A memory clobber would solve the problem, but would prevent reordering of - * all loads stores around it, which can hurt performance. Solution is to - * use a variable and mimic reads and writes to it to enforce serialisation - */ -static unsigned long __force_order; - -static inline unsigned long read_cr0(void) -{ - unsigned long val; - asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order)); - return val; -} - -static inline unsigned long read_cr2(void) -{ - unsigned long val; - asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order)); - return val; -} - -static inline unsigned long read_cr3(void) -{ - unsigned long val; - asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order)); - return val; -} - -static inline unsigned long read_cr4(void) -{ - unsigned long val; - asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order)); - return val; -} - -static inline unsigned long get_debugreg(int regno) -{ - unsigned long val = 0; /* Damn you, gcc! */ - - switch (regno) { - case 0: - asm("mov %%db0, %0" : "=r" (val)); - break; - case 1: - asm("mov %%db1, %0" : "=r" (val)); - break; - case 2: - asm("mov %%db2, %0" : "=r" (val)); - break; - case 3: - asm("mov %%db3, %0" : "=r" (val)); - break; - case 6: - asm("mov %%db6, %0" : "=r" (val)); - break; - case 7: - asm("mov %%db7, %0" : "=r" (val)); - break; - default: - val = 0; - } - return val; -} - void dump_regs(struct irq_regs *regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; @@ -679,3 +617,32 @@ asm(".globl irq_common_entry\n" \ DECLARE_INTERRUPT(253) \ DECLARE_INTERRUPT(254) \ DECLARE_INTERRUPT(255)); + +#if defined(CONFIG_INTEL_CORE_ARCH) +/* + * Get the number of CPU time counter ticks since it was read first time after + * restart. This yields a free running counter guaranteed to take almost 6 + * years to wrap around even at 100GHz clock rate. + */ +u64 get_ticks(void) +{ + static u64 tick_base; + u64 now_tick = rdtsc(); + + if (!tick_base) + tick_base = now_tick; + + return now_tick - tick_base; +} + +#define PLATFORM_INFO_MSR 0xce + +unsigned long get_tbclk(void) +{ + u32 ratio; + u64 platform_info = native_read_msr(PLATFORM_INFO_MSR); + + ratio = (platform_info >> 8) & 0xff; + return 100 * 1000 * 1000 * ratio; /* 100MHz times Max Non Turbo ratio */ +} +#endif diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index ec12e8044fd..e960e21f6e4 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -55,8 +55,16 @@ _x86boot_start: movl %eax, %cr0 wbinvd + /* Tell 32-bit code it is being entered from an in-RAM copy */ + movw $GD_FLG_WARM_BOOT, %bx + jmp 1f _start: - /* This is the 32-bit cold-reset entry point */ + /* + * This is the 32-bit cold-reset entry point. Initialize %bx to 0 + * in case we're preceeded by some sort of boot stub. + */ + movw $GD_FLG_COLD_BOOT, %bx +1: /* Load the segement registes to match the gdt loaded in start16.S */ movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S index cc393ff54fc..603bf1d2d3e 100644 --- a/arch/x86/cpu/start16.S +++ b/arch/x86/cpu/start16.S @@ -37,6 +37,9 @@ .code16 .globl start16 start16: + /* Set the Cold Boot / Hard Reset flag */ + movl $GD_FLG_COLD_BOOT, %ebx + /* * First we let the BSP do some early initialization * this code have to map the flash to its final position diff --git a/arch/x86/dts/coreboot.dtsi b/arch/x86/dts/coreboot.dtsi new file mode 100644 index 00000000000..4862a59704e --- /dev/null +++ b/arch/x86/dts/coreboot.dtsi @@ -0,0 +1,16 @@ +/include/ "skeleton.dtsi" + +/ { + aliases { + console = "/serial"; + }; + + serial { + compatible = "ns16550"; + reg-shift = <1>; + io-mapped = <1>; + multiplier = <1>; + baudrate = <115200>; + status = "disabled"; + }; +}; diff --git a/arch/x86/dts/skeleton.dtsi b/arch/x86/dts/skeleton.dtsi new file mode 100644 index 00000000000..b41d241de2c --- /dev/null +++ b/arch/x86/dts/skeleton.dtsi @@ -0,0 +1,13 @@ +/* + * Skeleton device tree; the bare minimum needed to boot; just include and + * add a compatible value. The bootloader will typically populate the memory + * node. + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + chosen { }; + aliases { }; + memory { device_type = "memory"; reg = <0 0>; }; +}; diff --git a/arch/x86/include/asm/arch-coreboot/timestamp.h b/arch/x86/include/asm/arch-coreboot/timestamp.h new file mode 100644 index 00000000000..d104912e066 --- /dev/null +++ b/arch/x86/include/asm/arch-coreboot/timestamp.h @@ -0,0 +1,52 @@ +/* + * This file is part of the coreboot project. + * + * 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 + */ + +#ifndef __COREBOOT_TIMESTAMP_H__ +#define __COREBOOT_TIMESTAMP_H__ + +enum timestamp_id { + /* coreboot specific timestamp IDs */ + TS_START_ROMSTAGE = 1, + TS_BEFORE_INITRAM = 2, + TS_AFTER_INITRAM = 3, + TS_END_ROMSTAGE = 4, + TS_START_COPYRAM = 8, + TS_END_COPYRAM = 9, + TS_START_RAMSTAGE = 10, + TS_DEVICE_ENUMERATE = 30, + TS_DEVICE_CONFIGURE = 40, + TS_DEVICE_ENABLE = 50, + TS_DEVICE_INITIALIZE = 60, + TS_DEVICE_DONE = 70, + TS_CBMEM_POST = 75, + TS_WRITE_TABLES = 80, + TS_LOAD_PAYLOAD = 90, + TS_ACPI_WAKE_JUMP = 98, + TS_SELFBOOT_JUMP = 99, + + /* U-Boot entry IDs start at 1000 */ + TS_U_BOOT_INITTED = 1000, /* This is where u-boot starts */ + TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel. */ +}; + +void timestamp_init(void); +void timestamp_add(enum timestamp_id id, uint64_t ts_time); +void timestamp_add_now(enum timestamp_id id); + +#endif diff --git a/arch/x86/include/asm/cache.h b/arch/x86/include/asm/cache.h index 87c9e0be42b..d4678d4916f 100644 --- a/arch/x86/include/asm/cache.h +++ b/arch/x86/include/asm/cache.h @@ -32,4 +32,20 @@ #define ARCH_DMA_MINALIGN 64 #endif +static inline void wbinvd(void) +{ + asm volatile ("wbinvd" : : : "memory"); +} + +static inline void invd(void) +{ + asm volatile("invd" : : : "memory"); +} + +/* Enable caches and write buffer */ +void enable_caches(void); + +/* Disable caches and write buffer */ +void disable_caches(void); + #endif /* __X86_CACHE_H__ */ diff --git a/arch/x86/include/asm/control_regs.h b/arch/x86/include/asm/control_regs.h new file mode 100644 index 00000000000..aa8be30bac7 --- /dev/null +++ b/arch/x86/include/asm/control_regs.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * (C) Copyright 2008-2011 + * Graeme Russ, <graeme.russ@gmail.com> + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se> + * + * Portions of this file are derived from the Linux kernel source + * Copyright (C) 1991, 1992 Linus Torvalds + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __X86_CONTROL_REGS_H +#define __X86_CONTROL_REGS_H + +/* + * The memory clobber prevents the GCC from reordering the read/write order + * of CR0 +*/ +static inline unsigned long read_cr0(void) +{ + unsigned long val; + + asm volatile ("movl %%cr0, %0" : "=r" (val) : : "memory"); + return val; +} + +static inline void write_cr0(unsigned long val) +{ + asm volatile ("movl %0, %%cr0" : : "r" (val) : "memory"); +} + +static inline unsigned long read_cr2(void) +{ + unsigned long val; + + asm volatile("mov %%cr2,%0\n\t" : "=r" (val) : : "memory"); + return val; +} + +static inline unsigned long read_cr3(void) +{ + unsigned long val; + + asm volatile("mov %%cr3,%0\n\t" : "=r" (val) : : "memory"); + return val; +} + +static inline unsigned long read_cr4(void) +{ + unsigned long val; + + asm volatile("mov %%cr4,%0\n\t" : "=r" (val) : : "memory"); + return val; +} + +static inline unsigned long get_debugreg(int regno) +{ + unsigned long val = 0; /* Damn you, gcc! */ + + switch (regno) { + case 0: + asm("mov %%db0, %0" : "=r" (val)); + break; + case 1: + asm("mov %%db1, %0" : "=r" (val)); + break; + case 2: + asm("mov %%db2, %0" : "=r" (val)); + break; + case 3: + asm("mov %%db3, %0" : "=r" (val)); + break; + case 6: + asm("mov %%db6, %0" : "=r" (val)); + break; + case 7: + asm("mov %%db7, %0" : "=r" (val)); + break; + default: + val = 0; + } + return val; +} + +#endif diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 35110a33322..dc6402b67db 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -78,6 +78,12 @@ static inline gd_t *get_fs_gd_ptr(void) #include <asm-generic/global_data_flags.h> +/* + * Our private Global Data Flags + */ +#define GD_FLG_COLD_BOOT 0x00100 /* Cold Boot */ +#define GD_FLG_WARM_BOOT 0x00200 /* Warm Boot */ + #define DECLARE_GLOBAL_DATA_PTR #endif /* __ASM_GBL_DATA_H */ diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h new file mode 100644 index 00000000000..0a37a85ad1f --- /dev/null +++ b/arch/x86/include/asm/gpio.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012, Google Inc. All rights reserved. + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _X86_GPIO_H_ +#define _X86_GPIO_H_ + +#include <asm-generic/gpio.h> + +#endif /* _X86_GPIO_H_ */ diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h index ade694fba33..2f437e03431 100644 --- a/arch/x86/include/asm/init_helpers.h +++ b/arch/x86/include/asm/init_helpers.h @@ -37,5 +37,6 @@ int init_bd_struct_r(void); int flash_init_r(void); int status_led_set_r(void); int set_load_addr_r(void); +int init_func_spi(void); #endif /* !_INIT_HELPERS_H_ */ diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 84a638da78d..86bac90e8e8 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -1,6 +1,8 @@ #ifndef _ASM_IO_H #define _ASM_IO_H +#include <compiler.h> + /* * This file contains the definitions for the x86 IO instructions * inb/inw/inl/outb/outw/outl and the "string versions" of the same @@ -220,7 +222,7 @@ static inline void sync(void) static inline void * map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) { - return (void *)paddr; + return (void *)(uintptr_t)paddr; } /* @@ -233,7 +235,7 @@ static inline void unmap_physmem(void *vaddr, unsigned long flags) static inline phys_addr_t virt_to_phys(void * vaddr) { - return (phys_addr_t)(vaddr); + return (phys_addr_t)(uintptr_t)(vaddr); } /* diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h new file mode 100644 index 00000000000..50175994cff --- /dev/null +++ b/arch/x86/include/asm/msr-index.h @@ -0,0 +1,469 @@ +/* + * Taken from the linux kernel file of the same name + * + * (C) Copyright 2012 + * Graeme Russ, <graeme.russ@gmail.com> + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ASM_X86_MSR_INDEX_H +#define _ASM_X86_MSR_INDEX_H + +/* CPU model specific register (MSR) numbers */ + +/* x86-64 specific MSRs */ +#define MSR_EFER 0xc0000080 /* extended feature register */ +#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */ +#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */ +#define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target */ +#define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */ +#define MSR_FS_BASE 0xc0000100 /* 64bit FS base */ +#define MSR_GS_BASE 0xc0000101 /* 64bit GS base */ +#define MSR_KERNEL_GS_BASE 0xc0000102 /* SwapGS GS shadow */ +#define MSR_TSC_AUX 0xc0000103 /* Auxiliary TSC */ + +/* EFER bits: */ +#define _EFER_SCE 0 /* SYSCALL/SYSRET */ +#define _EFER_LME 8 /* Long mode enable */ +#define _EFER_LMA 10 /* Long mode active (read-only) */ +#define _EFER_NX 11 /* No execute enable */ +#define _EFER_SVME 12 /* Enable virtualization */ +#define _EFER_LMSLE 13 /* Long Mode Segment Limit Enable */ +#define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */ + +#define EFER_SCE (1<<_EFER_SCE) +#define EFER_LME (1<<_EFER_LME) +#define EFER_LMA (1<<_EFER_LMA) +#define EFER_NX (1<<_EFER_NX) +#define EFER_SVME (1<<_EFER_SVME) +#define EFER_LMSLE (1<<_EFER_LMSLE) +#define EFER_FFXSR (1<<_EFER_FFXSR) + +/* Intel MSRs. Some also available on other CPUs */ +#define MSR_IA32_PERFCTR0 0x000000c1 +#define MSR_IA32_PERFCTR1 0x000000c2 +#define MSR_FSB_FREQ 0x000000cd + +#define MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2 +#define NHM_C3_AUTO_DEMOTE (1UL << 25) +#define NHM_C1_AUTO_DEMOTE (1UL << 26) +#define ATM_LNC_C6_AUTO_DEMOTE (1UL << 25) + +#define MSR_MTRRcap 0x000000fe +#define MSR_IA32_BBL_CR_CTL 0x00000119 +#define MSR_IA32_BBL_CR_CTL3 0x0000011e + +#define MSR_IA32_SYSENTER_CS 0x00000174 +#define MSR_IA32_SYSENTER_ESP 0x00000175 +#define MSR_IA32_SYSENTER_EIP 0x00000176 + +#define MSR_IA32_MCG_CAP 0x00000179 +#define MSR_IA32_MCG_STATUS 0x0000017a +#define MSR_IA32_MCG_CTL 0x0000017b + +#define MSR_OFFCORE_RSP_0 0x000001a6 +#define MSR_OFFCORE_RSP_1 0x000001a7 + +#define MSR_IA32_PEBS_ENABLE 0x000003f1 +#define MSR_IA32_DS_AREA 0x00000600 +#define MSR_IA32_PERF_CAPABILITIES 0x00000345 + +#define MSR_MTRRfix64K_00000 0x00000250 +#define MSR_MTRRfix16K_80000 0x00000258 +#define MSR_MTRRfix16K_A0000 0x00000259 +#define MSR_MTRRfix4K_C0000 0x00000268 +#define MSR_MTRRfix4K_C8000 0x00000269 +#define MSR_MTRRfix4K_D0000 0x0000026a +#define MSR_MTRRfix4K_D8000 0x0000026b +#define MSR_MTRRfix4K_E0000 0x0000026c +#define MSR_MTRRfix4K_E8000 0x0000026d +#define MSR_MTRRfix4K_F0000 0x0000026e +#define MSR_MTRRfix4K_F8000 0x0000026f +#define MSR_MTRRdefType 0x000002ff + +#define MSR_IA32_CR_PAT 0x00000277 + +#define MSR_IA32_DEBUGCTLMSR 0x000001d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x000001db +#define MSR_IA32_LASTBRANCHTOIP 0x000001dc +#define MSR_IA32_LASTINTFROMIP 0x000001dd +#define MSR_IA32_LASTINTTOIP 0x000001de + +/* DEBUGCTLMSR bits (others vary by model): */ +#define DEBUGCTLMSR_LBR (1UL << 0) +#define DEBUGCTLMSR_BTF (1UL << 1) +#define DEBUGCTLMSR_TR (1UL << 6) +#define DEBUGCTLMSR_BTS (1UL << 7) +#define DEBUGCTLMSR_BTINT (1UL << 8) +#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9) +#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10) +#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11) + +#define MSR_IA32_MC0_CTL 0x00000400 +#define MSR_IA32_MC0_STATUS 0x00000401 +#define MSR_IA32_MC0_ADDR 0x00000402 +#define MSR_IA32_MC0_MISC 0x00000403 + +#define MSR_AMD64_MC0_MASK 0xc0010044 + +#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x)) +#define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x)) +#define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x)) +#define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x)) + +#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x)) + +/* These are consecutive and not in the normal 4er MCE bank block */ +#define MSR_IA32_MC0_CTL2 0x00000280 +#define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x)) + +#define MSR_P6_PERFCTR0 0x000000c1 +#define MSR_P6_PERFCTR1 0x000000c2 +#define MSR_P6_EVNTSEL0 0x00000186 +#define MSR_P6_EVNTSEL1 0x00000187 + +/* AMD64 MSRs. Not complete. See the architecture manual for a more + complete list. */ + +#define MSR_AMD64_PATCH_LEVEL 0x0000008b +#define MSR_AMD64_NB_CFG 0xc001001f +#define MSR_AMD64_PATCH_LOADER 0xc0010020 +#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 +#define MSR_AMD64_OSVW_STATUS 0xc0010141 +#define MSR_AMD64_DC_CFG 0xc0011022 +#define MSR_AMD64_IBSFETCHCTL 0xc0011030 +#define MSR_AMD64_IBSFETCHLINAD 0xc0011031 +#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032 +#define MSR_AMD64_IBSOPCTL 0xc0011033 +#define MSR_AMD64_IBSOPRIP 0xc0011034 +#define MSR_AMD64_IBSOPDATA 0xc0011035 +#define MSR_AMD64_IBSOPDATA2 0xc0011036 +#define MSR_AMD64_IBSOPDATA3 0xc0011037 +#define MSR_AMD64_IBSDCLINAD 0xc0011038 +#define MSR_AMD64_IBSDCPHYSAD 0xc0011039 +#define MSR_AMD64_IBSCTL 0xc001103a +#define MSR_AMD64_IBSBRTARGET 0xc001103b + +/* Fam 15h MSRs */ +#define MSR_F15H_PERF_CTL 0xc0010200 +#define MSR_F15H_PERF_CTR 0xc0010201 + +/* Fam 10h MSRs */ +#define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058 +#define FAM10H_MMIO_CONF_ENABLE (1<<0) +#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf +#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2 +#define FAM10H_MMIO_CONF_BASE_MASK 0xfffffffULL +#define FAM10H_MMIO_CONF_BASE_SHIFT 20 +#define MSR_FAM10H_NODE_ID 0xc001100c + +/* K8 MSRs */ +#define MSR_K8_TOP_MEM1 0xc001001a +#define MSR_K8_TOP_MEM2 0xc001001d +#define MSR_K8_SYSCFG 0xc0010010 +#define MSR_K8_INT_PENDING_MSG 0xc0010055 +/* C1E active bits in int pending message */ +#define K8_INTP_C1E_ACTIVE_MASK 0x18000000 +#define MSR_K8_TSEG_ADDR 0xc0010112 +#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */ +#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */ +#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */ + +/* K7 MSRs */ +#define MSR_K7_EVNTSEL0 0xc0010000 +#define MSR_K7_PERFCTR0 0xc0010004 +#define MSR_K7_EVNTSEL1 0xc0010001 +#define MSR_K7_PERFCTR1 0xc0010005 +#define MSR_K7_EVNTSEL2 0xc0010002 +#define MSR_K7_PERFCTR2 0xc0010006 +#define MSR_K7_EVNTSEL3 0xc0010003 +#define MSR_K7_PERFCTR3 0xc0010007 +#define MSR_K7_CLK_CTL 0xc001001b +#define MSR_K7_HWCR 0xc0010015 +#define MSR_K7_FID_VID_CTL 0xc0010041 +#define MSR_K7_FID_VID_STATUS 0xc0010042 + +/* K6 MSRs */ +#define MSR_K6_WHCR 0xc0000082 +#define MSR_K6_UWCCR 0xc0000085 +#define MSR_K6_EPMR 0xc0000086 +#define MSR_K6_PSOR 0xc0000087 +#define MSR_K6_PFIR 0xc0000088 + +/* Centaur-Hauls/IDT defined MSRs. */ +#define MSR_IDT_FCR1 0x00000107 +#define MSR_IDT_FCR2 0x00000108 +#define MSR_IDT_FCR3 0x00000109 +#define MSR_IDT_FCR4 0x0000010a + +#define MSR_IDT_MCR0 0x00000110 +#define MSR_IDT_MCR1 0x00000111 +#define MSR_IDT_MCR2 0x00000112 +#define MSR_IDT_MCR3 0x00000113 +#define MSR_IDT_MCR4 0x00000114 +#define MSR_IDT_MCR5 0x00000115 +#define MSR_IDT_MCR6 0x00000116 +#define MSR_IDT_MCR7 0x00000117 +#define MSR_IDT_MCR_CTRL 0x00000120 + +/* VIA Cyrix defined MSRs*/ +#define MSR_VIA_FCR 0x00001107 +#define MSR_VIA_LONGHAUL 0x0000110a +#define MSR_VIA_RNG 0x0000110b +#define MSR_VIA_BCR2 0x00001147 + +/* Transmeta defined MSRs */ +#define MSR_TMTA_LONGRUN_CTRL 0x80868010 +#define MSR_TMTA_LONGRUN_FLAGS 0x80868011 +#define MSR_TMTA_LRTI_READOUT 0x80868018 +#define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a + +/* Intel defined MSRs. */ +#define MSR_IA32_P5_MC_ADDR 0x00000000 +#define MSR_IA32_P5_MC_TYPE 0x00000001 +#define MSR_IA32_TSC 0x00000010 +#define MSR_IA32_PLATFORM_ID 0x00000017 +#define MSR_IA32_EBL_CR_POWERON 0x0000002a +#define MSR_EBC_FREQUENCY_ID 0x0000002c +#define MSR_IA32_FEATURE_CONTROL 0x0000003a + +#define FEATURE_CONTROL_LOCKED (1<<0) +#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) +#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2) + +#define MSR_IA32_APICBASE 0x0000001b +#define MSR_IA32_APICBASE_BSP (1<<8) +#define MSR_IA32_APICBASE_ENABLE (1<<11) +#define MSR_IA32_APICBASE_BASE (0xfffff<<12) + +#define MSR_IA32_UCODE_WRITE 0x00000079 +#define MSR_IA32_UCODE_REV 0x0000008b + +#define MSR_IA32_PERF_STATUS 0x00000198 +#define MSR_IA32_PERF_CTL 0x00000199 + +#define MSR_IA32_MPERF 0x000000e7 +#define MSR_IA32_APERF 0x000000e8 + +#define MSR_IA32_THERM_CONTROL 0x0000019a +#define MSR_IA32_THERM_INTERRUPT 0x0000019b + +#define THERM_INT_HIGH_ENABLE (1 << 0) +#define THERM_INT_LOW_ENABLE (1 << 1) +#define THERM_INT_PLN_ENABLE (1 << 24) + +#define MSR_IA32_THERM_STATUS 0x0000019c + +#define THERM_STATUS_PROCHOT (1 << 0) +#define THERM_STATUS_POWER_LIMIT (1 << 10) + +#define MSR_THERM2_CTL 0x0000019d + +#define MSR_THERM2_CTL_TM_SELECT (1ULL << 16) + +#define MSR_IA32_MISC_ENABLE 0x000001a0 + +#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 + +#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 + +#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1 + +#define PACKAGE_THERM_STATUS_PROCHOT (1 << 0) +#define PACKAGE_THERM_STATUS_POWER_LIMIT (1 << 10) + +#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2 + +#define PACKAGE_THERM_INT_HIGH_ENABLE (1 << 0) +#define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1) +#define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24) + +/* Thermal Thresholds Support */ +#define THERM_INT_THRESHOLD0_ENABLE (1 << 15) +#define THERM_SHIFT_THRESHOLD0 8 +#define THERM_MASK_THRESHOLD0 (0x7f << THERM_SHIFT_THRESHOLD0) +#define THERM_INT_THRESHOLD1_ENABLE (1 << 23) +#define THERM_SHIFT_THRESHOLD1 16 +#define THERM_MASK_THRESHOLD1 (0x7f << THERM_SHIFT_THRESHOLD1) +#define THERM_STATUS_THRESHOLD0 (1 << 6) +#define THERM_LOG_THRESHOLD0 (1 << 7) +#define THERM_STATUS_THRESHOLD1 (1 << 8) +#define THERM_LOG_THRESHOLD1 (1 << 9) + +/* MISC_ENABLE bits: architectural */ +#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) +#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) +#define MSR_IA32_MISC_ENABLE_EMON (1ULL << 7) +#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1ULL << 11) +#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1ULL << 12) +#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16) +#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18) +#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22) +#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << 23) +#define MSR_IA32_MISC_ENABLE_XD_DISABLE (1ULL << 34) + +/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */ +#define MSR_IA32_MISC_ENABLE_X87_COMPAT (1ULL << 2) +#define MSR_IA32_MISC_ENABLE_TM1 (1ULL << 3) +#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE (1ULL << 4) +#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE (1ULL << 6) +#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK (1ULL << 8) +#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE (1ULL << 9) +#define MSR_IA32_MISC_ENABLE_FERR (1ULL << 10) +#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << 10) +#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << 13) +#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE (1ULL << 19) +#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20) +#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT (1ULL << 24) +#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE (1ULL << 37) +#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) +#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39) + +/* P4/Xeon+ specific */ +#define MSR_IA32_MCG_EAX 0x00000180 +#define MSR_IA32_MCG_EBX 0x00000181 +#define MSR_IA32_MCG_ECX 0x00000182 +#define MSR_IA32_MCG_EDX 0x00000183 +#define MSR_IA32_MCG_ESI 0x00000184 +#define MSR_IA32_MCG_EDI 0x00000185 +#define MSR_IA32_MCG_EBP 0x00000186 +#define MSR_IA32_MCG_ESP 0x00000187 +#define MSR_IA32_MCG_EFLAGS 0x00000188 +#define MSR_IA32_MCG_EIP 0x00000189 +#define MSR_IA32_MCG_RESERVED 0x0000018a + +/* Pentium IV performance counter MSRs */ +#define MSR_P4_BPU_PERFCTR0 0x00000300 +#define MSR_P4_BPU_PERFCTR1 0x00000301 +#define MSR_P4_BPU_PERFCTR2 0x00000302 +#define MSR_P4_BPU_PERFCTR3 0x00000303 +#define MSR_P4_MS_PERFCTR0 0x00000304 +#define MSR_P4_MS_PERFCTR1 0x00000305 +#define MSR_P4_MS_PERFCTR2 0x00000306 +#define MSR_P4_MS_PERFCTR3 0x00000307 +#define MSR_P4_FLAME_PERFCTR0 0x00000308 +#define MSR_P4_FLAME_PERFCTR1 0x00000309 +#define MSR_P4_FLAME_PERFCTR2 0x0000030a +#define MSR_P4_FLAME_PERFCTR3 0x0000030b +#define MSR_P4_IQ_PERFCTR0 0x0000030c +#define MSR_P4_IQ_PERFCTR1 0x0000030d +#define MSR_P4_IQ_PERFCTR2 0x0000030e +#define MSR_P4_IQ_PERFCTR3 0x0000030f +#define MSR_P4_IQ_PERFCTR4 0x00000310 +#define MSR_P4_IQ_PERFCTR5 0x00000311 +#define MSR_P4_BPU_CCCR0 0x00000360 +#define MSR_P4_BPU_CCCR1 0x00000361 +#define MSR_P4_BPU_CCCR2 0x00000362 +#define MSR_P4_BPU_CCCR3 0x00000363 +#define MSR_P4_MS_CCCR0 0x00000364 +#define MSR_P4_MS_CCCR1 0x00000365 +#define MSR_P4_MS_CCCR2 0x00000366 +#define MSR_P4_MS_CCCR3 0x00000367 +#define MSR_P4_FLAME_CCCR0 0x00000368 +#define MSR_P4_FLAME_CCCR1 0x00000369 +#define MSR_P4_FLAME_CCCR2 0x0000036a +#define MSR_P4_FLAME_CCCR3 0x0000036b +#define MSR_P4_IQ_CCCR0 0x0000036c +#define MSR_P4_IQ_CCCR1 0x0000036d +#define MSR_P4_IQ_CCCR2 0x0000036e +#define MSR_P4_IQ_CCCR3 0x0000036f +#define MSR_P4_IQ_CCCR4 0x00000370 +#define MSR_P4_IQ_CCCR5 0x00000371 +#define MSR_P4_ALF_ESCR0 0x000003ca +#define MSR_P4_ALF_ESCR1 0x000003cb +#define MSR_P4_BPU_ESCR0 0x000003b2 +#define MSR_P4_BPU_ESCR1 0x000003b3 +#define MSR_P4_BSU_ESCR0 0x000003a0 +#define MSR_P4_BSU_ESCR1 0x000003a1 +#define MSR_P4_CRU_ESCR0 0x000003b8 +#define MSR_P4_CRU_ESCR1 0x000003b9 +#define MSR_P4_CRU_ESCR2 0x000003cc +#define MSR_P4_CRU_ESCR3 0x000003cd +#define MSR_P4_CRU_ESCR4 0x000003e0 +#define MSR_P4_CRU_ESCR5 0x000003e1 +#define MSR_P4_DAC_ESCR0 0x000003a8 +#define MSR_P4_DAC_ESCR1 0x000003a9 +#define MSR_P4_FIRM_ESCR0 0x000003a4 +#define MSR_P4_FIRM_ESCR1 0x000003a5 +#define MSR_P4_FLAME_ESCR0 0x000003a6 +#define MSR_P4_FLAME_ESCR1 0x000003a7 +#define MSR_P4_FSB_ESCR0 0x000003a2 +#define MSR_P4_FSB_ESCR1 0x000003a3 +#define MSR_P4_IQ_ESCR0 0x000003ba +#define MSR_P4_IQ_ESCR1 0x000003bb +#define MSR_P4_IS_ESCR0 0x000003b4 +#define MSR_P4_IS_ESCR1 0x000003b5 +#define MSR_P4_ITLB_ESCR0 0x000003b6 +#define MSR_P4_ITLB_ESCR1 0x000003b7 +#define MSR_P4_IX_ESCR0 0x000003c8 +#define MSR_P4_IX_ESCR1 0x000003c9 +#define MSR_P4_MOB_ESCR0 0x000003aa +#define MSR_P4_MOB_ESCR1 0x000003ab +#define MSR_P4_MS_ESCR0 0x000003c0 +#define MSR_P4_MS_ESCR1 0x000003c1 +#define MSR_P4_PMH_ESCR0 0x000003ac +#define MSR_P4_PMH_ESCR1 0x000003ad +#define MSR_P4_RAT_ESCR0 0x000003bc +#define MSR_P4_RAT_ESCR1 0x000003bd +#define MSR_P4_SAAT_ESCR0 0x000003ae +#define MSR_P4_SAAT_ESCR1 0x000003af +#define MSR_P4_SSU_ESCR0 0x000003be +#define MSR_P4_SSU_ESCR1 0x000003bf /* guess: not in manual */ + +#define MSR_P4_TBPU_ESCR0 0x000003c2 +#define MSR_P4_TBPU_ESCR1 0x000003c3 +#define MSR_P4_TC_ESCR0 0x000003c4 +#define MSR_P4_TC_ESCR1 0x000003c5 +#define MSR_P4_U2L_ESCR0 0x000003b0 +#define MSR_P4_U2L_ESCR1 0x000003b1 + +#define MSR_P4_PEBS_MATRIX_VERT 0x000003f2 + +/* Intel Core-based CPU performance counters */ +#define MSR_CORE_PERF_FIXED_CTR0 0x00000309 +#define MSR_CORE_PERF_FIXED_CTR1 0x0000030a +#define MSR_CORE_PERF_FIXED_CTR2 0x0000030b +#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x0000038d +#define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e +#define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390 + +/* Geode defined MSRs */ +#define MSR_GEODE_BUSCONT_CONF0 0x00001900 + +/* Intel VT MSRs */ +#define MSR_IA32_VMX_BASIC 0x00000480 +#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 +#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482 +#define MSR_IA32_VMX_EXIT_CTLS 0x00000483 +#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484 +#define MSR_IA32_VMX_MISC 0x00000485 +#define MSR_IA32_VMX_CR0_FIXED0 0x00000486 +#define MSR_IA32_VMX_CR0_FIXED1 0x00000487 +#define MSR_IA32_VMX_CR4_FIXED0 0x00000488 +#define MSR_IA32_VMX_CR4_FIXED1 0x00000489 +#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a +#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b +#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c + +/* AMD-V MSRs */ + +#define MSR_VM_CR 0xc0010114 +#define MSR_VM_IGNNE 0xc0010115 +#define MSR_VM_HSAVE_PA 0xc0010117 + +#endif /* _ASM_X86_MSR_INDEX_H */ diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h new file mode 100644 index 00000000000..6030633d102 --- /dev/null +++ b/arch/x86/include/asm/msr.h @@ -0,0 +1,238 @@ +/* + * Taken from the linux kernel file of the same name + * + * (C) Copyright 2012 + * Graeme Russ, <graeme.russ@gmail.com> + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ASM_X86_MSR_H +#define _ASM_X86_MSR_H + +#include <asm/msr-index.h> + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +#include <linux/ioctl.h> + +#define X86_IOC_RDMSR_REGS _IOWR('c', 0xA0, __u32[8]) +#define X86_IOC_WRMSR_REGS _IOWR('c', 0xA1, __u32[8]) + +#ifdef __KERNEL__ + +#include <asm/errno.h> + +struct msr { + union { + struct { + u32 l; + u32 h; + }; + u64 q; + }; +}; + +struct msr_info { + u32 msr_no; + struct msr reg; + struct msr *msrs; + int err; +}; + +struct msr_regs_info { + u32 *regs; + int err; +}; + +static inline unsigned long long native_read_tscp(unsigned int *aux) +{ + unsigned long low, high; + asm volatile(".byte 0x0f,0x01,0xf9" + : "=a" (low), "=d" (high), "=c" (*aux)); + return low | ((u64)high << 32); +} + +/* + * both i386 and x86_64 returns 64-bit value in edx:eax, but gcc's "A" + * constraint has different meanings. For i386, "A" means exactly + * edx:eax, while for x86_64 it doesn't mean rdx:rax or edx:eax. Instead, + * it means rax *or* rdx. + */ +#ifdef CONFIG_X86_64 +#define DECLARE_ARGS(val, low, high) unsigned low, high +#define EAX_EDX_VAL(val, low, high) ((low) | ((u64)(high) << 32)) +#define EAX_EDX_ARGS(val, low, high) "a" (low), "d" (high) +#define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high) +#else +#define DECLARE_ARGS(val, low, high) unsigned long long val +#define EAX_EDX_VAL(val, low, high) (val) +#define EAX_EDX_ARGS(val, low, high) "A" (val) +#define EAX_EDX_RET(val, low, high) "=A" (val) +#endif + +static inline unsigned long long native_read_msr(unsigned int msr) +{ + DECLARE_ARGS(val, low, high); + + asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); + return EAX_EDX_VAL(val, low, high); +} + +static inline void native_write_msr(unsigned int msr, + unsigned low, unsigned high) +{ + asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); +} + +extern unsigned long long native_read_tsc(void); + +extern int native_rdmsr_safe_regs(u32 regs[8]); +extern int native_wrmsr_safe_regs(u32 regs[8]); + +static inline unsigned long long native_read_pmc(int counter) +{ + DECLARE_ARGS(val, low, high); + + asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); + return EAX_EDX_VAL(val, low, high); +} + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else +#include <errno.h> +/* + * Access to machine-specific registers (available on 586 and better only) + * Note: the rd* operations modify the parameters directly (without using + * pointer indirection), this allows gcc to optimize better + */ + +#define rdmsr(msr, val1, val2) \ +do { \ + u64 __val = native_read_msr((msr)); \ + (void)((val1) = (u32)__val); \ + (void)((val2) = (u32)(__val >> 32)); \ +} while (0) + +static inline void wrmsr(unsigned msr, unsigned low, unsigned high) +{ + native_write_msr(msr, low, high); +} + +#define rdmsrl(msr, val) \ + ((val) = native_read_msr((msr))) + +#define wrmsrl(msr, val) \ + native_write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32)) + +/* rdmsr with exception handling */ +#define rdmsr_safe(msr, p1, p2) \ +({ \ + int __err; \ + u64 __val = native_read_msr_safe((msr), &__err); \ + (*p1) = (u32)__val; \ + (*p2) = (u32)(__val >> 32); \ + __err; \ +}) + +static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) +{ + u32 gprs[8] = { 0 }; + int err; + + gprs[1] = msr; + gprs[7] = 0x9c5a203a; + + err = native_rdmsr_safe_regs(gprs); + + *p = gprs[0] | ((u64)gprs[2] << 32); + + return err; +} + +static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) +{ + u32 gprs[8] = { 0 }; + + gprs[0] = (u32)val; + gprs[1] = msr; + gprs[2] = val >> 32; + gprs[7] = 0x9c5a203a; + + return native_wrmsr_safe_regs(gprs); +} + +static inline int rdmsr_safe_regs(u32 regs[8]) +{ + return native_rdmsr_safe_regs(regs); +} + +static inline int wrmsr_safe_regs(u32 regs[8]) +{ + return native_wrmsr_safe_regs(regs); +} + +#define rdtscl(low) \ + ((low) = (u32)__native_read_tsc()) + +#define rdtscll(val) \ + ((val) = __native_read_tsc()) + +#define rdpmc(counter, low, high) \ +do { \ + u64 _l = native_read_pmc((counter)); \ + (low) = (u32)_l; \ + (high) = (u32)(_l >> 32); \ +} while (0) + +#define rdtscp(low, high, aux) \ +do { \ + unsigned long long _val = native_read_tscp(&(aux)); \ + (low) = (u32)_val; \ + (high) = (u32)(_val >> 32); \ +} while (0) + +#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux)) + +#endif /* !CONFIG_PARAVIRT */ + + +#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \ + (u32)((val) >> 32)) + +#define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2)) + +#define write_rdtscp_aux(val) wrmsr(MSR_TSC_AUX, (val), 0) + +struct msr *msrs_alloc(void); +void msrs_free(struct msr *msrs); + +#ifdef CONFIG_SMP +int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); +int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); +void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); +void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); +int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); +int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); +int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); +int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); + +#endif /* CONFIG_SMP */ +#endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_X86_MSR_H */ diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h new file mode 100644 index 00000000000..6842da500a9 --- /dev/null +++ b/arch/x86/include/asm/mtrr.h @@ -0,0 +1,206 @@ +/* + * Generic MTRR (Memory Type Range Register) ioctls. + * Taken from the Linux kernel + * + * (C) Copyright 2012 + * Graeme Russ, <graeme.russ@gmail.com> + * + * Copyright (C) 1997-1999 Richard Gooch <rgooch@atnf.csiro.au> + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ASM_X86_MTRR_H +#define _ASM_X86_MTRR_H + +#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) +#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +#include <linux/ioctl.h> +#include <errno.h> + +#define MTRR_IOCTL_BASE 'M' + +struct mtrr_sentry { + unsigned long base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int type; /* Type of region */ +}; + +/* + * Warning: this structure has a different order from i386 + * on x86-64. The 32bit emulation code takes care of that. + * But you need to use this for 64bit, otherwise your X server + * will break. + */ + +#ifdef __i386__ +struct mtrr_gentry { + unsigned int regnum; /* Register number */ + unsigned long base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int type; /* Type of region */ +}; + +#else /* __i386__ */ + +struct mtrr_gentry { + unsigned long base; /* Base address */ + unsigned int size; /* Size of region */ + unsigned int regnum; /* Register number */ + unsigned int type; /* Type of region */ +}; +#endif /* !__i386__ */ + +struct mtrr_var_range { + __u32 base_lo; + __u32 base_hi; + __u32 mask_lo; + __u32 mask_hi; +}; + +/* + * In the Intel processor's MTRR interface, the MTRR type is always held in + * an 8 bit field: + */ +typedef __u8 mtrr_type; + +#define MTRR_NUM_FIXED_RANGES 88 +#define MTRR_MAX_VAR_RANGES 256 + +struct mtrr_state_type { + struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES]; + mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES]; + unsigned char enabled; + unsigned char have_fixed; + mtrr_type def_type; +}; + +/* These are the various ioctls */ +#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry) +#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry) +#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry) +#define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry) +#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry) +#define MTRRIOC_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry) +#define MTRRIOC_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry) +#define MTRRIOC_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry) +#define MTRRIOC_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry) +#define MTRRIOC_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry) + +/* These are the region types */ +#define MTRR_TYPE_UNCACHABLE 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 + +#ifdef __KERNEL__ + +/* The following functions are for use by other drivers */ +# ifdef CONFIG_MTRR +extern u8 mtrr_type_lookup(u64 addr, u64 end); +extern void mtrr_save_fixed_ranges(void *); +extern void mtrr_save_state(void); +extern int mtrr_add(unsigned long base, unsigned long size, + unsigned int type, bool increment); +extern int mtrr_add_page(unsigned long base, unsigned long size, + unsigned int type, bool increment); +extern int mtrr_del(int reg, unsigned long base, unsigned long size); +extern int mtrr_del_page(int reg, unsigned long base, unsigned long size); +extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi); +extern void mtrr_ap_init(void); +extern void mtrr_bp_init(void); +extern void set_mtrr_aps_delayed_init(void); +extern void mtrr_aps_init(void); +extern void mtrr_bp_restore(void); +extern int mtrr_trim_uncached_memory(unsigned long end_pfn); +extern int amd_special_default_mtrr(void); +# else +static inline u8 mtrr_type_lookup(u64 addr, u64 end) +{ + /* + * Return no-MTRRs: + */ + return 0xff; +} +#define mtrr_save_fixed_ranges(arg) do {} while (0) +#define mtrr_save_state() do {} while (0) +static inline int mtrr_del(int reg, unsigned long base, unsigned long size) +{ + return -ENODEV; +} +static inline int mtrr_del_page(int reg, unsigned long base, unsigned long size) +{ + return -ENODEV; +} +static inline int mtrr_trim_uncached_memory(unsigned long end_pfn) +{ + return 0; +} +static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) +{ +} + +#define mtrr_ap_init() do {} while (0) +#define mtrr_bp_init() do {} while (0) +#define set_mtrr_aps_delayed_init() do {} while (0) +#define mtrr_aps_init() do {} while (0) +#define mtrr_bp_restore() do {} while (0) +# endif + +#ifdef CONFIG_COMPAT +#include <linux/compat.h> + +struct mtrr_sentry32 { + compat_ulong_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ +}; + +struct mtrr_gentry32 { + compat_ulong_t regnum; /* Register number */ + compat_uint_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ +}; + +#define MTRR_IOCTL_BASE 'M' + +#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32) +#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32) +#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32) +#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32) +#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32) +#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32) +#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32) +#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32) +#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32) +#define MTRRIOC32_KILL_PAGE_ENTRY \ + _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32) +#endif /* CONFIG_COMPAT */ + +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_X86_MTRR_H */ diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h index 9a40e383eb3..e9fde88f7d4 100644 --- a/arch/x86/include/asm/types.h +++ b/arch/x86/include/asm/types.h @@ -45,8 +45,8 @@ typedef unsigned long long u64; typedef u32 dma_addr_t; -typedef unsigned long phys_addr_t; -typedef unsigned long phys_size_t; +typedef unsigned long long phys_addr_t; +typedef unsigned long long phys_size_t; #endif /* __KERNEL__ */ diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index a4a5ae05d11..99062e59553 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -63,9 +63,20 @@ u32 isa_map_rom(u32 bus_addr, int size); /* arch/x86/lib/... */ int video_bios_init(void); -int video_init(void); void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn)); void board_init_f_r(void) __attribute__ ((noreturn)); +/* Read the time stamp counter */ +static inline uint64_t rdtsc(void) +{ + uint32_t high, low; + __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)); + return (((uint64_t)high) << 32) | low; +} + +/* board/... */ +void timer_set_tsc_base(uint64_t new_base); +uint64_t timer_get_tsc(void); + #endif /* _U_BOOT_I386_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 4325b2502ea..0a52cc896c6 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -32,7 +32,7 @@ COBJS-y += realmode.o SOBJS-y += realmode_switch.o COBJS-$(CONFIG_SYS_PC_BIOS) += bios_setup.o -COBJS-$(CONFIG_VIDEO) += video_bios.o +COBJS-$(CONFIG_VIDEO_VGA) += video_bios.o endif COBJS-y += board.o @@ -47,9 +47,10 @@ COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o COBJS-$(CONFIG_PCI) += pci.o COBJS-$(CONFIG_PCI) += pci_type1.o COBJS-y += relocate.o +COBJS-y += physmem.o COBJS-y += string.o COBJS-$(CONFIG_SYS_X86_ISR_TIMER) += timer.o -COBJS-$(CONFIG_VIDEO) += video.o +COBJS-$(CONFIG_VIDEO_VGA) += video.o COBJS-$(CONFIG_CMD_ZBOOT) += zimage.o SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index c7d89604cae..22bc26dde90 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -99,10 +99,17 @@ typedef int (init_fnc_t) (void); init_fnc_t *init_sequence_f[] = { cpu_init_f, board_early_init_f, +#ifdef CONFIG_OF_CONTROL + find_fdt, + fdtdec_check_fdt, +#endif env_init, init_baudrate_f, serial_init, console_init_f, +#ifdef CONFIG_OF_CONTROL + prepare_fdt, +#endif dram_init_f, calculate_relocation_address, @@ -154,6 +161,9 @@ init_fnc_t *init_sequence_r[] = { #ifndef CONFIG_SYS_NO_FLASH flash_init_r, #endif +#ifdef CONFIG_SPI + init_func_spi; +#endif env_relocate_r, #ifdef CONFIG_PCI pci_init_r, diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 87c7263fcb5..3eec9a61d66 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -28,9 +28,11 @@ #include <net.h> #include <ide.h> #include <serial.h> +#include <spi.h> #include <status_led.h> #include <asm/processor.h> #include <asm/u-boot-x86.h> +#include <linux/compiler.h> #include <asm/init_helpers.h> @@ -71,7 +73,7 @@ int init_baudrate_f(void) return 0; } -int calculate_relocation_address(void) +__weak int calculate_relocation_address(void) { ulong text_start = (ulong)&__text_start; ulong bss_end = (ulong)&__bss_end; @@ -85,15 +87,16 @@ int calculate_relocation_address(void) /* Stack is at top of available memory */ dest_addr = gd->ram_size; - gd->start_addr_sp = dest_addr; - /* U-Boot is below the stack */ - dest_addr -= CONFIG_SYS_STACK_SIZE; + /* U-Boot is at the top */ dest_addr -= (bss_end - text_start); dest_addr &= ~15; gd->relocaddr = dest_addr; gd->reloc_off = (dest_addr - text_start); + /* Stack is at the bottom, so it can grow down */ + gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN; + return 0; } @@ -160,3 +163,40 @@ int set_load_addr_r(void) return 0; } + +int init_func_spi(void) +{ + puts("SPI: "); + spi_init(); + puts("ready\n"); + return 0; +} + +#ifdef CONFIG_OF_CONTROL +int find_fdt(void) +{ +#ifdef CONFIG_OF_EMBED + /* Get a pointer to the FDT */ + gd->fdt_blob = _binary_dt_dtb_start; +#elif defined CONFIG_OF_SEPARATE + /* FDT is at end of image */ + gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE); +#endif + /* Allow the early environment to override the fdt address */ + gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, + (uintptr_t)gd->fdt_blob); + + return 0; +} + +int prepare_fdt(void) +{ + /* For now, put this check after the console is ready */ + if (fdtdec_prepare_fdt()) { + panic("** CONFIG_OF_CONTROL defined but no FDT - please see " + "doc/README.fdt-control"); + } + + return 0; +} +#endif diff --git a/arch/x86/lib/init_wrappers.c b/arch/x86/lib/init_wrappers.c index 71449fe6fa4..cca018fa9b0 100644 --- a/arch/x86/lib/init_wrappers.c +++ b/arch/x86/lib/init_wrappers.c @@ -21,6 +21,7 @@ * MA 02111-1307 USA */ #include <common.h> +#include <environment.h> #include <serial.h> #include <kgdb.h> #include <scsi.h> @@ -36,10 +37,35 @@ int serial_initialize_r(void) return 0; } +/* + * Tell if it's OK to load the environment early in boot. + * + * If CONFIG_OF_CONFIG is defined, we'll check with the FDT to see + * if this is OK (defaulting to saying it's not OK). + * + * NOTE: Loading the environment early can be a bad idea if security is + * important, since no verification is done on the environment. + * + * @return 0 if environment should not be loaded, !=0 if it is ok to load + */ +static int should_load_env(void) +{ +#ifdef CONFIG_OF_CONTROL + return fdtdec_get_config_int(gd->fdt_blob, "load-environment", 0); +#elif defined CONFIG_DELAY_ENVIRONMENT + return 0; +#else + return 1; +#endif +} + int env_relocate_r(void) { /* initialize environment */ - env_relocate(); + if (should_load_env()) + env_relocate(); + else + set_default_env(NULL); return 0; } diff --git a/arch/x86/lib/physmem.c b/arch/x86/lib/physmem.c new file mode 100644 index 00000000000..18f0e62acd0 --- /dev/null +++ b/arch/x86/lib/physmem.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#include <common.h> +#include <physmem.h> +#include <linux/compiler.h> + +/* Large pages are 2MB. */ +#define LARGE_PAGE_SIZE ((1 << 20) * 2) + +/* + * Paging data structures. + */ + +struct pdpe { + uint64_t p:1; + uint64_t mbz_0:2; + uint64_t pwt:1; + uint64_t pcd:1; + uint64_t mbz_1:4; + uint64_t avl:3; + uint64_t base:40; + uint64_t mbz_2:12; +}; + +typedef struct pdpe pdpt_t[512]; + +struct pde { + uint64_t p:1; /* present */ + uint64_t rw:1; /* read/write */ + uint64_t us:1; /* user/supervisor */ + uint64_t pwt:1; /* page-level writethrough */ + uint64_t pcd:1; /* page-level cache disable */ + uint64_t a:1; /* accessed */ + uint64_t d:1; /* dirty */ + uint64_t ps:1; /* page size */ + uint64_t g:1; /* global page */ + uint64_t avl:3; /* available to software */ + uint64_t pat:1; /* page-attribute table */ + uint64_t mbz_0:8; /* must be zero */ + uint64_t base:31; /* base address */ +}; + +typedef struct pde pdt_t[512]; + +static pdpt_t pdpt __aligned(4096); +static pdt_t pdts[4] __aligned(4096); + +/* + * Map a virtual address to a physical address and optionally invalidate any + * old mapping. + * + * @param virt The virtual address to use. + * @param phys The physical address to use. + * @param invlpg Whether to use invlpg to clear any old mappings. + */ +static void x86_phys_map_page(uintptr_t virt, phys_addr_t phys, int invlpg) +{ + /* Extract the two bit PDPT index and the 9 bit PDT index. */ + uintptr_t pdpt_idx = (virt >> 30) & 0x3; + uintptr_t pdt_idx = (virt >> 21) & 0x1ff; + + /* Set up a handy pointer to the appropriate PDE. */ + struct pde *pde = &(pdts[pdpt_idx][pdt_idx]); + + memset(pde, 0, sizeof(struct pde)); + pde->p = 1; + pde->rw = 1; + pde->us = 1; + pde->ps = 1; + pde->base = phys >> 21; + + if (invlpg) { + /* Flush any stale mapping out of the TLBs. */ + __asm__ __volatile__( + "invlpg %0\n\t" + : + : "m" (*(uint8_t *)virt) + ); + } +} + +/* Identity map the lower 4GB and turn on paging with PAE. */ +static void x86_phys_enter_paging(void) +{ + phys_addr_t page_addr; + unsigned i; + + /* Zero out the page tables. */ + memset(pdpt, 0, sizeof(pdpt)); + memset(pdts, 0, sizeof(pdts)); + + /* Set up the PDPT. */ + for (i = 0; i < ARRAY_SIZE(pdts); i++) { + pdpt[i].p = 1; + pdpt[i].base = ((uintptr_t)&pdts[i]) >> 12; + } + + /* Identity map everything up to 4GB. */ + for (page_addr = 0; page_addr < (1ULL << 32); + page_addr += LARGE_PAGE_SIZE) { + /* There's no reason to invalidate the TLB with paging off. */ + x86_phys_map_page(page_addr, page_addr, 0); + } + + /* Turn on paging */ + __asm__ __volatile__( + /* Load the page table address */ + "movl %0, %%cr3\n\t" + /* Enable pae */ + "movl %%cr4, %%eax\n\t" + "orl $0x00000020, %%eax\n\t" + "movl %%eax, %%cr4\n\t" + /* Enable paging */ + "movl %%cr0, %%eax\n\t" + "orl $0x80000000, %%eax\n\t" + "movl %%eax, %%cr0\n\t" + : + : "r" (pdpt) + : "eax" + ); +} + +/* Disable paging and PAE mode. */ +static void x86_phys_exit_paging(void) +{ + /* Turn off paging */ + __asm__ __volatile__ ( + /* Disable paging */ + "movl %%cr0, %%eax\n\t" + "andl $0x7fffffff, %%eax\n\t" + "movl %%eax, %%cr0\n\t" + /* Disable pae */ + "movl %%cr4, %%eax\n\t" + "andl $0xffffffdf, %%eax\n\t" + "movl %%eax, %%cr4\n\t" + : + : + : "eax" + ); +} + +/* + * Set physical memory to a particular value when the whole region fits on one + * page. + * + * @param map_addr The address that starts the physical page. + * @param offset How far into that page to start setting a value. + * @param c The value to set memory to. + * @param size The size in bytes of the area to set. + */ +static void x86_phys_memset_page(phys_addr_t map_addr, uintptr_t offset, int c, + unsigned size) +{ + /* + * U-Boot should be far away from the beginning of memory, so that's a + * good place to map our window on top of. + */ + const uintptr_t window = LARGE_PAGE_SIZE; + + /* Make sure the window is below U-Boot. */ + assert(window + LARGE_PAGE_SIZE < + gd->relocaddr - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_STACK_SIZE); + /* Map the page into the window and then memset the appropriate part. */ + x86_phys_map_page(window, map_addr, 1); + memset((void *)(window + offset), c, size); +} + +/* + * A physical memory anologue to memset with matching parameters and return + * value. + */ +phys_addr_t arch_phys_memset(phys_addr_t start, int c, phys_size_t size) +{ + const phys_addr_t max_addr = (phys_addr_t)~(uintptr_t)0; + const phys_addr_t orig_start = start; + + if (!size) + return orig_start; + + /* Handle memory below 4GB. */ + if (start <= max_addr) { + phys_size_t low_size = MIN(max_addr + 1 - start, size); + void *start_ptr = (void *)(uintptr_t)start; + + assert(((phys_addr_t)(uintptr_t)start) == start); + memset(start_ptr, c, low_size); + start += low_size; + size -= low_size; + } + + /* Use paging and PAE to handle memory above 4GB up to 64GB. */ + if (size) { + phys_addr_t map_addr = start & ~(LARGE_PAGE_SIZE - 1); + phys_addr_t offset = start - map_addr; + + x86_phys_enter_paging(); + + /* Handle the first partial page. */ + if (offset) { + phys_addr_t end = + MIN(map_addr + LARGE_PAGE_SIZE, start + size); + phys_size_t cur_size = end - start; + x86_phys_memset_page(map_addr, offset, c, cur_size); + size -= cur_size; + map_addr += LARGE_PAGE_SIZE; + } + /* Handle the complete pages. */ + while (size > LARGE_PAGE_SIZE) { + x86_phys_memset_page(map_addr, 0, c, LARGE_PAGE_SIZE); + size -= LARGE_PAGE_SIZE; + map_addr += LARGE_PAGE_SIZE; + } + /* Handle the last partial page. */ + if (size) + x86_phys_memset_page(map_addr, 0, c, size); + + x86_phys_exit_paging(); + } + return orig_start; +} diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index 200baaba6a2..23edca95269 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -80,12 +80,12 @@ int do_elf_reloc_fixups(void) /* Check that the target points into .text */ if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE && - *offset_ptr_ram < + *offset_ptr_ram <= (CONFIG_SYS_TEXT_BASE + size)) { *offset_ptr_ram += gd->reloc_off; } } - } while (re_src++ < re_end); + } while (++re_src < re_end); return 0; } diff --git a/arch/x86/lib/timer.c b/arch/x86/lib/timer.c index fd7032e92c9..a13424b3e37 100644 --- a/arch/x86/lib/timer.c +++ b/arch/x86/lib/timer.c @@ -37,6 +37,7 @@ struct timer_isr_function { static struct timer_isr_function *first_timer_isr; static unsigned long system_ticks; +static uint64_t base_value; /* * register_timer_isr() allows multiple architecture and board specific @@ -98,3 +99,19 @@ ulong get_timer(ulong base) { return system_ticks - base; } + +void timer_set_tsc_base(uint64_t new_base) +{ + base_value = new_base; +} + +uint64_t timer_get_tsc(void) +{ + uint64_t time_now; + + time_now = rdtsc(); + if (!base_value) + base_value = time_now; + + return time_now - base_value; +} diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index b8c672babdd..46af391f29f 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -36,6 +36,10 @@ #include <asm/realmode.h> #include <asm/byteorder.h> #include <asm/bootparam.h> +#ifdef CONFIG_SYS_COREBOOT +#include <asm/arch/timestamp.h> +#endif +#include <linux/compiler.h> /* * Memory lay-out: @@ -279,10 +283,23 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, return 0; } +/* + * Implement a weak default function for boards that optionally + * need to clean up the system before jumping to the kernel. + */ +__weak void board_final_cleanup(void) +{ +} + void boot_zimage(void *setup_base, void *load_address) { + board_final_cleanup(); + printf("\nStarting kernel ...\n\n"); +#ifdef CONFIG_SYS_COREBOOT + timestamp_add_now(TS_U_BOOT_START_KERNEL); +#endif #if defined CONFIG_ZBOOT_32 /* * Set %ebx, %ebp, and %edi to 0, %esi to point to the boot_params @@ -292,9 +309,9 @@ void boot_zimage(void *setup_base, void *load_address) * itself in arch/i386/cpu/cpu.c. */ __asm__ __volatile__ ( - "movl $0, %%ebp \n" - "cli \n" - "jmp %[kernel_entry] \n" + "movl $0, %%ebp\n" + "cli\n" + "jmp *%[kernel_entry]\n" :: [kernel_entry]"a"(load_address), [boot_params] "S"(setup_base), "b"(0), "D"(0) diff --git a/board/chromebook-x86/dts/x86-alex.dts b/board/chromebook-x86/dts/alex.dts index bd90d185f1c..cb6a9e41eed 100644 --- a/board/chromebook-x86/dts/x86-alex.dts +++ b/board/chromebook-x86/dts/alex.dts @@ -1,5 +1,7 @@ /dts-v1/; +/include/ "coreboot.dtsi" + / { #address-cells = <1>; #size-cells = <1>; @@ -10,19 +12,11 @@ silent_console = <0>; }; - aliases { - console = "/serial@e0401000"; - }; + gpio: gpio {}; - serial@e0401000 { - compatible = "ns16550"; - reg = <0xe0401000 0x40>; - id = <1>; - reg-shift = <1>; - baudrate = <115200>; - clock-frequency = <4000000>; - multiplier = <1>; - status = "ok"; + serial { + reg = <0x3f8 8>; + clock-frequency = <115200>; }; chosen { }; diff --git a/board/chromebook-x86/dts/link.dts b/board/chromebook-x86/dts/link.dts new file mode 100644 index 00000000000..af60f59de78 --- /dev/null +++ b/board/chromebook-x86/dts/link.dts @@ -0,0 +1,24 @@ +/dts-v1/; + +/include/ "coreboot.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "Google Link"; + compatible = "google,link", "intel,celeron-ivybridge"; + + config { + silent_console = <0>; + }; + + gpio: gpio {}; + + serial { + reg = <0x3f8 8>; + clock-frequency = <115200>; + }; + + chosen { }; + memory { device_type = "memory"; reg = <0 0>; }; +}; diff --git a/boards.cfg b/boards.cfg index 70a1569321f..35f38f31d4b 100644 --- a/boards.cfg +++ b/boards.cfg @@ -1100,7 +1100,7 @@ gr_cpci_ax2000 sparc leon3 - gaisler gr_ep2s60 sparc leon3 - gaisler grsim sparc leon3 - gaisler gr_xc3s_1500 sparc leon3 - gaisler -coreboot-x86 x86 x86 coreboot chromebook-x86 coreboot coreboot:SYS_TEXT_BASE=0xFC0000 +coreboot-x86 x86 x86 coreboot chromebook-x86 coreboot coreboot:SYS_TEXT_BASE=0x01110000 eNET x86 x86 eNET - sc520 eNET:SYS_TEXT_BASE=0x38040000 eNET_SRAM x86 x86 eNET - sc520 eNET:SYS_TEXT_BASE=0x19000000 # Target ARCH CPU Board name Vendor SoC Options diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d50ac3bfefd..2d97b4f1e4d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libgpio.o COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o +COBJS-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c new file mode 100644 index 00000000000..6fed01f71a0 --- /dev/null +++ b/drivers/gpio/intel_ich6_gpio.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * This is a GPIO driver for Intel ICH6 and later. The x86 GPIOs are accessed + * through the PCI bus. Each PCI device has 256 bytes of configuration space, + * consisting of a standard header and a device-specific set of registers. PCI + * bus 0, device 31, function 0 gives us access to the chipset GPIOs (among + * other things). Within the PCI configuration space, the GPIOBASE register + * tells us where in the device's I/O region we can find more registers to + * actually access the GPIOs. + * + * PCI bus/device/function 0:1f:0 => PCI config registers + * PCI config register "GPIOBASE" + * PCI I/O space + [GPIOBASE] => start of GPIO registers + * GPIO registers => gpio pin function, direction, value + * + * + * Danger Will Robinson! Bank 0 (GPIOs 0-31) seems to be fairly stable. Most + * ICH versions have more, but the decoding the matrix that describes them is + * absurdly complex and constantly changing. We'll provide Bank 1 and Bank 2, + * but they will ONLY work for certain unspecified chipsets because the offset + * from GPIOBASE changes randomly. Even then, many GPIOs are unimplemented or + * reserved or subject to arcane restrictions. + */ + +#include <common.h> +#include <pci.h> +#include <asm/gpio.h> +#include <asm/io.h> + +/* Where in config space is the register that points to the GPIO registers? */ +#define PCI_CFG_GPIOBASE 0x48 + +#define NUM_BANKS 3 + +/* Within the I/O space, where are the registers to control the GPIOs? */ +static struct { + u8 use_sel; + u8 io_sel; + u8 lvl; +} gpio_bank[NUM_BANKS] = { + { 0x00, 0x04, 0x0c }, /* Bank 0 */ + { 0x30, 0x34, 0x38 }, /* Bank 1 */ + { 0x40, 0x44, 0x48 } /* Bank 2 */ +}; + +static pci_dev_t dev; /* handle for 0:1f:0 */ +static u32 gpiobase; /* offset into I/O space */ +static int found_it_once; /* valid GPIO device? */ +static u32 lock[NUM_BANKS]; /* "lock" for access to pins */ + +static int bad_arg(int num, int *bank, int *bitnum) +{ + int i = num / 32; + int j = num % 32; + + if (num < 0 || i > NUM_BANKS) { + debug("%s: bogus gpio num: %d\n", __func__, num); + return -1; + } + *bank = i; + *bitnum = j; + return 0; +} + +static int mark_gpio(int bank, int bitnum) +{ + if (lock[bank] & (1UL << bitnum)) { + debug("%s: %d.%d already marked\n", __func__, bank, bitnum); + return -1; + } + lock[bank] |= (1 << bitnum); + return 0; +} + +static void clear_gpio(int bank, int bitnum) +{ + lock[bank] &= ~(1 << bitnum); +} + +static int notmine(int num, int *bank, int *bitnum) +{ + if (bad_arg(num, bank, bitnum)) + return -1; + return !(lock[*bank] & (1UL << *bitnum)); +} + +static int gpio_init(void) +{ + u8 tmpbyte; + u16 tmpword; + u32 tmplong; + + /* Have we already done this? */ + if (found_it_once) + return 0; + + /* Where should it be? */ + dev = PCI_BDF(0, 0x1f, 0); + + /* Is the device present? */ + pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword); + if (tmpword != PCI_VENDOR_ID_INTEL) { + debug("%s: wrong VendorID\n", __func__); + return -1; + } + + pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword); + debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword); + /* + * We'd like to validate the Device ID too, but pretty much any + * value is either a) correct with slight differences, or b) + * correct but undocumented. We'll have to check a bunch of other + * things instead... + */ + + /* I/O should already be enabled (it's a RO bit). */ + pci_read_config_word(dev, PCI_COMMAND, &tmpword); + if (!(tmpword & PCI_COMMAND_IO)) { + debug("%s: device IO not enabled\n", __func__); + return -1; + } + + /* Header Type must be normal (bits 6-0 only; see spec.) */ + pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte); + if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) { + debug("%s: invalid Header type\n", __func__); + return -1; + } + + /* Base Class must be a bridge device */ + pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte); + if (tmpbyte != PCI_CLASS_CODE_BRIDGE) { + debug("%s: invalid class\n", __func__); + return -1; + } + /* Sub Class must be ISA */ + pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte); + if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) { + debug("%s: invalid subclass\n", __func__); + return -1; + } + + /* Programming Interface must be 0x00 (no others exist) */ + pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte); + if (tmpbyte != 0x00) { + debug("%s: invalid interface type\n", __func__); + return -1; + } + + /* + * GPIOBASE moved to its current offset with ICH6, but prior to + * that it was unused (or undocumented). Check that it looks + * okay: not all ones or zeros, and mapped to I/O space (bit 0). + */ + pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong); + if (tmplong == 0x00000000 || tmplong == 0xffffffff || + !(tmplong & 0x00000001)) { + debug("%s: unexpected GPIOBASE value\n", __func__); + return -1; + } + + /* + * Okay, I guess we're looking at the right device. The actual + * GPIO registers are in the PCI device's I/O space, starting + * at the offset that we just read. Bit 0 indicates that it's + * an I/O address, not a memory address, so mask that off. + */ + gpiobase = tmplong & 0xfffffffe; + + /* Finally. These are the droids we're looking for. */ + found_it_once = 1; + return 0; +} + +int gpio_request(unsigned num, const char *label /* UNUSED */) +{ + u32 tmplong; + int i = 0, j = 0; + + /* Is the hardware ready? */ + if (gpio_init()) + return -1; + + if (bad_arg(num, &i, &j)) + return -1; + + /* + * Make sure that the GPIO pin we want isn't already in use for some + * built-in hardware function. We have to check this for every + * requested pin. + */ + tmplong = inl(gpiobase + gpio_bank[i].use_sel); + if (!(tmplong & (1UL << j))) { + debug("%s: gpio %d is reserved for internal use\n", __func__, + num); + return -1; + } + + return mark_gpio(i, j); +} + +int gpio_free(unsigned num) +{ + int i = 0, j = 0; + + if (notmine(num, &i, &j)) + return -1; + + clear_gpio(i, j); + return 0; +} + +int gpio_direction_input(unsigned num) +{ + u32 tmplong; + int i = 0, j = 0; + + if (notmine(num, &i, &j)) + return -1; + + tmplong = inl(gpiobase + gpio_bank[i].io_sel); + tmplong |= (1UL << j); + outl(gpiobase + gpio_bank[i].io_sel, tmplong); + return 0; +} + +int gpio_direction_output(unsigned num, int value) +{ + u32 tmplong; + int i = 0, j = 0; + + if (notmine(num, &i, &j)) + return -1; + + tmplong = inl(gpiobase + gpio_bank[i].io_sel); + tmplong &= ~(1UL << j); + outl(gpiobase + gpio_bank[i].io_sel, tmplong); + return 0; +} + +int gpio_get_value(unsigned num) +{ + u32 tmplong; + int i = 0, j = 0; + int r; + + if (notmine(num, &i, &j)) + return -1; + + tmplong = inl(gpiobase + gpio_bank[i].lvl); + r = (tmplong & (1UL << j)) ? 1 : 0; + return r; +} + +int gpio_set_value(unsigned num, int value) +{ + u32 tmplong; + int i = 0, j = 0; + + if (notmine(num, &i, &j)) + return -1; + + tmplong = inl(gpiobase + gpio_bank[i].lvl); + if (value) + tmplong |= (1UL << j); + else + tmplong &= ~(1UL << j); + outl(gpiobase + gpio_bank[i].lvl, tmplong); + return 0; +} diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 9388859da7e..26f673a96a9 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -2293,6 +2293,8 @@ int video_get_screen_columns(void) void video_clear(void) { + if (!video_fb_address) + return; #ifdef VIDEO_HW_RECTFILL video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */ 0, /* dest pos x */ diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index a010adc2d99..adeace0cf2e 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -35,10 +35,13 @@ * (easy to change) */ #define CONFIG_SYS_COREBOOT -#undef CONFIG_SHOW_BOOT_PROGRESS +#define CONFIG_SHOW_BOOT_PROGRESS #define CONFIG_LAST_STAGE_INIT #define CONFIG_X86_NO_RESET_VECTOR #define CONFIG_SYS_VSNPRINTF +#define CONFIG_INTEL_CORE_ARCH /* Sandy bridge and ivy bridge chipsets. */ +#define CONFIG_ZBOOT_32 +#define CONFIG_PHYSMEM /*----------------------------------------------------------------------- * Watchdog Configuration @@ -77,6 +80,7 @@ */ #define CONFIG_RTC_MC146818 #define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0 +#define CONFIG_SYS_ISA_IO CONFIG_SYS_ISA_IO_BASE_ADDRESS /*----------------------------------------------------------------------- * Serial Configuration @@ -102,18 +106,9 @@ #define CONFIG_SYS_STDIO_DEREGISTER #define CONFIG_CBMEM_CONSOLE -/* max. 1 IDE bus */ -#define CONFIG_SYS_IDE_MAXBUS 1 -/* max. 1 drive per IDE bus */ -#define CONFIG_SYS_IDE_MAXDEVICE (CONFIG_SYS_IDE_MAXBUS * 1) - -#define CONFIG_SYS_ATA_BASE_ADDR CONFIG_SYS_ISA_IO_BASE_ADDRESS -#define CONFIG_SYS_ATA_IDE0_OFFSET 0x01f0 -#define CONFIG_SYS_ATA_IDE1_OFFSET 0x0170 -#define CONFIG_SYS_ATA_DATA_OFFSET 0 -#define CONFIG_SYS_ATA_REG_OFFSET 0 -#define CONFIG_SYS_ATA_ALT_OFFSET 0x200 - +#define CONFIG_CMDLINE_EDITING +#define CONFIG_COMMAND_HISTORY +#define CONFIG_AUTOCOMPLETE #define CONFIG_SUPPORT_VFAT /************************************************************ @@ -124,19 +119,30 @@ /************************************************************ * DISK Partition support ************************************************************/ +#define CONFIG_EFI_PARTITION #define CONFIG_DOS_PARTITION #define CONFIG_MAC_PARTITION #define CONFIG_ISO_PARTITION /* Experimental */ +#define CONFIG_CMD_PART #define CONFIG_CMD_CBFS #define CONFIG_CMD_EXT4 #define CONFIG_CMD_EXT4_WRITE +#define CONFIG_PARTITION_UUIDS /*----------------------------------------------------------------------- * Video Configuration */ -#undef CONFIG_VIDEO -#undef CONFIG_CFB_CONSOLE +#define CONFIG_VIDEO +#define CONFIG_VIDEO_COREBOOT +#define CONFIG_VIDEO_SW_CURSOR +#define VIDEO_FB_16BPP_WORD_SWAP +#define CONFIG_I8042_KBD +#define CONFIG_CFB_CONSOLE +#define CONFIG_SYS_CONSOLE_INFO_QUIET + +/* x86 GPIOs are accessed through a PCI device */ +#define CONFIG_INTEL_ICH6_GPIO /*----------------------------------------------------------------------- * Command line configuration. @@ -150,6 +156,7 @@ #define CONFIG_CMD_ECHO #undef CONFIG_CMD_FLASH #define CONFIG_CMD_FPGA +#define CONFIG_CMD_GPIO #define CONFIG_CMD_IMI #undef CONFIG_CMD_IMLS #define CONFIG_CMD_IRQ @@ -167,12 +174,19 @@ #define CONFIG_CMD_SETGETDCR #define CONFIG_CMD_SOURCE #define CONFIG_CMD_XIMG -#define CONFIG_CMD_IDE +#define CONFIG_CMD_SCSI + #define CONFIG_CMD_FAT #define CONFIG_CMD_EXT2 +#define CONFIG_CMD_ZBOOT + #define CONFIG_BOOTDELAY 2 -#define CONFIG_BOOTARGS "root=/dev/mtdblock0 console=ttyS0,9600" +#define CONFIG_BOOTARGS \ + "root=/dev/sdb3 init=/sbin/init rootwait ro" +#define CONFIG_BOOTCOMMAND \ + "ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000" + #if defined(CONFIG_CMD_KGDB) #define CONFIG_KGDB_BAUDRATE 115200 diff --git a/include/pci.h b/include/pci.h index eba122f8c0e..15f583f069d 100644 --- a/include/pci.h +++ b/include/pci.h @@ -67,7 +67,130 @@ #define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ #define PCI_CLASS_DEVICE 0x0a /* Device class */ #define PCI_CLASS_CODE 0x0b /* Device class code */ +#define PCI_CLASS_CODE_TOO_OLD 0x00 +#define PCI_CLASS_CODE_STORAGE 0x01 +#define PCI_CLASS_CODE_NETWORK 0x02 +#define PCI_CLASS_CODE_DISPLAY 0x03 +#define PCI_CLASS_CODE_MULTIMEDIA 0x04 +#define PCI_CLASS_CODE_MEMORY 0x05 +#define PCI_CLASS_CODE_BRIDGE 0x06 +#define PCI_CLASS_CODE_COMM 0x07 +#define PCI_CLASS_CODE_PERIPHERAL 0x08 +#define PCI_CLASS_CODE_INPUT 0x09 +#define PCI_CLASS_CODE_DOCKING 0x0A +#define PCI_CLASS_CODE_PROCESSOR 0x0B +#define PCI_CLASS_CODE_SERIAL 0x0C +#define PCI_CLASS_CODE_WIRELESS 0x0D +#define PCI_CLASS_CODE_I2O 0x0E +#define PCI_CLASS_CODE_SATELLITE 0x0F +#define PCI_CLASS_CODE_CRYPTO 0x10 +#define PCI_CLASS_CODE_DATA 0x11 +/* Base Class 0x12 - 0xFE is reserved */ +#define PCI_CLASS_CODE_OTHER 0xFF + #define PCI_CLASS_SUB_CODE 0x0a /* Device sub-class code */ +#define PCI_CLASS_SUB_CODE_TOO_OLD_NOTVGA 0x00 +#define PCI_CLASS_SUB_CODE_TOO_OLD_VGA 0x01 +#define PCI_CLASS_SUB_CODE_STORAGE_SCSI 0x00 +#define PCI_CLASS_SUB_CODE_STORAGE_IDE 0x01 +#define PCI_CLASS_SUB_CODE_STORAGE_FLOPPY 0x02 +#define PCI_CLASS_SUB_CODE_STORAGE_IPIBUS 0x03 +#define PCI_CLASS_SUB_CODE_STORAGE_RAID 0x04 +#define PCI_CLASS_SUB_CODE_STORAGE_ATA 0x05 +#define PCI_CLASS_SUB_CODE_STORAGE_SATA 0x06 +#define PCI_CLASS_SUB_CODE_STORAGE_SAS 0x07 +#define PCI_CLASS_SUB_CODE_STORAGE_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_NETWORK_ETHERNET 0x00 +#define PCI_CLASS_SUB_CODE_NETWORK_TOKENRING 0x01 +#define PCI_CLASS_SUB_CODE_NETWORK_FDDI 0x02 +#define PCI_CLASS_SUB_CODE_NETWORK_ATM 0x03 +#define PCI_CLASS_SUB_CODE_NETWORK_ISDN 0x04 +#define PCI_CLASS_SUB_CODE_NETWORK_WORLDFIP 0x05 +#define PCI_CLASS_SUB_CODE_NETWORK_PICMG 0x06 +#define PCI_CLASS_SUB_CODE_NETWORK_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_DISPLAY_VGA 0x00 +#define PCI_CLASS_SUB_CODE_DISPLAY_XGA 0x01 +#define PCI_CLASS_SUB_CODE_DISPLAY_3D 0x02 +#define PCI_CLASS_SUB_CODE_DISPLAY_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_VIDEO 0x00 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_AUDIO 0x01 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_PHONE 0x02 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_MEMORY_RAM 0x00 +#define PCI_CLASS_SUB_CODE_MEMORY_FLASH 0x01 +#define PCI_CLASS_SUB_CODE_MEMORY_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_BRIDGE_HOST 0x00 +#define PCI_CLASS_SUB_CODE_BRIDGE_ISA 0x01 +#define PCI_CLASS_SUB_CODE_BRIDGE_EISA 0x02 +#define PCI_CLASS_SUB_CODE_BRIDGE_MCA 0x03 +#define PCI_CLASS_SUB_CODE_BRIDGE_PCI 0x04 +#define PCI_CLASS_SUB_CODE_BRIDGE_PCMCIA 0x05 +#define PCI_CLASS_SUB_CODE_BRIDGE_NUBUS 0x06 +#define PCI_CLASS_SUB_CODE_BRIDGE_CARDBUS 0x07 +#define PCI_CLASS_SUB_CODE_BRIDGE_RACEWAY 0x08 +#define PCI_CLASS_SUB_CODE_BRIDGE_SEMI_PCI 0x09 +#define PCI_CLASS_SUB_CODE_BRIDGE_INFINIBAND 0x0A +#define PCI_CLASS_SUB_CODE_BRIDGE_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_COMM_SERIAL 0x00 +#define PCI_CLASS_SUB_CODE_COMM_PARALLEL 0x01 +#define PCI_CLASS_SUB_CODE_COMM_MULTIPORT 0x02 +#define PCI_CLASS_SUB_CODE_COMM_MODEM 0x03 +#define PCI_CLASS_SUB_CODE_COMM_GPIB 0x04 +#define PCI_CLASS_SUB_CODE_COMM_SMARTCARD 0x05 +#define PCI_CLASS_SUB_CODE_COMM_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_PIC 0x00 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_DMA 0x01 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_TIMER 0x02 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_RTC 0x03 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_HOTPLUG 0x04 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_SD 0x05 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_INPUT_KEYBOARD 0x00 +#define PCI_CLASS_SUB_CODE_INPUT_DIGITIZER 0x01 +#define PCI_CLASS_SUB_CODE_INPUT_MOUSE 0x02 +#define PCI_CLASS_SUB_CODE_INPUT_SCANNER 0x03 +#define PCI_CLASS_SUB_CODE_INPUT_GAMEPORT 0x04 +#define PCI_CLASS_SUB_CODE_INPUT_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_DOCKING_GENERIC 0x00 +#define PCI_CLASS_SUB_CODE_DOCKING_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_PROCESSOR_386 0x00 +#define PCI_CLASS_SUB_CODE_PROCESSOR_486 0x01 +#define PCI_CLASS_SUB_CODE_PROCESSOR_PENTIUM 0x02 +#define PCI_CLASS_SUB_CODE_PROCESSOR_ALPHA 0x10 +#define PCI_CLASS_SUB_CODE_PROCESSOR_POWERPC 0x20 +#define PCI_CLASS_SUB_CODE_PROCESSOR_MIPS 0x30 +#define PCI_CLASS_SUB_CODE_PROCESSOR_COPROC 0x40 +#define PCI_CLASS_SUB_CODE_SERIAL_1394 0x00 +#define PCI_CLASS_SUB_CODE_SERIAL_ACCESSBUS 0x01 +#define PCI_CLASS_SUB_CODE_SERIAL_SSA 0x02 +#define PCI_CLASS_SUB_CODE_SERIAL_USB 0x03 +#define PCI_CLASS_SUB_CODE_SERIAL_FIBRECHAN 0x04 +#define PCI_CLASS_SUB_CODE_SERIAL_SMBUS 0x05 +#define PCI_CLASS_SUB_CODE_SERIAL_INFINIBAND 0x06 +#define PCI_CLASS_SUB_CODE_SERIAL_IPMI 0x07 +#define PCI_CLASS_SUB_CODE_SERIAL_SERCOS 0x08 +#define PCI_CLASS_SUB_CODE_SERIAL_CANBUS 0x09 +#define PCI_CLASS_SUB_CODE_WIRELESS_IRDA 0x00 +#define PCI_CLASS_SUB_CODE_WIRELESS_IR 0x01 +#define PCI_CLASS_SUB_CODE_WIRELESS_RF 0x10 +#define PCI_CLASS_SUB_CODE_WIRELESS_BLUETOOTH 0x11 +#define PCI_CLASS_SUB_CODE_WIRELESS_BROADBAND 0x12 +#define PCI_CLASS_SUB_CODE_WIRELESS_80211A 0x20 +#define PCI_CLASS_SUB_CODE_WIRELESS_80211B 0x21 +#define PCI_CLASS_SUB_CODE_WIRELESS_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_I2O_V1_0 0x00 +#define PCI_CLASS_SUB_CODE_SATELLITE_TV 0x01 +#define PCI_CLASS_SUB_CODE_SATELLITE_AUDIO 0x02 +#define PCI_CLASS_SUB_CODE_SATELLITE_VOICE 0x03 +#define PCI_CLASS_SUB_CODE_SATELLITE_DATA 0x04 +#define PCI_CLASS_SUB_CODE_CRYPTO_NETWORK 0x00 +#define PCI_CLASS_SUB_CODE_CRYPTO_ENTERTAINMENT 0x10 +#define PCI_CLASS_SUB_CODE_CRYPTO_OTHER 0x80 +#define PCI_CLASS_SUB_CODE_DATA_DPIO 0x00 +#define PCI_CLASS_SUB_CODE_DATA_PERFCNTR 0x01 +#define PCI_CLASS_SUB_CODE_DATA_COMMSYNC 0x10 +#define PCI_CLASS_SUB_CODE_DATA_MGMT 0x20 +#define PCI_CLASS_SUB_CODE_DATA_OTHER 0x80 #define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ #define PCI_LATENCY_TIMER 0x0d /* 8 bits */ diff --git a/include/physmem.h b/include/physmem.h new file mode 100644 index 00000000000..03d3a78b741 --- /dev/null +++ b/include/physmem.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +/* + * These functions work like memset but operate on physical memory which may + * not be accessible directly. + * + * @param s The physical address to start setting memory at. + * @param c The character to set each byte of the region to. + * @param n The number of bytes to set. + * + * @return The physical address of the memory which was set. + */ +phys_addr_t arch_phys_memset(phys_addr_t s, int c, phys_size_t n); diff --git a/lib/Makefile b/lib/Makefile index e44e0452331..f83f6e8d8c5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -48,6 +48,7 @@ COBJS-$(CONFIG_LMB) += lmb.o COBJS-y += ldiv.o COBJS-$(CONFIG_MD5) += md5.o COBJS-y += net_utils.o +COBJS-$(CONFIG_PHYSMEM) += physmem.o COBJS-y += qsort.o COBJS-$(CONFIG_SHA1) += sha1.o COBJS-$(CONFIG_SHA256) += sha256.o diff --git a/lib/physmem.c b/lib/physmem.c new file mode 100644 index 00000000000..0f035edcbe5 --- /dev/null +++ b/lib/physmem.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#include <common.h> +#include <physmem.h> + +static phys_addr_t __arch_phys_memset(phys_addr_t s, int c, phys_size_t n) +{ + void *s_ptr = (void *)(uintptr_t)s; + + assert(((phys_addr_t)(uintptr_t)s) == s); + assert(((phys_addr_t)(uintptr_t)(s + n)) == s + n); + return (phys_addr_t)(uintptr_t)memset(s_ptr, c, n); +} + +phys_addr_t arch_phys_memset(phys_addr_t s, int c, phys_size_t n) + __attribute__((weak, alias("__arch_phys_memset"))); |