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:
Chris Zankel 2016-08-10 18:36:43 +03:00 committed by Tom Rini
parent f225d39d30
commit de5e5cea02
9 changed files with 179 additions and 6 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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" \*/

View file

@ -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,
}; };

View file

@ -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
} }