summaryrefslogtreecommitdiff
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/cpu/coreboot/coreboot.c15
-rw-r--r--arch/x86/cpu/coreboot/sdram.c18
-rw-r--r--arch/x86/cpu/cpu.c23
-rw-r--r--arch/x86/cpu/interrupts.c7
-rw-r--r--arch/x86/cpu/u-boot.lds21
-rw-r--r--arch/x86/include/asm/global_data.h4
-rw-r--r--arch/x86/include/asm/init_helpers.h2
-rw-r--r--arch/x86/include/asm/relocate.h1
-rw-r--r--arch/x86/include/asm/u-boot-x86.h1
-rw-r--r--arch/x86/lib/board.c3
-rw-r--r--arch/x86/lib/init_helpers.c49
-rw-r--r--arch/x86/lib/init_wrappers.c1
-rw-r--r--arch/x86/lib/relocate.c37
-rw-r--r--arch/x86/lib/timer.c9
14 files changed, 139 insertions, 52 deletions
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 9c9431e0d9..f8e28f0c82 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -68,24 +68,21 @@ 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;
+ if (!gd->arch.tsc_prev) {
+ gd->arch.tsc_base_kclocks = rdtsc() / 1000;
+ gd->arch.tsc_prev = 0;
} else {
uint32_t now;
do {
- now = rdtsc() / 1000 - base;
- } while (now < (prev_stamp + MIN_PORT80_KCLOCKS_DELAY));
- prev_stamp = now;
+ now = rdtsc() / 1000 - gd->arch.tsc_base_kclocks;
+ } while (now < (gd->arch.tsc_prev + MIN_PORT80_KCLOCKS_DELAY));
+ gd->arch.tsc_prev = now;
}
#endif
outb(val, 0x80);
diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c
index 76274cb88e..a8136a06ab 100644
--- a/arch/x86/cpu/coreboot/sdram.c
+++ b/arch/x86/cpu/coreboot/sdram.c
@@ -60,12 +60,8 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
* address, and how far U-Boot is moved by relocation are set in the global
* data structure.
*/
-int calculate_relocation_address(void)
+ulong board_get_usable_ram_top(ulong total_size)
{
- 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;
@@ -87,21 +83,15 @@ int calculate_relocation_address(void)
continue;
/* Use this address if it's the largest so far. */
- if (end - uboot_size > dest_addr)
+ if (end > dest_addr)
dest_addr = end;
}
/* If no suitable area was found, return an error. */
if (!dest_addr)
- return 1;
+ panic("No available memory found for relocation");
- 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;
+ return (ulong)dest_addr;
}
int dram_init_f(void)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 6a23974ff5..1a2f85c1fe 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -228,3 +228,26 @@ void flush_dcache_range(unsigned long start, unsigned long stop)
void invalidate_dcache_range(unsigned long start, unsigned long stop)
{
}
+
+void dcache_enable(void)
+{
+ enable_caches();
+}
+
+void dcache_disable(void)
+{
+ disable_caches();
+}
+
+void icache_enable(void)
+{
+}
+
+void icache_disable(void)
+{
+}
+
+int icache_status(void)
+{
+ return 1;
+}
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index dd30a05a9d..6dc74e34c6 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -626,13 +626,12 @@ asm(".globl irq_common_entry\n" \
*/
u64 get_ticks(void)
{
- static u64 tick_base;
u64 now_tick = rdtsc();
- if (!tick_base)
- tick_base = now_tick;
+ if (!gd->arch.tsc_base)
+ gd->arch.tsc_base = now_tick;
- return now_tick - tick_base;
+ return now_tick - gd->arch.tsc_base;
}
#define PLATFORM_INFO_MSR 0xce
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds
index 2313cd793a..54f2fb76f7 100644
--- a/arch/x86/cpu/u-boot.lds
+++ b/arch/x86/cpu/u-boot.lds
@@ -46,9 +46,6 @@ SECTIONS
.data : { *(.data*) }
. = ALIGN(4);
- .dynsym : { *(.dynsym*) }
-
- . = ALIGN(4);
.hash : { *(.hash*) }
. = ALIGN(4);
@@ -58,15 +55,25 @@ SECTIONS
__data_end = .;
. = ALIGN(4);
- __bss_start = ABSOLUTE(.);
- .bss (NOLOAD) : { *(.bss) }
- . = ALIGN(4);
- __bss_end = ABSOLUTE(.);
+ .dynsym : { *(.dynsym*) }
. = ALIGN(4);
__rel_dyn_start = .;
.rel.dyn : { *(.rel.dyn) }
__rel_dyn_end = .;
+ . = ALIGN(4);
+ _end = .;
+
+ . = ALIGN(4);
+
+ __end = .;
+ .bss __rel_dyn_start (OVERLAY) : {
+ __bss_start = .;
+ *(.bss)
+ *(COM*)
+ . = ALIGN(4);
+ __bss_end = .;
+ }
/DISCARD/ : { *(.dynstr*) }
/DISCARD/ : { *(.dynamic*) }
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 8a96fc96e8..4fdb08090a 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -29,6 +29,10 @@
/* Architecture-specific global data */
struct arch_global_data {
struct global_data *gd_addr; /* Location of Global Data */
+ uint64_t tsc_base; /* Initial value returned by rdtsc() */
+ uint32_t tsc_base_kclocks; /* Initial tsc as a kclocks value */
+ uint32_t tsc_prev; /* For show_boot_progress() */
+ void *new_fdt; /* Relocated FDT */
};
#endif
diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h
index 2f437e0343..d018b290c1 100644
--- a/arch/x86/include/asm/init_helpers.h
+++ b/arch/x86/include/asm/init_helpers.h
@@ -38,5 +38,7 @@ int flash_init_r(void);
int status_led_set_r(void);
int set_load_addr_r(void);
int init_func_spi(void);
+int find_fdt(void);
+int prepare_fdt(void);
#endif /* !_INIT_HELPERS_H_ */
diff --git a/arch/x86/include/asm/relocate.h b/arch/x86/include/asm/relocate.h
index 33129ef64b..d371c9d641 100644
--- a/arch/x86/include/asm/relocate.h
+++ b/arch/x86/include/asm/relocate.h
@@ -27,6 +27,7 @@
#include <common.h>
int copy_uboot_to_ram(void);
+int copy_fdt_to_ram(void);
int clear_bss(void);
int do_elf_reloc_fixups(void);
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 99062e5955..948615d438 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -31,6 +31,7 @@ extern ulong __rel_dyn_start;
extern ulong __rel_dyn_end;
extern ulong __bss_start;
extern ulong __bss_end;
+extern ulong _end;
/* cpu/.../cpu.c */
int x86_cpu_init_r(void);
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index 22bc26dde9..2441a66ae2 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -32,6 +32,7 @@
*/
#include <common.h>
+#include <fdtdec.h>
#include <watchdog.h>
#include <stdio_dev.h>
#include <asm/u-boot-x86.h>
@@ -131,6 +132,7 @@ init_fnc_t *init_sequence_f[] = {
init_fnc_t *init_sequence_f_r[] = {
init_cache_f_r,
copy_uboot_to_ram,
+ copy_fdt_to_ram,
clear_bss,
do_elf_reloc_fixups,
@@ -217,6 +219,7 @@ static void do_init_loop(init_fnc_t **init_fnc_ptr)
void board_init_f(ulong boot_flags)
{
+ gd->fdt_blob = gd->arch.new_fdt = NULL;
gd->flags = boot_flags;
do_init_loop(init_sequence_f);
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 3eec9a61d6..414fdcc4c9 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -22,6 +22,7 @@
*/
#include <common.h>
#include <command.h>
+#include <fdtdec.h>
#include <stdio_dev.h>
#include <version.h>
#include <malloc.h>
@@ -73,26 +74,52 @@ int init_baudrate_f(void)
return 0;
}
-__weak int calculate_relocation_address(void)
+/* Get the top of usable RAM */
+__weak ulong board_get_usable_ram_top(ulong total_size)
{
- ulong text_start = (ulong)&__text_start;
- ulong bss_end = (ulong)&__bss_end;
+ return gd->ram_size;
+}
+
+int calculate_relocation_address(void)
+{
+ const ulong uboot_size = (uintptr_t)&__bss_end -
+ (uintptr_t)&__text_start;
+ ulong total_size;
ulong dest_addr;
+ ulong fdt_size = 0;
+#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL)
+ if (gd->fdt_blob)
+ fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
+#endif
+ total_size = ALIGN(uboot_size, 1 << 12) + CONFIG_SYS_MALLOC_LEN +
+ CONFIG_SYS_STACK_SIZE + fdt_size;
+
+ dest_addr = board_get_usable_ram_top(total_size);
/*
* NOTE: All destination address are rounded down to 16-byte
* boundary to satisfy various worst-case alignment
* requirements
*/
-
- /* Stack is at top of available memory */
- dest_addr = gd->ram_size;
-
- /* U-Boot is at the top */
- dest_addr -= (bss_end - text_start);
dest_addr &= ~15;
+
+#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL)
+ /*
+ * If the device tree is sitting immediate above our image then we
+ * must relocate it. If it is embedded in the data section, then it
+ * will be relocated with other data.
+ */
+ if (gd->fdt_blob) {
+ dest_addr -= fdt_size;
+ gd->arch.new_fdt = (void *)dest_addr;
+ dest_addr &= ~15;
+ }
+#endif
+ /* U-Boot is below the FDT */
+ dest_addr -= uboot_size;
+ dest_addr &= ~((1 << 12) - 1);
gd->relocaddr = dest_addr;
- gd->reloc_off = (dest_addr - text_start);
+ gd->reloc_off = dest_addr - (uintptr_t)&__text_start;
/* Stack is at the bottom, so it can grow down */
gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN;
@@ -180,7 +207,7 @@ int find_fdt(void)
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);
+ gd->fdt_blob = (ulong *)&_end;
#endif
/* Allow the early environment to override the fdt address */
gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
diff --git a/arch/x86/lib/init_wrappers.c b/arch/x86/lib/init_wrappers.c
index cca018fa9b..19af875c0e 100644
--- a/arch/x86/lib/init_wrappers.c
+++ b/arch/x86/lib/init_wrappers.c
@@ -22,6 +22,7 @@
*/
#include <common.h>
#include <environment.h>
+#include <fdtdec.h>
#include <serial.h>
#include <kgdb.h>
#include <scsi.h>
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c
index 23edca9526..3e370f2906 100644
--- a/arch/x86/lib/relocate.c
+++ b/arch/x86/lib/relocate.c
@@ -32,6 +32,7 @@
*/
#include <common.h>
+#include <libfdt.h>
#include <malloc.h>
#include <asm/u-boot-x86.h>
#include <asm/relocate.h>
@@ -46,6 +47,22 @@ int copy_uboot_to_ram(void)
return 0;
}
+int copy_fdt_to_ram(void)
+{
+ if (gd->arch.new_fdt) {
+ ulong fdt_size;
+
+ fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
+
+ memcpy(gd->arch.new_fdt, gd->fdt_blob, fdt_size);
+ debug("Relocated fdt from %p to %p, size %lx\n",
+ gd->fdt_blob, gd->arch.new_fdt, fdt_size);
+ gd->fdt_blob = gd->arch.new_fdt;
+ }
+
+ return 0;
+}
+
int clear_bss(void)
{
ulong dst_addr = (ulong)&__bss_start + gd->reloc_off;
@@ -56,12 +73,16 @@ int clear_bss(void)
return 0;
}
+/*
+ * This function has more error checking than you might expect. Please see
+ * the commit message for more informaiton.
+ */
int do_elf_reloc_fixups(void)
{
Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start);
Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
- Elf32_Addr *offset_ptr_rom;
+ Elf32_Addr *offset_ptr_rom, *last_offset = NULL;
Elf32_Addr *offset_ptr_ram;
/* The size of the region of u-boot that runs out of RAM. */
@@ -72,7 +93,8 @@ int do_elf_reloc_fixups(void)
offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
/* Check that the location of the relocation is in .text */
- if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) {
+ if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE &&
+ offset_ptr_rom > last_offset) {
/* Switch to the in-RAM version */
offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom +
@@ -83,8 +105,19 @@ int do_elf_reloc_fixups(void)
*offset_ptr_ram <=
(CONFIG_SYS_TEXT_BASE + size)) {
*offset_ptr_ram += gd->reloc_off;
+ } else {
+ debug(" %p: rom reloc %x, ram %p, value %x,"
+ " limit %lx\n", re_src,
+ re_src->r_offset, offset_ptr_ram,
+ *offset_ptr_ram,
+ CONFIG_SYS_TEXT_BASE + size);
}
+ } else {
+ debug(" %p: rom reloc %x, last %p\n", re_src,
+ re_src->r_offset, last_offset);
}
+ last_offset = offset_ptr_rom;
+
} while (++re_src < re_end);
return 0;
diff --git a/arch/x86/lib/timer.c b/arch/x86/lib/timer.c
index a13424b3e3..1f8ce609e2 100644
--- a/arch/x86/lib/timer.c
+++ b/arch/x86/lib/timer.c
@@ -37,7 +37,6 @@ 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
@@ -102,7 +101,7 @@ ulong get_timer(ulong base)
void timer_set_tsc_base(uint64_t new_base)
{
- base_value = new_base;
+ gd->arch.tsc_base = new_base;
}
uint64_t timer_get_tsc(void)
@@ -110,8 +109,8 @@ uint64_t timer_get_tsc(void)
uint64_t time_now;
time_now = rdtsc();
- if (!base_value)
- base_value = time_now;
+ if (!gd->arch.tsc_base)
+ gd->arch.tsc_base = time_now;
- return time_now - base_value;
+ return time_now - gd->arch.tsc_base;
}