
Hi Simon,
On Tue, Jul 12, 2016 at 03:56:05PM -0600, Simon Glass wrote:
[...]
Reviewed-by: Simon Glass sjg@chromium.org
Some comments below.
diff --git a/arch/Kconfig b/arch/Kconfig index 566f044..a36ac2f 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -83,6 +83,13 @@ config X86 select DM_SPI select DM_SPI_FLASH
+config XTENSA
bool "Xtensa architecture"
select CREATE_ARCH_SYMLINK
select HAVE_GENERIC_BOARD
This doesn't exist anymore as the migration is complete.
select SUPPORT_OF_CONTROL
select SYS_GENERIC_BOARD
Same here.
Ok, will remove both.
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
Needs a help message. Should SYS_ASCDISP go in drivers/video?
Ok, will move it there and write help message.
[...]
diff --git a/arch/xtensa/cpu/cpu.c b/arch/xtensa/cpu/cpu.c new file mode 100644 index 0000000..fb7f810 --- /dev/null +++ b/arch/xtensa/cpu/cpu.c @@ -0,0 +1,92 @@ +/*
- (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;
+#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
+/*
- 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");
All of this can be replaced by a call to sysreset_walk_halt() I think, if you have a suitable UCLASS_RESET driver.
Ok, let me look at that.
return 0;
+}
+/*
- We currently run always with caches enabled when running for mmemory.
Do you mean 'from memory'?
Yes, will fix.
[...]
diff --git a/arch/xtensa/cpu/exceptions.c b/arch/xtensa/cpu/exceptions.c new file mode 100644 index 0000000..412ca5f --- /dev/null +++ b/arch/xtensa/cpu/exceptions.c @@ -0,0 +1,64 @@ +/*
- (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) +{
display_printf("!! EXCCAUSE = %2ld", regs->exccause);
printf("Unhandled Exception: EXCCAUSE = %ld (pc %lx)\n",
regs->exccause, regs->pc);
udelay(10000000); /* 10s to read display message */
Probably not needed? Up to you though.
I'd either drop it together with ASCII display, or leave them both.
[...]
diff --git a/arch/xtensa/cpu/start.S b/arch/xtensa/cpu/start.S new file mode 100644 index 0000000..ac32efb --- /dev/null +++ b/arch/xtensa/cpu/start.S
[...]
+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
/* Clear BSS */
movi a2, _bss_start
movi a3, _bss_end
Can you please use board_init_f_init_reserve(), etc.? You can copy how ARM does things perhaps. This should not be in assembly.
We use them, one screen below. What exactly should not be in assembly? BSS zeroing?
__loopt a2, a3, a4, 2
s32i a0, a2, 0
__endla a2, a3, 4
/* 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
As above. This is using the old approach.
I see the same sequence in the ARM's _main in arch/arm/lib/crt0.S:
mov r0, sp bl board_init_f_alloc_reserve mov sp, r0 /* set up gd here, outside any C code */ mov r9, r0 bl board_init_f_init_reserve
mov r0, #0 bl board_init_f
What is 'the new approach' and how does it differ from the old?
[...]
/* Does not return here. */
nit: drop periods before */
Ok.
[...]
+fast_alloca_exception: /* must be at _WindowUnderflow4 + 16
*/ ?
Oops, right.
[...]
diff --git a/arch/xtensa/cpu/u-boot.lds b/arch/xtensa/cpu/u-boot.lds new file mode 100644 index 0000000..853ae5a --- /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) }
Are you including the list regions, etc.? u_boot_list is what it is in most .lds files.
Yes, it's in the SECTION_u_boot_list a few lines above.
[...]
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),
/*
- Given
Ok.
[...]
diff --git a/arch/xtensa/lib/bootm.c b/arch/xtensa/lib/bootm.c new file mode 100644 index 0000000..8c89d2c --- /dev/null +++ b/arch/xtensa/lib/bootm.c
[...]
+/*
- 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;
Do you not use device tree with Linux? It looks like you need to support both that and tags?
We can use device tree with linux, but that's not mandatory. When it's used we pass DTB in one of the tags.