summaryrefslogtreecommitdiffstats
path: root/arch/arc
diff options
context:
space:
mode:
authorAlexey Brodkin <abrodkin@synopsys.com>2015-01-13 18:35:46 +0300
committerAlexey Brodkin <abrodkin@synopsys.com>2015-02-13 09:17:51 +0300
commitf13606b77d32344d35f6430eb45cffd47302e244 (patch)
tree51f37e30744315357efdec447a3ccb2d11ef56f0 /arch/arc
parentbd2a4888b123713adec271d6c8040ca9f609aa2f (diff)
downloadtalos-obmc-uboot-f13606b77d32344d35f6430eb45cffd47302e244.tar.gz
talos-obmc-uboot-f13606b77d32344d35f6430eb45cffd47302e244.zip
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 <abrodkin@synopsys.com>
Diffstat (limited to 'arch/arc')
-rw-r--r--arch/arc/Kconfig59
-rw-r--r--arch/arc/config.mk12
-rw-r--r--arch/arc/cpu/arcv2/Makefile7
-rw-r--r--arch/arc/cpu/arcv2/start.S254
-rw-r--r--arch/arc/include/asm/cache.h6
5 files changed, 335 insertions, 3 deletions
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 <asm-offsets.h>
+#include <config.h>
+#include <asm/arcregs.h>
+
+/*
+ * 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 */
OpenPOWER on IntegriCloud