mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
xtensa: add support for the xtensa processor architecture [1/2]
The Xtensa processor architecture is a configurable, extensible, and synthesizable 32-bit RISC processor core provided by Cadence. This is the first part of the basic architecture port with changes to common files. The 'arch/xtensa' directory, and boards and additional drivers will be in separate commits. 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>
This commit is contained in:
parent
f225d39d30
commit
de5e5cea02
9 changed files with 179 additions and 6 deletions
|
@ -454,6 +454,11 @@ S: Maintained
|
||||||
T: git git://git.denx.de/u-boot-x86.git
|
T: git git://git.denx.de/u-boot-x86.git
|
||||||
F: arch/x86/
|
F: arch/x86/
|
||||||
|
|
||||||
|
XTENSA
|
||||||
|
M: Max Filippov <jcmvbkbc@gmail.com>
|
||||||
|
S: Maintained
|
||||||
|
F: arch/xtensa/
|
||||||
|
|
||||||
THE REST
|
THE REST
|
||||||
M: Tom Rini <trini@konsulko.com>
|
M: Tom Rini <trini@konsulko.com>
|
||||||
L: u-boot@lists.denx.de
|
L: u-boot@lists.denx.de
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -557,6 +557,14 @@ else
|
||||||
include/config/auto.conf: ;
|
include/config/auto.conf: ;
|
||||||
endif # $(dot-config)
|
endif # $(dot-config)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Xtensa linker script cannot be preprocessed with -ansi because of
|
||||||
|
# preprocessor operations on strings that don't make C identifiers.
|
||||||
|
#
|
||||||
|
ifeq ($(CONFIG_XTENSA),)
|
||||||
|
LDPPFLAGS += -ansi
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||||
KBUILD_CFLAGS += -Os
|
KBUILD_CFLAGS += -Os
|
||||||
else
|
else
|
||||||
|
@ -1312,7 +1320,7 @@ $(timestamp_h): $(srctree)/Makefile FORCE
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
quiet_cmd_cpp_lds = LDS $@
|
quiet_cmd_cpp_lds = LDS $@
|
||||||
cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
|
cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
|
||||||
-D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<
|
-D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<
|
||||||
|
|
||||||
u-boot.lds: $(LDSCRIPT) prepare FORCE
|
u-boot.lds: $(LDSCRIPT) prepare FORCE
|
||||||
|
|
|
@ -524,6 +524,14 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(CONFIG_XTENSA)
|
||||||
|
|
||||||
|
int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
|
{
|
||||||
|
print_std_bdinfo(gd->bd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "a case for this architecture does not exist!"
|
#error "a case for this architecture does not exist!"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -54,6 +54,8 @@
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
|
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
|
||||||
#include <asm/init_helpers.h>
|
#include <asm/init_helpers.h>
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_X86) || defined(CONFIG_ARC) || defined(CONFIG_XTENSA)
|
||||||
#include <asm/relocate.h>
|
#include <asm/relocate.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SANDBOX
|
#ifdef CONFIG_SANDBOX
|
||||||
|
@ -271,7 +273,8 @@ static int setup_mon_len(void)
|
||||||
gd->mon_len = (ulong)&__bss_end - (ulong)_start;
|
gd->mon_len = (ulong)&__bss_end - (ulong)_start;
|
||||||
#elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
|
#elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
|
||||||
gd->mon_len = (ulong)&_end - (ulong)_init;
|
gd->mon_len = (ulong)&_end - (ulong)_init;
|
||||||
#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2)
|
#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2) || \
|
||||||
|
defined(CONFIG_XTENSA)
|
||||||
gd->mon_len = CONFIG_SYS_MONITOR_LEN;
|
gd->mon_len = CONFIG_SYS_MONITOR_LEN;
|
||||||
#elif defined(CONFIG_NDS32)
|
#elif defined(CONFIG_NDS32)
|
||||||
gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start);
|
gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start);
|
||||||
|
@ -971,7 +974,7 @@ static init_fnc_t init_sequence_f[] = {
|
||||||
* - board info struct
|
* - board info struct
|
||||||
*/
|
*/
|
||||||
setup_dest_addr,
|
setup_dest_addr,
|
||||||
#if defined(CONFIG_BLACKFIN)
|
#if defined(CONFIG_BLACKFIN) || defined(CONFIG_XTENSA)
|
||||||
/* Blackfin u-boot monitor should be on top of the ram */
|
/* Blackfin u-boot monitor should be on top of the ram */
|
||||||
reserve_uboot,
|
reserve_uboot,
|
||||||
#endif
|
#endif
|
||||||
|
@ -1003,7 +1006,7 @@ static init_fnc_t init_sequence_f[] = {
|
||||||
# endif
|
# endif
|
||||||
#endif /* CONFIG_DM_VIDEO */
|
#endif /* CONFIG_DM_VIDEO */
|
||||||
reserve_trace,
|
reserve_trace,
|
||||||
#if !defined(CONFIG_BLACKFIN)
|
#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_XTENSA)
|
||||||
reserve_uboot,
|
reserve_uboot,
|
||||||
#endif
|
#endif
|
||||||
#ifndef CONFIG_SPL_BUILD
|
#ifndef CONFIG_SPL_BUILD
|
||||||
|
@ -1036,6 +1039,9 @@ static init_fnc_t init_sequence_f[] = {
|
||||||
clear_bss,
|
clear_bss,
|
||||||
do_elf_reloc_fixups,
|
do_elf_reloc_fixups,
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(CONFIG_XTENSA)
|
||||||
|
clear_bss,
|
||||||
|
#endif
|
||||||
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
|
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
|
||||||
jump_to_copy,
|
jump_to_copy,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -93,6 +93,7 @@ static const table_entry_t uimage_arch[] = {
|
||||||
{ IH_ARCH_ARM64, "arm64", "AArch64", },
|
{ IH_ARCH_ARM64, "arm64", "AArch64", },
|
||||||
{ IH_ARCH_ARC, "arc", "ARC", },
|
{ IH_ARCH_ARC, "arc", "ARC", },
|
||||||
{ IH_ARCH_X86_64, "x86_64", "AMD x86_64", },
|
{ IH_ARCH_X86_64, "x86_64", "AMD x86_64", },
|
||||||
|
{ IH_ARCH_XTENSA, "xtensa", "Xtensa", },
|
||||||
{ -1, "", "", },
|
{ -1, "", "", },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
97
doc/README.xtensa
Normal file
97
doc/README.xtensa
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
U-Boot for the Xtensa Architecture
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Xtensa Architecture and Diamond Cores
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Xtensa is a configurable processor architecture from Tensilica, Inc.
|
||||||
|
Diamond Cores are pre-configured instances available for license and
|
||||||
|
SoC cores in the same manner as ARM, MIPS, etc.
|
||||||
|
|
||||||
|
Xtensa licensees create their own Xtensa cores with selected features
|
||||||
|
and custom instructions, registers and co-processors. The custom core
|
||||||
|
is configured with Tensilica tools and built with Tensilica's Xtensa
|
||||||
|
Processor Generator.
|
||||||
|
|
||||||
|
There are an effectively infinite number of CPUs in the Xtensa
|
||||||
|
architecture family. It is, however, not feasible to support individual
|
||||||
|
Xtensa CPUs in U-Boot. Therefore, there is only a single 'xtensa' CPU
|
||||||
|
in the cpu tree of U-Boot.
|
||||||
|
|
||||||
|
In the same manner as the Linux port to Xtensa, U-Boot adapts to an
|
||||||
|
individual Xtensa core configuration using a set of macros provided with
|
||||||
|
the particular core. This is part of what is known as the hardware
|
||||||
|
abstraction layer (HAL). For the purpose of U-Boot, the HAL consists only
|
||||||
|
of a few header files. These provide CPP macros that customize sources,
|
||||||
|
Makefiles, and the linker script.
|
||||||
|
|
||||||
|
|
||||||
|
Adding support for an additional processor configuration
|
||||||
|
--------------------------------------------------------
|
||||||
|
|
||||||
|
The header files for one particular processor configuration are inside
|
||||||
|
a variant-specific directory located in the arch/xtensa/include/asm
|
||||||
|
directory. The name of that directory starts with 'arch-' followed by
|
||||||
|
the name for the processor configuration, for example, arch-dc233c for
|
||||||
|
the Diamond DC233 processor.
|
||||||
|
|
||||||
|
core.h Definitions for the core itself.
|
||||||
|
|
||||||
|
The following files are part of the overlay but not used by U-Boot.
|
||||||
|
|
||||||
|
tie.h Co-processors and custom extensions defined
|
||||||
|
in the Tensilica Instruction Extension (TIE)
|
||||||
|
language.
|
||||||
|
tie-asm.h Assembly macros to access custom-defined registers
|
||||||
|
and states.
|
||||||
|
|
||||||
|
|
||||||
|
Global Data Pointer, Exported Function Stubs, and the ABI
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
To support standalone applications launched with the "go" command,
|
||||||
|
U-Boot provides a jump table of entrypoints to exported functions
|
||||||
|
(grep for EXPORT_FUNC). The implementation for Xtensa depends on
|
||||||
|
which ABI (or function calling convention) is used.
|
||||||
|
|
||||||
|
Windowed ABI presents unique difficulties with the approach based on
|
||||||
|
keeping global data pointer in dedicated register. Because the register
|
||||||
|
window rotates during a call, there is no register that is constantly
|
||||||
|
available for the gd pointer. Therefore, on xtensa gd is a simple
|
||||||
|
global variable. Another difficulty arises from the requirement to have
|
||||||
|
an 'entry' at the beginning of a function, which rotates the register
|
||||||
|
file and reserves a stack frame. This is an integral part of the
|
||||||
|
windowed ABI implemented in hardware. It makes using a jump table to an
|
||||||
|
arbitrary (separately compiled) function a bit tricky. Use of a simple
|
||||||
|
wrapper is also very tedious due to the need to move all possible
|
||||||
|
register arguments and adjust the stack to handle arguments that cannot
|
||||||
|
be passed in registers. The most efficient approach is to have the jump
|
||||||
|
table perform the 'entry' so as to pretend it's the start of the real
|
||||||
|
function. This requires decoding the target function's 'entry'
|
||||||
|
instruction to determine the stack frame size, and adjusting the stack
|
||||||
|
pointer accordingly, then jumping into the target function just after
|
||||||
|
the 'entry'. Decoding depends on the processor's endianness so uses the
|
||||||
|
HAL. The implementation (12 instructions) is in examples/stubs.c.
|
||||||
|
|
||||||
|
|
||||||
|
Access to Invalid Memory Addresses
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
U-Boot does not check if memory addresses given as arguments to commands
|
||||||
|
such as "md" are valid. There are two possible types of invalid
|
||||||
|
addresses: an area of physical address space may not be mapped to RAM
|
||||||
|
or peripherals, or in the presence of MMU an area of virtual address
|
||||||
|
space may not be mapped to physical addresses.
|
||||||
|
|
||||||
|
Accessing first type of invalid addresses may result in hardware lockup,
|
||||||
|
reading of meaningless data, written data being ignored or an exception,
|
||||||
|
depending on the CPU wiring to the system. Accessing second type of
|
||||||
|
invalid addresses always ends with an exception.
|
||||||
|
|
||||||
|
U-Boot for Xtensa provides a special memory exception handler that
|
||||||
|
reports such access attempts and resets the board.
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
Chris Zankel
|
||||||
|
Ross Morley
|
|
@ -240,6 +240,53 @@ gd_t *global_data;
|
||||||
" ld r10, [r10, %1]\n" \
|
" ld r10, [r10, %1]\n" \
|
||||||
" j [r10]\n" \
|
" j [r10]\n" \
|
||||||
: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r10");
|
: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r10");
|
||||||
|
#elif defined(CONFIG_XTENSA)
|
||||||
|
/*
|
||||||
|
* Global data ptr is in global_data, jump table ptr is in jt.
|
||||||
|
* Windowed ABI: Jump just past 'entry' in target and adjust stack frame
|
||||||
|
* (extract stack frame size from target 'entry' instruction).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void **jt;
|
||||||
|
|
||||||
|
#if defined(__XTENSA_CALL0_ABI__)
|
||||||
|
#define EXPORT_FUNC(f, a, x, ...) \
|
||||||
|
asm volatile ( \
|
||||||
|
" .extern jt\n" \
|
||||||
|
" .globl " #x "\n" \
|
||||||
|
" .align 4\n" \
|
||||||
|
#x ":\n" \
|
||||||
|
" l32i a8, %0, 0\n" \
|
||||||
|
" l32i a8, a8, %1\n" \
|
||||||
|
" jx a8\n" \
|
||||||
|
: : "r"(jt), "i" (FO(x)) : "a8");
|
||||||
|
#elif defined(__XTENSA_WINDOWED_ABI__)
|
||||||
|
#if XCHAL_HAVE_BE
|
||||||
|
# define SFT "8"
|
||||||
|
#else
|
||||||
|
# define SFT "12"
|
||||||
|
#endif
|
||||||
|
#define EXPORT_FUNC(f, a, x, ...) \
|
||||||
|
asm volatile ( \
|
||||||
|
" .extern jt\n" \
|
||||||
|
" .globl " #x "\n" \
|
||||||
|
" .align 4\n" \
|
||||||
|
#x ":\n" \
|
||||||
|
" entry sp, 16\n" \
|
||||||
|
" l32i a8, %0, 0\n" \
|
||||||
|
" l32i a8, a8, %1\n" \
|
||||||
|
" l32i a9, a8, 0\n" \
|
||||||
|
" extui a9, a9, " SFT ", 12\n" \
|
||||||
|
" subx8 a9, a9, sp\n" \
|
||||||
|
" movi a10, 16\n" \
|
||||||
|
" sub a9, a10, a9\n" \
|
||||||
|
" movsp sp, a9\n" \
|
||||||
|
" addi a8, a8, 3\n" \
|
||||||
|
" jx a8\n" \
|
||||||
|
: : "r"(jt), "i" (FO(x)) : "a8", "a9", "a10");
|
||||||
|
#else
|
||||||
|
#error Unsupported Xtensa ABI
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
/*" addi $sp, $sp, -24\n" \
|
/*" addi $sp, $sp, -24\n" \
|
||||||
" br $r16\n" \*/
|
" br $r16\n" \*/
|
||||||
|
|
|
@ -200,6 +200,7 @@ enum {
|
||||||
IH_ARCH_ARM64, /* ARM64 */
|
IH_ARCH_ARM64, /* ARM64 */
|
||||||
IH_ARCH_ARC, /* Synopsys DesignWare ARC */
|
IH_ARCH_ARC, /* Synopsys DesignWare ARC */
|
||||||
IH_ARCH_X86_64, /* AMD x86_64, Intel and Via */
|
IH_ARCH_X86_64, /* AMD x86_64, Intel and Via */
|
||||||
|
IH_ARCH_XTENSA, /* Xtensa */
|
||||||
|
|
||||||
IH_ARCH_COUNT,
|
IH_ARCH_COUNT,
|
||||||
};
|
};
|
||||||
|
|
|
@ -126,7 +126,7 @@ struct stat {
|
||||||
|
|
||||||
#endif /* __MIPS__ */
|
#endif /* __MIPS__ */
|
||||||
|
|
||||||
#if defined(__AVR32__) || defined(__SH__)
|
#if defined(__AVR32__) || defined(__SH__) || defined(__XTENSA__)
|
||||||
|
|
||||||
struct stat {
|
struct stat {
|
||||||
unsigned long st_dev;
|
unsigned long st_dev;
|
||||||
|
@ -149,7 +149,7 @@ struct stat {
|
||||||
unsigned long __unused5;
|
unsigned long __unused5;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __AVR32__ || __SH__ */
|
#endif /* __AVR32__ || __SH__ || __XTENSA__ */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue