summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorHeiko Schocher <hs@denx.de>2010-09-17 13:10:39 +0200
committerWolfgang Denk <wd@denx.de>2010-09-19 19:29:53 +0200
commitf1d2b313c9eb6808d30c16a9eb5251240452a56c (patch)
tree8b5488d9e882947ef493c0e579aebaa5f40413f4 /arch/arm
parent4fff329df2516a7d9242d0642c07c4506f859051 (diff)
ARM: add relocation support
!! This breaks support for all arm boards !! To compile in old style, you must define CONFIG_SYS_ARM_WITHOUT_RELOC or you can compile with "CONFIG_SYS_ARM_WITHOUT_RELOC=1 ./MAKEALL board" !! This define will be removed soon, so convert your board to use relocation support Portions of this work were supported by funding from the CE Linux Forum. Signed-off-by: Heiko Schocher <hs@denx.de> Fix boot from NAND for non-ARM systems Signed-off-by: Wolfgang Denk <wd@denx.de>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/config.mk8
-rw-r--r--arch/arm/include/asm/config.h3
-rw-r--r--arch/arm/include/asm/global_data.h11
-rw-r--r--arch/arm/include/asm/u-boot-arm.h14
-rw-r--r--arch/arm/lib/board.c468
-rw-r--r--arch/arm/lib/cache-cp15.c37
-rw-r--r--arch/arm/lib/interrupts.c19
7 files changed, 553 insertions, 7 deletions
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index e10dafca58..6923f6dafa 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -33,6 +33,14 @@ STANDALONE_LOAD_ADDR = 0xc100000
endif
endif
+ifndef CONFIG_SYS_ARM_WITHOUT_RELOC
+# needed for relocation
+PLATFORM_RELFLAGS += -fPIC
+endif
+
+ifdef CONFIG_SYS_ARM_WITHOUT_RELOC
+PLATFORM_CPPFLAGS += -DCONFIG_SYS_ARM_WITHOUT_RELOC
+endif
PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h
index b76fd8eb48..4e8dfd7bc5 100644
--- a/arch/arm/include/asm/config.h
+++ b/arch/arm/include/asm/config.h
@@ -21,7 +21,8 @@
#ifndef _ASM_CONFIG_H_
#define _ASM_CONFIG_H_
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
/* Relocation to SDRAM works on all ARM boards */
#define CONFIG_RELOC_FIXUP_WORKS
-
+#endif
#endif
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 0bc464a3f6..6152f348f3 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -47,6 +47,17 @@ typedef struct global_data {
#ifdef CONFIG_FSL_ESDHC
unsigned long sdhc_clk;
#endif
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+ unsigned long relocaddr; /* Start address of U-Boot in RAM */
+ phys_size_t ram_size; /* RAM size */
+ unsigned long mon_len; /* monitor len */
+ unsigned long irq_sp; /* irq stack pointer */
+ unsigned long start_addr_sp; /* start_addr_stackpointer */
+ unsigned long reloc_off;
+#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))
+ unsigned long tlb_addr;
+#endif
+#endif
void **jt; /* jump table */
char env_buf[32]; /* buffer for getenv() before reloc. */
} gd_t;
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h
index 6d2f8bccb5..faf800a17b 100644
--- a/arch/arm/include/asm/u-boot-arm.h
+++ b/arch/arm/include/asm/u-boot-arm.h
@@ -30,11 +30,20 @@
#define _U_BOOT_ARM_H_ 1
/* for the following variables, see start.S */
-extern ulong _armboot_start; /* code start */
extern ulong _bss_start; /* code + data end == BSS start */
extern ulong _bss_end; /* BSS end */
extern ulong IRQ_STACK_START; /* top of IRQ stack */
extern ulong FIQ_STACK_START; /* top of FIQ stack */
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+extern ulong _armboot_start; /* code start */
+#else
+extern ulong _TEXT_BASE; /* code start */
+extern ulong _datarel_start;
+extern ulong _datarelrolocal_start;
+extern ulong _datarellocal_start;
+extern ulong _datarelro_start;
+extern ulong IRQ_STACK_START_IN; /* 8 bytes in IRQ stack */
+#endif
/* cpu/.../cpu.c */
int cpu_init(void);
@@ -47,6 +56,9 @@ int arch_misc_init(void);
/* board/.../... */
int board_init(void);
int dram_init (void);
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+void dram_init_banksize (void);
+#endif
void setup_serial_tag (struct tag **params);
void setup_revision_tag (struct tag **params);
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index e17f182e18..5f2dfd08ac 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -126,7 +126,12 @@ static int init_baudrate (void)
{
char tmp[64]; /* long enough for environment variables */
int i = getenv_f("baudrate", tmp, sizeof (tmp));
+
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+ gd->baudrate = (i > 0)
+#else
gd->bd->bi_baudrate = gd->baudrate = (i > 0)
+#endif
? (int) simple_strtoul (tmp, NULL, 10)
: CONFIG_BAUDRATE;
@@ -137,7 +142,12 @@ static int display_banner (void)
{
printf ("\n\n%s\n\n", version_string);
debug ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
- _armboot_start, _bss_start, _bss_end);
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+ _TEXT_BASE,
+#else
+ _armboot_start,
+#endif
+ _bss_start, _bss_end);
#ifdef CONFIG_MODEM_SUPPORT
debug ("Modem Support enabled\n");
#endif
@@ -180,6 +190,7 @@ static int display_dram_config (void)
return (0);
}
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
#ifndef CONFIG_SYS_NO_FLASH
static void display_flash_config (ulong size)
{
@@ -187,6 +198,7 @@ static void display_flash_config (ulong size)
print_size (size, "\n");
}
#endif /* CONFIG_SYS_NO_FLASH */
+#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
static int init_func_i2c (void)
@@ -234,6 +246,7 @@ typedef int (init_fnc_t) (void);
int print_cpuinfo (void);
+#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init, /* basic arch cpu dependent setup */
@@ -449,6 +462,459 @@ extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
/* NOTREACHED - no way out of command loop except booting */
}
+#else
+void __dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+ gd->bd->bi_dram[0].size = gd->ram_size;
+}
+void dram_init_banksize(void)
+ __attribute__((weak, alias("__dram_init_banksize")));
+
+init_fnc_t *init_sequence[] = {
+#if defined(CONFIG_ARCH_CPU_INIT)
+ arch_cpu_init, /* basic arch cpu dependent setup */
+#endif
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+ board_early_init_f,
+#endif
+ timer_init, /* initialize timer */
+#ifdef CONFIG_FSL_ESDHC
+ get_clocks,
+#endif
+ env_init, /* initialize environment */
+ init_baudrate, /* initialze baudrate settings */
+ serial_init, /* serial communications setup */
+ console_init_f, /* stage 1 init of console */
+ display_banner, /* say that we are here */
+#if defined(CONFIG_DISPLAY_CPUINFO)
+ print_cpuinfo, /* display cpu info (and speed) */
+#endif
+#if defined(CONFIG_DISPLAY_BOARDINFO)
+ checkboard, /* display board info */
+#endif
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+ init_func_i2c,
+#endif
+ dram_init, /* configure available RAM banks */
+#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
+ arm_pci_init,
+#endif
+ NULL,
+};
+
+void board_init_f (ulong bootflag)
+{
+ bd_t *bd;
+ init_fnc_t **init_fnc_ptr;
+ gd_t *id;
+ ulong addr, addr_sp;
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_SP_ADDR);
+ /* compiler optimization barrier needed for GCC >= 3.4 */
+ __asm__ __volatile__("": : :"memory");
+
+ memset ((void*)gd, 0, sizeof (gd_t));
+
+ gd->mon_len = _bss_end - _TEXT_BASE;
+
+ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+ if ((*init_fnc_ptr)() != 0) {
+ hang ();
+ }
+ }
+
+ debug ("monitor len: %08lX\n", gd->mon_len);
+ /*
+ * Ram is setup, size stored in gd !!
+ */
+ debug ("ramsize: %08lX\n", gd->ram_size);
+#if defined(CONFIG_SYS_MEM_TOP_HIDE)
+ /*
+ * Subtract specified amount of memory to hide so that it won't
+ * get "touched" at all by U-Boot. By fixing up gd->ram_size
+ * the Linux kernel should now get passed the now "corrected"
+ * memory size and won't touch it either. This should work
+ * for arch/ppc and arch/powerpc. Only Linux board ports in
+ * arch/powerpc with bootwrapper support, that recalculate the
+ * memory size from the SDRAM controller setup will have to
+ * get fixed.
+ */
+ gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
+#endif
+
+ addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
+
+#ifdef CONFIG_LOGBUFFER
+#ifndef CONFIG_ALT_LB_ADDR
+ /* reserve kernel log buffer */
+ addr -= (LOGBUFF_RESERVE);
+ debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
+#endif
+#endif
+
+#ifdef CONFIG_PRAM
+ /*
+ * reserve protected RAM
+ */
+ i = getenv_r ("pram", (char *)tmp, sizeof (tmp));
+ reg = (i > 0) ? simple_strtoul ((const char *)tmp, NULL, 10) : CONFIG_PRAM;
+ addr -= (reg << 10); /* size is in kB */
+ debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
+#endif /* CONFIG_PRAM */
+
+#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE))
+ /* reserve TLB table */
+ addr -= (4096 * 4);
+
+ /* round down to next 64 kB limit */
+ addr &= ~(0x10000 - 1);
+
+ gd->tlb_addr = addr;
+ debug ("TLB table at: %08lx\n", addr);
+#endif
+
+ /* round down to next 4 kB limit */
+ addr &= ~(4096 - 1);
+ debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
+
+#ifdef CONFIG_VFD
+# ifndef PAGE_SIZE
+# define PAGE_SIZE 4096
+# endif
+ /*
+ * reserve memory for VFD display (always full pages)
+ */
+ addr -= vfd_setmem (addr);
+ gd->fb_base = addr;
+#endif /* CONFIG_VFD */
+
+#ifdef CONFIG_LCD
+ /* reserve memory for LCD display (always full pages) */
+ addr = lcd_setmem (addr);
+ gd->fb_base = addr;
+#endif /* CONFIG_LCD */
+
+ /*
+ * reserve memory for U-Boot code, data & bss
+ * round down to next 4 kB limit
+ */
+ addr -= gd->mon_len;
+ addr &= ~(4096 - 1);
+
+ debug ("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
+
+#ifndef CONFIG_PRELOADER
+ /*
+ * reserve memory for malloc() arena
+ */
+ addr_sp = addr - TOTAL_MALLOC_LEN;
+ debug ("Reserving %dk for malloc() at: %08lx\n",
+ TOTAL_MALLOC_LEN >> 10, addr_sp);
+ /*
+ * (permanently) allocate a Board Info struct
+ * and a permanent copy of the "global" data
+ */
+ addr_sp -= sizeof (bd_t);
+ bd = (bd_t *) addr_sp;
+ gd->bd = bd;
+ debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
+ sizeof (bd_t), addr_sp);
+ addr_sp -= sizeof (gd_t);
+ id = (gd_t *) addr_sp;
+ debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
+ sizeof (gd_t), addr_sp);
+
+ /* setup stackpointer for exeptions */
+ gd->irq_sp = addr_sp;
+#ifdef CONFIG_USE_IRQ
+ addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
+ debug ("Reserving %zu Bytes for IRQ stack at: %08lx\n",
+ CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
+#endif
+ /* leave 3 words for abort-stack */
+ addr_sp -= 3;
+
+ /* 8-byte alignment for ABI compliance */
+ addr_sp &= ~0x07;
+#else
+ addr_sp += 128; /* leave 32 words for abort-stack */
+ gd->irq_sp = addr_sp;
+#endif
+
+ debug ("New Stack Pointer is: %08lx\n", addr_sp);
+
+#ifdef CONFIG_POST
+ post_bootmode_init();
+ post_run (NULL, POST_ROM | post_bootmode_get(0));
+#endif
+
+ gd->bd->bi_baudrate = gd->baudrate;
+ /* Ram ist board specific, so move it to board code ... */
+ dram_init_banksize();
+ display_dram_config(); /* and display it */
+
+ gd->relocaddr = addr;
+ gd->start_addr_sp = addr_sp;
+ gd->reloc_off = addr - _TEXT_BASE;
+ debug ("relocation Offset is: %08lx\n", gd->reloc_off);
+ memcpy (id, (void *)gd, sizeof (gd_t));
+
+ relocate_code (addr_sp, id, addr);
+
+ /* NOTREACHED - relocate_code() does not return */
+}
+
+#if !defined(CONFIG_SYS_NO_FLASH)
+static char *failed = "*** failed ***\n";
+#endif
+
+/************************************************************************
+ *
+ * This is the next part if the initialization sequence: we are now
+ * running from RAM and have a "normal" C environment, i. e. global
+ * data can be written, BSS has been cleared, the stack size in not
+ * that critical any more, etc.
+ *
+ ************************************************************************
+ */
+void board_init_r (gd_t *id, ulong dest_addr)
+{
+ char *s;
+ bd_t *bd;
+ ulong malloc_start;
+#if !defined(CONFIG_SYS_NO_FLASH)
+ ulong flash_size;
+#endif
+#if !defined(CONFIG_RELOC_FIXUP_WORKS)
+ extern void malloc_bin_reloc (void);
+#if defined(CONFIG_CMD_BMP)
+ extern void bmp_reloc(void);
+#endif
+#if defined(CONFIG_CMD_I2C)
+ extern void i2c_reloc(void);
+#endif
+#endif
+
+ gd = id;
+ bd = gd->bd;
+
+ gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
+
+ monitor_flash_len = _bss_start - _TEXT_BASE;
+ debug ("monitor flash len: %08lX\n", monitor_flash_len);
+ board_init(); /* Setup chipselects */
+
+#ifdef CONFIG_SERIAL_MULTI
+ serial_initialize();
+#endif
+
+ debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
+#if !defined(CONFIG_RELOC_FIXUP_WORKS)
+ /*
+ * We have to relocate the command table manually
+ */
+ fixup_cmdtable(&__u_boot_cmd_start,
+ (ulong)(&__u_boot_cmd_end - &__u_boot_cmd_start));
+#if defined(CONFIG_CMD_BMP)
+ bmp_reloc();
+#endif
+#if defined(CONFIG_CMD_I2C)
+ i2c_reloc();
+#endif
+#endif /* !defined(CONFIG_RELOC_FIXUP_WORKS) */
+
+#ifdef CONFIG_LOGBUFFER
+ logbuff_init_ptrs ();
+#endif
+#ifdef CONFIG_POST
+ post_output_backlog ();
+#ifndef CONFIG_RELOC_FIXUP_WORKS
+ post_reloc ();
+#endif
+#endif
+
+ /* The Malloc area is immediately below the monitor copy in DRAM */
+ malloc_start = dest_addr - TOTAL_MALLOC_LEN;
+ mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
+#if !defined(CONFIG_RELOC_FIXUP_WORKS)
+ malloc_bin_reloc ();
+#endif
+
+#if !defined(CONFIG_SYS_NO_FLASH)
+ puts ("FLASH: ");
+
+ if ((flash_size = flash_init ()) > 0) {
+# ifdef CONFIG_SYS_FLASH_CHECKSUM
+ print_size (flash_size, "");
+ /*
+ * Compute and print flash CRC if flashchecksum is set to 'y'
+ *
+ * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
+ */
+ s = getenv ("flashchecksum");
+ if (s && (*s == 'y')) {
+ printf (" CRC: %08X",
+ crc32 (0, (const unsigned char *) CONFIG_SYS_FLASH_BASE, flash_size)
+ );
+ }
+ putc ('\n');
+# else /* !CONFIG_SYS_FLASH_CHECKSUM */
+ print_size (flash_size, "\n");
+# endif /* CONFIG_SYS_FLASH_CHECKSUM */
+ } else {
+ puts (failed);
+ hang ();
+ }
+#endif
+
+#if defined(CONFIG_CMD_NAND)
+ puts ("NAND: ");
+ nand_init(); /* go init the NAND */
+#endif
+
+#if defined(CONFIG_CMD_ONENAND)
+ onenand_init();
+#endif
+
+#ifdef CONFIG_HAS_DATAFLASH
+ AT91F_DataflashInit();
+ dataflash_print_info();
+#endif
+
+ /* initialize environment */
+ env_relocate ();
+
+#ifdef CONFIG_VFD
+ /* must do this after the framebuffer is allocated */
+ drv_vfd_init();
+#endif /* CONFIG_VFD */
+
+ /* IP Address */
+ gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+
+ stdio_init (); /* get the devices list going. */
+
+ jumptable_init ();
+
+#if defined(CONFIG_API)
+ /* Initialize API */
+ api_init ();
+#endif
+
+ console_init_r (); /* fully init console as a device */
+
+#if defined(CONFIG_ARCH_MISC_INIT)
+ /* miscellaneous arch dependent initialisations */
+ arch_misc_init ();
+#endif
+#if defined(CONFIG_MISC_INIT_R)
+ /* miscellaneous platform dependent initialisations */
+ misc_init_r ();
+#endif
+
+ /* set up exceptions */
+ interrupt_init ();
+ /* enable exceptions */
+ enable_interrupts ();
+
+ /* Perform network card initialisation if necessary */
+#ifdef CONFIG_DRIVER_TI_EMAC
+ /* XXX: this needs to be moved to board init */
+extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
+ if (getenv ("ethaddr")) {
+ uchar enetaddr[6];
+ eth_getenv_enetaddr("ethaddr", enetaddr);
+ davinci_eth_set_mac_addr(enetaddr);
+ }
+#endif
+
+#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
+ /* XXX: this needs to be moved to board init */
+ if (getenv ("ethaddr")) {
+ uchar enetaddr[6];
+ eth_getenv_enetaddr("ethaddr", enetaddr);
+ smc_set_mac_addr(enetaddr);
+ }
+#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
+
+ /* Initialize from environment */
+ if ((s = getenv ("loadaddr")) != NULL) {
+ load_addr = simple_strtoul (s, NULL, 16);
+ }
+#if defined(CONFIG_CMD_NET)
+ if ((s = getenv ("bootfile")) != NULL) {
+ copy_filename (BootFile, s, sizeof (BootFile));
+ }
+#endif
+
+#ifdef BOARD_LATE_INIT
+ board_late_init ();
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+ puts ("MMC: ");
+ mmc_initialize (gd->bd);
+#endif
+
+#ifdef CONFIG_BITBANGMII
+ bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+#if defined(CONFIG_NET_MULTI)
+ puts ("Net: ");
+#endif
+ eth_initialize(gd->bd);
+#if defined(CONFIG_RESET_PHY_R)
+ debug ("Reset Ethernet PHY\n");
+ reset_phy();
+#endif
+#endif
+
+#ifdef CONFIG_POST
+ post_run (NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
+ /*
+ * Export available size of memory for Linux,
+ * taking into account the protected RAM at top of memory
+ */
+ {
+ ulong pram;
+ uchar memsz[32];
+#ifdef CONFIG_PRAM
+ char *s;
+
+ if ((s = getenv ("pram")) != NULL) {
+ pram = simple_strtoul (s, NULL, 10);
+ } else {
+ pram = CONFIG_PRAM;
+ }
+#else
+ pram=0;
+#endif
+#ifdef CONFIG_LOGBUFFER
+#ifndef CONFIG_ALT_LB_ADDR
+ /* Also take the logbuffer into account (pram is in kB) */
+ pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
+#endif
+#endif
+ sprintf ((char *)memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
+ setenv ("mem", (char *)memsz);
+ }
+#endif
+
+ /* main_loop() can return to retry autoboot, if so just run it again. */
+ for (;;) {
+ main_loop ();
+ }
+
+ /* NOTREACHED - no way out of command loop except booting */
+}
+#endif /* defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
void hang (void)
{
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
index b2811f35a6..fe6d45987b 100644
--- a/arch/arm/lib/cache-cp15.c
+++ b/arch/arm/lib/cache-cp15.c
@@ -44,17 +44,44 @@ static void cp_delay (void)
asm volatile("" : : : "memory");
}
-/* to activate the MMU we need to set up virtual memory: use 1M areas in bss */
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+static inline void dram_bank_mmu_setup(int bank)
+{
+ u32 *page_table = (u32 *)gd->tlb_addr;
+ bd_t *bd = gd->bd;
+ int i;
+
+ debug("%s: bank: %d\n", __func__, bank);
+ for (i = bd->bi_dram[bank].start >> 20;
+ i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20;
+ i++) {
+ page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP;
+ }
+}
+#endif
+
+/* to activate the MMU we need to set up virtual memory: use 1M areas */
static inline void mmu_setup(void)
{
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+ u32 *page_table = (u32 *)gd->tlb_addr;
+#else
static u32 __attribute__((aligned(16384))) page_table[4096];
bd_t *bd = gd->bd;
- int i, j;
+ int j;
+#endif
+ int i;
u32 reg;
/* Set up an identity-mapping for all 4GB, rw for everyone */
for (i = 0; i < 4096; i++)
page_table[i] = i << 20 | (3 << 10) | 0x12;
+
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ dram_bank_mmu_setup(i);
+ }
+#else
/* Then, enable cacheable and bufferable for RAM only */
for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) {
for (i = bd->bi_dram[j].start >> 20;
@@ -63,6 +90,7 @@ static inline void mmu_setup(void)
page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP;
}
}
+#endif
/* Copy the page table address to cp15 */
asm volatile("mcr p15, 0, %0, c2, c0, 0"
@@ -74,7 +102,6 @@ static inline void mmu_setup(void)
reg = get_cr(); /* get control reg. */
cp_delay();
set_cr(reg | CR_M);
-
}
/* cache_bit must be either CR_I or CR_C */
@@ -96,6 +123,10 @@ static void cache_disable(uint32_t cache_bit)
uint32_t reg;
if (cache_bit == CR_C) {
+ /* if cache isn;t enabled no need to disable */
+ reg = get_cr();
+ if ((reg & CR_C) != CR_C)
+ return;
/* if disabling data cache, disable mmu too */
cache_bit |= CR_M;
flush_cache(0, ~0);
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
index 1f2b815611..9a21e7b40a 100644
--- a/arch/arm/lib/interrupts.c
+++ b/arch/arm/lib/interrupts.c
@@ -38,15 +38,20 @@
#include <common.h>
#include <asm/proc-armv/ptrace.h>
-#ifdef CONFIG_USE_IRQ
DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_USE_IRQ
int interrupt_init (void)
{
/*
* setup up stacks if necessary
*/
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+ IRQ_STACK_START = gd->irq_sp - 4;
+ IRQ_STACK_START_IN = gd->irq_sp + 8;
+#else
IRQ_STACK_START = _armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4;
+#endif
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
return arch_interrupt_init();
@@ -81,6 +86,18 @@ int disable_interrupts (void)
return (old & 0x80) == 0;
}
#else
+#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
+int interrupt_init (void)
+{
+ /*
+ * setup up stacks if necessary
+ */
+ IRQ_STACK_START_IN = gd->irq_sp + 8;
+
+ return 0;
+}
+#endif
+
void enable_interrupts (void)
{
return;