diff options
43 files changed, 3107 insertions, 0 deletions
| diff --git a/arch/Kconfig b/arch/Kconfig index 92d4b97701b..d718a681712 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -88,6 +88,11 @@ config X86  	select DM_SPI  	select DM_SPI_FLASH +config XTENSA +	bool "Xtensa architecture" +	select CREATE_ARCH_SYMLINK +	select SUPPORT_OF_CONTROL +  endchoice  config SYS_ARCH @@ -161,3 +166,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 00000000000..bb6a678f87b --- /dev/null +++ b/arch/xtensa/Kconfig @@ -0,0 +1,18 @@ +menu "Xtensa architecture" +	depends on XTENSA + +config SYS_ARCH +	string +	default "xtensa" + +config SYS_CPU +	string "Xtensa Core Variant" + +choice +	prompt "Target select" + + +endchoice + + +endmenu diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile new file mode 100644 index 00000000000..130d76f6be5 --- /dev/null +++ b/arch/xtensa/Makefile @@ -0,0 +1,8 @@ +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +head-y := arch/xtensa/cpu/start.o + +libs-y += arch/xtensa/cpu/ +libs-y += arch/xtensa/lib/ diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk new file mode 100644 index 00000000000..7dd8d8a741f --- /dev/null +++ b/arch/xtensa/config.mk @@ -0,0 +1,12 @@ +# +# (C) Copyright 2007 - 2013 Tensilica, Inc. +# (C) Copyright 2014 - 2016 Cadence Design Systems Inc. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +CROSS_COMPILE ?= xtensa-linux- +PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \ +		     -ffunction-sections -fdata-sections + +LDFLAGS_FINAL += --gc-sections diff --git a/arch/xtensa/cpu/Makefile b/arch/xtensa/cpu/Makefile new file mode 100644 index 00000000000..e83f6207d8c --- /dev/null +++ b/arch/xtensa/cpu/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2007 - 2013 Tensilica, Inc. +# (C) Copyright 2014 - 2016 Cadence Design Systems Inc. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y = cpu.o exceptions.o +extra-y = start.o diff --git a/arch/xtensa/cpu/cpu.c b/arch/xtensa/cpu/cpu.c new file mode 100644 index 00000000000..6787a6182c8 --- /dev/null +++ b/arch/xtensa/cpu/cpu.c @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2008 - 2013 Tensilica Inc. + * (C) Copyright 2014 - 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <linux/stringify.h> +#include <asm/global_data.h> +#include <asm/cache.h> +#include <asm/string.h> +#include <asm/misc.h> + +DECLARE_GLOBAL_DATA_PTR; + +gd_t *gd __attribute__((section(".data"))); + +#if defined(CONFIG_DISPLAY_CPUINFO) +/* + * Print information about the CPU. + */ + +int print_cpuinfo(void) +{ +	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; +} +#endif + +int arch_cpu_init(void) +{ +	gd->ram_size = CONFIG_SYS_SDRAM_SIZE; +	return 0; +} diff --git a/arch/xtensa/cpu/exceptions.c b/arch/xtensa/cpu/exceptions.c new file mode 100644 index 00000000000..16639a08e8b --- /dev/null +++ b/arch/xtensa/cpu/exceptions.c @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2008 - 2013 Tensilica Inc. + * (C) Copyright 2014 - 2016 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/string.h> +#include <asm/regs.h> + +typedef void (*handler_t)(struct pt_regs *); + +void unhandled_exception(struct pt_regs *regs) +{ +	printf("Unhandled Exception: EXCCAUSE = %ld, EXCVADDR = %lx, pc = %lx\n", +	       regs->exccause, regs->excvaddr, regs->pc); +	panic("*** PANIC\n"); +} + +handler_t exc_table[EXCCAUSE_LAST] = { +	[0 ... EXCCAUSE_LAST-1]			= unhandled_exception, +}; + +int interrupt_init(void) +{ +	return 0; +} + +void enable_interrupts(void) +{ +} + +int disable_interrupts(void) +{ +	return 0; +} diff --git a/arch/xtensa/cpu/start.S b/arch/xtensa/cpu/start.S new file mode 100644 index 00000000000..8e4bc99e429 --- /dev/null +++ b/arch/xtensa/cpu/start.S @@ -0,0 +1,677 @@ +/* + * (C) Copyright 2008 - 2013 Tensilica Inc. + * (C) Copyright 2014 - 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> +#include <asm/asmmacro.h> +#include <asm/cacheasm.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) + +/* + * Cache attributes are different for full MMU and region protection. + */ + +#if XCHAL_HAVE_PTP_MMU +#define CA_WRITEBACK	(0x7) +#else +#define CA_WRITEBACK	(0x4) +#endif + +/* + * 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_PTP_MMU +	wsr	a0, PTEVADDR +#endif + +	/* Disable dbreak debug exceptions */ + +#if XCHAL_HAVE_DEBUG && XCHAL_NUM_DBREAK > 0 +	.set	_index, 0 +	.rept	XCHAL_NUM_DBREAK +	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 + +#if XCHAL_HAVE_LOOPS +	/* Disable loops */ + +	wsr	a0, LCOUNT +#endif + +	/* 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 */ + +	___unlock_dcache_all a2, a3 +	___invalidate_dcache_all a2, a3 +	___unlock_icache_all a2, a3 +	___invalidate_icache_all a2, a3 + +	isync + +	/* 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 + +	/* If there's memory protection option with 512MB TLB regions and +	 * cache attributes in TLB entries and caching is not inhibited, +	 * enable data/instruction cache for relocated image. +	 */ +#if XCHAL_HAVE_SPANNING_WAY && \ +	(!defined(CONFIG_SYS_DCACHE_OFF) || \ +	 !defined(CONFIG_SYS_ICACHE_OFF)) +	srli	a7, a4, 29 +	slli	a7, a7, 29 +	addi	a7, a7, XCHAL_SPANNING_WAY +#ifndef CONFIG_SYS_DCACHE_OFF +	rdtlb1	a8, a7 +	srli	a8, a8, 4 +	slli	a8, a8, 4 +	addi	a8, a8, CA_WRITEBACK +	wdtlb	a8, a7 +#endif +#ifndef CONFIG_SYS_ICACHE_OFF +	ritlb1	a8, a7 +	srli	a8, a8, 4 +	slli	a8, a8, 4 +	addi	a8, a8, CA_WRITEBACK +	witlb	a8, a7 +#endif +	isync +#endif + +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 + +	/* Writeback */ + +	___flush_dcache_all a2, a3 + +#ifdef __XTENSA_WINDOWED_ABI__ +	/* +	 * In windowed ABI caller and call target need to be within the same +	 * gigabyte. Put the rest of the code into the text segment and jump +	 * there. +	 */ + +	movi	a4, .Lboard_init_code +	jx	a4 + +	.text +	.align	4 +.Lboard_init_code: +#endif + +	movi	a0, 0 +	movi	sp, (CONFIG_SYS_TEXT_ADDR - 16) & 0xfffffff0 + +#ifdef CONFIG_DEBUG_UART +	movi	a4, debug_uart_init +#ifdef __XTENSA_CALL0_ABI__ +	callx0	a4 +#else +	callx4	a4 +#endif +#endif + +	movi	a4, board_init_f_alloc_reserve + +#ifdef __XTENSA_CALL0_ABI__ +	mov	a2, sp +	callx0	a4 +	mov	sp, a2 +#else +	mov	a6, sp +	callx4	a4 +	movsp	sp, a6 +#endif + +	movi	a4, board_init_f_init_reserve + +#ifdef __XTENSA_CALL0_ABI__ +	callx0	a4 +#else +	callx4	a4 +#endif + +        /* +	 * Call board initialization routine (never returns). +	 */ + +	movi	a4, board_init_f + +#ifdef __XTENSA_CALL0_ABI__ +	movi	a2, 0 +	callx0	a4 +#else +	movi	a6, 0 +	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. + * + * a2 = addr_sp + * a3 = gd + * a4 = destination address + */ +	.text +	.globl relocate_code +	.align 4 +relocate_code: +	abi_entry + +#ifdef __XTENSA_CALL0_ABI__ +	mov	a1, a2 +	mov	a2, a3 +	mov	a3, a4 +	movi	a0, board_init_r +	callx0	a0 +#else +	/* We can't movsp here, because the chain of stack frames may cross +	 * the now reserved memory. We need to toss all window frames except +	 * the current, create new pristine stack frame and start from scratch. +	 */ +	rsr	a0, windowbase +	ssl	a0 +	movi	a0, 1 +	sll	a0, a0 +	wsr	a0, windowstart +	rsync + +	movi	a0, 0 + +	/* Reserve 16-byte save area */ +	addi	sp, a2, -16 +	mov	a6, a3 +	mov	a7, a4 +	movi	a4, board_init_r +	callx4	a4 +#endif +	ill + +#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 + +#if XCHAL_HAVE_WINDOWED +	/* 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 +#endif +	/* 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 */ + +#if XCHAL_HAVE_WINDOWED +	rsr	a2, WINDOWSTART +	s32i	a2, a1, PT_WINDOWSTART +#endif + +	rsr	a2, SAR +	rsr	a3, EPC1 +	rsr	a4, EXCVADDR +	s32i	a2, a1, PT_SAR +	s32i	a3, a1, PT_PC +	s32i	a4, a1, PT_EXCVADDR + +#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 + +#if XCHAL_HAVE_WINDOWED +	/* 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 +#endif + +	/* 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 + +#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 b/arch/xtensa/cpu/u-boot.lds new file mode 100644 index 00000000000..853ae5a9489 --- /dev/null +++ b/arch/xtensa/cpu/u-boot.lds @@ -0,0 +1,116 @@ +/* + * (C) Copyright 2008 - 2013 Tensilica, Inc. + * (C) Copyright 2014 - 2016 Cadence Design Systems 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 function. 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(.); +#if XCHAL_HAVE_WINDOWED +    RELOCATE2(WindowVectors,text); +#endif +    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(.); +  } + +#if XCHAL_HAVE_WINDOWED +  SECTION_VECTOR(WindowVectors,text,XCHAL_WINDOW_VECTORS_VADDR, +		 FOLLOWING(.reloc_table)) +  SECTION_VECTOR(KernelExceptionVector,literal,XCHAL_KERNEL_VECTOR_VADDR-8, +		 FOLLOWING(.WindowVectors.text)) +#else +  SECTION_VECTOR(KernelExceptionVector,literal,XCHAL_KERNEL_VECTOR_VADDR-8, +		 FOLLOWING(.reloc_table)) +#endif +  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)) + +  __monitor_start = CONFIG_SYS_TEXT_ADDR; + +  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),) + +  __monitor_end = .; + +  /* +   * 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. +   * +   */ + +   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/dts/Makefile b/arch/xtensa/dts/Makefile new file mode 100644 index 00000000000..eacf6f313bd --- /dev/null +++ b/arch/xtensa/dts/Makefile @@ -0,0 +1,13 @@ +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +targets += $(dtb-y) + +DTC_FLAGS += + +PHONY += dtbs +dtbs: $(addprefix $(obj)/, $(dtb-y)) +	@: + +clean-files := *.dtb diff --git a/arch/xtensa/dts/include/dt-bindings b/arch/xtensa/dts/include/dt-bindings new file mode 120000 index 00000000000..0cecb3d0805 --- /dev/null +++ b/arch/xtensa/dts/include/dt-bindings @@ -0,0 +1 @@ +../../../../include/dt-bindings
\ No newline at end of file diff --git a/arch/xtensa/include/asm/addrspace.h b/arch/xtensa/include/asm/addrspace.h new file mode 100644 index 00000000000..1d62259fd5b --- /dev/null +++ b/arch/xtensa/include/asm/addrspace.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2008-2013 Tensilica Inc. + * Copyright (C) 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef _XTENSA_ADDRSPACE_H +#define _XTENSA_ADDRSPACE_H + +#include <asm/arch/core.h> + +/* + * MMU Memory Map + * + * noMMU and v3 MMU have identity mapped address space on reset. + * V2 MMU: + *   IO (uncached)	f0000000..ffffffff	-> f000000 + *   IO (cached)	e0000000..efffffff	-> f000000 + *   MEM (uncached)	d8000000..dfffffff	-> 0000000 + *   MEM (cached)	d0000000..d7ffffff	-> 0000000 + * + * The actual location of memory and IO is the board property. + */ + +#define IOADDR(x)		(CONFIG_SYS_IO_BASE + (x)) +#define MEMADDR(x)		(CONFIG_SYS_MEMORY_BASE + (x)) +#define PHYSADDR(x)		((x) - XCHAL_VECBASE_RESET_VADDR + \ +				 XCHAL_VECBASE_RESET_PADDR) + +#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 00000000000..b7adc7e1980 --- /dev/null +++ b/arch/xtensa/include/asm/asmmacro.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2005 - 2013 Tensilica Inc. + * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef _XTENSA_ASMMACRO_H +#define _XTENSA_ASMMACRO_H + +#include <asm/arch/core.h> + +/* + * Function entry and return macros for supported ABIs. + */ + +#if defined(__XTENSA_WINDOWED_ABI__) +#define abi_entry	entry	sp, 16 +#define abi_ret		retw +#elif defined(__XTENSA_CALL0_ABI__) +#define abi_entry +#define abi_ret		ret +#else +#error Unsupported Xtensa ABI +#endif + +/* + * 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, as, incr + *	   ar	start address (modified) + *	   as	scratch register used by __loops/__loopi macros or + *		end address used by __loopt 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/atomic.h b/arch/xtensa/include/asm/atomic.h new file mode 100644 index 00000000000..a75baa09e0a --- /dev/null +++ b/arch/xtensa/include/asm/atomic.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef _XTENSA_ATOMIC_H +#define _XTENSA_ATOMIC_H + +#include <asm/system.h> + +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i)	{ (i) } + +#define atomic_read(v)		((v)->counter) +#define atomic_set(v, i)	((v)->counter = (i)) + +static inline void atomic_add(int i, atomic_t *v) +{ +	unsigned long flags; + +	local_irq_save(flags); +	v->counter += i; +	local_irq_restore(flags); +} + +static inline void atomic_sub(int i, atomic_t *v) +{ +	unsigned long flags; + +	local_irq_save(flags); +	v->counter -= i; +	local_irq_restore(flags); +} + +static inline void atomic_inc(atomic_t *v) +{ +	unsigned long flags; + +	local_irq_save(flags); +	++v->counter; +	local_irq_restore(flags); +} + +static inline void atomic_dec(atomic_t *v) +{ +	unsigned long flags; + +	local_irq_save(flags); +	--v->counter; +	local_irq_restore(flags); +} + +#endif diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h new file mode 100644 index 00000000000..550d12f4986 --- /dev/null +++ b/arch/xtensa/include/asm/bitops.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2001 - 2012 Tensilica Inc. + * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef _XTENSA_BITOPS_H +#define _XTENSA_BITOPS_H + +#include <asm/system.h> +#include <asm-generic/bitops/fls.h> +#include <asm-generic/bitops/__fls.h> +#include <asm-generic/bitops/fls64.h> +#include <asm-generic/bitops/__ffs.h> + +static inline int test_bit(int nr, const void *addr) +{ +	return ((unsigned char *)addr)[nr >> 3] & (1u << (nr & 7)); +} + +static inline int test_and_set_bit(int nr, volatile void *addr) +{ +	unsigned long flags; +	unsigned char tmp; +	unsigned char mask = 1u << (nr & 7); + +	local_irq_save(flags); +	tmp = ((unsigned char *)addr)[nr >> 3]; +	((unsigned char *)addr)[nr >> 3] |= mask; +	local_irq_restore(flags); + +	return tmp & mask; +} + +#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 00000000000..a2a9013ebf1 --- /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 00000000000..278653ce481 --- /dev/null +++ b/arch/xtensa/include/asm/byteorder.h @@ -0,0 +1,83 @@ +/* + * 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 00000000000..08c534ca014 --- /dev/null +++ b/arch/xtensa/include/asm/cache.h @@ -0,0 +1,25 @@ +/* + * 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_dcache_all(void); +void __flush_invalidate_dcache_range(unsigned long addr, unsigned long size); +void __invalidate_dcache_all(void); +void __invalidate_dcache_range(unsigned long addr, unsigned long size); + +void __invalidate_icache_all(void); +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 00000000000..342a8177e41 --- /dev/null +++ b/arch/xtensa/include/asm/cacheasm.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2006 Tensilica Inc. + * Copyright (C) 2014 - 2016 Cadence Design Systems 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 + + +	.macro	___unlock_dcache_all ar at + +#if XCHAL_DCACHE_LINE_LOCKABLE && XCHAL_DCACHE_SIZE +	__loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___unlock_icache_all ar at + +#if XCHAL_ICACHE_LINE_LOCKABLE && XCHAL_ICACHE_SIZE +	__loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE XCHAL_ICACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___flush_invalidate_dcache_all ar at + +#if XCHAL_DCACHE_SIZE +	__loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___flush_dcache_all ar at + +#if XCHAL_DCACHE_SIZE +	__loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___invalidate_dcache_all ar at + +#if XCHAL_DCACHE_SIZE +	__loop_cache_all \ar \at dii __stringify(DCACHE_WAY_SIZE) \ +			 XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___invalidate_icache_all ar at + +#if XCHAL_ICACHE_SIZE +	__loop_cache_all \ar \at iii __stringify(ICACHE_WAY_SIZE) \ +			 XCHAL_ICACHE_LINEWIDTH +#endif + +	.endm + + + +	.macro	___flush_invalidate_dcache_range ar as at + +#if XCHAL_DCACHE_SIZE +	__loop_cache_range \ar \as \at dhwbi XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___flush_dcache_range ar as at + +#if XCHAL_DCACHE_SIZE +	__loop_cache_range \ar \as \at dhwb XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___invalidate_dcache_range ar as at + +#if XCHAL_DCACHE_SIZE +	__loop_cache_range \ar \as \at dhi XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___invalidate_icache_range ar as at + +#if XCHAL_ICACHE_SIZE +	__loop_cache_range \ar \as \at ihi XCHAL_ICACHE_LINEWIDTH +#endif + +	.endm + + + +	.macro	___flush_invalidate_dcache_page ar as + +#if XCHAL_DCACHE_SIZE +	__loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro ___flush_dcache_page ar as + +#if XCHAL_DCACHE_SIZE +	__loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___invalidate_dcache_page ar as + +#if XCHAL_DCACHE_SIZE +	__loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH +#endif + +	.endm + + +	.macro	___invalidate_icache_page ar as + +#if XCHAL_ICACHE_SIZE +	__loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH +#endif + +	.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 00000000000..db1ea87c30b --- /dev/null +++ b/arch/xtensa/include/asm/config.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2009 Tensilica Inc. + * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef _ASM_CONFIG_H_ +#define _ASM_CONFIG_H_ + +#include <asm/arch/core.h> + +#define CONFIG_LMB + +/* + * Make boot parameters available in the MMUv2 virtual memory layout by + * restricting used physical memory to the first 128MB. + */ +#if XCHAL_HAVE_PTP_MMU +#define CONFIG_VERY_BIG_RAM +#define CONFIG_MAX_MEM_MAPPED (128 << 20) +#endif + +#endif diff --git a/arch/xtensa/include/asm/errno.h b/arch/xtensa/include/asm/errno.h new file mode 100644 index 00000000000..4c82b503d92 --- /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 00000000000..45693457ad3 --- /dev/null +++ b/arch/xtensa/include/asm/global_data.h @@ -0,0 +1,20 @@ +/* + * (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> + +#define DECLARE_GLOBAL_DATA_PTR     extern gd_t *gd + +#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 00000000000..e34d6e1d7fa --- /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); +} + +/* + * 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) + +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) +{ +} + +static inline phys_addr_t virt_to_phys(void *vaddr) +{ +	return (phys_addr_t)((unsigned long)vaddr); +} + +/* + * 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 00000000000..62a1c052685 --- /dev/null +++ b/arch/xtensa/include/asm/ldscript.h @@ -0,0 +1,222 @@ +/* + * (C) Copyright 2007 Tensilica, Inc. + * (C) Copyright 2014 - 2016 Cadence Design Systems 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.*)						\ +		*(.dtb.init.rodata)					\ +		*(.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 00000000000..3f46161a9fb --- /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 00000000000..5a2708fbeff --- /dev/null +++ b/arch/xtensa/include/asm/misc.h @@ -0,0 +1,20 @@ +/* + * (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 + +/* 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 00000000000..821115c0066 --- /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 00000000000..8822f80f8dc --- /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 00000000000..d187dbf4c98 --- /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 00000000000..0a82a221dda --- /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/relocate.h b/arch/xtensa/include/asm/relocate.h new file mode 100644 index 00000000000..9c4ce239885 --- /dev/null +++ b/arch/xtensa/include/asm/relocate.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef _ASM_XTENSA_RELOCATE_H +#define _ASM_XTENSA_RELOCATE_H + +#include <common.h> + +int clear_bss(void); + +#endif	/* _ASM_XTENSA_RELOCATE_H */ diff --git a/arch/xtensa/include/asm/sections.h b/arch/xtensa/include/asm/sections.h new file mode 100644 index 00000000000..2309b146388 --- /dev/null +++ b/arch/xtensa/include/asm/sections.h @@ -0,0 +1,12 @@ +/* + * 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> + +#endif diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h new file mode 100644 index 00000000000..65a36016741 --- /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/system.h b/arch/xtensa/include/asm/system.h new file mode 100644 index 00000000000..5b710089c11 --- /dev/null +++ b/arch/xtensa/include/asm/system.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef _XTENSA_SYSTEM_H +#define _XTENSA_SYSTEM_H + +#include <asm/arch/core.h> + +#if XCHAL_HAVE_INTERRUPTS +#define local_irq_save(flags) \ +	__asm__ __volatile__ ("rsil %0, %1" \ +			      : "=a"(flags) \ +			      : "I"(XCHAL_EXCM_LEVEL) \ +			      : "memory") +#define local_irq_restore(flags) \ +	__asm__ __volatile__ ("wsr %0, ps\n\t" \ +			      "rsync" \ +			      :: "a"(flags) : "memory") +#else +#define local_irq_save(flags) ((void)(flags)) +#define local_irq_restore(flags) ((void)(flags)) +#endif + +#endif diff --git a/arch/xtensa/include/asm/types.h b/arch/xtensa/include/asm/types.h new file mode 100644 index 00000000000..f7eda9dc590 --- /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 00000000000..cfdc0367b33 --- /dev/null +++ b/arch/xtensa/include/asm/u-boot.h @@ -0,0 +1,41 @@ +/* + * (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 + +#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 00000000000..536f3642e39 --- /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/lib/Makefile b/arch/xtensa/lib/Makefile new file mode 100644 index 00000000000..7c7d8d59bca --- /dev/null +++ b/arch/xtensa/lib/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2007 - 2013 Tensilica Inc. +# (C) Copyright 2014 - 2016 Cadence Design Systems Inc. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-$(CONFIG_CMD_BOOTM) += bootm.o + +obj-y 	+= cache.o misc.o relocate.o time.o diff --git a/arch/xtensa/lib/bootm.c b/arch/xtensa/lib/bootm.c new file mode 100644 index 00000000000..1604bb95368 --- /dev/null +++ b/arch/xtensa/lib/bootm.c @@ -0,0 +1,197 @@ +/* + * (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; +	ulong initrd_start, initrd_end; +	char *commandline = getenv("bootargs"); + +	if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO))) +		return 0; + +	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)images->ep); + +	flush_dcache_range((unsigned long)params_start, (unsigned long)params); + +	if (flag & BOOTM_STATE_OS_FAKE_GO) +		return 0; + +	/* +	 * _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" (images->ep) +		      : "a2"); + +	/* Does not return */ + +	return 1; +} + diff --git a/arch/xtensa/lib/cache.c b/arch/xtensa/lib/cache.c new file mode 100644 index 00000000000..26808390926 --- /dev/null +++ b/arch/xtensa/lib/cache.c @@ -0,0 +1,60 @@ +/* + * (C) Copyright 2008 - 2013 Tensilica Inc. + * (C) Copyright 2014 - 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/cache.h> + +/* + * We currently run always with caches enabled when running from memory. + * 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_all(void) +{ +	__flush_dcache_all(); +	__invalidate_icache_all(); +} + +void flush_dcache_range(ulong start_addr, ulong end_addr) +{ +	__flush_invalidate_dcache_range(start_addr, end_addr - start_addr); +} + +void invalidate_dcache_range(ulong start, ulong stop) +{ +	__invalidate_dcache_range(start, stop - start); +} + +void invalidate_dcache_all(void) +{ +	__invalidate_dcache_all(); +} + +void invalidate_icache_all(void) +{ +	__invalidate_icache_all(); +} diff --git a/arch/xtensa/lib/misc.S b/arch/xtensa/lib/misc.S new file mode 100644 index 00000000000..449a6db8fd6 --- /dev/null +++ b/arch/xtensa/lib/misc.S @@ -0,0 +1,179 @@ +/* + * Miscellaneous assembly functions. + * + * Copyright (C) 2001 - 2007 Tensilica Inc. + * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. + * + * Chris Zankel	<chris@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) + +	abi_entry + +	___invalidate_icache_page a2 a3 +	isync + +	abi_ret + +ENDPROC(__invalidate_icache_page) + +/* + * void __invalidate_dcache_page(ulong start) + */ + +ENTRY(__invalidate_dcache_page) + +	abi_entry + +	___invalidate_dcache_page a2 a3 +	dsync + +	abi_ret + +ENDPROC(__invalidate_dcache_page) + +/* + * void __flush_invalidate_dcache_page(ulong start) + */ + +ENTRY(__flush_invalidate_dcache_page) + +	abi_entry + +	___flush_invalidate_dcache_page a2 a3 + +	dsync +	abi_ret + +ENDPROC(__flush_invalidate_dcache_page) + +/* + * void __flush_dcache_page(ulong start) + */ + +ENTRY(__flush_dcache_page) + +	abi_entry + +	___flush_dcache_page a2 a3 + +	dsync +	abi_ret + +ENDPROC(__flush_dcache_page) + +/* + * void __invalidate_icache_range(ulong start, ulong size) + */ + +ENTRY(__invalidate_icache_range) + +	abi_entry + +	___invalidate_icache_range a2 a3 a4 +	isync + +	abi_ret + +ENDPROC(__invalidate_icache_range) + +/* + * void __flush_invalidate_dcache_range(ulong start, ulong size) + */ + +ENTRY(__flush_invalidate_dcache_range) + +	abi_entry + +	___flush_invalidate_dcache_range a2 a3 a4 +	dsync + +	abi_ret + +ENDPROC(__flush_invalidate_dcache_range) + +/* + * void _flush_dcache_range(ulong start, ulong size) + */ + +ENTRY(__flush_dcache_range) + +	abi_entry + +	___flush_dcache_range a2 a3 a4 +	dsync + +	abi_ret + +ENDPROC(__flush_dcache_range) + +/* + * void _invalidate_dcache_range(ulong start, ulong size) + */ + +ENTRY(__invalidate_dcache_range) + +	abi_entry + +	___invalidate_dcache_range a2 a3 a4 + +	abi_ret + +ENDPROC(__invalidate_dcache_range) + +/* + * void _invalidate_icache_all(void) + */ + +ENTRY(__invalidate_icache_all) + +	abi_entry + +	___invalidate_icache_all a2 a3 +	isync + +	abi_ret + +ENDPROC(__invalidate_icache_all) + +/* + * void _flush_invalidate_dcache_all(void) + */ + +ENTRY(__flush_invalidate_dcache_all) + +	abi_entry + +	___flush_invalidate_dcache_all a2 a3 +	dsync + +	abi_ret + +ENDPROC(__flush_invalidate_dcache_all) + +/* + * void _invalidate_dcache_all(void) + */ + +ENTRY(__invalidate_dcache_all) + +	abi_entry + +	___invalidate_dcache_all a2 a3 +	dsync + +	abi_ret + +ENDPROC(__invalidate_dcache_all) diff --git a/arch/xtensa/lib/relocate.c b/arch/xtensa/lib/relocate.c new file mode 100644 index 00000000000..3f747ec55a1 --- /dev/null +++ b/arch/xtensa/lib/relocate.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2016 Cadence Design Systems Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <asm/relocate.h> +#include <asm/sections.h> +#include <asm/string.h> + +int clear_bss(void) +{ +	size_t len = (size_t)&__bss_end - (size_t)&__bss_start; + +	memset((void *)&__bss_start, 0x00, len); +	return 0; +} + diff --git a/arch/xtensa/lib/time.c b/arch/xtensa/lib/time.c new file mode 100644 index 00000000000..1332072ffe3 --- /dev/null +++ b/arch/xtensa/lib/time.c @@ -0,0 +1,121 @@ +/* + * (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; +} + +#if XCHAL_HAVE_CCOUNT +unsigned long timer_get_us(void) +{ +	unsigned long ccount; + +	__asm__ volatile ("rsr %0, CCOUNT" : "=a"(ccount)); +	return ccount / (CONFIG_SYS_CLK_FREQ / 1000000); +} +#endif | 
