xtensa: add support for the xtensa processor architecture [1/2]
authorChris Zankel <chris@zankel.net>
Wed, 10 Aug 2016 15:36:43 +0000 (18:36 +0300)
committerTom Rini <trini@konsulko.com>
Mon, 15 Aug 2016 22:46:38 +0000 (18:46 -0400)
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>
MAINTAINERS
Makefile
cmd/bdinfo.c
common/board_f.c
common/image.c
doc/README.xtensa [new file with mode: 0644]
examples/standalone/stubs.c
include/image.h
include/linux/stat.h

index 8905f88cf97f0b923abe719ad4bf438b0f90fe08..e0bf6794bf0c2446d96e56e2c130c9ca6841a302 100644 (file)
@@ -454,6 +454,11 @@ S: Maintained
 T:     git git://git.denx.de/u-boot-x86.git
 F:     arch/x86/
 
+XTENSA
+M:     Max Filippov <jcmvbkbc@gmail.com>
+S:     Maintained
+F:     arch/xtensa/
+
 THE REST
 M:     Tom Rini <trini@konsulko.com>
 L:     u-boot@lists.denx.de
index 91634d5d3147375beadad0a27a83667512710264..a2f5569b9c1424f36eb5f9d1d098f9dddba97647 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -557,6 +557,14 @@ else
 include/config/auto.conf: ;
 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
 KBUILD_CFLAGS  += -Os
 else
@@ -1312,7 +1320,7 @@ $(timestamp_h): $(srctree)/Makefile FORCE
 
 # ---------------------------------------------------------------------------
 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 $@ $<
 
 u-boot.lds: $(LDSCRIPT) prepare FORCE
index 637463ed028e37e234721bc438b1936d9e599327..e0bd15d54b0fdad49f6077ede75ceca80aa1c0b1 100644 (file)
@@ -524,6 +524,14 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        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
  #error "a case for this architecture does not exist!"
 #endif
index c4501affd9da3b8a8e978ada308ceef4d335a5c5..da381dbd93b4d7de42a547874c8e652decfe5a7d 100644 (file)
@@ -54,6 +54,8 @@
 #include <asm/sections.h>
 #if defined(CONFIG_X86) || defined(CONFIG_ARC)
 #include <asm/init_helpers.h>
+#endif
+#if defined(CONFIG_X86) || defined(CONFIG_ARC) || defined(CONFIG_XTENSA)
 #include <asm/relocate.h>
 #endif
 #ifdef CONFIG_SANDBOX
@@ -271,7 +273,8 @@ static int setup_mon_len(void)
        gd->mon_len = (ulong)&__bss_end - (ulong)_start;
 #elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
        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;
 #elif defined(CONFIG_NDS32)
        gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start);
@@ -971,7 +974,7 @@ static init_fnc_t init_sequence_f[] = {
         *  - board info struct
         */
        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 */
        reserve_uboot,
 #endif
@@ -1003,7 +1006,7 @@ static init_fnc_t init_sequence_f[] = {
 # endif
 #endif /* CONFIG_DM_VIDEO */
        reserve_trace,
-#if !defined(CONFIG_BLACKFIN)
+#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_XTENSA)
        reserve_uboot,
 #endif
 #ifndef CONFIG_SPL_BUILD
@@ -1036,6 +1039,9 @@ static init_fnc_t init_sequence_f[] = {
        clear_bss,
        do_elf_reloc_fixups,
 #endif
+#if defined(CONFIG_XTENSA)
+       clear_bss,
+#endif
 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
        jump_to_copy,
 #endif
index af155b229b9dc2b5c5268732060860055d033a84..7ad04ca19b80dbc6b627daae558a86423cdd7e9c 100644 (file)
@@ -93,6 +93,7 @@ static const table_entry_t uimage_arch[] = {
        {       IH_ARCH_ARM64,          "arm64",        "AArch64",      },
        {       IH_ARCH_ARC,            "arc",          "ARC",          },
        {       IH_ARCH_X86_64,         "x86_64",       "AMD x86_64",   },
+       {       IH_ARCH_XTENSA,         "xtensa",       "Xtensa",       },
        {       -1,                     "",             "",             },
 };
 
diff --git a/doc/README.xtensa b/doc/README.xtensa
new file mode 100644 (file)
index 0000000..4068582
--- /dev/null
@@ -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
index 0d62067e03be4cbf97e1cd8c38adf503f9120700..a8b7e14c049081278280b95325a2edefe58a16b0 100644 (file)
@@ -240,6 +240,53 @@ gd_t *global_data;
 "      ld      r10, [r10, %1]\n" \
 "      j       [r10]\n" \
        : : "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
 /*"    addi    $sp, $sp, -24\n"        \
 "      br      $r16\n"                 \*/
index 734def31178438b758404f3daba40b63cd1b31dc..64da722649092b1163e8dff3b7bd204a9d43396f 100644 (file)
@@ -200,6 +200,7 @@ enum {
        IH_ARCH_ARM64,                  /* ARM64        */
        IH_ARCH_ARC,                    /* Synopsys DesignWare ARC */
        IH_ARCH_X86_64,                 /* AMD x86_64, Intel and Via */
+       IH_ARCH_XTENSA,                 /* Xtensa       */
 
        IH_ARCH_COUNT,
 };
index cef636959e3ef1b462a6263745b06f288c92eac6..1af0876621d98a424d0af010dbdf848136d41f59 100644 (file)
@@ -126,7 +126,7 @@ struct stat {
 
 #endif /* __MIPS__ */
 
-#if defined(__AVR32__) || defined(__SH__)
+#if defined(__AVR32__) || defined(__SH__) || defined(__XTENSA__)
 
 struct stat {
        unsigned long st_dev;
@@ -149,7 +149,7 @@ struct stat {
        unsigned long  __unused5;
 };
 
-#endif /* __AVR32__ || __SH__ */
+#endif /* __AVR32__ || __SH__  || __XTENSA__ */
 
 #ifdef __cplusplus
 }