[U-Boot] [PATCH 6/8] xtensa: add support for the xtensa processor architecture [2/2]
Max Filippov
jcmvbkbc at gmail.com
Wed Aug 20 19:42:11 CEST 2014
From: Chris Zankel <chris at zankel.net>
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 at zankel.net>
Signed-off-by: Max Filippov <jcmvbkbc at gmail.com>
---
arch/Kconfig | 4 +
arch/xtensa/Kconfig | 26 ++
arch/xtensa/config.mk | 13 +
arch/xtensa/cpu/.gitignore | 1 +
arch/xtensa/cpu/Makefile | 13 +
arch/xtensa/cpu/config.mk | 9 +
arch/xtensa/cpu/cpu.c | 84 +++++
arch/xtensa/cpu/exceptions.c | 67 ++++
arch/xtensa/cpu/start.S | 672 ++++++++++++++++++++++++++++++++++
arch/xtensa/cpu/u-boot.lds.S | 107 ++++++
arch/xtensa/include/asm/addrspace.h | 43 +++
arch/xtensa/include/asm/asmmacro.h | 136 +++++++
arch/xtensa/include/asm/bitops.h | 14 +
arch/xtensa/include/asm/bootparam.h | 54 +++
arch/xtensa/include/asm/byteorder.h | 81 ++++
arch/xtensa/include/asm/cache.h | 20 +
arch/xtensa/include/asm/cacheasm.h | 187 ++++++++++
arch/xtensa/include/asm/config.h | 17 +
arch/xtensa/include/asm/errno.h | 1 +
arch/xtensa/include/asm/global_data.h | 24 ++
arch/xtensa/include/asm/io.h | 148 ++++++++
arch/xtensa/include/asm/ldscript.h | 220 +++++++++++
arch/xtensa/include/asm/linkage.h | 4 +
arch/xtensa/include/asm/misc.h | 24 ++
arch/xtensa/include/asm/posix_types.h | 74 ++++
arch/xtensa/include/asm/processor.h | 11 +
arch/xtensa/include/asm/ptrace.h | 133 +++++++
arch/xtensa/include/asm/regs.h | 95 +++++
arch/xtensa/include/asm/sections.h | 15 +
arch/xtensa/include/asm/string.h | 10 +
arch/xtensa/include/asm/types.h | 60 +++
arch/xtensa/include/asm/u-boot.h | 43 +++
arch/xtensa/include/asm/unaligned.h | 6 +
arch/xtensa/include/asm/xtensa.h | 36 ++
arch/xtensa/lib/Makefile | 9 +
arch/xtensa/lib/board.c | 173 +++++++++
arch/xtensa/lib/bootm.c | 202 ++++++++++
arch/xtensa/lib/misc.S | 178 +++++++++
arch/xtensa/lib/time.c | 111 ++++++
39 files changed, 3125 insertions(+)
create mode 100644 arch/xtensa/Kconfig
create mode 100644 arch/xtensa/config.mk
create mode 100644 arch/xtensa/cpu/.gitignore
create mode 100644 arch/xtensa/cpu/Makefile
create mode 100644 arch/xtensa/cpu/config.mk
create mode 100644 arch/xtensa/cpu/cpu.c
create mode 100644 arch/xtensa/cpu/exceptions.c
create mode 100644 arch/xtensa/cpu/start.S
create mode 100644 arch/xtensa/cpu/u-boot.lds.S
create mode 100644 arch/xtensa/include/asm/addrspace.h
create mode 100644 arch/xtensa/include/asm/asmmacro.h
create mode 100644 arch/xtensa/include/asm/bitops.h
create mode 100644 arch/xtensa/include/asm/bootparam.h
create mode 100644 arch/xtensa/include/asm/byteorder.h
create mode 100644 arch/xtensa/include/asm/cache.h
create mode 100644 arch/xtensa/include/asm/cacheasm.h
create mode 100644 arch/xtensa/include/asm/config.h
create mode 100644 arch/xtensa/include/asm/errno.h
create mode 100644 arch/xtensa/include/asm/global_data.h
create mode 100644 arch/xtensa/include/asm/io.h
create mode 100644 arch/xtensa/include/asm/ldscript.h
create mode 100644 arch/xtensa/include/asm/linkage.h
create mode 100644 arch/xtensa/include/asm/misc.h
create mode 100644 arch/xtensa/include/asm/posix_types.h
create mode 100644 arch/xtensa/include/asm/processor.h
create mode 100644 arch/xtensa/include/asm/ptrace.h
create mode 100644 arch/xtensa/include/asm/regs.h
create mode 100644 arch/xtensa/include/asm/sections.h
create mode 100644 arch/xtensa/include/asm/string.h
create mode 100644 arch/xtensa/include/asm/types.h
create mode 100644 arch/xtensa/include/asm/u-boot.h
create mode 100644 arch/xtensa/include/asm/unaligned.h
create mode 100644 arch/xtensa/include/asm/xtensa.h
create mode 100644 arch/xtensa/lib/Makefile
create mode 100644 arch/xtensa/lib/board.c
create mode 100644 arch/xtensa/lib/bootm.c
create mode 100644 arch/xtensa/lib/misc.S
create mode 100644 arch/xtensa/lib/time.c
diff --git a/arch/Kconfig b/arch/Kconfig
index 8620a4f..d19386a 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -47,6 +47,9 @@ config SPARC
config X86
bool "x86 architecture"
+config XTENSA
+ bool "Xtensa architecture"
+
endchoice
source "arch/arc/Kconfig"
@@ -64,3 +67,4 @@ source "arch/sandbox/Kconfig"
source "arch/sh/Kconfig"
source "arch/sparc/Kconfig"
source "arch/x86/Kconfig"
+source "arch/xtensa/Kconfig"
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
new file mode 100644
index 0000000..e4e3625
--- /dev/null
+++ b/arch/xtensa/Kconfig
@@ -0,0 +1,26 @@
+menu "Xtensa architecture"
+ depends on XTENSA
+
+config SYS_ARCH
+ string
+ default "xtensa"
+
+config SYS_CPU
+ string "Xtensa Core Variant"
+
+choice
+ prompt "Target select"
+
+
+endchoice
+
+
+config HAVE_SYS_ASCDISP
+ bool
+
+config SYS_ASCDISP
+ bool "System LCD Display"
+ default y
+ depends on HAVE_SYS_ASCDISP
+
+endmenu
diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk
new file mode 100644
index 0000000..a9a5e99
--- /dev/null
+++ b/arch/xtensa/config.mk
@@ -0,0 +1,13 @@
+#
+# (C) Copyright 2007 - 2014 Tensilica, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+CROSS_COMPILE ?= xtensa-linux-
+PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls
+
+CPUDIR = arch/$(ARCH)/cpu
+
+__HAVE_ARCH_GENERIC_BOARD := y
+
diff --git a/arch/xtensa/cpu/.gitignore b/arch/xtensa/cpu/.gitignore
new file mode 100644
index 0000000..09f1be0
--- /dev/null
+++ b/arch/xtensa/cpu/.gitignore
@@ -0,0 +1 @@
+u-boot.lds
diff --git a/arch/xtensa/cpu/Makefile b/arch/xtensa/cpu/Makefile
new file mode 100644
index 0000000..e47af19
--- /dev/null
+++ b/arch/xtensa/cpu/Makefile
@@ -0,0 +1,13 @@
+#
+# (C) Copyright 2007 - 2013 Tensilica, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y = cpu.o exceptions.o
+extra-y = start.o
+
+$(obj).depend.%: %.lds.S
+ $(CC) -M $(CPPFLAGS) $(EXTRA_CPPFLAGS_DEP) \
+ -MQ $(obj)$(basename $<) $< >$@
+
diff --git a/arch/xtensa/cpu/config.mk b/arch/xtensa/cpu/config.mk
new file mode 100644
index 0000000..986b1f6
--- /dev/null
+++ b/arch/xtensa/cpu/config.mk
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2007 - 2013 Tensilica, Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+# The linker script is pre-processed by CPP to adapt to the Xtensa core.
+LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds.S
+LDPPFLAGS := -I$(srctree)/include
diff --git a/arch/xtensa/cpu/cpu.c b/arch/xtensa/cpu/cpu.c
new file mode 100644
index 0000000..828f029
--- /dev/null
+++ b/arch/xtensa/cpu/cpu.c
@@ -0,0 +1,84 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * CPU specific code
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/stringify.h>
+#include <asm/cache.h>
+#include <asm/string.h>
+#include <asm/misc.h>
+
+#ifndef __XTENSA_CALL0_ABI__
+gd_t *gd;
+#endif
+
+/*
+ * Print information about the CPU.
+ */
+
+int checkcpu(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ char buf[120], mhz[8];
+ uint32_t id0, id1;
+
+ asm volatile ("rsr %0, 176\n"
+ "rsr %1, 208\n"
+ : "=r"(id0), "=r"(id1));
+
+ sprintf(buf, "CPU: Xtensa %s (id: %08x:%08x) at %s MHz\n",
+ XCHAL_CORE_ID, id0, id1, strmhz(mhz, gd->cpu_clk));
+ puts(buf);
+ return 0;
+}
+
+/*
+ * Implement the "reset" command.
+ * We need support from the board, though.
+ */
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ board_reset();
+
+ /* Shouldn't come back! */
+ printf("****** RESET FAILED ******\n");
+ return 0;
+}
+
+/*
+ * We currently run always with caches enabled when running for mmemory.
+ * Xtensa version D or later will support changing cache behavior, so
+ * we could implement it if necessary.
+ */
+
+int dcache_status(void)
+{
+ return 1;
+}
+
+void dcache_enable(void)
+{
+}
+
+void dcache_disable(void)
+{
+}
+
+void flush_cache(ulong start_addr, ulong size)
+{
+ __flush_invalidate_dcache_range(start_addr, size);
+ __invalidate_icache_range(start_addr, size);
+}
+
+void flush_dcache_range(ulong start_addr, ulong end_addr)
+{
+ __flush_invalidate_dcache_range(start_addr, end_addr - start_addr);
+}
diff --git a/arch/xtensa/cpu/exceptions.c b/arch/xtensa/cpu/exceptions.c
new file mode 100644
index 0000000..6edc6e4
--- /dev/null
+++ b/arch/xtensa/cpu/exceptions.c
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ * (C) Copyright 2014 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Exception handling.
+ * We currently don't handle any exception and force a reset.
+ * (Note that alloca is a special case and handled in start.S)
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/xtensa.h>
+#include <asm/string.h>
+#include <asm/regs.h>
+
+typedef void (*handler_t)(struct pt_regs *);
+
+void xtensa_mem_exc_dummy(struct pt_regs *);
+
+void unhandled_exception(struct pt_regs *regs)
+{
+#ifdef CONFIG_SYS_ASCDISP
+ display_printf("!! EXCCAUSE = %2ld", regs->exccause);
+#endif
+ printf("Unhandled Exception: EXCCAUSE = %ld (pc %lx)\n",
+ regs->exccause, regs->pc);
+ udelay(10000000); /* 10s to read display message */
+ panic("*** PANIC\n");
+}
+
+#define E(cause) EXCCAUSE_ ## cause
+
+handler_t exc_table[EXCCAUSE_LAST] = {
+ [0 ... EXCCAUSE_LAST-1] = unhandled_exception,
+ [EXCCAUSE_LOAD_STORE_ERROR] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_UNALIGNED] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_LOAD_STORE_DATA_ERROR] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_LOAD_STORE_ADDR_ERROR] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_FETCH_CACHE_ATTRIBUTE] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_DTLB_MISS] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_DTLB_MULTIHIT] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_DTLB_PRIVILEGE] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_DTLB_SIZE_RESTRICTION] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_LOAD_CACHE_ATTRIBUTE] = xtensa_mem_exc_dummy,
+ [EXCCAUSE_STORE_CACHE_ATTRIBUTE] = xtensa_mem_exc_dummy,
+};
+
+#ifdef CONFIG_USE_IRQ
+#error "Use of interrupts is not supported in Avnet/Xtensa ports"
+#else
+int interrupt_init(void)
+{
+ return 0;
+}
+void enable_interrupts(void)
+{
+ return;
+}
+int disable_interrupts(void)
+{
+ return 0;
+}
+#endif
diff --git a/arch/xtensa/cpu/start.S b/arch/xtensa/cpu/start.S
new file mode 100644
index 0000000..3d31c88
--- /dev/null
+++ b/arch/xtensa/cpu/start.S
@@ -0,0 +1,672 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/asmmacro.h>
+#include <asm/regs.h>
+#include <asm/arch/tie.h>
+#include <asm-offsets.h>
+
+/*
+ * Offsets into the the pt_regs struture.
+ * Make sure these always match with the structure defined in ptrace.h!
+ */
+
+#define PT_PC 0
+#define PT_PS 4
+#define PT_DEPC 8
+#define PT_EXCCAUSE 12
+#define PT_EXCVADDR 16
+#define PT_DEBUGCAUSE 20
+#define PT_WMASK 24
+#define PT_LBEG 28
+#define PT_LEND 32
+#define PT_LCOUNT 36
+#define PT_SAR 40
+#define PT_WINDOWBASE 44
+#define PT_WINDOWSTART 48
+#define PT_SYSCALL 52
+#define PT_ICOUNTLEVEL 56
+#define PT_RESERVED 60
+#define PT_AREG 64
+#define PT_SIZE (64 + 64)
+
+/*
+ * Reset vector.
+ * Only a trampoline to jump to _start
+ * (Note that we have to mark the section writable as the section contains
+ * a relocatable literal)
+ */
+
+ .section .ResetVector.text, "awx"
+ .global _ResetVector
+_ResetVector:
+
+ j 1f
+ .align 4
+2: .long _start
+1: l32r a2, 2b
+ jx a2
+
+
+/*
+ * Processor initialization. We still run in rom space.
+ *
+ * NOTE: Running in ROM
+ * For Xtensa, we currently don't allow to run some code from ROM but
+ * unpack the data immediately to memory. This requires, for example,
+ * that DDR has been set up before running U-Boot. (See also comments
+ * inline for ways to change it)
+ */
+
+ .section .reset.text, "ax"
+ .global _start
+ .align 4
+_start:
+ /* Keep a0 = 0 for various initializations. */
+
+ movi a0, 0
+
+ /*
+ * For full MMU cores, put page table at unmapped virtual address.
+ * This ensures that accesses outside the static maps result
+ * in miss exceptions rather than random behaviour.
+ */
+
+#if XCHAL_HAVE_TLBS
+ wsr a0, PTEVADDR
+#endif
+
+ /* Disable dbreak debug exceptions. */
+
+#if XCHAL_HAVE_DEBUG && XCHAL_NUM_DBREAK > 0
+ .set _index, 0
+ .rept XCHAL_NUM_DBREAK - 1
+ wsr a0, DBREAKC + _index
+ .set _index, _index + 1
+ .endr
+#endif
+
+ /* Reset windowbase and windowstart. */
+
+#if XCHAL_HAVE_WINDOWED
+ movi a3, 1
+ wsr a3, windowstart
+ wsr a0, windowbase
+ rsync
+ movi a0, 0 /* windowbase might have changed */
+#endif
+
+#
+# Vecbase in bitstream may differ from header files
+# set or check it.
+#
+
+#if XCHAL_HAVE_VECBASE
+ movi a3, XCHAL_VECBASE_RESET_VADDR /* VECBASE reset value */
+ wsr a3, VECBASE
+#endif
+
+ /* Disable loops. */
+
+ wsr a0, LCOUNT
+
+ /* Set PS.WOE = 0, PS.EXCM = 0 (for loop), PS.INTLEVEL = EXCM level */
+
+#if XCHAL_HAVE_XEA1
+ movi a2, 1
+#else
+ movi a2, XCHAL_EXCM_LEVEL
+#endif
+ wsr a2, PS
+ rsync
+
+ /* Unlock and invalidate caches. */
+
+ movi a2, 0
+ __loopi a2, a3, XCHAL_DCACHE_SIZE, 4 << XCHAL_DCACHE_LINEWIDTH
+#if XCHAL_DCACHE_LINE_LOCKABLE
+ diu a2, 0 << XCHAL_DCACHE_LINEWIDTH
+ diu a2, 1 << XCHAL_DCACHE_LINEWIDTH
+ diu a2, 2 << XCHAL_DCACHE_LINEWIDTH
+ diu a2, 3 << XCHAL_DCACHE_LINEWIDTH
+#endif
+ dii a2, 0 << XCHAL_DCACHE_LINEWIDTH
+ dii a2, 1 << XCHAL_DCACHE_LINEWIDTH
+ dii a2, 2 << XCHAL_DCACHE_LINEWIDTH
+ dii a2, 3 << XCHAL_DCACHE_LINEWIDTH
+ __endla a2, a3, 4 << XCHAL_DCACHE_LINEWIDTH
+
+ movi a2, 0
+ __loopi a2, a3, XCHAL_ICACHE_SIZE, 4 << XCHAL_ICACHE_LINEWIDTH
+#if XCHAL_ICACHE_LINE_LOCKABLE
+ iiu a2, 0 << XCHAL_ICACHE_LINEWIDTH
+ iiu a2, 1 << XCHAL_ICACHE_LINEWIDTH
+ iiu a2, 2 << XCHAL_ICACHE_LINEWIDTH
+ iiu a2, 3 << XCHAL_ICACHE_LINEWIDTH
+#endif
+ iii a2, 0 << XCHAL_ICACHE_LINEWIDTH
+ iii a2, 1 << XCHAL_ICACHE_LINEWIDTH
+ iii a2, 2 << XCHAL_ICACHE_LINEWIDTH
+ iii a2, 3 << XCHAL_ICACHE_LINEWIDTH
+ __endla a2, a3, 4 << XCHAL_ICACHE_LINEWIDTH
+
+ isync
+
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+ movi a2, XCHAL_SPANNING_WAY
+ movi a3, 7
+ wdtlb a3, a2
+ witlb a3, a2
+ isync
+#endif
+
+ /* Unpack data sections. */
+
+ movi a2, __reloc_table_start
+ movi a3, __reloc_table_end
+
+1: beq a2, a3, 3f # no more entries?
+ l32i a4, a2, 0 # start destination (in RAM)
+ l32i a5, a2, 4 # end destination (in RAM)
+ l32i a6, a2, 8 # start source (in ROM)
+ addi a2, a2, 12 # next entry
+ beq a4, a5, 1b # skip, empty entry
+ beq a4, a6, 1b # skip, source and destination are the same
+
+2: l32i a7, a6, 0
+ addi a6, a6, 4
+ s32i a7, a4, 0
+ addi a4, a4, 4
+ bltu a4, a5, 2b
+ j 1b
+
+3: /* All code and initalized data segments have been copied. */
+
+ /* Setup PS, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
+
+#if __XTENSA_CALL0_ABI__
+ movi a2, XCHAL_EXCM_LEVEL
+#else
+ movi a2, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
+#endif
+ wsr a2, PS
+ rsync
+
+
+ /*
+ * Setup a small stack for some early initialization c-code.
+ * Also, set up a temporary GD.
+ * (reserve 16 bytes for the call4 stack frame)
+ */
+
+ /* Clear BSS */
+
+ movi a2, _bss_start
+ movi a3, _bss_end
+
+ __loopt a2, a3, a4, 2
+ s32i a0, a2, 0
+ __endla a2, a4, 4
+
+ /* Writeback */
+
+ movi a2, 0
+ __loopi a2, a3, XCHAL_DCACHE_SIZE, 4 << XCHAL_DCACHE_LINEWIDTH
+ diwb a2, 0 << XCHAL_DCACHE_LINEWIDTH
+ diwb a2, 1 << XCHAL_DCACHE_LINEWIDTH
+ diwb a2, 2 << XCHAL_DCACHE_LINEWIDTH
+ diwb a2, 3 << XCHAL_DCACHE_LINEWIDTH
+ __endla a2, a3, 4 << XCHAL_DCACHE_LINEWIDTH
+
+
+ /*
+ * Call board initialization routine (never returns).
+ */
+
+ movi a6, (CONFIG_SYS_GD_ADDR & -16) & 0xffffffff
+ movi a1, (CONFIG_SYS_SP_TOP & -16) & 0xffffffff
+
+ movi a4, xtensa_board_init
+
+#ifdef __XTENSA_CALL0_ABI__
+ mov a2, a6
+ mov a3, a1
+ callx0 a4
+#else
+ mov a7, a1
+ addi a1, a1, -16
+ callx4 a4
+#endif
+ /* Never Returns */
+ ill
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * a0 = addr_sp
+ * a1 = gd
+ * a2 = destination address
+ */
+ .text
+ .globl relocate_code
+ .align 4
+relocate_code:
+ entry a1, 16
+ retw
+
+#if XCHAL_HAVE_EXCEPTIONS
+
+/*
+ * Exception vectors.
+ *
+ * Various notes:
+ * - We currently don't use the user exception vector (PS.UM is always 0),
+ * but do define such a vector, just in case. They both jump to the
+ * same exception handler, though.
+ * - We currently only save the bare minimum number of registers:
+ * a0...a15, sar, loop-registers, exception register (epc1, excvaddr,
+ * exccause, depc)
+ * - WINDOWSTART is only saved to identify if registers have been spilled
+ * to the wrong stack (exception stack) while executing the exception
+ * handler.
+ */
+
+ .section .KernelExceptionVector.text, "ax"
+ .global _KernelExceptionVector
+_KernelExceptionVector:
+
+ wsr a2, EXCSAVE1
+ movi a2, ExceptionHandler
+ jx a2
+
+ .section .UserExceptionVector.text, "ax"
+ .global _UserExceptionVector
+_UserExceptionVector:
+
+ wsr a2, EXCSAVE1
+ movi a2, ExceptionHandler
+ jx a2
+
+#if !XCHAL_HAVE_XEA1
+ .section .DoubleExceptionVector.text, "ax"
+ .global _DoubleExceptionVector
+_DoubleExceptionVector:
+
+#ifdef __XTENSA_CALL0_ABI__
+ wsr a0, EXCSAVE1
+ movi a0, hang # report and ask user to reset board
+ callx0 a0
+#else
+ wsr a4, EXCSAVE1
+ movi a4, hang # report and ask user to reset board
+ callx4 a4
+#endif
+#endif
+ /* Does not return here. */
+
+
+ .text
+ .align 4
+ExceptionHandler:
+
+ rsr a2, EXCCAUSE # find handler
+
+ /* Special case for alloca handler. */
+
+ bnei a2, 5, 1f # jump if not alloca exception
+
+ addi a1, a1, -16 - 4 # create a small stack frame
+ s32i a3, a1, 0 # and save a3 (a2 still in excsave1)
+ movi a2, fast_alloca_exception
+ jx a2 # jump to fast_alloca_exception
+
+ /* All other exceptions go here: */
+
+ /* Create ptrace stack and save a0...a3 */
+
+1: addi a2, a1, - PT_SIZE - 16
+ s32i a0, a2, PT_AREG + 0 * 4
+ s32i a1, a2, PT_AREG + 1 * 4
+ s32i a3, a2, PT_AREG + 3 * 4
+ rsr a3, EXCSAVE1
+ s32i a3, a2, PT_AREG + 2 * 4
+ mov a1, a2
+
+ /* Save remaining AR registers. */
+
+ s32i a4, a1, PT_AREG + 4 * 4
+ s32i a5, a1, PT_AREG + 5 * 4
+ s32i a6, a1, PT_AREG + 6 * 4
+ s32i a7, a1, PT_AREG + 7 * 4
+ s32i a8, a1, PT_AREG + 8 * 4
+ s32i a9, a1, PT_AREG + 9 * 4
+ s32i a10, a1, PT_AREG + 10 * 4
+ s32i a11, a1, PT_AREG + 11 * 4
+ s32i a12, a1, PT_AREG + 12 * 4
+ s32i a13, a1, PT_AREG + 13 * 4
+ s32i a14, a1, PT_AREG + 14 * 4
+ s32i a15, a1, PT_AREG + 15 * 4
+
+ /* Save SRs */
+
+ rsr a2, WINDOWSTART
+ s32i a2, a1, PT_WINDOWSTART
+
+ rsr a2, SAR
+ rsr a3, EPC1
+ s32i a2, a1, PT_SAR
+ s32i a3, a1, PT_PC
+
+#if XCHAL_HAVE_LOOPS
+ movi a2, 0
+ rsr a3, LBEG
+ xsr a2, LCOUNT
+ s32i a3, a1, PT_LBEG
+ rsr a3, LEND
+ s32i a2, a1, PT_LCOUNT
+ s32i a3, a1, PT_LEND
+#endif
+
+ /* Set up C environment and call registered handler. */
+ /* Setup stack, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
+
+ rsr a2, EXCCAUSE
+#if XCHAL_HAVE_XEA1
+ movi a3, (1<<PS_WOE_BIT) | 1
+#elif __XTENSA_CALL0_ABI__
+ movi a3, XCHAL_EXCM_LEVEL
+#else
+ movi a3, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
+#endif
+ xsr a3, PS
+ rsync
+ s32i a2, a1, PT_EXCCAUSE
+ s32i a3, a1, PT_PS
+
+ movi a0, exc_table
+ addx4 a0, a2, a0
+ l32i a0, a0, 0
+#ifdef __XTENSA_CALL0_ABI__
+ mov a2, a1 # Provide stack frame as only argument
+ callx0 a0
+ l32i a3, a1, PT_PS
+#else
+ mov a6, a1 # Provide stack frame as only argument
+ callx4 a0
+#endif
+
+ /* Restore PS and go to exception mode (PS.EXCM=1) */
+
+ wsr a3, PS
+
+ /* Restore SR registers */
+
+#if XCHAL_HAVE_LOOPS
+ l32i a2, a1, PT_LBEG
+ l32i a3, a1, PT_LEND
+ l32i a4, a1, PT_LCOUNT
+ wsr a2, LBEG
+ wsr a3, LEND
+ wsr a4, LCOUNT
+#endif
+
+ l32i a2, a1, PT_SAR
+ l32i a3, a1, PT_PC
+ wsr a2, SAR
+ wsr a3, EPC1
+
+ /* Do we need to simulate a MOVSP? */
+
+ l32i a2, a1, PT_WINDOWSTART
+ addi a3, a2, -1
+ and a2, a2, a3
+ beqz a2, 1f # Skip if regs were spilled before exc.
+
+ rsr a2, WINDOWSTART
+ addi a3, a2, -1
+ and a2, a2, a3
+ bnez a2, 1f # Skip if registers aren't spilled now
+
+ addi a2, a1, -16
+ l32i a4, a2, 0
+ l32i a5, a2, 4
+ s32i a4, a1, PT_SIZE + 0
+ s32i a5, a1, PT_SIZE + 4
+ l32i a4, a2, 8
+ l32i a5, a2, 12
+ s32i a4, a1, PT_SIZE + 8
+ s32i a5, a1, PT_SIZE + 12
+
+ /* Restore address register. */
+
+1: l32i a15, a1, PT_AREG + 15 * 4
+ l32i a14, a1, PT_AREG + 14 * 4
+ l32i a13, a1, PT_AREG + 13 * 4
+ l32i a12, a1, PT_AREG + 12 * 4
+ l32i a11, a1, PT_AREG + 11 * 4
+ l32i a10, a1, PT_AREG + 10 * 4
+ l32i a9, a1, PT_AREG + 9 * 4
+ l32i a8, a1, PT_AREG + 8 * 4
+ l32i a7, a1, PT_AREG + 7 * 4
+ l32i a6, a1, PT_AREG + 6 * 4
+ l32i a5, a1, PT_AREG + 5 * 4
+ l32i a4, a1, PT_AREG + 4 * 4
+ l32i a3, a1, PT_AREG + 3 * 4
+ l32i a2, a1, PT_AREG + 2 * 4
+ l32i a0, a1, PT_AREG + 0 * 4
+
+ l32i a1, a1, PT_AREG + 1 * 4 # Remove ptrace stack frame
+
+ rfe
+
+
+/*
+ * Dummy memory exception handler to avoid crash/hang on load/store of
+ * an invalid address (such as might be requested by user "md" command).
+ * U-Boot currently does not provide a hook to prevent accessing invalid
+ * addresses nor to inform the user, so we have to try to live with it.
+ * Simply skip the offending instruction (don't care what load returns).
+ * This is ugly (and possibly dangerous in Xtensa FLIX configs), but if we
+ * get here we're in trouble anyway, so might as well *try* to recover.
+ * void xtensa_mem_exc_dummy(struct pt_regs*);
+ */
+ /* Table of instruction sizes based on op0 field. */
+ .section .rodata, "a"
+ .type op0_format_lengths, @object
+ .align 4
+op0_format_lengths:
+ .byte XCHAL_OP0_FORMAT_LENGTHS
+
+ .text
+ .global xtensa_mem_exc_dummy
+ .type xtensa_mem_exc_dummy, @function
+ .align 4
+xtensa_mem_exc_dummy:
+
+#ifndef __XTENSA_CALL0_ABI__
+ entry a1, 16
+#endif
+
+ /* Decode the size of the instruction that caused the exception. */
+ l32i a3, a2, PT_PC /* a3 = PC of exception */
+ l8ui a4, a3, 0 /* a4 = first byte of insn */
+ movi a5, op0_format_lengths /* a5 = table of instruction sizes */
+ #if XCHAL_HAVE_BE
+ extui a4, a4, 4, 4 /* a4 = op0 = big end nibble */
+ #else
+ extui a4, a4, 0, 4 /* a4 = op0 = little end nibble */
+ #endif
+ add a5, a5, a4 /* index table with op0 */
+ l8ui a4, a5, 0 /* a4 = instruction size */
+
+ /* Increment the PC past the instruction that caused the exception. */
+ add a3, a3, a4 /* PC += size of insn */
+ #if XCHAL_HAVE_LOOPS
+ l32i a4, a2, PT_LEND /* if (PC == LEND */
+ bne a3, a4, 1f
+ l32i a4, a2, PT_LCOUNT /* && LCOUNT != 0) */
+ beqz a4, 1f /* { */
+ addi a4, a4, -1 /* --LCOUNT */
+ l32i a3, a2, PT_LBEG /* PC = LBEG */
+ s32i a4, a2, PT_LCOUNT /* } */
+ #endif
+1: s32i a3, a2, PT_PC /* update PC */
+
+#ifdef __XTENSA_CALL0_ABI__
+ ret
+#else
+ retw
+#endif
+
+#endif /* XCHAL_HAVE_EXCEPTIONS */
+
+#if XCHAL_HAVE_WINDOWED
+
+/*
+ * Window overflow and underflow handlers.
+ * The handlers must be 64 bytes apart, first starting with the underflow
+ * handlers underflow-4 to underflow-12, then the overflow handlers
+ * overflow-4 to overflow-12.
+ *
+ * Note: We rerun the underflow handlers if we hit an exception, so
+ * we try to access any page that would cause a page fault early.
+ */
+
+ .section .WindowVectors.text, "ax"
+
+/* 4-Register Window Overflow Vector (Handler) */
+
+ .align 64
+.global _WindowOverflow4
+_WindowOverflow4:
+ s32e a0, a5, -16
+ s32e a1, a5, -12
+ s32e a2, a5, -8
+ s32e a3, a5, -4
+ rfwo
+
+
+/* 4-Register Window Underflow Vector (Handler) */
+
+ .align 64
+.global _WindowUnderflow4
+_WindowUnderflow4:
+ l32e a0, a5, -16
+ l32e a1, a5, -12
+ l32e a2, a5, -8
+ l32e a3, a5, -4
+ rfwu
+
+/*
+ * a0: a0
+ * a1: new stack pointer = a1 - 16 - 4
+ * a2: available, saved in excsave1
+ * a3: available, saved on stack *a1
+ */
+
+/* 15*/ .byte 0xff
+
+fast_alloca_exception: /* must be at _WindowUnderflow4 + 16
+
+/* 16*/ rsr a2, PS
+/* 19*/ rsr a3, WINDOWBASE
+/* 22*/ extui a2, a2, PS_OWB_SHIFT, PS_OWB_SHIFT
+/* 25*/ xor a2, a2, a3
+/* 28*/ rsr a3, PS
+/* 31*/ slli a2, a2, PS_OWB_SHIFT
+/* 34*/ xor a2, a3, a2
+/* 37*/ wsr a2, PS
+
+/* 40*/ _l32i a3, a1, 0
+/* 43*/ addi a1, a1, 16 + 4
+/* 46*/ rsr a2, EXCSAVE1
+
+/* 49*/ rotw -1
+/* 52*/ _bbci.l a4, 31, _WindowUnderflow4 /* 0x: call4 */
+/* 55*/ rotw -1
+/* 58*/ _bbci.l a8, 30, _WindowUnderflow8 /* 10: call8 */
+/* 61*/ _j __WindowUnderflow12 /* 11: call12 */
+/* 64*/
+
+/* 8-Register Window Overflow Vector (Handler) */
+
+ .align 64
+.global _WindowOverflow8
+_WindowOverflow8:
+ s32e a0, a9, -16
+ l32e a0, a1, -12
+ s32e a2, a9, -8
+ s32e a1, a9, -12
+ s32e a3, a9, -4
+ s32e a4, a0, -32
+ s32e a5, a0, -28
+ s32e a6, a0, -24
+ s32e a7, a0, -20
+ rfwo
+
+/* 8-Register Window Underflow Vector (Handler) */
+
+ .align 64
+.global _WindowUnderflow8
+_WindowUnderflow8:
+ l32e a1, a9, -12
+ l32e a0, a9, -16
+ l32e a7, a1, -12
+ l32e a2, a9, -8
+ l32e a4, a7, -32
+ l32e a3, a9, -4
+ l32e a5, a7, -28
+ l32e a6, a7, -24
+ l32e a7, a7, -20
+ rfwu
+
+/* 12-Register Window Overflow Vector (Handler) */
+
+ .align 64
+.global _WindowOverflow12
+_WindowOverflow12:
+ s32e a0, a13, -16
+ l32e a0, a1, -12
+ s32e a1, a13, -12
+ s32e a2, a13, -8
+ s32e a3, a13, -4
+ s32e a4, a0, -48
+ s32e a5, a0, -44
+ s32e a6, a0, -40
+ s32e a7, a0, -36
+ s32e a8, a0, -32
+ s32e a9, a0, -28
+ s32e a10, a0, -24
+ s32e a11, a0, -20
+ rfwo
+
+/* 12-Register Window Underflow Vector (Handler) */
+
+ .org _WindowOverflow12 + 64 - 3
+__WindowUnderflow12:
+ rotw -1
+.global _WindowUnderflow12
+_WindowUnderflow12:
+ l32e a1, a13, -12
+ l32e a0, a13, -16
+ l32e a11, a1, -12
+ l32e a2, a13, -8
+ l32e a4, a11, -48
+ l32e a8, a11, -32
+ l32e a3, a13, -4
+ l32e a5, a11, -44
+ l32e a6, a11, -40
+ l32e a7, a11, -36
+ l32e a9, a11, -28
+ l32e a10, a11, -24
+ l32e a11, a11, -20
+ rfwu
+
+#endif /* XCHAL_HAVE_WINDOWED */
diff --git a/arch/xtensa/cpu/u-boot.lds.S b/arch/xtensa/cpu/u-boot.lds.S
new file mode 100644
index 0000000..ff2fe83
--- /dev/null
+++ b/arch/xtensa/cpu/u-boot.lds.S
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/ldscript.h>
+#include <asm/arch/core.h>
+#include <asm/addrspace.h>
+#include <asm-offsets.h>
+
+OUTPUT_ARCH(xtensa)
+ENTRY(_start)
+
+/*
+ * U-Boot resets from SYSROM and unpacks itself from a ROM store to RAM.
+ * The reset vector is usually near the base of SYSROM and has room
+ * above it for the ROM store into which the rest of U-Boot is packed.
+ * The ROM store also needs to be above any other vectors that are in ROM.
+ * If a core has its vectors near the top of ROM, this must be edited.
+ *
+ * Note that to run C code out of ROM, the processor would have to support
+ * 'relocatable' exception vectors and provide a scratch memory for the
+ * initial stack. Not all Xtensa processor configurations support that, so
+ * we can simplify the boot process and unpack U-Boot to RAM immediately.
+ * This, however, requires that memory have been initialized throug some
+ * other means (serial ROM, for example) or are initialized early (requiring
+ * an assembler functiont. See start.S for more details)
+ */
+
+SECTIONS
+{
+ . = + SIZEOF_HEADERS;
+ SECTION_ResetVector(XCHAL_RESET_VECTOR_VADDR, LMA_EQ_VMA)
+
+ .reloc_table ALIGN(4) : FOLLOWING(.ResetVector.text)
+ {
+ __reloc_table_start = ABSOLUTE(.);
+ RELOCATE2(WindowVectors,text);
+ RELOCATE2(KernelExceptionVector,literal);
+ RELOCATE2(KernelExceptionVector,text);
+ RELOCATE2(UserExceptionVector,literal);
+ RELOCATE2(UserExceptionVector,text);
+ RELOCATE2(DoubleExceptionVector,literal);
+ RELOCATE2(DoubleExceptionVector,text);
+ RELOCATE1(text);
+ RELOCATE1(rodata);
+ RELOCATE1(data);
+ RELOCATE1(u_boot_list);
+ __reloc_table_end = ABSOLUTE(.);
+ }
+
+ SECTION_VECTOR(WindowVectors,text,XCHAL_WINDOW_VECTORS_VADDR,
+ FOLLOWING(.reloc_table))
+ SECTION_VECTOR(KernelExceptionVector,literal,XCHAL_KERNEL_VECTOR_VADDR-8,
+ FOLLOWING(.WindowVectors.text))
+ SECTION_VECTOR(KernelExceptionVector,text,XCHAL_KERNEL_VECTOR_VADDR,
+ FOLLOWING(.KernelExceptionVector.literal))
+ SECTION_VECTOR(UserExceptionVector,literal,XCHAL_USER_VECTOR_VADDR-8,
+ FOLLOWING(.KernelExceptionVector.text))
+ SECTION_VECTOR(UserExceptionVector,text,XCHAL_USER_VECTOR_VADDR,
+ FOLLOWING(.UserExceptionVector.literal))
+ SECTION_VECTOR(DoubleExceptionVector,literal,XCHAL_DOUBLEEXC_VECTOR_VADDR-8,
+ FOLLOWING(.UserExceptionVector.text))
+ SECTION_VECTOR(DoubleExceptionVector,text,XCHAL_DOUBLEEXC_VECTOR_VADDR,
+ FOLLOWING(.DoubleExceptionVector.literal))
+
+
+ SECTION_text(CONFIG_SYS_TEXT_ADDR, FOLLOWING(.DoubleExceptionVector.text))
+ SECTION_rodata(ALIGN(16), FOLLOWING(.text))
+ SECTION_u_boot_list(ALIGN(16), FOLLOWING(.rodata))
+ SECTION_data(ALIGN(16), FOLLOWING(.u_boot_list))
+
+ __reloc_end = .;
+ __init_end = .;
+
+ SECTION_bss(__init_end (OVERLAY),)
+
+ /*
+ * On many Xtensa boards a region of RAM may be mapped to the ROM address
+ * space to facilitate on-chip-debug, and U-Boot must fit with that region.
+ * The config variables CONFIG_SYS_MONITOR_* define the region.
+ * If U-Boot extends beyond this region it will appear discontiguous in the
+ * address space and is in danger of overwriting itself during unpacking
+ * ("relocation").
+ * This causes U-Boot to crash in a way that is difficult to debug. On some
+ * boards (such as xtav60) the region is small enough that U-Boot will not
+ * fit if compiled entirely with -O0 (a common scenario). To avoid a lengthy
+ * debugging session when this happens, ensure a link-time error occurs.
+ *
+ */
+
+ __monitor_start = LOADADDR(.ResetVector.text);
+ __monitor_end = LOADADDR(.data) + SIZEOF(.data);
+ ASSERT(__monitor_end - __monitor_start <= CONFIG_SYS_MONITOR_LEN,
+ "U-Boot ROM image is too large. Check optimization level.")
+
+ SECTION_xtensa
+ SECTION_debug
+
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.hash*) }
+ /DISCARD/ : { *(.interp) }
+ /DISCARD/ : { *(.got*) }
+ /DISCARD/ : { *(.dynsym) }
+}
diff --git a/arch/xtensa/include/asm/addrspace.h b/arch/xtensa/include/asm/addrspace.h
new file mode 100644
index 0000000..5e6ecd9
--- /dev/null
+++ b/arch/xtensa/include/asm/addrspace.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008-2013 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_ADDRSPACE_H
+#define _XTENSA_ADDRSPACE_H
+
+#include <asm/arch/core.h>
+
+/*
+ * MMU Memory Map
+ *
+ * V2 MMU:
+ * IO (uncached) f0000000..ffffffff -> f000000
+ * IO (cached) e0000000..efffffff -> f000000
+ * MEM (uncached) d8000000..dfffffff -> 0000000
+ * MEM (cached) d0000000..d7ffffff -> 0000000
+ *
+ * V3 MMU:
+ * IO (uncached) f0000000..ffffffff -> f000000
+ * MEM (uncached) 00000000..0fffffff -> 0000000
+ *
+ */
+
+/* Region typically starting at 0xf0000000 */
+#define CONFIG_SYS_IO_BASE 0xf0000000
+
+/*
+ * Region typically starting at
+ * 0xD0000000 for V2 MMU
+ * and
+ * 0x00000000 for V3 MMU
+ */
+#define CONFIG_SYS_MEMORY_BASE \
+ (XCHAL_VECBASE_RESET_VADDR - XCHAL_VECBASE_RESET_PADDR)
+
+#define IOADDR(x) (CONFIG_SYS_IO_BASE + (x))
+#define MEMADDR(x) (CONFIG_SYS_MEMORY_BASE + (x))
+#define PHYSADDR(x) ((x) - (CONFIG_SYS_MEMORY_BASE))
+
+#endif /* _XTENSA_ADDRSPACE_H */
diff --git a/arch/xtensa/include/asm/asmmacro.h b/arch/xtensa/include/asm/asmmacro.h
new file mode 100644
index 0000000..d8e3565
--- /dev/null
+++ b/arch/xtensa/include/asm/asmmacro.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2005 - 2013 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_ASMMACRO_H
+#define _XTENSA_ASMMACRO_H
+
+#include <asm/arch/core.h>
+
+/*
+ * Some little helpers for loops. Use zero-overhead-loops
+ * where applicable and if supported by the processor.
+ *
+ * __loopi ar, at, size, inc
+ * ar register initialized with the start address
+ * at scratch register used by macro
+ * size size immediate value
+ * inc increment
+ *
+ * __loops ar, as, at, inc_log2[, mask_log2][, cond][, ncond]
+ * ar register initialized with the start address
+ * as register initialized with the size
+ * at scratch register use by macro
+ * inc_log2 increment [in log2]
+ * mask_log2 mask [in log2]
+ * cond true condition (used in loop'cond')
+ * ncond false condition (used in b'ncond')
+ *
+ * __loop as
+ * restart loop. 'as' register must not have been modified!
+ *
+ * __endla ar, at, incr
+ * ar start address (modified)
+ * as scratch register used by macro
+ * inc increment
+ */
+
+#if XCHAL_HAVE_LOOPS
+
+.macro __loopi ar, at, size, incr
+ movi \at, ((\size + \incr - 1) / (\incr))
+ loop \at, 99f
+.endm
+
+
+.macro __loops ar, as, at, incr_log2, mask_log2, cond, ncond
+ .ifgt \incr_log2 - 1
+ addi \at, \as, (1 << \incr_log2) - 1
+ .ifnc \mask_log2,
+ extui \at, \at, \incr_log2, \mask_log2
+ .else
+ srli \at, \at, \incr_log2
+ .endif
+ .endif
+ loop\cond \at, 99f
+.endm
+
+
+.macro __loopt ar, as, at, incr_log2
+ sub \at, \as, \ar
+ .ifgt \incr_log2 - 1
+ addi \at, \at, (1 << \incr_log2) - 1
+ srli \at, \at, \incr_log2
+ .endif
+ loop \at, 99f
+.endm
+
+
+.macro __loop as
+ loop \as, 99f
+.endm
+
+
+.macro __endl ar, as
+99:
+.endm
+
+
+#else
+
+.macro __loopi ar, at, size, incr
+ movi \at, ((\size + \incr - 1) / (\incr))
+ addi \at, \ar, \size
+98:
+.endm
+
+
+.macro __loops ar, as, at, incr_log2, mask_log2, cond, ncond
+ .ifnc \mask_log2,
+ extui \at, \as, \incr_log2, \mask_log2
+ .else
+ .ifnc \ncond,
+ srli \at, \as, \incr_log2
+ .endif
+ .endif
+ .ifnc \ncond,
+ b\ncond \at, 99f
+
+ .endif
+ .ifnc \mask_log2,
+ slli \at, \at, \incr_log2
+ add \at, \ar, \at
+ .else
+ add \at, \ar, \as
+ .endif
+98:
+.endm
+
+.macro __loopt ar, as, at, incr_log2
+98:
+.endm
+
+
+.macro __loop as
+98:
+.endm
+
+
+.macro __endl ar, as
+ bltu \ar, \as, 98b
+99:
+.endm
+
+
+#endif
+
+
+.macro __endla ar, as, incr
+ addi \ar, \ar, \incr
+ __endl \ar \as
+.endm
+
+
+#endif /* _XTENSA_ASMMACRO_H */
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
new file mode 100644
index 0000000..9cb84ac
--- /dev/null
+++ b/arch/xtensa/include/asm/bitops.h
@@ -0,0 +1,14 @@
+/*
+ * Atomic operations that C can't guarantee us.Useful for resource counting etc.
+ *
+ * Copyright (C) 2001 - 2012 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_BITOPS_H
+#define _XTENSA_BITOPS_H
+
+/* Use generic implementation */
+
+#endif /* _XTENSA_BITOPS_H */
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h
new file mode 100644
index 0000000..dd79485
--- /dev/null
+++ b/arch/xtensa/include/asm/bootparam.h
@@ -0,0 +1,54 @@
+/*
+ * Definition of the Linux/Xtensa boot parameter structure
+ *
+ * Copyright (C) 2001 - 2009 Tensilica Inc.
+ *
+ * (Concept borrowed from the 68K port)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_BOOTPARAM_H
+#define _XTENSA_BOOTPARAM_H
+
+#define BP_VERSION 0x0001
+
+#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/
+#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */
+#define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */
+#define BP_TAG_SERIAL_BAUDRATE 0x1004 /* baud rate of current console. */
+#define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */
+#define BP_TAG_FDT 0x1006 /* flat device tree */
+
+#define BP_TAG_FIRST 0x7B0B /* first tag with a version number */
+#define BP_TAG_LAST 0x7E0B /* last tag */
+
+#ifndef __ASSEMBLY__
+
+/* All records are aligned to 4 bytes */
+
+struct bp_tag {
+ unsigned short id; /* tag id */
+ unsigned short size; /* size of this record excluding the structure*/
+ unsigned long data[0]; /* data */
+};
+
+#define bp_tag_next(tag) \
+ ((struct bp_tag *)((unsigned long)((tag) + 1) + (tag)->size))
+
+struct meminfo {
+ unsigned long type;
+ unsigned long start;
+ unsigned long end;
+};
+
+#define MEMORY_TYPE_CONVENTIONAL 0x1000
+#define MEMORY_TYPE_NONE 0x2000
+
+struct sysmem_info {
+ int nr_banks;
+ struct meminfo bank[0];
+};
+
+#endif
+#endif
diff --git a/arch/xtensa/include/asm/byteorder.h b/arch/xtensa/include/asm/byteorder.h
new file mode 100644
index 0000000..485bc4b
--- /dev/null
+++ b/arch/xtensa/include/asm/byteorder.h
@@ -0,0 +1,81 @@
+/*
+ * Based on Linux/Xtensa kernel version
+ *
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_BYTEORDER_H
+#define _XTENSA_BYTEORDER_H
+
+#include <asm/types.h>
+
+static inline __attribute__((const)) __u32 ___arch__swab32(__u32 x)
+{
+ __u32 res;
+
+ /* instruction sequence from Xtensa ISA release 2/2000 */
+ __asm__("ssai 8\n\t"
+ "srli %0, %1, 16\n\t"
+ "src %0, %0, %1\n\t"
+ "src %0, %0, %0\n\t"
+ "src %0, %1, %0\n"
+ : "=&a" (res)
+ : "a" (x)
+ );
+ return res;
+}
+
+static inline __attribute__((const)) __u16 ___arch__swab16(__u16 x)
+{
+ /* Given that 'short' values are signed (i.e., can be negative),
+ * we cannot assume that the upper 16-bits of the register are
+ * zero. We are careful to mask values after shifting.
+ */
+
+ /* There exists an anomaly between xt-gcc and xt-xcc. xt-gcc
+ * inserts an extui instruction after putting this function inline
+ * to ensure that it uses only the least-significant 16 bits of
+ * the result. xt-xcc doesn't use an extui, but assumes the
+ * __asm__ macro follows convention that the upper 16 bits of an
+ * 'unsigned short' result are still zero. This macro doesn't
+ * follow convention; indeed, it leaves garbage in the upport 16
+ * bits of the register.
+ *
+ * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
+ * types while the return type of the function is a 16-bit type
+ * forces both compilers to insert exactly one extui instruction
+ * (or equivalent) to mask off the upper 16 bits.
+ */
+
+ __u32 res;
+ __u32 tmp;
+
+ __asm__("extui %1, %2, 8, 8\n\t"
+ "slli %0, %2, 8\n\t"
+ "or %0, %0, %1\n"
+ : "=&a" (res), "=&a" (tmp)
+ : "a" (x)
+ );
+
+ return res;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __BYTEORDER_HAS_U64__
+# define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __XTENSA_EL__
+# include <linux/byteorder/little_endian.h>
+#elif defined(__XTENSA_EB__)
+# include <linux/byteorder/big_endian.h>
+#else
+# error processor byte order undefined!
+#endif
+
+#endif /* _XTENSA_BYTEORDER_H */
diff --git a/arch/xtensa/include/asm/cache.h b/arch/xtensa/include/asm/cache.h
new file mode 100644
index 0000000..3999122
--- /dev/null
+++ b/arch/xtensa/include/asm/cache.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2009 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _XTENSA_CACHE_H
+#define _XTENSA_CACHE_H
+
+#include <asm/arch/core.h>
+
+#define ARCH_DMA_MINALIGN XCHAL_DCACHE_LINESIZE
+
+#ifndef __ASSEMBLY__
+
+void __flush_invalidate_dcache_range(unsigned long addr, unsigned long size);
+void __invalidate_icache_range(unsigned long addr, unsigned long size);
+
+#endif
+
+#endif /* _XTENSA_CACHE_H */
diff --git a/arch/xtensa/include/asm/cacheasm.h b/arch/xtensa/include/asm/cacheasm.h
new file mode 100644
index 0000000..6c62cce
--- /dev/null
+++ b/arch/xtensa/include/asm/cacheasm.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2006 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_CACHEASM_H
+#define _XTENSA_CACHEASM_H
+
+#include <asm/cache.h>
+#include <asm/asmmacro.h>
+#include <linux/stringify.h>
+
+#define PAGE_SIZE 4096
+#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE/XCHAL_DCACHE_WAYS)
+#define ICACHE_WAY_SIZE (XCHAL_ICACHE_SIZE/XCHAL_ICACHE_WAYS)
+#define DCACHE_WAY_SHIFT (XCHAL_DCACHE_SETWIDTH + XCHAL_DCACHE_LINEWIDTH)
+#define ICACHE_WAY_SHIFT (XCHAL_ICACHE_SETWIDTH + XCHAL_ICACHE_LINEWIDTH)
+
+/*
+ * Define cache functions as macros here so that they can be used
+ * by the kernel and boot loader. We should consider moving them to a
+ * library that can be linked by both.
+ *
+ * Locking
+ *
+ * ___unlock_dcache_all
+ * ___unlock_icache_all
+ *
+ * Flush and invaldating
+ *
+ * ___flush_invalidate_dcache_{all|range|page}
+ * ___flush_dcache_{all|range|page}
+ * ___invalidate_dcache_{all|range|page}
+ * ___invalidate_icache_{all|range|page}
+ *
+ */
+
+ .macro __loop_cache_all ar at insn size line_width
+
+ movi \ar, 0
+
+ __loopi \ar, \at, \size, (4 << (\line_width))
+
+ \insn \ar, 0 << (\line_width)
+ \insn \ar, 1 << (\line_width)
+ \insn \ar, 2 << (\line_width)
+ \insn \ar, 3 << (\line_width)
+
+ __endla \ar, \at, 4 << (\line_width)
+
+ .endm
+
+
+ .macro __loop_cache_range ar as at insn line_width
+
+ extui \at, \ar, 0, \line_width
+ add \as, \as, \at
+
+ __loops \ar, \as, \at, \line_width
+ \insn \ar, 0
+ __endla \ar, \at, (1 << (\line_width))
+
+ .endm
+
+
+ .macro __loop_cache_page ar at insn line_width
+
+ __loopi \ar, \at, PAGE_SIZE, 4 << (\line_width)
+
+ \insn \ar, 0 << (\line_width)
+ \insn \ar, 1 << (\line_width)
+ \insn \ar, 2 << (\line_width)
+ \insn \ar, 3 << (\line_width)
+
+ __endla \ar, \at, 4 << (\line_width)
+
+ .endm
+
+
+#if XCHAL_DCACHE_LINE_LOCKABLE
+
+ .macro ___unlock_dcache_all ar at
+
+ __loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+#endif
+
+#if XCHAL_ICACHE_LINE_LOCKABLE
+
+ .macro ___unlock_icache_all ar at
+
+ __loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+#endif
+
+ .macro ___flush_invalidate_dcache_all ar at
+
+ __loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___flush_dcache_all ar at
+
+ __loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_dcache_all ar at
+
+ __loop_cache_all \ar \at dii __stringify(DCACHE_WAY_SIZE) \
+ XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_icache_all ar at
+
+ __loop_cache_all \ar \at iii __stringify(ICACHE_WAY_SIZE) \
+ XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+
+
+
+ .macro ___flush_invalidate_dcache_range ar as at
+
+ __loop_cache_range \ar \as \at dhwbi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___flush_dcache_range ar as at
+
+ __loop_cache_range \ar \as \at dhwb XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_dcache_range ar as at
+
+ __loop_cache_range \ar \as \at dhi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_icache_range ar as at
+
+ __loop_cache_range \ar \as \at ihi XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+
+
+
+ .macro ___flush_invalidate_dcache_page ar as
+
+ __loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___flush_dcache_page ar as
+
+ __loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_dcache_page ar as
+
+ __loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH
+
+ .endm
+
+
+ .macro ___invalidate_icache_page ar as
+
+ __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH
+
+ .endm
+
+#endif /* _XTENSA_CACHEASM_H */
diff --git a/arch/xtensa/include/asm/config.h b/arch/xtensa/include/asm/config.h
new file mode 100644
index 0000000..98cf7c7
--- /dev/null
+++ b/arch/xtensa/include/asm/config.h
@@ -0,0 +1,17 @@
+/*
+ * config file header
+ *
+ * Copyright (C) 2009 Tensilica Inc.
+ * Based on the Linux/Xtensa version of this header.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ASM_CONFIG_H_
+#define _ASM_CONFIG_H_
+
+#include <asm/arch/core.h>
+
+#define CONFIG_LMB
+
+#endif
diff --git a/arch/xtensa/include/asm/errno.h b/arch/xtensa/include/asm/errno.h
new file mode 100644
index 0000000..4c82b50
--- /dev/null
+++ b/arch/xtensa/include/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/xtensa/include/asm/global_data.h b/arch/xtensa/include/asm/global_data.h
new file mode 100644
index 0000000..3563a5e
--- /dev/null
+++ b/arch/xtensa/include/asm/global_data.h
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2007, Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_GBL_DATA_H
+#define _XTENSA_GBL_DATA_H
+
+/* Architecture-specific global data */
+
+struct arch_global_data {
+ unsigned long cpu_clk;
+};
+
+#include <asm-generic/global_data.h>
+
+#ifdef __XTENSA_CALL0_ABI__
+# define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd __asm__ ("a14")
+#else
+# define DECLARE_GLOBAL_DATA_PTR extern gd_t *gd
+#endif
+
+#endif /* _XTENSA_GBL_DATA_H */
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
new file mode 100644
index 0000000..dd01063
--- /dev/null
+++ b/arch/xtensa/include/asm/io.h
@@ -0,0 +1,148 @@
+/*
+ * IO header file
+ *
+ * Copyright (C) 2001-2007 Tensilica Inc.
+ * Based on the Linux/Xtensa version of this header.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_IO_H
+#define _XTENSA_IO_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+
+/*
+ * swap functions to change byte order from little-endian to big-endian and
+ * vice versa.
+ */
+
+static inline unsigned short _swapw(unsigned short v)
+{
+ return (v << 8) | (v >> 8);
+}
+
+static inline unsigned int _swapl(unsigned int v)
+{
+ return (v << 24) | ((v & 0xff00) << 8) | ((v >> 8) & 0xff00) | (v >> 24);
+}
+
+static inline void iounmap(void *addr)
+{
+}
+
+/*
+ * Generic I/O
+ */
+
+#define readb(addr) \
+ ({ unsigned char __v = (*(volatile unsigned char *)(addr)); __v; })
+#define readw(addr) \
+ ({ unsigned short __v = (*(volatile unsigned short *)(addr)); __v; })
+#define readl(addr) \
+ ({ unsigned int __v = (*(volatile unsigned int *)(addr)); __v; })
+#define writeb(b, addr) (void)((*(volatile unsigned char *)(addr)) = (b))
+#define writew(b, addr) (void)((*(volatile unsigned short *)(addr)) = (b))
+#define writel(b, addr) (void)((*(volatile unsigned int *)(addr)) = (b))
+
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+/* These are the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl, the "string" versions
+ * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
+ * inb_p/inw_p/...
+ * The macros don't do byte-swapping.
+ */
+
+#define inb(port) readb((u8 *)((port)))
+#define outb(val, port) writeb((val), (u8 *)((unsigned long)(port)))
+#define inw(port) readw((u16 *)((port)))
+#define outw(val, port) writew((val), (u16 *)((unsigned long)(port)))
+#define inl(port) readl((u32 *)((port)))
+#define outl(val, port) writel((val), (u32 *)((unsigned long)(port)))
+
+#define inb_p(port) inb((port))
+#define outb_p(val, port) outb((val), (port))
+#define inw_p(port) inw((port))
+#define outw_p(val, port) outw((val), (port))
+#define inl_p(port) inl((port))
+#define outl_p(val, port) outl((val), (port))
+
+void insb(unsigned long port, void *dst, unsigned long count);
+void insw(unsigned long port, void *dst, unsigned long count);
+void insl(unsigned long port, void *dst, unsigned long count);
+void outsb(unsigned long port, const void *src, unsigned long count);
+void outsw(unsigned long port, const void *src, unsigned long count);
+void outsl(unsigned long port, const void *src, unsigned long count);
+
+#define IO_SPACE_LIMIT ~0
+
+#define memset_io(a, b, c) memset((void *)(a), (b), (c))
+#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
+#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c))
+
+/* At this point the Xtensa doesn't provide byte swap instructions */
+
+#ifdef __XTENSA_EB__
+# define in_8(addr) (*(u8 *)(addr))
+# define in_le16(addr) _swapw(*(u16 *)(addr))
+# define in_le32(addr) _swapl(*(u32 *)(addr))
+# define out_8(b, addr) *(u8 *)(addr) = (b)
+# define out_le16(b, addr) *(u16 *)(addr) = _swapw(b)
+# define out_le32(b, addr) *(u32 *)(addr) = _swapl(b)
+#elif defined(__XTENSA_EL__)
+# define in_8(addr) (*(u8 *)(addr))
+# define in_le16(addr) (*(u16 *)(addr))
+# define in_le32(addr) (*(u32 *)(addr))
+# define out_8(b, addr) *(u8 *)(addr) = (b)
+# define out_le16(b, addr) *(u16 *)(addr) = (b)
+# define out_le32(b, addr) *(u32 *)(addr) = (b)
+#else
+# error processor byte order undefined!
+#endif
+
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
+#define MAP_NOCACHE (0)
+#define MAP_WRCOMBINE (0)
+#define MAP_WRBACK (0)
+#define MAP_WRTHROUGH (0)
+
+/* We are using uncached addresses, ie: 0x80000000 ... */
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+ return (void *)paddr;
+}
+
+/*
+ * Take down a mapping set up by map_physmem().
+ */
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+}
+
+/*
+ * Dummy function to keep U-Boot's cfi_flash.c driver happy.
+ */
+static inline void sync(void)
+{
+}
+
+#endif /* _XTENSA_IO_H */
diff --git a/arch/xtensa/include/asm/ldscript.h b/arch/xtensa/include/asm/ldscript.h
new file mode 100644
index 0000000..4d34fa6
--- /dev/null
+++ b/arch/xtensa/include/asm/ldscript.h
@@ -0,0 +1,220 @@
+/*
+ * (C) Copyright 2007 Tensilica, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_LDSCRIPT_H
+#define _XTENSA_LDSCRIPT_H
+
+/*
+ * This linker script is pre-processed with CPP to avoid hard-coding
+ * addresses that depend on the Xtensa core configuration, because
+ * this FPGA board can be used with a huge variety of Xtensa cores.
+ */
+
+#include <asm/arch/core.h>
+#include <asm/addrspace.h>
+
+#define ALIGN_LMA 4
+#define LMA_EQ_VMA
+#define FORCE_OUTPUT . = .
+#define FOLLOWING(sec) \
+ AT(((LOADADDR(sec) + SIZEOF(sec) + ALIGN_LMA-1)) & ~(ALIGN_LMA-1))
+
+/*
+ * Specify an output section that will be added to the ROM store table
+ * (PACKED_SECTION) or one that will be resident in ROM (RESIDENT_SECTION).
+ * 'symname' is a base name for section boundary symbols *_start & *_end.
+ * 'lma' is the load address at which a section will be packed in ROM.
+ * 'region' is the basename identifying a memory region and program header.
+ * 'keep' prevents removal of empty sections (must be 'KEEP' or 'NOKEEP').
+ */
+
+#define RELOCATE1(_sec_) \
+ LONG(_##_sec_##_start); \
+ LONG(_##_sec_##_end); \
+ LONG(LOADADDR(.##_sec_));
+
+#define RELOCATE2(_sym_, _sec_) \
+ LONG(_##_sym_##_##_sec_##_start); \
+ LONG(_##_sym_##_##_sec_##_end); \
+ LONG(LOADADDR(.##_sym_##.##_sec_));
+
+#define SECTION_VECTOR(_sym_, _sec_, _vma_, _lma_) \
+.##_sym_##.##_sec_ _vma_ : _lma_ \
+{ \
+ . = ALIGN(4); \
+ _##_sym_##_##_sec_##_start = ABSOLUTE(.); \
+ KEEP(*(.##_sym_##.##_sec_)) \
+ _##_sym_##_##_sec_##_end = ABSOLUTE(.); \
+}
+
+/* In MMU configs there are two aliases of SYSROM, cached and uncached.
+ * For various reasons it is simpler to use the uncached mapping for load
+ * addresses, so ROM sections end up contiguous with the reset vector and
+ * we get a compact binary image. However we can gain performance by doing
+ * the unpacking from the cached ROM mapping. So we adjust all the load
+ * addresses in the ROM store table with an offset to the cached mapping,
+ * including the symbols referring to the ROM store table itself.
+ */
+
+#define SECTION_ResetVector(_vma_, _lma_) \
+ .ResetVector.text _vma_ : _lma_ \
+ { \
+ FORCE_OUTPUT; \
+ KEEP(*(.ResetVector.text)); \
+ KEEP(*(.reset.literal .reset.text)) \
+ }
+
+#define SECTION_text(_vma_, _lma_) \
+ .text _vma_ : _lma_ \
+ { \
+ _text_start = ABSOLUTE(.); \
+ *(.literal .text) \
+ *(.literal.* .text.* .stub) \
+ *(.gnu.warning .gnu.linkonce.literal.*) \
+ *(.gnu.linkonce.t.*.literal .gnu.linkonce.t.*) \
+ *(.fini.literal) \
+ *(.fini) \
+ *(.gnu.version) \
+ _text_end = ABSOLUTE(.); \
+ }
+
+#define SECTION_rodata(_vma_, _lma_) \
+ .rodata _vma_ : _lma_ \
+ { \
+ _rodata_start = ABSOLUTE(.); \
+ *(.rodata) \
+ *(.rodata.str1.4) \
+ *(.gnu.linkonce.r.*) \
+ *(.rodata1) \
+ __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); \
+ *(.xt_except_table) \
+ *(.gcc_except_table) \
+ *(.gnu.linkonce.e.*) \
+ *(.gnu.version_r) \
+ . = ALIGN(16); \
+ _rodata_end = ABSOLUTE(.); \
+ }
+
+#define SECTION_u_boot_list(_vma_, _lma_) \
+ .u_boot_list _vma_ : _lma_ \
+ { \
+ _u_boot_list_start = ABSOLUTE(.); \
+ KEEP(*(SORT(.u_boot_list*))); \
+ _u_boot_list_end = ABSOLUTE(.); \
+ }
+
+#define SECTION_data(_vma_, _lma_) \
+ .data _vma_ : _lma_ \
+ { \
+ _data_start = ABSOLUTE(.); \
+ *(.data) \
+ *(.data.*) \
+ *(.gnu.linkonce.d.*) \
+ *(.data1) \
+ *(.sdata) \
+ *(.sdata.*) \
+ *(.gnu.linkonce.s.*) \
+ *(.sdata2) \
+ *(.sdata2.*) \
+ *(.gnu.linkonce.s2.*) \
+ *(.jcr) \
+ *(.eh_frame) \
+ *(.dynamic) \
+ *(.gnu.version_d) \
+ _data_end = ABSOLUTE(.); \
+ }
+
+#define SECTION_lit4(_vma_, _lma_) \
+ .lit4 _vma_ : _lma_ \
+ { \
+ _lit4_start = ABSOLUTE(.); \
+ *(*.lit4) \
+ *(.gnu.linkonce.lit4.*) \
+ _lit4_end = ABSOLUTE(.); \
+ }
+
+#define SECTION_bss(_vma_, _lma_) \
+ .bss _vma_ : _lma_ \
+ { \
+ . = ALIGN(8); \
+ _bss_start = ABSOLUTE(.); \
+ __bss_start = ABSOLUTE(.); \
+ *(.dynsbss) \
+ *(.sbss) \
+ *(.sbss.*) \
+ *(.gnu.linkonce.sb.*) \
+ *(.scommon) \
+ *(.sbss2) \
+ *(.sbss2.*) \
+ *(.gnu.linkonce.sb2.*) \
+ *(.dynbss) \
+ *(.bss) \
+ *(.bss.*) \
+ *(.gnu.linkonce.b.*) \
+ *(COMMON) \
+ *(.sram.bss) \
+ . = ALIGN(8); \
+ _bss_end = ABSOLUTE(.); \
+ __bss_end = ABSOLUTE(.); \
+ _end = ALIGN(0x8); \
+ PROVIDE(end = ALIGN(0x8)); \
+ _stack_sentry = ALIGN(0x8); \
+ }
+
+#define SECTION_debug \
+ .debug 0 : { *(.debug) } \
+ .line 0 : { *(.line) } \
+ .debug_srcinfo 0 : { *(.debug_srcinfo) } \
+ .debug_sfnames 0 : { *(.debug_sfnames) } \
+ .debug_aranges 0 : { *(.debug_aranges) } \
+ .debug_pubnames 0 : { *(.debug_pubnames) } \
+ .debug_info 0 : { *(.debug_info) } \
+ .debug_abbrev 0 : { *(.debug_abbrev) } \
+ .debug_line 0 : { *(.debug_line) } \
+ .debug_frame 0 : { *(.debug_frame) } \
+ .debug_str 0 : { *(.debug_str) } \
+ .debug_loc 0 : { *(.debug_loc) } \
+ .debug_macinfo 0 : { *(.debug_macinfo) } \
+ .debug_weaknames 0 : { *(.debug_weaknames) } \
+ .debug_funcnames 0 : { *(.debug_funcnames) } \
+ .debug_typenames 0 : { *(.debug_typenames) } \
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+#define SECTION_xtensa \
+ .xt.insn 0 : \
+ { \
+ KEEP (*(.xt.insn)) \
+ KEEP (*(.gnu.linkonce.x.*)) \
+ } \
+ .xt.prop 0 : \
+ { \
+ KEEP (*(.xt.prop)) \
+ KEEP (*(.xt.prop.*)) \
+ KEEP (*(.gnu.linkonce.prop.*)) \
+ } \
+ .xt.lit 0 : \
+ { \
+ KEEP (*(.xt.lit)) \
+ KEEP (*(.xt.lit.*)) \
+ KEEP (*(.gnu.linkonce.p.*)) \
+ } \
+ .xt.profile_range 0 : \
+ { \
+ KEEP (*(.xt.profile_range)) \
+ KEEP (*(.gnu.linkonce.profile_range.*)) \
+ } \
+ .xt.profile_ranges 0 : \
+ { \
+ KEEP (*(.xt.profile_ranges)) \
+ KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) \
+ } \
+ .xt.profile_files 0 : \
+ { \
+ KEEP (*(.xt.profile_files)) \
+ KEEP (*(.gnu.linkonce.xt.profile_files.*)) \
+ }
+
+#endif /* _XTENSA_LDSCRIPT_H */
diff --git a/arch/xtensa/include/asm/linkage.h b/arch/xtensa/include/asm/linkage.h
new file mode 100644
index 0000000..3f46161
--- /dev/null
+++ b/arch/xtensa/include/asm/linkage.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#endif
diff --git a/arch/xtensa/include/asm/misc.h b/arch/xtensa/include/asm/misc.h
new file mode 100644
index 0000000..365c5e7
--- /dev/null
+++ b/arch/xtensa/include/asm/misc.h
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2008, Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef _XTENSA_MISC_H
+#define _XTENSA_MISC_H
+
+/* Defined in cpu/xtensa/u-boot.lds.S */
+void *__memory_avail_start;
+void *__memory_avail_end;
+
+/* Used in cpu/xtensa/cpu.c */
+void board_reset(void);
+
+#endif /* _XTENSA_MISC_H */
diff --git a/arch/xtensa/include/asm/posix_types.h b/arch/xtensa/include/asm/posix_types.h
new file mode 100644
index 0000000..821115c
--- /dev/null
+++ b/arch/xtensa/include/asm/posix_types.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007, Tensilica Inc.
+ *
+ * Based on the ARM version: Copyright (C) 1996-1998 Russell King.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _XTENSA_POSIX_TYPES_H
+#define _XTENSA_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_dev_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+ int val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+ int __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+#define __FD_SET(fd, fdsetp) \
+ (((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
+
+#undef __FD_CLR
+#define __FD_CLR(fd, fdsetp) \
+ (((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31)))
+
+#undef __FD_ISSET
+#define __FD_ISSET(fd, fdsetp) \
+ ((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0)
+
+#undef __FD_ZERO
+#define __FD_ZERO(fdsetp) \
+ (memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+
+#endif
+
+#endif /* _XTENSA_POSIX_TYPES_H */
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
new file mode 100644
index 0000000..8822f80
--- /dev/null
+++ b/arch/xtensa/include/asm/processor.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 1997 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_PROCESSOR_H
+#define _XTENSA_PROCESSOR_H
+
+
+#endif /* _XTENSA_PROCESSOR_H */
diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h
new file mode 100644
index 0000000..bb8ca61
--- /dev/null
+++ b/arch/xtensa/include/asm/ptrace.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_PTRACE_H
+#define _XTENSA_PTRACE_H
+
+#include <compiler.h>
+
+/*
+ * Kernel stack
+ *
+ * +-----------------------+ -------- STACK_SIZE
+ * | register file | |
+ * +-----------------------+ |
+ * | struct pt_regs | |
+ * +-----------------------+ | ------ PT_REGS_OFFSET
+ * double : 16 bytes spill area : | ^
+ * exception :- - - - - - - - - - - -: | |
+ * frame : struct pt_regs : | |
+ * :- - - - - - - - - - - -: | |
+ * | | | |
+ * | memory stack | | |
+ * | | | |
+ * ~ ~ ~ ~
+ * ~ ~ ~ ~
+ * | | | |
+ * | | | |
+ * +-----------------------+ | | --- STACK_BIAS
+ * | struct task_struct | | | ^
+ * current --> +-----------------------+ | | |
+ * | struct thread_info | | | |
+ * +-----------------------+ --------
+ */
+
+#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
+
+/* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
+
+#define EXC_TABLE_KSTK 0x004 /* Kernel Stack */
+#define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */
+#define EXC_TABLE_FIXUP 0x00c /* Fixup handler */
+#define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */
+#define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */
+#define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */
+#define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */
+#define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */
+#define EXC_TABLE_SIZE 0x400
+
+/* Registers used by strace */
+
+#define REG_A_BASE 0xfc000000
+#define REG_AR_BASE 0x04000000
+#define REG_PC 0x14000000
+#define REG_PS 0x080000e6
+#define REG_WB 0x08000048
+#define REG_WS 0x08000049
+#define REG_LBEG 0x08000000
+#define REG_LEND 0x08000001
+#define REG_LCOUNT 0x08000002
+#define REG_SAR 0x08000003
+#define REG_DEPC 0x080000c0
+#define REG_EXCCAUSE 0x080000e8
+#define REG_EXCVADDR 0x080000ee
+#define SYSCALL_NR 0x1
+
+#define AR_REGNO_TO_A_REGNO(ar, wb) (ar - wb*4) & ~(XCHAL_NUM_AREGS - 1)
+
+/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
+
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_GETFPREGSIZE 18
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+ unsigned long pc; /* 4 */
+ unsigned long ps; /* 8 */
+ unsigned long depc; /* 12 */
+ unsigned long exccause; /* 16 */
+ unsigned long excvaddr; /* 20 */
+ unsigned long debugcause; /* 24 */
+ unsigned long wmask; /* 28 */
+ unsigned long lbeg; /* 32 */
+ unsigned long lend; /* 36 */
+ unsigned long lcount; /* 40 */
+ unsigned long sar; /* 44 */
+ unsigned long windowbase; /* 48 */
+ unsigned long windowstart; /* 52 */
+ unsigned long syscall; /* 56 */
+ unsigned long icountlevel; /* 60 */
+ int reserved[1]; /* 64 */
+
+ /* Make sure the areg field is 16 bytes aligned. */
+ int align[0] __aligned(16);
+
+ /* current register frame.
+ * Note: The ESF for kernel exceptions ends after 16 registers!
+ */
+ unsigned long areg[16]; /* 128 (64) */
+};
+
+#ifdef __KERNEL__
+
+# define task_pt_regs(tsk) ((struct pt_regs *) \
+ (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
+# define user_mode(regs) (((regs)->ps & 0x00000020) != 0)
+# define instruction_pointer(regs) ((regs)->pc)
+void show_regs(struct pt_regs *);
+
+# ifndef CONFIG_SMP
+# define profile_pc(regs) instruction_pointer(regs)
+# endif
+#endif /* __KERNEL__ */
+
+#else /* __ASSEMBLY__ */
+
+#ifdef __KERNEL__
+# include <asm/asm-offsets.h>
+#define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE)
+#endif
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _XTENSA_PTRACE_H */
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h
new file mode 100644
index 0000000..6f623ef
--- /dev/null
+++ b/arch/xtensa/include/asm/regs.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2006 Tensilica, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_REGS_H
+#define _XTENSA_REGS_H
+
+/* Special registers. */
+
+#define IBREAKA 128
+#define DBREAKA 144
+#define DBREAKC 160
+
+/* Special names for read-only and write-only interrupt registers. */
+
+#define INTREAD 226
+#define INTSET 226
+#define INTCLEAR 227
+
+/* EXCCAUSE register fields */
+
+#define EXCCAUSE_EXCCAUSE_SHIFT 0
+#define EXCCAUSE_EXCCAUSE_MASK 0x3F
+
+#define EXCCAUSE_ILLEGAL_INSTRUCTION 0
+#define EXCCAUSE_SYSTEM_CALL 1
+#define EXCCAUSE_INSTRUCTION_FETCH_ERROR 2
+#define EXCCAUSE_LOAD_STORE_ERROR 3
+#define EXCCAUSE_LEVEL1_INTERRUPT 4
+#define EXCCAUSE_ALLOCA 5
+#define EXCCAUSE_INTEGER_DIVIDE_BY_ZERO 6
+#define EXCCAUSE_SPECULATION 7
+#define EXCCAUSE_PRIVILEGED 8
+#define EXCCAUSE_UNALIGNED 9
+#define EXCCAUSE_INSTR_DATA_ERROR 12
+#define EXCCAUSE_LOAD_STORE_DATA_ERROR 13
+#define EXCCAUSE_INSTR_ADDR_ERROR 14
+#define EXCCAUSE_LOAD_STORE_ADDR_ERROR 15
+#define EXCCAUSE_ITLB_MISS 16
+#define EXCCAUSE_ITLB_MULTIHIT 17
+#define EXCCAUSE_ITLB_PRIVILEGE 18
+#define EXCCAUSE_ITLB_SIZE_RESTRICTION 19
+#define EXCCAUSE_FETCH_CACHE_ATTRIBUTE 20
+#define EXCCAUSE_DTLB_MISS 24
+#define EXCCAUSE_DTLB_MULTIHIT 25
+#define EXCCAUSE_DTLB_PRIVILEGE 26
+#define EXCCAUSE_DTLB_SIZE_RESTRICTION 27
+#define EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28
+#define EXCCAUSE_STORE_CACHE_ATTRIBUTE 29
+#define EXCCAUSE_COPROCESSOR0_DISABLED 32
+#define EXCCAUSE_COPROCESSOR1_DISABLED 33
+#define EXCCAUSE_COPROCESSOR2_DISABLED 34
+#define EXCCAUSE_COPROCESSOR3_DISABLED 35
+#define EXCCAUSE_COPROCESSOR4_DISABLED 36
+#define EXCCAUSE_COPROCESSOR5_DISABLED 37
+#define EXCCAUSE_COPROCESSOR6_DISABLED 38
+#define EXCCAUSE_COPROCESSOR7_DISABLED 39
+#define EXCCAUSE_LAST 63
+
+/* PS register fields. */
+
+#define PS_WOE_BIT 18
+#define PS_CALLINC_SHIFT 16
+#define PS_CALLINC_MASK 0x00030000
+#define PS_OWB_SHIFT 8
+#define PS_OWB_MASK 0x00000F00
+#define PS_RING_SHIFT 6
+#define PS_RING_MASK 0x000000C0
+#define PS_UM_BIT 5
+#define PS_EXCM_BIT 4
+#define PS_INTLEVEL_SHIFT 0
+#define PS_INTLEVEL_MASK 0x0000000F
+
+/* DBREAKCn register fields. */
+
+#define DBREAKC_MASK_BIT 0
+#define DBREAKC_MASK_MASK 0x0000003F
+#define DBREAKC_LOAD_BIT 30
+#define DBREAKC_LOAD_MASK 0x40000000
+#define DBREAKC_STOR_BIT 31
+#define DBREAKC_STOR_MASK 0x80000000
+
+/* DEBUGCAUSE register fields. */
+
+#define DEBUGCAUSE_DEBUGINT_BIT 5 /* External debug interrupt */
+#define DEBUGCAUSE_BREAKN_BIT 4 /* BREAK.N instruction */
+#define DEBUGCAUSE_BREAK_BIT 3 /* BREAK instruction */
+#define DEBUGCAUSE_DBREAK_BIT 2 /* DBREAK match */
+#define DEBUGCAUSE_IBREAK_BIT 1 /* IBREAK match */
+#define DEBUGCAUSE_ICOUNT_BIT 0 /* ICOUNT would incr. to zero */
+
+#endif /* _XTENSA_SPECREG_H */
+
diff --git a/arch/xtensa/include/asm/sections.h b/arch/xtensa/include/asm/sections.h
new file mode 100644
index 0000000..2430daa
--- /dev/null
+++ b/arch/xtensa/include/asm/sections.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __ASM_XTENSA_SECTIONS_H
+#define __ASM_XTENSA_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+extern void *_text_start;
+#define CONFIG_SYS_TEXT_BASE ((unsigned int)&_text_start)
+
+#endif
diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h
new file mode 100644
index 0000000..65a3601
--- /dev/null
+++ b/arch/xtensa/include/asm/string.h
@@ -0,0 +1,10 @@
+#ifndef _XTENSA_STRING_H
+#define _XTENSA_STRING_H
+
+/*
+ * Use the generic string functions in U-Boot's lib_generic.
+ * In the boot loader we care about compactness more than performance.
+ * Prototypes will be taken from <linux/string.h>
+ */
+
+#endif /* _XTENSA_STRING_H */
diff --git a/arch/xtensa/include/asm/types.h b/arch/xtensa/include/asm/types.h
new file mode 100644
index 0000000..e30f519
--- /dev/null
+++ b/arch/xtensa/include/asm/types.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 1997 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_TYPES_H
+#define _XTENSA_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide. */
+
+typedef u32 dma_addr_t;
+
+typedef unsigned long phys_addr_t;
+typedef unsigned long phys_size_t;
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_TYPES_H */
diff --git a/arch/xtensa/include/asm/u-boot.h b/arch/xtensa/include/asm/u-boot.h
new file mode 100644
index 0000000..15fbf2e
--- /dev/null
+++ b/arch/xtensa/include/asm/u-boot.h
@@ -0,0 +1,43 @@
+/*
+ * (C) Copyright 2007, Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef _XTENSA_U_BOOT_H
+#define _XTENSA_U_BOOT_H
+
+#ifdef CONFIG_SYS_GENERIC_BOARD
+/* Use the generic board which requires a unified bd_info */
+#include <asm-generic/u-boot.h>
+#else
+
+#ifndef __ASSEMBLY__
+typedef struct bd_info {
+ int bi_baudrate; /* serial console baudrate */
+ unsigned long bi_ip_addr; /* IP Address */
+ unsigned char bi_enetaddr[6]; /* Ethernet adress */
+ unsigned long bi_boot_params; /* where this board expects params */
+ unsigned long bi_memstart; /* start of DRAM memory VA */
+ unsigned long bi_memsize; /* size of DRAM memory in bytes */
+ unsigned long bi_flashstart; /* start of FLASH memory */
+ unsigned long bi_flashsize; /* size of FLASH memory */
+ unsigned long bi_flashoffset; /* offset to skip UBoot image */
+} bd_t;
+#endif /* __ ASSEMBLY__ */
+
+#endif /* CONFIG_SYS_GENERIC_BOARD */
+
+/* For image.h:image_check_target_arch() */
+#define IH_ARCH_DEFAULT IH_ARCH_XTENSA
+
+int dram_init(void);
+
+#endif /* _XTENSA_U_BOOT_H */
diff --git a/arch/xtensa/include/asm/unaligned.h b/arch/xtensa/include/asm/unaligned.h
new file mode 100644
index 0000000..536f364
--- /dev/null
+++ b/arch/xtensa/include/asm/unaligned.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_XTENSA_UNALIGNED_H
+#define _ASM_XTENSA_UNALIGNED_H
+
+#include <asm-generic/unaligned.h>
+
+#endif /* _ASM_XTENSA_UNALIGNED_H */
diff --git a/arch/xtensa/include/asm/xtensa.h b/arch/xtensa/include/asm/xtensa.h
new file mode 100644
index 0000000..94b9788
--- /dev/null
+++ b/arch/xtensa/include/asm/xtensa.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 Tensilica, Inc.
+ *
+ * A place for global definitions specific to Xtensa-based ports.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _XTENSA_H_
+#define _XTENSA_H_
+
+#include <stdarg.h>
+#include <config.h>
+#include <asm/u-boot.h>
+
+/* Much of this is not specific to Xtensa and should move to a common header. */
+
+/* Quote a macro value as a string constant. */
+#define QUOTE1(s) #s
+#define QUOTE(s) QUOTE1(s)
+
+/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
+#define ALIGNUP(n, val) (((val) + (n)-1) & -(n))
+
+#ifdef CONFIG_SYS_ASCDISP
+/*
+ * Print a formatted string to the board's ASCII character display.
+ * String may have embedded newlines. Starts at top left and wraps long lines.
+ */
+void display_printf(const char *fmt, ...);
+void lcd_disp_at_pos(char *, unsigned char);
+#else
+#define display_printf(fmt, args)
+#endif
+
+#endif /* _XTENSA_H_ */
diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile
new file mode 100644
index 0000000..6650d24
--- /dev/null
+++ b/arch/xtensa/lib/Makefile
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2007 - 2013 Tensilica Inc.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_CMD_BOOTM) += bootm.o
+
+obj-y += misc.o time.o board.o
diff --git a/arch/xtensa/lib/board.c b/arch/xtensa/lib/board.c
new file mode 100644
index 0000000..53d6e40
--- /dev/null
+++ b/arch/xtensa/lib/board.c
@@ -0,0 +1,173 @@
+/*
+ * (C) Copyright 2008 - 2013, Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <stdio_dev.h>
+#include <version.h>
+#include <net.h>
+#include <config.h>
+#include <linux/stringify.h>
+#include <asm/xtensa.h>
+#include <asm/addrspace.h>
+#include <asm/bootparam.h>
+
+/* Import linker-defined symbols (see u-boot.lds) */
+extern void *__monitor_start, *__monitor_end;
+
+void board_init_r(gd_t *id, ulong dest_addr);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef __XTENSA_CALL0_ABI__
+gd_t *gd;
+#endif
+
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING ""
+#endif
+
+ulong monitor_flash_len; /* size of U-Boot packed image in flash */
+
+const char version_string[] =
+ U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"CONFIG_IDENT_STRING;
+
+
+/*
+ * Initialize baudrate settings in global and board data structures.
+ * This does not actually initialize the UART or set its baudrate.
+ * Return 0 on success (OK to continue), else non-zero (hang).
+ */
+static int init_baudrate(void)
+{
+ gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
+ return 0;
+}
+
+/*
+ * Initialize System RAM parameters and display RAM size.
+ * Install dummy exception handler that ignores load/store exceptions.
+ * Return 0 on success (OK to continue), else non-zero (hang).
+ */
+static int init_sysram(void)
+{
+ gd->ram_size = CONFIG_SYS_MEMORY_SIZE;
+ gd->ram_top = CONFIG_SYS_MEMORY_TOP;
+ gd->relocaddr = CONFIG_SYS_TEXT_ADDR;
+
+ gd->bd->bi_memstart = CONFIG_SYS_SDRAM_PHYS;
+ gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
+
+ puts("DRAM: ");
+ print_size(gd->bd->bi_memsize, "\n");
+
+ return 0;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+#ifdef CONFIG_SYS_ASCDISP
+static int display_freq(void)
+{
+ char mhz[8];
+ /* Announce our arrival and clock frequency */
+ display_printf("U-Boot %5s MHz", strmhz(mhz, gd->cpu_clk));
+
+ return 0;
+}
+#else
+static int display_freq(void)
+{
+ return 0;
+}
+#endif
+#endif
+
+
+/*
+ * Breath some life into the board...
+ *
+ * The first part of initialization is running from Flash memory;
+ * its main purpose is to initialize the RAM so that we
+ * can relocate the monitor code to RAM.
+ *
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependend #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+typedef int (init_fnc_t) (void);
+
+init_fnc_t *init_sequence[] = {
+ board_postclk_init,
+ env_init,
+ init_baudrate,
+ serial_init,
+ console_init_f,
+ display_options,
+ checkcpu,
+#if defined(CONFIG_DISPLAY_CPUINFO)
+ display_freq,
+#endif
+ checkboard,
+ misc_init_f,
+ init_sysram,
+#ifdef CONFIG_SYS_ACDISP
+ acdisp
+#endif
+ NULL,
+};
+
+
+/*
+ * Initialize board.
+ */
+
+void xtensa_board_init(ulong gd_addr)
+{
+ /*
+ * All RAM sections have been unpacked to RAM (relocated)
+ * and the board has been initialized.
+ */
+ init_fnc_t **init_fnc_ptr;
+ bd_t *bd;
+
+ /* Don't cross 1GB range */
+ ulong memsize = CONFIG_SYS_SDRAM_SIZE;
+ ulong maxsize = 0x40000000 - (CONFIG_SYS_SDRAM_SIZE & 0x3fffffff);
+ if (memsize > maxsize)
+ memsize = maxsize;
+
+ gd = (gd_t *)gd_addr;
+ memset(gd, 0, sizeof(gd_t));
+ gd->flags = GD_FLG_RELOC; /* relocation is already done */
+
+ bd = (bd_t *)((ulong)gd + ((sizeof(gd_t) + 15) & -16));
+ memset(bd, 0, sizeof(bd_t));
+ gd->bd = bd;
+
+ /* Reserve memory for passing linux boot parameters to kernel */
+ bd->bi_boot_params = (ulong)bd + ((sizeof(bd_t) + 15) & -16);
+
+ /*
+ * Perform initialization sequence, call functions enumerated above.
+ */
+ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+ if ((*init_fnc_ptr)() != 0)
+ hang();
+ }
+
+ /* the parameters gd_t *id and ulong dest_addr are unused for Xtensa */
+ board_init_r(NULL, 0);
+
+ /* NOT REACHED */
+ hang();
+}
diff --git a/arch/xtensa/lib/bootm.c b/arch/xtensa/lib/bootm.c
new file mode 100644
index 0000000..8bd4a4e
--- /dev/null
+++ b/arch/xtensa/lib/bootm.c
@@ -0,0 +1,202 @@
+/*
+ * (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;
+ image_header_t *hdr = images->legacy_hdr_os;
+ ulong initrd_start, initrd_end;
+ char *commandline = getenv("bootargs");
+ void (*kernel)(struct bp_tag *);
+
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+ return 0;
+
+ kernel = (void *)ntohl(hdr->ih_ep);
+
+ if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+ printf("Magic Number:0x%x != IH_MAGIC:0x%x\n",
+ ntohl(hdr->ih_magic), IH_MAGIC);
+ }
+
+ 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)kernel);
+
+ flush_dcache_range((unsigned long)params_start, (unsigned long)params);
+
+ /*
+ * _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" (kernel)
+ : "a2");
+
+ /* Does not return */
+
+ return 1;
+}
+
diff --git a/arch/xtensa/lib/misc.S b/arch/xtensa/lib/misc.S
new file mode 100644
index 0000000..6fd5bb4
--- /dev/null
+++ b/arch/xtensa/lib/misc.S
@@ -0,0 +1,178 @@
+/*
+ * Miscellaneous assembly functions.
+ *
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ *
+ * Chris Zankel <chris at zankel.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+
+#include <linux/linkage.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheasm.h>
+
+/*
+ * void __invalidate_icache_page(ulong start)
+ */
+
+ENTRY(__invalidate_icache_page)
+
+ entry sp, 16
+
+ ___invalidate_icache_page a2 a3
+ isync
+
+ retw
+
+ENDPROC(__invalidate_icache_page)
+
+/*
+ * void __invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__invalidate_dcache_page)
+
+ entry sp, 16
+
+ ___invalidate_dcache_page a2 a3
+ dsync
+
+ retw
+
+ENDPROC(__invalidate_dcache_page)
+
+/*
+ * void __flush_invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_invalidate_dcache_page)
+
+ entry sp, 16
+
+ ___flush_invalidate_dcache_page a2 a3
+
+ dsync
+ retw
+
+ENDPROC(__flush_invalidate_dcache_page)
+
+/*
+ * void __flush_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_dcache_page)
+
+ entry sp, 16
+
+ ___flush_dcache_page a2 a3
+
+ dsync
+ retw
+
+ENDPROC(__flush_dcache_page)
+
+/*
+ * void __invalidate_icache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_icache_range)
+
+ entry sp, 16
+
+ ___invalidate_icache_range a2 a3 a4
+ isync
+
+ retw
+
+ENDPROC(__invalidate_icache_range)
+
+/*
+ * void __flush_invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_invalidate_dcache_range)
+
+ entry sp, 16
+
+ ___flush_invalidate_dcache_range a2 a3 a4
+ dsync
+
+ retw
+
+ENDPROC(__flush_invalidate_dcache_range)
+
+/*
+ * void _flush_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_dcache_range)
+
+ entry sp, 16
+
+ ___flush_dcache_range a2 a3 a4
+ dsync
+
+ retw
+
+ENDPROC(__flush_dcache_range)
+
+/*
+ * void _invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_dcache_range)
+
+ entry sp, 16
+
+ ___invalidate_dcache_range a2 a3 a4
+
+ retw
+
+ENDPROC(__invalidate_dcache_range)
+
+/*
+ * void _invalidate_icache_all(void)
+ */
+
+ENTRY(__invalidate_icache_all)
+
+ entry sp, 16
+
+ ___invalidate_icache_all a2 a3
+ isync
+
+ retw
+
+ENDPROC(__invalidate_icache_all)
+
+/*
+ * void _flush_invalidate_dcache_all(void)
+ */
+
+ENTRY(__flush_invalidate_dcache_all)
+
+ entry sp, 16
+
+ ___flush_invalidate_dcache_all a2 a3
+ dsync
+
+ retw
+
+ENDPROC(__flush_invalidate_dcache_all)
+
+/*
+ * void _invalidate_dcache_all(void)
+ */
+
+ENTRY(__invalidate_dcache_all)
+
+ entry sp, 16
+
+ ___invalidate_dcache_all a2 a3
+ dsync
+
+ retw
+
+ENDPROC(__invalidate_dcache_all)
diff --git a/arch/xtensa/lib/time.c b/arch/xtensa/lib/time.c
new file mode 100644
index 0000000..831335b
--- /dev/null
+++ b/arch/xtensa/lib/time.c
@@ -0,0 +1,111 @@
+/*
+ * (C) Copyright 2008 - 2013 Tensilica Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/global_data.h>
+#include <linux/stringify.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if XCHAL_HAVE_CCOUNT
+static ulong get_ccount(void)
+{
+ ulong ccount;
+ asm volatile ("rsr %0,"__stringify(CCOUNT) : "=a" (ccount));
+ return ccount;
+}
+#else
+static ulong fake_ccount;
+#define get_ccount() fake_ccount
+#endif
+
+static void delay_cycles(unsigned cycles)
+{
+#if XCHAL_HAVE_CCOUNT
+ unsigned expiry = get_ccount() + cycles;
+ while ((signed)(expiry - get_ccount()) > 0)
+ ;
+#else
+#warning "Without Xtensa timer option, timing will not be accurate."
+
+ /*
+ * Approximate the cycle count by a loop iteration count.
+ * This is highly dependent on config and optimization.
+ */
+
+ volatile unsigned i;
+ for (i = cycles >> 4U; i > 0; --i)
+ ;
+ fake_ccount += cycles;
+#endif
+}
+
+/*
+ * Delay (busy-wait) for a number of microseconds.
+ */
+
+void __udelay(unsigned long usec)
+{
+ ulong lo, hi, i;
+ ulong mhz = CONFIG_SYS_CLK_FREQ / 1000000;
+
+ /* Scale to support full 32-bit usec range */
+
+ lo = usec & ((1<<22)-1);
+ hi = usec >> 22UL;
+ for (i = 0; i < hi; ++i)
+ delay_cycles(mhz << 22);
+ delay_cycles(mhz * lo);
+}
+
+
+/*
+ * Return the elapsed time (ticks) since 'base'.
+ */
+
+ulong get_timer(ulong base)
+{
+ /* Don't tie up a timer; use cycle counter if available (or fake it). */
+
+#if XCHAL_HAVE_CCOUNT
+ register ulong ccount;
+ __asm__ volatile ("rsr %0, CCOUNT" : "=a"(ccount));
+ return ccount / (CONFIG_SYS_CLK_FREQ / CONFIG_SYS_HZ) - base;
+#else
+ /*
+ * Add at least the overhead of this call (in cycles).
+ * Avoids hanging in case caller doesn't use udelay().
+ * Note that functions that don't call udelay() (such as
+ * the "sleep" command) will not get a significant delay
+ * because there is no time reference.
+ */
+
+ fake_ccount += 20;
+ return fake_ccount / (CONFIG_SYS_CLK_FREQ / CONFIG_SYS_HZ) - base;
+#endif
+}
+
+
+/*
+ * This function is derived from ARM/PowerPC code (read timebase as long long).
+ * On Xtensa it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+ return get_timer(0);
+}
+
+/*
+ * This function is derived from ARM/PowerPC code (timebase clock frequency).
+ * On Xtensa it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+ ulong tbclk;
+
+ tbclk = CONFIG_SYS_HZ;
+ return tbclk;
+}
--
1.8.1.4
More information about the U-Boot
mailing list