diff options
| author | John Rigby <john.rigby@linaro.org> | 2010-10-13 13:57:36 -0600 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2010-10-18 22:54:00 +0200 | 
| commit | 2d1916e48bd871f29fa4634a69f6ef709b772be5 (patch) | |
| tree | 0771af2031232ca86c41ca467a98a6782f24685b | |
| parent | fca43cc8018327cbe13e943932fbf75772275192 (diff) | |
| download | olio-uboot-2014.01-2d1916e48bd871f29fa4634a69f6ef709b772be5.tar.xz olio-uboot-2014.01-2d1916e48bd871f29fa4634a69f6ef709b772be5.zip | |
ARM: add flat device tree support
Based on other architectures already supported.
Tested on OMAP3 Beagle board and another unnamed ARM platform.
Signed-off-by: John Rigby <john.rigby@linaro.org>
Tested-by: Rob Herring <rob.herring@smooth-stone.com>
Acked-by: Wolfgang Denk <wd@denx.de>
| -rw-r--r-- | arch/arm/include/asm/config.h | 2 | ||||
| -rw-r--r-- | arch/arm/lib/bootm.c | 137 | 
2 files changed, 123 insertions, 16 deletions
| diff --git a/arch/arm/include/asm/config.h b/arch/arm/include/asm/config.h index 4e8dfd7bc..d8e33fc51 100644 --- a/arch/arm/include/asm/config.h +++ b/arch/arm/include/asm/config.h @@ -25,4 +25,6 @@  /* Relocation to SDRAM works on all ARM boards */  #define CONFIG_RELOC_FIXUP_WORKS  #endif +#define CONFIG_LMB +#define CONFIG_SYS_BOOT_RAMDISK_HIGH  #endif diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 310132126..2e7b2e1f3 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -26,6 +26,9 @@  #include <image.h>  #include <u-boot/zlib.h>  #include <asm/byteorder.h> +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h>  DECLARE_GLOBAL_DATA_PTR; @@ -50,12 +53,52 @@ static void setup_end_tag (bd_t *bd);  static struct tag *params;  #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ -int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) +static ulong get_sp(void); +#if defined(CONFIG_OF_LIBFDT) +static int bootm_linux_fdt(int machid, bootm_headers_t *images); +#endif + +void arch_lmb_reserve(struct lmb *lmb) +{ +	ulong sp; + +	/* +	 * Booting a (Linux) kernel image +	 * +	 * Allocate space for command line and board info - the +	 * address should be as high as possible within the reach of +	 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused +	 * memory, which means far enough below the current stack +	 * pointer. +	 */ +	sp = get_sp(); +	debug("## Current stack ends at 0x%08lx ", sp); + +	/* adjust sp by 1K to be safe */ +	sp -= 1024; +	lmb_reserve(lmb, sp, +		    gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp); +} + +static void announce_and_cleanup(void) +{ +	printf("\nStarting kernel ...\n\n"); + +#ifdef CONFIG_USB_DEVICE +	{ +		extern void udc_disconnect(void); +		udc_disconnect(); +	} +#endif +	cleanup_before_linux(); +} + +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)  {  	bd_t	*bd = gd->bd;  	char	*s;  	int	machid = bd->bi_arch_number; -	void	(*theKernel)(int zero, int arch, uint params); +	void	(*kernel_entry)(int zero, int arch, uint params);  #ifdef CONFIG_CMDLINE_TAG  	char *commandline = getenv ("bootargs"); @@ -64,8 +107,6 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima  	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))  		return 1; -	theKernel = (void (*)(int, int, uint))images->ep; -  	s = getenv ("machid");  	if (s) {  		machid = simple_strtoul (s, NULL, 16); @@ -74,8 +115,15 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima  	show_boot_progress (15); +#ifdef CONFIG_OF_LIBFDT +	if (images->ft_len) +		return bootm_linux_fdt(machid, images); +#endif + +	kernel_entry = (void (*)(int, int, uint))images->ep; +  	debug ("## Transferring control to Linux (at address %08lx) ...\n", -	       (ulong) theKernel); +	       (ulong) kernel_entry);  #if defined (CONFIG_SETUP_MEMORY_TAGS) || \      defined (CONFIG_CMDLINE_TAG) || \ @@ -99,27 +147,76 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima  	if (images->rd_start && images->rd_end)  		setup_initrd_tag (bd, images->rd_start, images->rd_end);  #endif -	setup_end_tag (bd); +	setup_end_tag(bd);  #endif -	/* we assume that the kernel is in place */ -	printf ("\nStarting kernel ...\n\n"); +	announce_and_cleanup(); -#ifdef CONFIG_USB_DEVICE -	{ -		extern void udc_disconnect (void); -		udc_disconnect (); +	kernel_entry(0, machid, bd->bi_boot_params); +	/* does not return */ + +	return 1; +} + +#if defined(CONFIG_OF_LIBFDT) +static int fixup_memory_node(void *blob) +{ +	bd_t	*bd = gd->bd; +	int bank; +	u64 start[CONFIG_NR_DRAM_BANKS]; +	u64 size[CONFIG_NR_DRAM_BANKS]; + +	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { +		start[bank] = bd->bi_dram[bank].start; +		size[bank] = bd->bi_dram[bank].size;  	} -#endif -	cleanup_before_linux (); +	return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); +} + +static int bootm_linux_fdt(int machid, bootm_headers_t *images) +{ +	ulong rd_len; +	bd_t *bd = gd->bd; +	char *s; +	void (*kernel_entry)(int zero, int dt_machid, void *dtblob); +	ulong bootmap_base = getenv_bootm_low(); +	ulong of_size = images->ft_len; +	char **of_flat_tree = &images->ft_addr; +	ulong *initrd_start = &images->initrd_start; +	ulong *initrd_end = &images->initrd_end; +	struct lmb *lmb = &images->lmb; +	int ret; + +	kernel_entry = (void (*)(int, int, void *))images->ep; + +	rd_len = images->rd_end - images->rd_start; +	ret = boot_ramdisk_high(lmb, images->rd_start, rd_len, +				initrd_start, initrd_end); +	if (ret) +		return ret; -	theKernel (0, machid, bd->bi_boot_params); +	ret = boot_relocate_fdt(lmb, bootmap_base, of_flat_tree, &of_size); +	if (ret) +		return ret; + +	debug("## Transferring control to Linux (at address %08lx) ...\n", +	       (ulong) kernel_entry); + +	fdt_chosen(*of_flat_tree, 1); + +	fixup_memory_node(*of_flat_tree); + +	fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); + +	announce_and_cleanup(); + +	kernel_entry(0, machid, *of_flat_tree);  	/* does not return */  	return 1;  } - +#endif  #if defined (CONFIG_SETUP_MEMORY_TAGS) || \      defined (CONFIG_CMDLINE_TAG) || \ @@ -239,4 +336,12 @@ static void setup_end_tag (bd_t *bd)  	params->hdr.size = 0;  } +static ulong get_sp(void) +{ +	ulong ret; + +	asm("mov %0, sp" : "=r"(ret) : ); +	return ret; +} +  #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ |