diff options
| author | Tom Rini <trini@ti.com> | 2012-12-07 06:43:40 -0700 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2012-12-07 08:47:59 -0700 | 
| commit | fd4d564b3c80b111f18c93adb14233a6a7ddb0e9 (patch) | |
| tree | a42d63aae4f7c07f441321c18098a85cbcc45dee /arch/x86/cpu/coreboot/sdram.c | |
| parent | 13d43555a9154cf12255023c47e80d947d7d0604 (diff) | |
| parent | ac426b7290e3a96c97fbc093f15cd0660e0edaf2 (diff) | |
| download | olio-uboot-2014.01-fd4d564b3c80b111f18c93adb14233a6a7ddb0e9.tar.xz olio-uboot-2014.01-fd4d564b3c80b111f18c93adb14233a6a7ddb0e9.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-x86
Diffstat (limited to 'arch/x86/cpu/coreboot/sdram.c')
| -rw-r--r-- | arch/x86/cpu/coreboot/sdram.c | 72 | 
1 files changed, 70 insertions, 2 deletions
| 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;  } |