diff options
| -rw-r--r-- | arch/arm/config.mk | 8 | ||||
| -rw-r--r-- | arch/arm/include/asm/config.h | 3 | ||||
| -rw-r--r-- | arch/arm/include/asm/global_data.h | 11 | ||||
| -rw-r--r-- | arch/arm/include/asm/u-boot-arm.h | 14 | ||||
| -rw-r--r-- | arch/arm/lib/board.c | 468 | ||||
| -rw-r--r-- | arch/arm/lib/cache-cp15.c | 37 | ||||
| -rw-r--r-- | arch/arm/lib/interrupts.c | 19 | ||||
| -rw-r--r-- | common/cmd_bdinfo.c | 11 | ||||
| -rw-r--r-- | common/cmd_bmp.c | 6 | ||||
| -rw-r--r-- | common/cmd_i2c.c | 6 | ||||
| -rw-r--r-- | doc/README.arm-relocation | 321 | ||||
| -rw-r--r-- | nand_spl/nand_boot.c | 7 | ||||
| -rw-r--r-- | nand_spl/nand_boot_fsl_nfc.c | 7 | 
13 files changed, 910 insertions, 8 deletions
| diff --git a/arch/arm/config.mk b/arch/arm/config.mk index e10dafca5..6923f6daf 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 b76fd8eb4..4e8dfd7bc 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 0bc464a3f..6152f348f 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 6d2f8bccb..faf800a17 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 e17f182e1..5f2dfd08a 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 b2811f35a..fe6d45987 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 1f2b81561..9a21e7b40 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; diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 7a96d95cc..6b611b148 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -343,7 +343,16 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	printf ("ip_addr     = %pI4\n", &bd->bi_ip_addr);  #endif  	printf ("baudrate    = %d bps\n", bd->bi_baudrate); - +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +#if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE)) +	print_num ("TLB addr", gd->tlb_addr); +#endif +	print_num ("relocaddr", gd->relocaddr); +	print_num ("reloc off", gd->reloc_off); +	print_num ("irq_sp", gd->irq_sp);	/* irq stack pointer */ +	print_num ("sp start ", gd->start_addr_sp); +	print_num ("FB base  ", gd->fb_base); +#endif  	return 0;  } diff --git a/common/cmd_bmp.c b/common/cmd_bmp.c index d51cc554c..6fa8a1502 100644 --- a/common/cmd_bmp.c +++ b/common/cmd_bmp.c @@ -137,6 +137,12 @@ static cmd_tbl_t cmd_bmp_sub[] = {  	U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""),  }; +#ifndef CONFIG_RELOC_FIXUP_WORKS +void bmp_reloc(void) { +	fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub)); +} +#endif +  /*   * Subroutine:  do_bmp   * diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index a7b65edd5..0a0cfceb4 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -1284,6 +1284,12 @@ static cmd_tbl_t cmd_i2c_sub[] = {  	U_BOOT_CMD_MKENT(speed, 1, 1, do_i2c_bus_speed, "", ""),  }; +#ifndef CONFIG_RELOC_FIXUP_WORKS +void i2c_reloc(void) { +	fixup_cmdtable(cmd_i2c_sub, ARRAY_SIZE(cmd_i2c_sub)); +} +#endif +  static int do_i2c(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  {  	cmd_tbl_t *c; diff --git a/doc/README.arm-relocation b/doc/README.arm-relocation new file mode 100644 index 000000000..6be1a1292 --- /dev/null +++ b/doc/README.arm-relocation @@ -0,0 +1,321 @@ +To make relocation on arm working, the following changes are done: + +Add new compilerflag: + +-fPIC + +	-> compiler generates position independent code + +changes in board code: + +- dram_init: +  - bd pointer is now at this point not accessible, so only +    detect the real dramsize, and store it in gd->ram_size. +    best detected with get_ram_size(); +    ToDo: move there also the dram initialization on boards where +          it is possible. +  - setup the bd_t dram bank info in the new function +    dram_init_banksize(). + +- board.c code is adapted from ppc code + +- undef CONFIG_RELOC_FIXUP_WORKS + +  -> cmdtabl, and subcommand table must be handled from "hand" +     collected in section "__datarellocal_start". + +  - How To fixup the sections: + +    __datarel_start, __datarelrolocal_start, __datarellocal_start and +    __datarelro_start + +    automatically? Then it should be possible to define again +    CONFIG_RELOC_FIXUP_WORKS + +- irq stack setup is now not longer on a fix position, instead it is +  calculated in board_init_f, and stored in gd->irq_sp + +------------------------------------------------------------------------------------- + +To compile a board without relocation, define CONFIG_SYS_ARM_WITHOUT_RELOC +This possibility will removed!! So please fix your board to compile without +CONFIG_SYS_ARM_WITHOUT_RELOC defined!!! + +------------------------------------------------------------------------------------- + +ToDo: + +- fill in bd_t infos (check) +- adapt all boards + +- maybe adapt TEXT_BASE (this must be checked from board maintainers) +  This *must* be done for boards, which boot from NOR flash + +  on other boards if TEXT_BASE = relocation baseaddr, this saves +  one copying from u-boot code. + +- new function dram_init_banksize() is actual board specific. Maybe +  we make a weak default function in arch/arm/lib/board.c ? + +------------------------------------------------------------------------------------- + +Relocation with NAND_SPL (example for the tx25): + +- cpu copies the first page from NAND to 0xbb000000 (IMX_NFC_BASE) +  and start with code execution on this address. + +- The First page contains u-boot code from u-boot:nand_spl/nand_boot_fsl_nfc.c +  which inits the dram, cpu registers, reloacte itself to TEXT_BASE  and loads +  the "real" u-boot to CONFIG_SYS_NAND_U_BOOT_DST and starts execution +  @CONFIG_SYS_NAND_U_BOOT_START + +- This u-boot does no ram int, nor cpu register setup. Just looks +  where it have to relocate and relocate itself to this address. +  If relocate address = TEXT_BASE(not the same, as the TEXT_BASE +  from the nand_spl code), no need to copy, just go on with bss clear +  and jump to board_init_r. + +------------------------------------------------------------------------------------- + +Relocation: +How to translate flash addresses in GOT to ram addresses. +This is automagically done from code, but this example +shows, how this magic code works ;-) +(example on the qong board) + +Find a variable: + +a) search it in System.map +(for example flash_info) + +a005b4c0 B BootpID +a005b4c4 B BootpTry +a005b4c8 b slave +a005b4cc B flash_info +^^^^^^^^ +a005c908 b saved_sector.4002 +a005c910 b cfi_mtd_info +a005c9c0 b cfi_mtd_names +a005c9d0 B mtd_table + +--------------------------------------- + +b) create hexdump from u-boot code: + +hexdump -C u-boot > gnlmpfhex + +--------------------------------------- + +c) search the variables address in the hexdump + + +* +0005fc80  00 00 00 00 00 00 00 00  2c 06 01 a0 18 cd 05 a0  |........,.......| +0005fc90  9c d4 05 a0 bc b4 05 a0  1c 7f 05 a0 f0 05 01 a0  |................| +0005fca0  08 5a 04 a0 1c ab 05 a0  ec a4 05 a0 98 c3 01 a0  |.Z..............| +0005fcb0  a0 d6 05 a0 04 71 05 a0  c0 f9 00 a0 3c cd 05 a0  |.....q......<...| +0005fcc0  cc b4 05 a0 f0 fa 00 a0  f0 d6 05 a0 10 86 05 a0  |................| +          ^^^^^^^^^^^ +0005fcd0  a4 16 06 a0 dc 64 05 a0  18 86 05 a0 52 48 05 a0  |.....d......RH..| +0005fce0  c0 86 05 a0 24 6e 02 a0  b4 6c 05 a0 b0 94 01 a0  |....$n...l......| +0005fcf0  1c 86 05 a0 50 85 05 a0  d4 0c 06 a0 bc 0b 06 a0  |....P...........| + + +-> 0005fcc0 + +---------------------------------------- + +d) know we calculate this address in RAM + + +  8ff08000	(new address of code in RAM *1) + ++ 0005fcc0 + +- 00008000	(offset of text *2) + +---------- + +  8ff5fcc0	-> Addr GOT in RAM + +*1: +activate debug and look for the line: +Now running in RAM - U-Boot at: 8ff08000 +                                ^^^^^^^^ +                                new address of u-boot code in RAM + +*2: +Section Headers: +  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al +  [ 0]                   NULL            00000000 000000 000000 00      0   0  0 +  [ 1] .text             PROGBITS        a0000000 008000 04599c 00  AX  0   0 32 +                                                  ^^^^^^ +                                                  Offset of text + +---------------------------------------- + +e) now we look in 8ff5fcc0 (RAM) + + +QongEVB>md 0x8ff5fcc0 +8ff5fcc0 : a005b4cc a000faf0 a005d6f0 a0058610  ................ +           ^^^^^^^^ +           Bingo, here we have the old flash address (when relocation +           is working, here is the fixed ram address. see @ f, how +           it gets calculated) + + +---------------------------------------- + +f) now translate it in the new RAM address + +  a005b4cc + +- a0000000     TextBase + ++ 8ff08000     new address of u-boot in ram +---------- +  8ff634cc + +QongEVB>mm 0x8ff5fcc0 0x8ff634cc 1 +QongEVB>md 0x8ff5fcc0 +8ff5fcc0 : 8ff634cc a000faf0 a005d6f0 a0058610  .4.............. +8ff5fcd0 : a00616a4 a00564dc a0058618 a0054852  .....d......RH.. + +As this must be done for all address in the GOT, the u-boot +code did this automagically ... :-) + +---------------------------------------------- + +g) check if the new address is really in the bss section: + +bss start: +8ff6054c	(8ff08000 + 0005854C monitorlen) + +bss end: +8ff698ac	(8ff08000 + 618AC) + +8ff634cc is in bss :-) + +---------------------------------------------- + +h) u-boot prints: + +important  addresses: + +U-Boot code: A0000000 -> A005854C  BSS: -> A00618AC	TextBase 0xa0000000 +Now running in RAM - U-Boot at: 8ff08000		relocBase 0x8ff08000 + + +--------- + +U-Boot 2010.06-rc2-00002-gf8fbb25-dirty (Jun 18 2010 - 17:07:19) + +U-Boot code: A0000000 -> A005854C  BSS: -> A00618AC +CPU:   Freescale i.MX31 at 398 MHz +Board: DAVE/DENX Qong +mon: FFFFFFFF gd->monLen: 000618AC +Top of RAM usable for U-Boot at: 90000000 +LCD panel info: 640 x 480, 16 bit/pix +Reserving 600k for LCD Framebuffer at: 8ff6a000 +Reserving 390k for U-Boot at: 8ff08000 +Reserving 1280k for malloc() at: 8fdc8000 +Reserving 28 Bytes for Board Info at: 8fdc7fe4 +Reserving 48 Bytes for Global Data at: 8fdc7fb4 +New Stack Pointer is: 8fdc7fb0 +RAM Configuration: +Bank #0: 80000000 256 MiB +mon: 0005854C gd->monLen: 000618AC +Now running in RAM - U-Boot at: 8ff08000 + +------------------------------------------------------------------------------------- + +Debugging u-boot in RAM: +(example on the qong board) + +a) add in config.mk: + +PLATFORM_CPPFLAGS += -DDEBUG + +----------------- + +b) start debugger + +arm-linux-gdb u-boot + +[hs@pollux u-boot]$ arm-linux-gdb u-boot +GNU gdb Red Hat Linux (6.7-2rh) +Copyright (C) 2007 Free Software Foundation, Inc. +License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law.  Type "show copying" +and "show warranty" for details. +This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux". +The target architecture is set automatically (currently arm) +.. +(gdb) + +----------------- + +c) connect to target + +target remote bdi10:2001 + +(gdb) target remote bdi10:2001 +Remote debugging using bdi10:2001 +0x8ff17f10 in ?? () +(gdb) + +----------------- + +d) discard symbol-file + +(gdb) symbol-file +Discard symbol table from `/home/hs/celf/u-boot/u-boot'? (y or n) y +No symbol file now. +(gdb) + +----------------- + +e) load new symbol table: + +(gdb) add-symbol-file u-boot 0x8ff08000 +add symbol table from file "u-boot" at +        .text_addr = 0x8ff08000 +(y or n) y +Reading symbols from /home/hs/celf/u-boot/u-boot...done. +(gdb) c +Continuing. +^C +Program received signal SIGSTOP, Stopped (signal). +0x8ff17f18 in serial_getc () at serial_mxc.c:192 +192             while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY); +(gdb) + +add-symbol-file u-boot 0x8ff08000 +                       ^^^^^^^^^^ +                       get this address from u-boot debug printfs + +U-Boot 2010.06-rc2-00009-gf77b8b8-dirty (Jun 22 2010 - 09:43:46) + +U-Boot code: A0000000 -> A0058BAC  BSS: -> A0061F10 +CPU:   Freescale i.MX31 at 398 MHz +Board: DAVE/DENX Qong +mon: FFFFFFFF gd->monLen: 00061F10 +Top of RAM usable for U-Boot at: 90000000 +LCD panel info: 640 x 480, 16 bit/pix +Reserving 600k for LCD Framebuffer at: 8ff6a000 +Reserving 391k for U-Boot at: 8ff08000 +                              ^^^^^^^^ +Reserving 1280k for malloc() at: 8fdc8000 +Reserving 24 Bytes for Board Info at: 8fdc7fe8 +Reserving 52 Bytes for Global Data at: 8fdc7fb4 +New Stack Pointer is: 8fdc7fb0 +RAM Configuration: +Bank #0: 80000000 256 MiB +relocation Offset is: eff08000 +mon: 00058BAC gd->monLen: 00061F10 +Now running in RAM - U-Boot at: 8ff08000 +                                ^^^^^^^^ + +Now you can use gdb as usual :-) diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c index b9fd6f544..0580dbf47 100644 --- a/nand_spl/nand_boot.c +++ b/nand_spl/nand_boot.c @@ -221,6 +221,13 @@ static int nand_load(struct mtd_info *mtd, unsigned int offs,  	return 0;  } +#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +void board_init_f (ulong bootflag) +{ +	relocate_code (TEXT_BASE - TOTAL_MALLOC_LEN, NULL, TEXT_BASE); +} +#endif +  /*   * The main entry for NAND booting. It's necessary that SDRAM is already   * configured and available since this code loads the main U-Boot image diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index ea3566b87..f89d54261 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -263,6 +263,13 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf)  	return 0;  } +#if defined(CONFIG_ARM) && !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +void board_init_f (ulong bootflag) +{ +	relocate_code (TEXT_BASE - TOTAL_MALLOC_LEN, NULL, TEXT_BASE); +} +#endif +  /*   * The main entry for NAND booting. It's necessary that SDRAM is already   * configured and available since this code loads the main U-Boot image |