diff options
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 2afd30cd5..b1d3e959f 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 3cc25755f..3cc25755f 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 000000000..4858fc372 --- /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 22a643c9d..9c9431e0d 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 f8fdac631..76274cb88 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 000000000..2ca7a57bc --- /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 fabfbd1bf..315e87afe 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 43ec3f8b0..dd30a05a9 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 ec12e8044..e960e21f6 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 cc393ff54..603bf1d2d 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 000000000..4862a5970 --- /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 000000000..b41d241de --- /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 000000000..d104912e0 --- /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 87c9e0be4..d4678d491 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 000000000..aa8be30ba --- /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 35110a333..dc6402b67 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 000000000..0a37a85ad --- /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 ade694fba..2f437e034 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 84a638da7..86bac90e8 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 000000000..50175994c --- /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 000000000..6030633d1 --- /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 000000000..6842da500 --- /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 9a40e383e..e9fde88f7 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 a4a5ae05d..99062e595 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 4325b2502..0a52cc896 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 c7d89604c..22bc26dde 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 87c7263fc..3eec9a61d 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 71449fe6f..cca018fa9 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 000000000..18f0e62ac --- /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 200baaba6..23edca952 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 fd7032e92..a13424b3e 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 b8c672bab..46af391f2 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 bd90d185f..cb6a9e41e 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 000000000..af60f59de --- /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 70a156932..35f38f31d 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 d50ac3bfe..2d97b4f1e 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 000000000..6fed01f71 --- /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 9388859da..26f673a96 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 a010adc2d..adeace0cf 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 eba122f8c..15f583f06 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 000000000..03d3a78b7 --- /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 e44e04523..f83f6e8d8 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 000000000..0f035edcb --- /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"))); |