From f13606b77d32344d35f6430eb45cffd47302e244 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 13 Jan 2015 18:35:46 +0300 Subject: [PATCH] arc: introduce U-Boot port for ARCv2 ISA ARC HS and ARC EM are new cores based on ARCv2 ISA which is binary incompatible with ISAv1 (AKA ARCompact). Significant difference between ISAv2 and v1 is implementation of interrupt vector table. In v1 it is implemented in the same way as on many other architectures - as a special location where user may put whether code executed in place (if machine word of space is enough) or jump to a full-scale interrupt handler. In v2 interrupt table is just an array of adresses of real interrupt handlers. That requires a separate section for IVT that is not encoded as code by assembler. This change adds support for following cores: * ARC EM6 (simple 32-bit microcontroller without MMU) * ARC HS36 (advanced 32-bit microcontroller without MMU) * ARC HS38 (advanced 32-bit microcontroller with MMU) As a part of ARC HS38 new version of MMU (v4) was introduced. Also this change adds AXS131 board which is the same DW ARC SDP base board but with ARC HS38 CPU tile. Signed-off-by: Alexey Brodkin --- arch/arc/Kconfig | 59 +++++++- arch/arc/config.mk | 12 ++ arch/arc/cpu/arcv2/Makefile | 7 + arch/arc/cpu/arcv2/start.S | 254 +++++++++++++++++++++++++++++++++++ arch/arc/include/asm/cache.h | 6 +- configs/axs103_defconfig | 5 + 6 files changed, 340 insertions(+), 3 deletions(-) create mode 100644 arch/arc/cpu/arcv2/Makefile create mode 100644 arch/arc/cpu/arcv2/start.S create mode 100644 configs/axs103_defconfig diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index a8dc4e2336..24f5c02c76 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -8,30 +8,79 @@ config USE_PRIVATE_LIBGCC default y config SYS_CPU - default "arcv1" + default "arcv1" if ISA_ARCOMPACT + default "arcv2" if ISA_ARCV2 + +choice + prompt "ARC Instruction Set" + default ISA_ARCOMPACT + +config ISA_ARCOMPACT + bool "ARCompact ISA" + help + The original ARC ISA of ARC600/700 cores + +config ISA_ARCV2 + bool "ARC ISA v2" + help + ISA for the Next Generation ARC-HS cores + +endchoice choice prompt "CPU selection" - default CPU_ARC770D + default CPU_ARC770D if ISA_ARCOMPACT + default CPU_ARCHS38 if ISA_ARCV2 config CPU_ARC750D bool "ARC 750D" select ARC_MMU_V2 + depends on ISA_ARCOMPACT help Choose this option to build an U-Boot for ARC750D CPU. config CPU_ARC770D bool "ARC 770D" select ARC_MMU_V3 + depends on ISA_ARCOMPACT help Choose this option to build an U-Boot for ARC770D CPU. +config CPU_ARCEM6 + bool "ARC EM6" + select ARC_MMU_ABSENT + depends on ISA_ARCV2 + help + Next Generation ARC Core based on ISA-v2 ISA without MMU. + +config CPU_ARCHS36 + bool "ARC HS36" + select ARC_MMU_ABSENT + depends on ISA_ARCV2 + help + Next Generation ARC Core based on ISA-v2 ISA without MMU. + +config CPU_ARCHS38 + bool "ARC HS38" + select ARC_MMU_V4 + depends on ISA_ARCV2 + help + Next Generation ARC Core based on ISA-v2 ISA with MMU. + endchoice choice prompt "MMU Version" default ARC_MMU_V3 if CPU_ARC770D default ARC_MMU_V2 if CPU_ARC750D + default ARC_MMU_ABSENT if CPU_ARCEM6 + default ARC_MMU_ABSENT if CPU_ARCHS36 + default ARC_MMU_V4 if CPU_ARCHS38 + +config ARC_MMU_ABSENT + bool "No MMU" + help + No MMU config ARC_MMU_V2 bool "MMU v2" @@ -48,6 +97,12 @@ config ARC_MMU_V3 Variable Page size (1k-16k), var JTLB size 128 x (2 or 4) Shared Address Spaces (SASID) +config ARC_MMU_V4 + bool "MMU v4" + depends on CPU_ARCHS38 + help + Introduced as a part of ARC HS38 release. + endchoice config CPU_BIG_ENDIAN diff --git a/arch/arc/config.mk b/arch/arc/config.mk index f1e81b6895..4fcd4076c4 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -38,6 +38,18 @@ ifdef CONFIG_CPU_ARC770D PLATFORM_CPPFLAGS += -marc700 -mlock -mswape endif +ifdef CONFIG_CPU_ARCEM6 +PLATFORM_CPPFLAGS += -marcem +endif + +ifdef CONFIG_CPU_ARCHS34 +PLATFORM_CPPFLAGS += -marchs +endif + +ifdef CONFIG_CPU_ARCHS38 +PLATFORM_CPPFLAGS += -marchs +endif + PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 # Needed for relocation diff --git a/arch/arc/cpu/arcv2/Makefile b/arch/arc/cpu/arcv2/Makefile new file mode 100644 index 0000000000..cc69e5a17e --- /dev/null +++ b/arch/arc/cpu/arcv2/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += start.o diff --git a/arch/arc/cpu/arcv2/start.S b/arch/arc/cpu/arcv2/start.S new file mode 100644 index 0000000000..3ce689675f --- /dev/null +++ b/arch/arc/cpu/arcv2/start.S @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +/* + * Note on the LD/ST addressing modes with address register write-back + * + * LD.a same as LD.aw + * + * LD.a reg1, [reg2, x] => Pre Incr + * Eff Addr for load = [reg2 + x] + * + * LD.ab reg1, [reg2, x] => Post Incr + * Eff Addr for load = [reg2] + */ + +.macro PUSH reg + st.a \reg, [%sp, -4] +.endm + +.macro PUSHAX aux + lr %r9, [\aux] + PUSH %r9 +.endm + +.macro SAVE_R1_TO_R24 + PUSH %r1 + PUSH %r2 + PUSH %r3 + PUSH %r4 + PUSH %r5 + PUSH %r6 + PUSH %r7 + PUSH %r8 + PUSH %r9 + PUSH %r10 + PUSH %r11 + PUSH %r12 + PUSH %r13 + PUSH %r14 + PUSH %r15 + PUSH %r16 + PUSH %r17 + PUSH %r18 + PUSH %r19 + PUSH %r20 + PUSH %r21 + PUSH %r22 + PUSH %r23 + PUSH %r24 +.endm + +.macro SAVE_ALL_SYS + /* saving %r0 to reg->r0 in advance since weread %ecr into it */ + st %r0, [%sp, -8] + lr %r0, [%ecr] /* all stack addressing is manual so far */ + st %r0, [%sp] + st %sp, [%sp, -4] + /* now move %sp to reg->r0 position so we can do "push" automatically */ + sub %sp, %sp, 8 + + SAVE_R1_TO_R24 + PUSH %r25 + PUSH %gp + PUSH %fp + PUSH %blink + PUSHAX %eret + PUSHAX %erstatus + PUSH %lp_count + PUSHAX %lp_end + PUSHAX %lp_start + PUSHAX %erbta +.endm + +.macro SAVE_EXCEPTION_SOURCE +#ifdef CONFIG_MMU + /* If MMU exists exception faulting address is loaded in EFA reg */ + lr %r0, [%efa] +#else + /* Otherwise in ERET (exception return) reg */ + lr %r0, [%eret] +#endif +.endm + +.section .ivt, "a",@progbits +.align 4 + /* Critical system events */ +.word _start /* 0 - 0x000 */ +.word memory_error /* 1 - 0x008 */ +.word instruction_error /* 2 - 0x010 */ + + /* Exceptions */ +.word EV_MachineCheck /* 0x100, Fatal Machine check (0x20) */ +.word EV_TLBMissI /* 0x108, Intruction TLB miss (0x21) */ +.word EV_TLBMissD /* 0x110, Data TLB miss (0x22) */ +.word EV_TLBProtV /* 0x118, Protection Violation (0x23) + or Misaligned Access */ +.word EV_PrivilegeV /* 0x120, Privilege Violation (0x24) */ +.word EV_Trap /* 0x128, Trap exception (0x25) */ +.word EV_Extension /* 0x130, Extn Intruction Excp (0x26) */ + + /* Device interrupts */ +.rept 29 + j interrupt_handler /* 3:31 - 0x018:0xF8 */ +.endr + +.text +.globl _start +_start: + /* Setup interrupt vector base that matches "__text_start" */ + sr __ivt_start, [ARC_AUX_INTR_VEC_BASE] + + /* Setup stack pointer */ + mov %sp, CONFIG_SYS_INIT_SP_ADDR + mov %fp, %sp + + /* Clear bss */ + mov %r0, __bss_start + mov %r1, __bss_end + +clear_bss: + st.ab 0, [%r0, 4] + brlt %r0, %r1, clear_bss + + /* Zero the one and only argument of "board_init_f" */ + mov_s %r0, 0 + j board_init_f + +memory_error: + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_memory_error + +instruction_error: + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_instruction_error + +interrupt_handler: + /* Todo - save and restore CPU context when interrupts will be in use */ + bl do_interrupt_handler + rtie + +EV_MachineCheck: + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_machine_check_fault + +EV_TLBMissI: + SAVE_ALL_SYS + mov %r0, %sp + j do_itlb_miss + +EV_TLBMissD: + SAVE_ALL_SYS + mov %r0, %sp + j do_dtlb_miss + +EV_TLBProtV: + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_tlb_prot_violation + +EV_PrivilegeV: + SAVE_ALL_SYS + mov %r0, %sp + j do_privilege_violation + +EV_Trap: + SAVE_ALL_SYS + mov %r0, %sp + j do_trap + +EV_Extension: + SAVE_ALL_SYS + mov %r0, %sp + j do_extension + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r0 = start_addr_sp + * r1 = new__gd + * r2 = relocaddr + */ +.align 4 +.globl relocate_code +relocate_code: + /* + * r0-r12 might be clobbered by C functions + * so we use r13-r16 for storage here + */ + mov %r13, %r0 /* save addr_sp */ + mov %r14, %r1 /* save addr of gd */ + mov %r15, %r2 /* save addr of destination */ + + mov %r16, %r2 /* %r9 - relocation offset */ + sub %r16, %r16, __image_copy_start + +/* Set up the stack */ +stack_setup: + mov %sp, %r13 + mov %fp, %sp + +/* Check if monitor is loaded right in place for relocation */ + mov %r0, __image_copy_start + cmp %r0, %r15 /* skip relocation if code loaded */ + bz do_board_init_r /* in target location already */ + +/* Copy data (__image_copy_start - __image_copy_end) to new location */ + mov %r1, %r15 + mov %r2, __image_copy_end + sub %r2, %r2, %r0 /* r3 <- amount of bytes to copy */ + asr %r2, %r2, 2 /* r3 <- amount of words to copy */ + mov %lp_count, %r2 + lp copy_end + ld.ab %r2,[%r0,4] + st.ab %r2,[%r1,4] +copy_end: + +/* Fix relocations related issues */ + bl do_elf_reloc_fixups +#ifndef CONFIG_SYS_ICACHE_OFF + bl invalidate_icache_all +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + bl flush_dcache_all +#endif + +/* Update position of intterupt vector table */ + lr %r0, [ARC_AUX_INTR_VEC_BASE] /* Read current position */ + add %r0, %r0, %r16 /* Update address */ + sr %r0, [ARC_AUX_INTR_VEC_BASE] /* Write new position */ + +do_board_init_r: +/* Prepare for exection of "board_init_r" in relocated monitor */ + mov %r2, board_init_r /* old address of "board_init_r()" */ + add %r2, %r2, %r16 /* new address of "board_init_r()" */ + mov %r0, %r14 /* 1-st parameter: gd_t */ + mov %r1, %r15 /* 2-nd parameter: dest_addr */ + j [%r2] diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 2725961221..8a77cd93af 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -17,10 +17,14 @@ #define ARCH_DMA_MINALIGN 128 #endif -#if defined(CONFIG_ARC_MMU_V2) +#if defined(ARC_MMU_ABSENT) +#define CONFIG_ARC_MMU_VER 0 +#elif defined(CONFIG_ARC_MMU_V2) #define CONFIG_ARC_MMU_VER 2 #elif defined(CONFIG_ARC_MMU_V3) #define CONFIG_ARC_MMU_VER 3 +#elif defined(CONFIG_ARC_MMU_V4) +#define CONFIG_ARC_MMU_VER 4 #endif #endif /* __ASM_ARC_CACHE_H */ diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig new file mode 100644 index 0000000000..c63dd4ab2e --- /dev/null +++ b/configs/axs103_defconfig @@ -0,0 +1,5 @@ +CONFIG_SYS_TEXT_BASE=0x81000000 +CONFIG_SYS_CLK_FREQ=50000000 +CONFIG_ARC=y +CONFIG_ISA_ARCV2=y +CONFIG_TARGET_AXS101=y -- 2.39.2