diff options
author | Chris Zankel <chris@zankel.net> | 2016-08-10 18:36:44 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-08-15 18:46:38 -0400 |
commit | c978b52410016b0ab5a213f235596340af8d45f7 (patch) | |
tree | b01e9a8ea9a92fe962a545974339677b87dcc1ba /arch/xtensa/lib/bootm.c | |
parent | de5e5cea022ab44006ff1edf45a39f0943fb9dff (diff) |
xtensa: add support for the xtensa processor architecture [2/2]
The Xtensa processor architecture is a configurable, extensible,
and synthesizable 32-bit RISC processor core provided by Tensilica, inc.
This is the second part of the basic architecture port, adding the
'arch/xtensa' directory and a readme file.
Signed-off-by: Chris Zankel <chris@zankel.net>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'arch/xtensa/lib/bootm.c')
-rw-r--r-- | arch/xtensa/lib/bootm.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/arch/xtensa/lib/bootm.c b/arch/xtensa/lib/bootm.c new file mode 100644 index 0000000000..1604bb9536 --- /dev/null +++ b/arch/xtensa/lib/bootm.c @@ -0,0 +1,197 @@ +/* + * (C) Copyright 2008 - 2013 Tensilica Inc. + * (C) Copyright 2014 Cadence Design Systems Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <command.h> +#include <u-boot/zlib.h> +#include <asm/byteorder.h> +#include <asm/addrspace.h> +#include <asm/bootparam.h> +#include <asm/cache.h> +#include <image.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Setup boot-parameters. + */ + +static struct bp_tag *setup_first_tag(struct bp_tag *params) +{ + params->id = BP_TAG_FIRST; + params->size = sizeof(long); + *(unsigned long *)¶ms->data = BP_VERSION; + + return bp_tag_next(params); +} + +static struct bp_tag *setup_last_tag(struct bp_tag *params) +{ + params->id = BP_TAG_LAST; + params->size = 0; + + return bp_tag_next(params); +} + +static struct bp_tag *setup_memory_tag(struct bp_tag *params) +{ + struct bd_info *bd = gd->bd; + struct meminfo *mem; + + params->id = BP_TAG_MEMORY; + params->size = sizeof(struct meminfo); + mem = (struct meminfo *)params->data; + mem->type = MEMORY_TYPE_CONVENTIONAL; + mem->start = bd->bi_memstart; + mem->end = bd->bi_memstart + bd->bi_memsize; + + printf(" MEMORY: tag:0x%04x, type:0X%lx, start:0X%lx, end:0X%lx\n", + BP_TAG_MEMORY, mem->type, mem->start, mem->end); + + return bp_tag_next(params); +} + +static struct bp_tag *setup_commandline_tag(struct bp_tag *params, + char *cmdline) +{ + int len; + + if (!cmdline) + return params; + + len = strlen(cmdline); + + params->id = BP_TAG_COMMAND_LINE; + params->size = (len + 3) & -4; + strcpy((char *)params->data, cmdline); + + printf(" COMMAND_LINE: tag:0x%04x, size:%u, data:'%s'\n", + BP_TAG_COMMAND_LINE, params->size, cmdline); + + return bp_tag_next(params); +} + +static struct bp_tag *setup_ramdisk_tag(struct bp_tag *params, + unsigned long rd_start, + unsigned long rd_end) +{ + struct meminfo *mem; + + if (rd_start == rd_end) + return params; + + /* Add a single banked memory */ + + params->id = BP_TAG_INITRD; + params->size = sizeof(struct meminfo); + + mem = (struct meminfo *)params->data; + mem->type = MEMORY_TYPE_CONVENTIONAL; + mem->start = PHYSADDR(rd_start); + mem->end = PHYSADDR(rd_end); + + printf(" INITRD: tag:0x%x, type:0X%04lx, start:0X%lx, end:0X%lx\n", + BP_TAG_INITRD, mem->type, mem->start, mem->end); + + return bp_tag_next(params); +} + +static struct bp_tag *setup_serial_tag(struct bp_tag *params) +{ + params->id = BP_TAG_SERIAL_BAUDRATE; + params->size = sizeof(unsigned long); + params->data[0] = gd->baudrate; + + printf(" SERIAL_BAUDRATE: tag:0x%04x, size:%u, baudrate:%lu\n", + BP_TAG_SERIAL_BAUDRATE, params->size, params->data[0]); + + return bp_tag_next(params); +} + +#ifdef CONFIG_OF_LIBFDT + +static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start) +{ + params->id = BP_TAG_FDT; + params->size = sizeof(unsigned long); + params->data[0] = (unsigned long)fdt_start; + + printf(" FDT: tag:0x%04x, size:%u, start:0x%lx\n", + BP_TAG_FDT, params->size, params->data[0]); + + return bp_tag_next(params); +} + +#endif + +/* + * Boot Linux. + */ + +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +{ + struct bp_tag *params, *params_start; + ulong initrd_start, initrd_end; + char *commandline = getenv("bootargs"); + + if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO))) + return 0; + + show_boot_progress(15); + + if (images->rd_start) { + initrd_start = images->rd_start; + initrd_end = images->rd_end; + } else { + initrd_start = 0; + initrd_end = 0; + } + + params_start = (struct bp_tag *)gd->bd->bi_boot_params; + params = params_start; + params = setup_first_tag(params); + params = setup_memory_tag(params); + params = setup_commandline_tag(params, commandline); + params = setup_serial_tag(params); + + if (initrd_start) + params = setup_ramdisk_tag(params, initrd_start, initrd_end); + +#ifdef CONFIG_OF_LIBFDT + if (images->ft_addr) + params = setup_fdt_tag(params, images->ft_addr); +#endif + + printf("\n"); + + params = setup_last_tag(params); + + show_boot_progress(15); + + printf("Transferring Control to Linux @0x%08lx ...\n\n", + (ulong)images->ep); + + flush_dcache_range((unsigned long)params_start, (unsigned long)params); + + if (flag & BOOTM_STATE_OS_FAKE_GO) + return 0; + + /* + * _start() in vmlinux expects boot params in register a2. + * NOTE: + * Disable/delete your u-boot breakpoints before stepping into linux. + */ + asm volatile ("mov a2, %0\n\t" + "jx %1\n\t" + : : "a" (params_start), "a" (images->ep) + : "a2"); + + /* Does not return */ + + return 1; +} + |