u-boot-brain/board/armltd/vexpress64/vexpress64.c
Darwin Rambo 261d27605c arm: Add support for semihosting for armv8 fastmodel targets.
The armv8 ARM Trusted Firmware (ATF) can be used to load various ATF
images and u-boot, and does this for virtual platforms by using
semihosting. This commit extends this idea by allowing u-boot to also
use semihosting to load the kernel/ramdisk/dtb. This eliminates the need
for a bootwrapper and produces a more realistic boot sequence with
virtual models.

Though the semihosting code is quite generic, support for armv7 in
fastmodel is less useful due to the wide range of available silicon
and the lack of a free armv7 fastmodel, so this change contains an
untested armv7 placeholder for the service trap opcode.

Please refer to doc/README.semihosting for a more detailed description
of semihosting and how it is used with the armv8 virtual platforms.

Signed-off-by: Darwin Rambo <drambo@broadcom.com>
Cc: trini@ti.com
Cc: fenghua@phytium.com.cn
Cc: bhupesh.sharma@freescale.com
2014-07-03 08:35:45 +02:00

148 lines
3.5 KiB
C

/*
* (C) Copyright 2013
* David Feng <fenghua@phytium.com.cn>
* Sharma Bhupesh <bhupesh.sharma@freescale.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <malloc.h>
#include <errno.h>
#include <netdev.h>
#include <asm/io.h>
#include <linux/compiler.h>
#include <asm/semihosting.h>
DECLARE_GLOBAL_DATA_PTR;
int board_init(void)
{
return 0;
}
int dram_init(void)
{
/*
* Clear spin table so that secondary processors
* observe the correct value after waken up from wfe.
*/
*(unsigned long *)CPU_RELEASE_ADDR = 0;
gd->ram_size = PHYS_SDRAM_1_SIZE;
return 0;
}
/*
* Board specific reset that is system reset.
*/
void reset_cpu(ulong addr)
{
}
#ifdef CONFIG_BOARD_LATE_INIT
int board_late_init(void)
{
#ifdef CONFIG_SEMIHOSTING
/*
* Please refer to doc/README.semihosting for a more complete
* description.
*
* We require that the board include file defines these env variables:
* - kernel_name
* - kernel_addr_r
* - initrd_name
* - initrd_addr_r
* - fdt_name
* - fdt_addr_r
*
* For the "fdt chosen" startup macro, this code will then define:
* - initrd_end (based on initrd_addr_r plus actual initrd_size)
*
* We will then load the kernel, initrd, and fdt into the specified
* locations in memory in a similar way that the ATF fastmodel code
* uses semihosting calls to load other boot stages and u-boot itself.
*/
/* Env variable strings */
char *kernel_name = getenv("kernel_name");
char *kernel_addr_str = getenv("kernel_addr_r");
char *initrd_name = getenv("initrd_name");
char *initrd_addr_str = getenv("initrd_addr_r");
char *fdt_name = getenv("fdt_name");
char *fdt_addr_str = getenv("fdt_addr_r");
char initrd_end_str[64];
/* Actual addresses converted from env variables */
void *kernel_addr_r;
void *initrd_addr_r;
void *fdt_addr_r;
/* Actual initrd base and size */
unsigned long initrd_base;
unsigned long initrd_size;
/* Space available */
int avail;
/* Make sure the environment variables needed are set */
if (!(kernel_addr_str && initrd_addr_str && fdt_addr_str)) {
printf("%s: Define {kernel/initrd/fdt}_addr_r\n", __func__);
return -1;
}
if (!(kernel_name && initrd_name && fdt_name)) {
printf("%s: Define {kernel/initrd/fdt}_name\n", __func__);
return -1;
}
/* Get exact initrd_size */
initrd_size = smh_len(initrd_name);
if (initrd_size == -1) {
printf("%s: Can't get file size for \'%s\'\n", __func__,
initrd_name);
return -1;
}
/* Set initrd_end */
initrd_base = simple_strtoul(initrd_addr_str, NULL, 16);
initrd_addr_r = (void *)initrd_base;
sprintf(initrd_end_str, "0x%lx", initrd_base + initrd_size - 1);
setenv("initrd_end", initrd_end_str);
/* Load kernel to memory */
fdt_addr_r = (void *)simple_strtoul(fdt_addr_str, NULL, 16);
kernel_addr_r = (void *)simple_strtoul(kernel_addr_str, NULL, 16);
/*
* The kernel must be lower in memory than fdt and loading the
* kernel must not trample the fdt or vice versa.
*/
avail = fdt_addr_r - kernel_addr_r;
if (avail < 0) {
printf("%s: fdt must be after kernel\n", __func__);
return -1;
}
smh_load(kernel_name, kernel_addr_r, avail, 1);
/* Load fdt to memory */
smh_load(fdt_name, fdt_addr_r, 0x20000, 1);
/* Load initrd to memory */
smh_load(initrd_name, initrd_addr_r, initrd_size, 1);
#endif /* CONFIG_SEMIHOSTING */
return 0;
}
#endif /* CONFIG_BOARD_LATE_INIT */
/*
* Board specific ethernet initialization routine.
*/
int board_eth_init(bd_t *bis)
{
int rc = 0;
#ifdef CONFIG_SMC91111
rc = smc91111_initialize(0, CONFIG_SMC91111_BASE);
#endif
return rc;
}