From f8cf3d1ebdf7622f65c4eeba9eae1ed04982de12 Mon Sep 17 00:00:00 2001 From: Igor Guryanov Date: Wed, 24 Dec 2014 16:07:07 +0300 Subject: arc: check caches existence before use Some cache operations ({i|d}cache_{enable|disable|status} or flush_dcache_all) are built and used even if CONFIG_SYS_{I|D}CACHE_OFF is set. This is required for force disable of caches on early boot. What if something was executed before U-boot and enabled caches (low-level bootloaders, previously run kernel etc.)? But if CPU doesn't really have caches any attempt to access cache-related AUX registers triggers instruction error exception. So for convenience we'll try to avoid exceptions by checking if CPU actually has caches (we check separately data and instruction cache existence) at all. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/cpu/arc700/cache.c | 29 +++++++++++++++++++++++++++++ arch/arc/include/asm/arcregs.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/arch/arc/cpu/arc700/cache.c b/arch/arc/cpu/arc700/cache.c index 39d522d22f2..fa19a13b7e6 100644 --- a/arch/arc/cpu/arc700/cache.c +++ b/arch/arc/cpu/arc700/cache.c @@ -14,21 +14,34 @@ #define DC_CTRL_CACHE_DISABLE (1 << 0) #define DC_CTRL_INV_MODE_FLUSH (1 << 6) #define DC_CTRL_FLUSH_STATUS (1 << 8) +#define CACHE_VER_NUM_MASK 0xF int icache_status(void) { + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) + return 0; + return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != IC_CTRL_CACHE_DISABLE; } void icache_enable(void) { + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) + return; + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & ~IC_CTRL_CACHE_DISABLE); } void icache_disable(void) { + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) + return; + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | IC_CTRL_CACHE_DISABLE); } @@ -43,24 +56,40 @@ void invalidate_icache_all(void) int dcache_status(void) { + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return 0; + return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != DC_CTRL_CACHE_DISABLE; } void dcache_enable(void) { + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return; + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); } void dcache_disable(void) { + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return; + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | DC_CTRL_CACHE_DISABLE); } void flush_dcache_all(void) { + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return; + /* Do flush of entire cache */ write_aux_reg(ARC_AUX_DC_FLSH, 1); diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 5d48d11bab6..8ace87fa0f2 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -24,6 +24,7 @@ #if (CONFIG_ARC_MMU_VER > 2) #define ARC_AUX_IC_PTAG 0x1E #endif +#define ARC_BCR_IC_BUILD 0x77 /* Timer related auxiliary registers */ #define ARC_AUX_TIMER0_CNT 0x21 /* Timer 0 count */ @@ -42,6 +43,7 @@ #if (CONFIG_ARC_MMU_VER > 2) #define ARC_AUX_DC_PTAG 0x5C #endif +#define ARC_BCR_DC_BUILD 0x72 #ifndef __ASSEMBLY__ /* Accessors for auxiliary registers */ -- cgit v1.3.1 From e47d733867b2da336754718f7eaa7f51655dbefa Mon Sep 17 00:00:00 2001 From: Igor Guryanov Date: Wed, 24 Dec 2014 16:26:14 +0300 Subject: arc: add ECR (exception cause register) output Exception cause register (ECR) contains value that describes a reason for exception that has happened. This helps a lot to figure-out what went wrong. Now we print this register contents when dumping registers. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/cpu/arc700/interrupts.c | 1 + arch/arc/cpu/arc700/start.S | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arc/cpu/arc700/interrupts.c b/arch/arc/cpu/arc700/interrupts.c index d93a6eb547b..7dde74b4385 100644 --- a/arch/arc/cpu/arc700/interrupts.c +++ b/arch/arc/cpu/arc700/interrupts.c @@ -61,6 +61,7 @@ static void print_reg_file(long *reg_rev, int start_num) void show_regs(struct pt_regs *regs) { + printf("ECR:\t0x%08lx\n", regs->ecr); printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n", regs->ret, regs->blink, regs->status32); printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25); diff --git a/arch/arc/cpu/arc700/start.S b/arch/arc/cpu/arc700/start.S index 563513b6904..4d505bfb7ca 100644 --- a/arch/arc/cpu/arc700/start.S +++ b/arch/arc/cpu/arc700/start.S @@ -57,11 +57,13 @@ .endm .macro SAVE_ALL_SYS - + /* saving %r0 to reg->r0 in advance since we read %ecr into it */ + st %r0, [%sp, -8] + lr %r0, [%ecr] /* all stack addressing is manual so far */ st %r0, [%sp] - lr %r0, [%ecr] - st %r0, [%sp, 8] /* ECR */ - st %sp, [%sp, 4] + 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 -- cgit v1.3.1 From c0e9535e1d582ec089c743b705752392fcf3d9a2 Mon Sep 17 00:00:00 2001 From: Igor Guryanov Date: Wed, 24 Dec 2014 16:31:26 +0300 Subject: arc: interrupts - fix mask setup To disable interrupts we need to reset corresponding flags in STATUS32 register. For this we need to OR flags for interrupts level1 and level2 and then AND with current value in STATUS32. Before that implementation was incorrect. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/cpu/arc700/interrupts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arc/cpu/arc700/interrupts.c b/arch/arc/cpu/arc700/interrupts.c index 7dde74b4385..d7cab3bb409 100644 --- a/arch/arc/cpu/arc700/interrupts.c +++ b/arch/arc/cpu/arc700/interrupts.c @@ -23,7 +23,7 @@ int interrupt_init(void) int disable_interrupts(void) { int status = read_aux_reg(ARC_AUX_STATUS32); - int state = (status | E1_MASK | E2_MASK) ? 1 : 0; + int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0; status &= ~(E1_MASK | E2_MASK); /* STATUS32 register is updated indirectly with "FLAG" instruction */ -- cgit v1.3.1 From dcb431e723f132d0df63fb1e711042a6bbfc3a6a Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Wed, 24 Dec 2014 17:00:29 +0300 Subject: arc: add dependences on MMU presence Depending on MMU presence in CPU there're differences in HW behavior. For example address of instruction that caused exception is put in ECR register if MMU exists and in ERET register otherwise. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/config.mk | 4 ++++ arch/arc/cpu/arc700/start.S | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/arc/config.mk b/arch/arc/config.mk index e408800a919..5321987a566 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -21,6 +21,10 @@ ifeq ($(CROSS_COMPILE),) CROSS_COMPILE := $(ARC_CROSS_COMPILE) endif +ifdef CONFIG_ARC_MMU_VER +CONFIG_MMU = 1 +endif + PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 # Needed for relocation diff --git a/arch/arc/cpu/arc700/start.S b/arch/arc/cpu/arc700/start.S index 4d505bfb7ca..2318282bf40 100644 --- a/arch/arc/cpu/arc700/start.S +++ b/arch/arc/cpu/arc700/start.S @@ -78,6 +78,16 @@ 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 + .align 4 .globl _start _start: @@ -102,13 +112,13 @@ _start: memory_error: SAVE_ALL_SYS - lr %r0, [%efa] + SAVE_EXCEPTION_SOURCE mov %r1, %sp j do_memory_error instruction_error: SAVE_ALL_SYS - lr %r0, [%efa] + SAVE_EXCEPTION_SOURCE mov %r1, %sp j do_instruction_error @@ -119,7 +129,7 @@ interrupt_handler: EV_MachineCheck: SAVE_ALL_SYS - lr %r0, [%efa] + SAVE_EXCEPTION_SOURCE mov %r1, %sp j do_machine_check_fault @@ -135,7 +145,7 @@ EV_TLBMissD: EV_TLBProtV: SAVE_ALL_SYS - lr %r0, [%efa] + SAVE_EXCEPTION_SOURCE mov %r1, %sp j do_tlb_prot_violation -- cgit v1.3.1 From 20a58ac0d8e09d0bf1a74c6b68fea22784512b51 Mon Sep 17 00:00:00 2001 From: Igor Guryanov Date: Wed, 24 Dec 2014 17:17:11 +0300 Subject: arc: introduce separate section for interrupt vector table Even though existing implementation works fine in preparation to submission of ARCv2 architecture we need this change. In case of ARCv2 interrupt vector table consists of just addresses of corresponding handlers. And if those addresses will be in .text section then assembler will encode them as everything in .text section as middle-endian and then on real execution CPU will read swapped addresses and will jump into the wild. Once introduced new section is situated so .text section remains the first which allows us to use common linker option for linking everything to a specified CONFIG_SYS_TEXT_BASE. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/Makefile | 2 -- arch/arc/cpu/arc700/Makefile | 3 +-- arch/arc/cpu/arc700/start.S | 49 +++++++++++++++++++++-------------------- arch/arc/cpu/arc700/u-boot.lds | 15 ++++++++++++- arch/arc/include/asm/sections.h | 2 ++ arch/arc/lib/relocate.c | 4 ++-- arch/arc/lib/sections.c | 2 ++ 7 files changed, 46 insertions(+), 31 deletions(-) diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 03ea6dbae0d..a59231e70eb 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -2,8 +2,6 @@ # SPDX-License-Identifier: GPL-2.0+ # -head-y := arch/arc/cpu/$(CPU)/start.o - libs-y += arch/arc/cpu/$(CPU)/ libs-y += arch/arc/lib/ diff --git a/arch/arc/cpu/arc700/Makefile b/arch/arc/cpu/arc700/Makefile index cdc50022901..021e3a2b5d0 100644 --- a/arch/arc/cpu/arc700/Makefile +++ b/arch/arc/cpu/arc700/Makefile @@ -4,10 +4,9 @@ # SPDX-License-Identifier: GPL-2.0+ # -extra-y += start.o - obj-y += cache.o obj-y += cpu.o obj-y += interrupts.o obj-y += reset.o +obj-y += start.o obj-y += timer.o diff --git a/arch/arc/cpu/arc700/start.S b/arch/arc/cpu/arc700/start.S index 2318282bf40..01cfba49339 100644 --- a/arch/arc/cpu/arc700/start.S +++ b/arch/arc/cpu/arc700/start.S @@ -88,11 +88,11 @@ #endif .endm +.section .ivt, "ax",@progbits .align 4 -.globl _start -_start: +_ivt: /* Critical system events */ - j reset /* 0 - 0x000 */ + j _start /* 0 - 0x000 */ j memory_error /* 1 - 0x008 */ j instruction_error /* 2 - 0x010 */ @@ -110,6 +110,28 @@ _start: j EV_Trap /* 0x128, Trap exception (0x25) */ j EV_Extension /* 0x130, Extn Intruction Excp (0x26) */ +.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 @@ -164,27 +186,6 @@ EV_Extension: mov %r0, %sp j do_extension - -reset: - /* Setup interrupt vector base that matches "__text_start" */ - sr __text_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 - /* * void relocate_code (addr_sp, gd, addr_moni) * diff --git a/arch/arc/cpu/arc700/u-boot.lds b/arch/arc/cpu/arc700/u-boot.lds index 2d01b21b367..ccddbf7dc9b 100644 --- a/arch/arc/cpu/arc700/u-boot.lds +++ b/arch/arc/cpu/arc700/u-boot.lds @@ -13,7 +13,6 @@ SECTIONS .text : { *(.__text_start) *(.__image_copy_start) - CPUDIR/start.o (.text*) *(.text*) } @@ -23,6 +22,20 @@ SECTIONS *(.__text_end) } + . = ALIGN(1024); + .ivt_start : { + *(.__ivt_start) + } + + .ivt : + { + *(.ivt) + } + + .ivt_end : { + *(.__ivt_end) + } + . = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h index 18484a17f21..2a7a98713da 100644 --- a/arch/arc/include/asm/sections.h +++ b/arch/arc/include/asm/sections.h @@ -10,5 +10,7 @@ #include extern ulong __text_end; +extern ulong __ivt_start; +extern ulong __ivt_end; #endif /* __ASM_ARC_SECTIONS_H */ diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c index 2482bcdffcc..5618b6ae938 100644 --- a/arch/arc/lib/relocate.c +++ b/arch/arc/lib/relocate.c @@ -44,7 +44,7 @@ int do_elf_reloc_fixups(void) #ifdef __LITTLE_ENDIAN__ /* If location in ".text" section swap value */ if ((unsigned int)offset_ptr_rom < - (unsigned int)&__text_end) + (unsigned int)&__ivt_end) val = (val << 16) | (val >> 16); #endif @@ -55,7 +55,7 @@ int do_elf_reloc_fixups(void) #ifdef __LITTLE_ENDIAN__ /* If location in ".text" section swap value */ if ((unsigned int)offset_ptr_rom < - (unsigned int)&__text_end) + (unsigned int)&__ivt_end) val = (val << 16) | (val >> 16); #endif memcpy(offset_ptr_ram, &val, sizeof(int)); diff --git a/arch/arc/lib/sections.c b/arch/arc/lib/sections.c index b0b46a4e9ae..a72c6946d53 100644 --- a/arch/arc/lib/sections.c +++ b/arch/arc/lib/sections.c @@ -19,3 +19,5 @@ char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end"))); char __text_start[0] __attribute__((section(".__text_start"))); char __text_end[0] __attribute__((section(".__text_end"))); char __init_end[0] __attribute__((section(".__init_end"))); +char __ivt_start[0] __attribute__((section(".__ivt_start"))); +char __ivt_end[0] __attribute__((section(".__ivt_end"))); -- cgit v1.3.1 From 1c91a3d9790c6d8f4bcb0d896936672509a1439d Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Fri, 26 Dec 2014 19:36:30 +0300 Subject: arc: relocate - minor refactoring and clean-up * use better symbols for relocatable region boundaries ("__image_copy_start" instead of "CONFIG_SYS_TEXT_BASE") * remove useless debug messages because they will only show up in case of both problem (when normal "if" branch won't be taken) and DEBUG take place which is pretty rare situation. Signed-off-by: Alexey Brodkin --- arch/arc/include/asm/sections.h | 1 + arch/arc/lib/relocate.c | 15 ++++----------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h index 2a7a98713da..b8f2a859fd9 100644 --- a/arch/arc/include/asm/sections.h +++ b/arch/arc/include/asm/sections.h @@ -12,5 +12,6 @@ extern ulong __text_end; extern ulong __ivt_start; extern ulong __ivt_end; +extern ulong __image_copy_start; #endif /* __ASM_ARC_SECTIONS_H */ diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c index 5618b6ae938..7797782563b 100644 --- a/arch/arc/lib/relocate.c +++ b/arch/arc/lib/relocate.c @@ -26,7 +26,7 @@ int do_elf_reloc_fixups(void) offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; /* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE && + if (offset_ptr_rom >= (Elf32_Addr *)&__image_copy_start && offset_ptr_rom > last_offset) { unsigned int val; /* Switch to the in-RAM version */ @@ -48,9 +48,9 @@ int do_elf_reloc_fixups(void) val = (val << 16) | (val >> 16); #endif - /* Check that the target points into .text */ - if (val >= CONFIG_SYS_TEXT_BASE && val <= - (unsigned int)&__bss_end) { + /* Check that the target points into executable */ + if (val >= (unsigned int)&__image_copy_start && val <= + (unsigned int)&__image_copy_end) { val += gd->reloc_off; #ifdef __LITTLE_ENDIAN__ /* If location in ".text" section swap value */ @@ -59,14 +59,7 @@ int do_elf_reloc_fixups(void) val = (val << 16) | (val >> 16); #endif memcpy(offset_ptr_ram, &val, sizeof(int)); - } else { - debug(" %p: rom reloc %x, ram %p, value %x, limit %x\n", - re_src, re_src->r_offset, offset_ptr_ram, - val, (unsigned int)&__bss_end); } - } else { - debug(" %p: rom reloc %x, last %p\n", re_src, - re_src->r_offset, last_offset); } last_offset = offset_ptr_rom; -- cgit v1.3.1 From 70a0442a420ccea85e6255fedb760448c5b7b87f Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Sun, 28 Dec 2014 02:45:37 +0300 Subject: arc: move linker script in arch/arc/cpu folder This way we'll be able to use the same one script for either ARC CPU. Signed-off-by: Alexey Brodkin --- arch/arc/cpu/arc700/u-boot.lds | 85 ------------------------------------------ arch/arc/cpu/u-boot.lds | 85 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 85 deletions(-) delete mode 100644 arch/arc/cpu/arc700/u-boot.lds create mode 100644 arch/arc/cpu/u-boot.lds diff --git a/arch/arc/cpu/arc700/u-boot.lds b/arch/arc/cpu/arc700/u-boot.lds deleted file mode 100644 index ccddbf7dc9b..00000000000 --- a/arch/arc/cpu/arc700/u-boot.lds +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -OUTPUT_FORMAT("elf32-littlearc", "elf32-littlearc", "elf32-littlearc") -OUTPUT_ARCH(arc) -ENTRY(_start) -SECTIONS -{ - . = ALIGN(4); - .text : { - *(.__text_start) - *(.__image_copy_start) - *(.text*) - } - - . = ALIGN(4); - .text_end : - { - *(.__text_end) - } - - . = ALIGN(1024); - .ivt_start : { - *(.__ivt_start) - } - - .ivt : - { - *(.ivt) - } - - .ivt_end : { - *(.__ivt_end) - } - - . = ALIGN(4); - .rodata : { - *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) - } - - . = ALIGN(4); - .data : { - *(.data*) - } - - . = ALIGN(4); - .u_boot_list : { - KEEP(*(SORT(.u_boot_list*))); - } - - . = ALIGN(4); - .rel_dyn_start : { - *(.__rel_dyn_start) - } - - .rela.dyn : { - *(.rela.dyn) - } - - .rel_dyn_end : { - *(.__rel_dyn_end) - } - - . = ALIGN(4); - .bss_start : { - *(.__bss_start); - } - - .bss : { - *(.bss*) - } - - .bss_end : { - *(.__bss_end); - } - - . = ALIGN(4); - .image_copy_end : { - *(.__image_copy_end) - *(.__init_end) - } -} diff --git a/arch/arc/cpu/u-boot.lds b/arch/arc/cpu/u-boot.lds new file mode 100644 index 00000000000..ccddbf7dc9b --- /dev/null +++ b/arch/arc/cpu/u-boot.lds @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearc", "elf32-littlearc", "elf32-littlearc") +OUTPUT_ARCH(arc) +ENTRY(_start) +SECTIONS +{ + . = ALIGN(4); + .text : { + *(.__text_start) + *(.__image_copy_start) + *(.text*) + } + + . = ALIGN(4); + .text_end : + { + *(.__text_end) + } + + . = ALIGN(1024); + .ivt_start : { + *(.__ivt_start) + } + + .ivt : + { + *(.ivt) + } + + .ivt_end : { + *(.__ivt_end) + } + + . = ALIGN(4); + .rodata : { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + .rel_dyn_start : { + *(.__rel_dyn_start) + } + + .rela.dyn : { + *(.rela.dyn) + } + + .rel_dyn_end : { + *(.__rel_dyn_end) + } + + . = ALIGN(4); + .bss_start : { + *(.__bss_start); + } + + .bss : { + *(.bss*) + } + + .bss_end : { + *(.__bss_end); + } + + . = ALIGN(4); + .image_copy_end : { + *(.__image_copy_end) + *(.__init_end) + } +} -- cgit v1.3.1 From 660d5f0d495197b4057bc1b3bdd201e500b03f1a Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Sun, 28 Dec 2014 02:42:12 +0300 Subject: arc: move common sources in library "reset.c" and "cpu.c" have no architecture-specific code at all. Others are applicable to either ARC CPU. This change is a preparation to submission of ARCv2 architecture port. Even though ARCv1 and ARCv2 ISAs are not binary compatible most of built-in modules still have the same programming model - AUX registers are mapped in the same addresses and hold the same data (new featues extend existing ones). So only low-level assembly code (start-up, interrupt handlers) is left as CPU(actually ISA)-specific. This significantyl simplifies maintenance of multiple CPUs/ISAs. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/cpu/arc700/Makefile | 7 +- arch/arc/cpu/arc700/cache.c | 167 --------------------------------------- arch/arc/cpu/arc700/cpu.c | 47 ----------- arch/arc/cpu/arc700/interrupts.c | 143 --------------------------------- arch/arc/cpu/arc700/reset.c | 19 ----- arch/arc/cpu/arc700/timer.c | 24 ------ arch/arc/lib/Makefile | 6 ++ arch/arc/lib/cache.c | 167 +++++++++++++++++++++++++++++++++++++++ arch/arc/lib/cpu.c | 47 +++++++++++ arch/arc/lib/interrupts.c | 143 +++++++++++++++++++++++++++++++++ arch/arc/lib/reset.c | 19 +++++ arch/arc/lib/timer.c | 24 ++++++ 12 files changed, 407 insertions(+), 406 deletions(-) delete mode 100644 arch/arc/cpu/arc700/cache.c delete mode 100644 arch/arc/cpu/arc700/cpu.c delete mode 100644 arch/arc/cpu/arc700/interrupts.c delete mode 100644 arch/arc/cpu/arc700/reset.c delete mode 100644 arch/arc/cpu/arc700/timer.c create mode 100644 arch/arc/lib/cache.c create mode 100644 arch/arc/lib/cpu.c create mode 100644 arch/arc/lib/interrupts.c create mode 100644 arch/arc/lib/reset.c create mode 100644 arch/arc/lib/timer.c diff --git a/arch/arc/cpu/arc700/Makefile b/arch/arc/cpu/arc700/Makefile index 021e3a2b5d0..3704ebeeaef 100644 --- a/arch/arc/cpu/arc700/Makefile +++ b/arch/arc/cpu/arc700/Makefile @@ -4,9 +4,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += cache.o -obj-y += cpu.o -obj-y += interrupts.o -obj-y += reset.o -obj-y += start.o -obj-y += timer.o +obj-y += start.o diff --git a/arch/arc/cpu/arc700/cache.c b/arch/arc/cpu/arc700/cache.c deleted file mode 100644 index fa19a13b7e6..00000000000 --- a/arch/arc/cpu/arc700/cache.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -/* Bit values in IC_CTRL */ -#define IC_CTRL_CACHE_DISABLE (1 << 0) - -/* Bit values in DC_CTRL */ -#define DC_CTRL_CACHE_DISABLE (1 << 0) -#define DC_CTRL_INV_MODE_FLUSH (1 << 6) -#define DC_CTRL_FLUSH_STATUS (1 << 8) -#define CACHE_VER_NUM_MASK 0xF - -int icache_status(void) -{ - /* If no cache in CPU exit immediately */ - if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) - return 0; - - return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != - IC_CTRL_CACHE_DISABLE; -} - -void icache_enable(void) -{ - /* If no cache in CPU exit immediately */ - if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) - return; - - write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & - ~IC_CTRL_CACHE_DISABLE); -} - -void icache_disable(void) -{ - /* If no cache in CPU exit immediately */ - if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) - return; - - write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | - IC_CTRL_CACHE_DISABLE); -} - -void invalidate_icache_all(void) -{ -#ifndef CONFIG_SYS_ICACHE_OFF - /* Any write to IC_IVIC register triggers invalidation of entire I$ */ - write_aux_reg(ARC_AUX_IC_IVIC, 1); -#endif /* CONFIG_SYS_ICACHE_OFF */ -} - -int dcache_status(void) -{ - /* If no cache in CPU exit immediately */ - if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) - return 0; - - return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != - DC_CTRL_CACHE_DISABLE; -} - -void dcache_enable(void) -{ - /* If no cache in CPU exit immediately */ - if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) - return; - - write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & - ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); -} - -void dcache_disable(void) -{ - /* If no cache in CPU exit immediately */ - if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) - return; - - write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | - DC_CTRL_CACHE_DISABLE); -} - -void flush_dcache_all(void) -{ - /* If no cache in CPU exit immediately */ - if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) - return; - - /* Do flush of entire cache */ - write_aux_reg(ARC_AUX_DC_FLSH, 1); - - /* Wait flush end */ - while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) - ; -} - -#ifndef CONFIG_SYS_DCACHE_OFF -static void dcache_flush_line(unsigned addr) -{ -#if (CONFIG_ARC_MMU_VER > 2) - write_aux_reg(ARC_AUX_DC_PTAG, addr); -#endif - write_aux_reg(ARC_AUX_DC_FLDL, addr); - - /* Wait flush end */ - while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) - ; - -#ifndef CONFIG_SYS_ICACHE_OFF - /* - * Invalidate I$ for addresses range just flushed from D$. - * If we try to execute data flushed above it will be valid/correct - */ -#if (CONFIG_ARC_MMU_VER > 2) - write_aux_reg(ARC_AUX_IC_PTAG, addr); -#endif - write_aux_reg(ARC_AUX_IC_IVIL, addr); -#endif /* CONFIG_SYS_ICACHE_OFF */ -} -#endif /* CONFIG_SYS_DCACHE_OFF */ - -void flush_dcache_range(unsigned long start, unsigned long end) -{ -#ifndef CONFIG_SYS_DCACHE_OFF - unsigned int addr; - - start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); - end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); - - for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) - dcache_flush_line(addr); -#endif /* CONFIG_SYS_DCACHE_OFF */ -} - -void invalidate_dcache_range(unsigned long start, unsigned long end) -{ -#ifndef CONFIG_SYS_DCACHE_OFF - unsigned int addr; - - start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); - end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); - - for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { -#if (CONFIG_ARC_MMU_VER > 2) - write_aux_reg(ARC_AUX_DC_PTAG, addr); -#endif - write_aux_reg(ARC_AUX_DC_IVDL, addr); - } -#endif /* CONFIG_SYS_DCACHE_OFF */ -} - -void invalidate_dcache_all(void) -{ -#ifndef CONFIG_SYS_DCACHE_OFF - /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ - write_aux_reg(ARC_AUX_DC_IVDC, 1); -#endif /* CONFIG_SYS_DCACHE_OFF */ -} - -void flush_cache(unsigned long start, unsigned long size) -{ - flush_dcache_range(start, start + size); -} diff --git a/arch/arc/cpu/arc700/cpu.c b/arch/arc/cpu/arc700/cpu.c deleted file mode 100644 index 50634b860f7..00000000000 --- a/arch/arc/cpu/arc700/cpu.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -int arch_cpu_init(void) -{ -#ifdef CONFIG_SYS_ICACHE_OFF - icache_disable(); -#else - icache_enable(); - invalidate_icache_all(); -#endif - - flush_dcache_all(); -#ifdef CONFIG_SYS_DCACHE_OFF - dcache_disable(); -#else - dcache_enable(); -#endif - timer_init(); - -/* In simulation (ISS) "CHIPID" and "ARCNUM" are all "ff" */ - if ((read_aux_reg(ARC_AUX_IDENTITY) & 0xffffff00) == 0xffffff00) - gd->arch.running_on_hw = 0; - else - gd->arch.running_on_hw = 1; - - gd->cpu_clk = CONFIG_SYS_CLK_FREQ; - gd->ram_size = CONFIG_SYS_SDRAM_SIZE; - - return 0; -} - -int arch_early_init_r(void) -{ - gd->bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; - gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE; - return 0; -} diff --git a/arch/arc/cpu/arc700/interrupts.c b/arch/arc/cpu/arc700/interrupts.c deleted file mode 100644 index d7cab3bb409..00000000000 --- a/arch/arc/cpu/arc700/interrupts.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -/* Bit values in STATUS32 */ -#define E1_MASK (1 << 1) /* Level 1 interrupts enable */ -#define E2_MASK (1 << 2) /* Level 2 interrupts enable */ - -int interrupt_init(void) -{ - return 0; -} - -/* - * returns true if interrupts had been enabled before we disabled them - */ -int disable_interrupts(void) -{ - int status = read_aux_reg(ARC_AUX_STATUS32); - int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0; - - status &= ~(E1_MASK | E2_MASK); - /* STATUS32 register is updated indirectly with "FLAG" instruction */ - __asm__("flag %0" : : "r" (status)); - return state; -} - -void enable_interrupts(void) -{ - unsigned int status = read_aux_reg(ARC_AUX_STATUS32); - - status |= E1_MASK | E2_MASK; - /* STATUS32 register is updated indirectly with "FLAG" instruction */ - __asm__("flag %0" : : "r" (status)); -} - -static void print_reg_file(long *reg_rev, int start_num) -{ - unsigned int i; - - /* Print 3 registers per line */ - for (i = start_num; i < start_num + 25; i++) { - printf("r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev); - if (((i + 1) % 3) == 0) - printf("\n"); - - /* Because pt_regs has registers reversed */ - reg_rev--; - } - - /* Add new-line if none was inserted in the end of loop above */ - if (((i + 1) % 3) != 0) - printf("\n"); -} - -void show_regs(struct pt_regs *regs) -{ - printf("ECR:\t0x%08lx\n", regs->ecr); - printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n", - regs->ret, regs->blink, regs->status32); - printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25); - printf("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", regs->bta, - regs->sp, regs->fp); - printf("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start, - regs->lp_end, regs->lp_count); - - print_reg_file(&(regs->r0), 0); -} - -void bad_mode(struct pt_regs *regs) -{ - if (regs) - show_regs(regs); - - panic("Resetting CPU ...\n"); -} - -void do_memory_error(unsigned long address, struct pt_regs *regs) -{ - printf("Memory error exception @ 0x%lx\n", address); - bad_mode(regs); -} - -void do_instruction_error(unsigned long address, struct pt_regs *regs) -{ - printf("Instruction error exception @ 0x%lx\n", address); - bad_mode(regs); -} - -void do_machine_check_fault(unsigned long address, struct pt_regs *regs) -{ - printf("Machine check exception @ 0x%lx\n", address); - bad_mode(regs); -} - -void do_interrupt_handler(void) -{ - printf("Interrupt fired\n"); - bad_mode(0); -} - -void do_itlb_miss(struct pt_regs *regs) -{ - printf("I TLB miss exception\n"); - bad_mode(regs); -} - -void do_dtlb_miss(struct pt_regs *regs) -{ - printf("D TLB miss exception\n"); - bad_mode(regs); -} - -void do_tlb_prot_violation(unsigned long address, struct pt_regs *regs) -{ - printf("TLB protection violation or misaligned access @ 0x%lx\n", - address); - bad_mode(regs); -} - -void do_privilege_violation(struct pt_regs *regs) -{ - printf("Privilege violation exception\n"); - bad_mode(regs); -} - -void do_trap(struct pt_regs *regs) -{ - printf("Trap exception\n"); - bad_mode(regs); -} - -void do_extension(struct pt_regs *regs) -{ - printf("Extension instruction exception\n"); - bad_mode(regs); -} diff --git a/arch/arc/cpu/arc700/reset.c b/arch/arc/cpu/arc700/reset.c deleted file mode 100644 index 98ebf1d4456..00000000000 --- a/arch/arc/cpu/arc700/reset.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) -{ - printf("Put your restart handler here\n"); - -#ifdef DEBUG - /* Stop debug session here */ - __asm__("brk"); -#endif - return 0; -} diff --git a/arch/arc/cpu/arc700/timer.c b/arch/arc/cpu/arc700/timer.c deleted file mode 100644 index a0acbbc01a4..00000000000 --- a/arch/arc/cpu/arc700/timer.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#define NH_MODE (1 << 1) /* Disable timer if CPU is halted */ - -int timer_init(void) -{ - write_aux_reg(ARC_AUX_TIMER0_CTRL, NH_MODE); - /* Set max value for counter/timer */ - write_aux_reg(ARC_AUX_TIMER0_LIMIT, 0xffffffff); - /* Set initial count value and restart counter/timer */ - write_aux_reg(ARC_AUX_TIMER0_CNT, 0); - return 0; -} - -unsigned long timer_read_counter(void) -{ - return read_aux_reg(ARC_AUX_TIMER0_CNT); -} diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile index 7675f855d5a..bae44199a41 100644 --- a/arch/arc/lib/Makefile +++ b/arch/arc/lib/Makefile @@ -4,6 +4,9 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-y += cache.o +obj-y += cpu.o +obj-y += interrupts.o obj-y += sections.o obj-y += relocate.o obj-y += strchr-700.o @@ -13,4 +16,7 @@ obj-y += strlen.o obj-y += memcmp.o obj-y += memcpy-700.o obj-y += memset.o +obj-y += reset.o +obj-y += timer.o + obj-$(CONFIG_CMD_BOOTM) += bootm.o diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c new file mode 100644 index 00000000000..fa19a13b7e6 --- /dev/null +++ b/arch/arc/lib/cache.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +/* Bit values in IC_CTRL */ +#define IC_CTRL_CACHE_DISABLE (1 << 0) + +/* Bit values in DC_CTRL */ +#define DC_CTRL_CACHE_DISABLE (1 << 0) +#define DC_CTRL_INV_MODE_FLUSH (1 << 6) +#define DC_CTRL_FLUSH_STATUS (1 << 8) +#define CACHE_VER_NUM_MASK 0xF + +int icache_status(void) +{ + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) + return 0; + + return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != + IC_CTRL_CACHE_DISABLE; +} + +void icache_enable(void) +{ + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) + return; + + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & + ~IC_CTRL_CACHE_DISABLE); +} + +void icache_disable(void) +{ + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) + return; + + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | + IC_CTRL_CACHE_DISABLE); +} + +void invalidate_icache_all(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + /* Any write to IC_IVIC register triggers invalidation of entire I$ */ + write_aux_reg(ARC_AUX_IC_IVIC, 1); +#endif /* CONFIG_SYS_ICACHE_OFF */ +} + +int dcache_status(void) +{ + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return 0; + + return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != + DC_CTRL_CACHE_DISABLE; +} + +void dcache_enable(void) +{ + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return; + + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & + ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); +} + +void dcache_disable(void) +{ + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return; + + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | + DC_CTRL_CACHE_DISABLE); +} + +void flush_dcache_all(void) +{ + /* If no cache in CPU exit immediately */ + if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) + return; + + /* Do flush of entire cache */ + write_aux_reg(ARC_AUX_DC_FLSH, 1); + + /* Wait flush end */ + while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) + ; +} + +#ifndef CONFIG_SYS_DCACHE_OFF +static void dcache_flush_line(unsigned addr) +{ +#if (CONFIG_ARC_MMU_VER > 2) + write_aux_reg(ARC_AUX_DC_PTAG, addr); +#endif + write_aux_reg(ARC_AUX_DC_FLDL, addr); + + /* Wait flush end */ + while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) + ; + +#ifndef CONFIG_SYS_ICACHE_OFF + /* + * Invalidate I$ for addresses range just flushed from D$. + * If we try to execute data flushed above it will be valid/correct + */ +#if (CONFIG_ARC_MMU_VER > 2) + write_aux_reg(ARC_AUX_IC_PTAG, addr); +#endif + write_aux_reg(ARC_AUX_IC_IVIL, addr); +#endif /* CONFIG_SYS_ICACHE_OFF */ +} +#endif /* CONFIG_SYS_DCACHE_OFF */ + +void flush_dcache_range(unsigned long start, unsigned long end) +{ +#ifndef CONFIG_SYS_DCACHE_OFF + unsigned int addr; + + start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); + end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); + + for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) + dcache_flush_line(addr); +#endif /* CONFIG_SYS_DCACHE_OFF */ +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ +#ifndef CONFIG_SYS_DCACHE_OFF + unsigned int addr; + + start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); + end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); + + for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { +#if (CONFIG_ARC_MMU_VER > 2) + write_aux_reg(ARC_AUX_DC_PTAG, addr); +#endif + write_aux_reg(ARC_AUX_DC_IVDL, addr); + } +#endif /* CONFIG_SYS_DCACHE_OFF */ +} + +void invalidate_dcache_all(void) +{ +#ifndef CONFIG_SYS_DCACHE_OFF + /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ + write_aux_reg(ARC_AUX_DC_IVDC, 1); +#endif /* CONFIG_SYS_DCACHE_OFF */ +} + +void flush_cache(unsigned long start, unsigned long size) +{ + flush_dcache_range(start, start + size); +} diff --git a/arch/arc/lib/cpu.c b/arch/arc/lib/cpu.c new file mode 100644 index 00000000000..50634b860f7 --- /dev/null +++ b/arch/arc/lib/cpu.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int arch_cpu_init(void) +{ +#ifdef CONFIG_SYS_ICACHE_OFF + icache_disable(); +#else + icache_enable(); + invalidate_icache_all(); +#endif + + flush_dcache_all(); +#ifdef CONFIG_SYS_DCACHE_OFF + dcache_disable(); +#else + dcache_enable(); +#endif + timer_init(); + +/* In simulation (ISS) "CHIPID" and "ARCNUM" are all "ff" */ + if ((read_aux_reg(ARC_AUX_IDENTITY) & 0xffffff00) == 0xffffff00) + gd->arch.running_on_hw = 0; + else + gd->arch.running_on_hw = 1; + + gd->cpu_clk = CONFIG_SYS_CLK_FREQ; + gd->ram_size = CONFIG_SYS_SDRAM_SIZE; + + return 0; +} + +int arch_early_init_r(void) +{ + gd->bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE; + return 0; +} diff --git a/arch/arc/lib/interrupts.c b/arch/arc/lib/interrupts.c new file mode 100644 index 00000000000..d7cab3bb409 --- /dev/null +++ b/arch/arc/lib/interrupts.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +/* Bit values in STATUS32 */ +#define E1_MASK (1 << 1) /* Level 1 interrupts enable */ +#define E2_MASK (1 << 2) /* Level 2 interrupts enable */ + +int interrupt_init(void) +{ + return 0; +} + +/* + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts(void) +{ + int status = read_aux_reg(ARC_AUX_STATUS32); + int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0; + + status &= ~(E1_MASK | E2_MASK); + /* STATUS32 register is updated indirectly with "FLAG" instruction */ + __asm__("flag %0" : : "r" (status)); + return state; +} + +void enable_interrupts(void) +{ + unsigned int status = read_aux_reg(ARC_AUX_STATUS32); + + status |= E1_MASK | E2_MASK; + /* STATUS32 register is updated indirectly with "FLAG" instruction */ + __asm__("flag %0" : : "r" (status)); +} + +static void print_reg_file(long *reg_rev, int start_num) +{ + unsigned int i; + + /* Print 3 registers per line */ + for (i = start_num; i < start_num + 25; i++) { + printf("r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev); + if (((i + 1) % 3) == 0) + printf("\n"); + + /* Because pt_regs has registers reversed */ + reg_rev--; + } + + /* Add new-line if none was inserted in the end of loop above */ + if (((i + 1) % 3) != 0) + printf("\n"); +} + +void show_regs(struct pt_regs *regs) +{ + printf("ECR:\t0x%08lx\n", regs->ecr); + printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n", + regs->ret, regs->blink, regs->status32); + printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25); + printf("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", regs->bta, + regs->sp, regs->fp); + printf("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start, + regs->lp_end, regs->lp_count); + + print_reg_file(&(regs->r0), 0); +} + +void bad_mode(struct pt_regs *regs) +{ + if (regs) + show_regs(regs); + + panic("Resetting CPU ...\n"); +} + +void do_memory_error(unsigned long address, struct pt_regs *regs) +{ + printf("Memory error exception @ 0x%lx\n", address); + bad_mode(regs); +} + +void do_instruction_error(unsigned long address, struct pt_regs *regs) +{ + printf("Instruction error exception @ 0x%lx\n", address); + bad_mode(regs); +} + +void do_machine_check_fault(unsigned long address, struct pt_regs *regs) +{ + printf("Machine check exception @ 0x%lx\n", address); + bad_mode(regs); +} + +void do_interrupt_handler(void) +{ + printf("Interrupt fired\n"); + bad_mode(0); +} + +void do_itlb_miss(struct pt_regs *regs) +{ + printf("I TLB miss exception\n"); + bad_mode(regs); +} + +void do_dtlb_miss(struct pt_regs *regs) +{ + printf("D TLB miss exception\n"); + bad_mode(regs); +} + +void do_tlb_prot_violation(unsigned long address, struct pt_regs *regs) +{ + printf("TLB protection violation or misaligned access @ 0x%lx\n", + address); + bad_mode(regs); +} + +void do_privilege_violation(struct pt_regs *regs) +{ + printf("Privilege violation exception\n"); + bad_mode(regs); +} + +void do_trap(struct pt_regs *regs) +{ + printf("Trap exception\n"); + bad_mode(regs); +} + +void do_extension(struct pt_regs *regs) +{ + printf("Extension instruction exception\n"); + bad_mode(regs); +} diff --git a/arch/arc/lib/reset.c b/arch/arc/lib/reset.c new file mode 100644 index 00000000000..98ebf1d4456 --- /dev/null +++ b/arch/arc/lib/reset.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + printf("Put your restart handler here\n"); + +#ifdef DEBUG + /* Stop debug session here */ + __asm__("brk"); +#endif + return 0; +} diff --git a/arch/arc/lib/timer.c b/arch/arc/lib/timer.c new file mode 100644 index 00000000000..a0acbbc01a4 --- /dev/null +++ b/arch/arc/lib/timer.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#define NH_MODE (1 << 1) /* Disable timer if CPU is halted */ + +int timer_init(void) +{ + write_aux_reg(ARC_AUX_TIMER0_CTRL, NH_MODE); + /* Set max value for counter/timer */ + write_aux_reg(ARC_AUX_TIMER0_LIMIT, 0xffffffff); + /* Set initial count value and restart counter/timer */ + write_aux_reg(ARC_AUX_TIMER0_CNT, 0); + return 0; +} + +unsigned long timer_read_counter(void) +{ + return read_aux_reg(ARC_AUX_TIMER0_CNT); +} -- cgit v1.3.1 From e20bcb046b245d78f63c99811fc0ccdc6661aa82 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Thu, 25 Dec 2014 18:47:45 +0300 Subject: board/synopsys: remove selection of CPU from the board Both ARCangel4 and AXS10x are FPGA-based boards so they may have different CPUs. For now we have only 1 option (ARC700) and we define this as default in arch Kconfig. Signed-off-by: Alexey Brodkin --- arch/arc/Kconfig | 3 +++ board/synopsys/Kconfig | 6 ------ board/synopsys/axs101/Kconfig | 3 --- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index d3ef58be043..6a77b8f34c9 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -4,6 +4,9 @@ menu "ARC architecture" config SYS_ARCH default "arc" +config SYS_CPU + default "arc700" + choice prompt "Target select" diff --git a/board/synopsys/Kconfig b/board/synopsys/Kconfig index a54d3dfde36..f614f88cc61 100644 --- a/board/synopsys/Kconfig +++ b/board/synopsys/Kconfig @@ -1,8 +1,5 @@ if TARGET_ARCANGEL4 -config SYS_CPU - default "arc700" - config SYS_VENDOR default "synopsys" @@ -13,9 +10,6 @@ endif if TARGET_ARCANGEL4_BE -config SYS_CPU - default "arc700" - config SYS_VENDOR default "synopsys" diff --git a/board/synopsys/axs101/Kconfig b/board/synopsys/axs101/Kconfig index 84482658880..79e5400ea86 100644 --- a/board/synopsys/axs101/Kconfig +++ b/board/synopsys/axs101/Kconfig @@ -1,8 +1,5 @@ if TARGET_AXS101 -config SYS_CPU - default "arc700" - config SYS_BOARD default "axs101" -- cgit v1.3.1 From fdff23702a361e89a153222233231af4d00d6e2a Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Thu, 25 Dec 2014 18:54:58 +0300 Subject: arc: rename "arc700" in "arcv1" As a preparation to ARCv2 port submission we rename "arc700" folder to "arcv1" which stands for ARCv1 ISA also known as ARCompact. This will allow us to add more flavours of binary-compatible ARCv1 CPUs like ARC600 if needed later on and all required ARCv2 CPUs (which are binary incompatible with ARCv1) in "arcv2" folder in subsequent commits. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/Kconfig | 2 +- arch/arc/cpu/arc700/Makefile | 7 -- arch/arc/cpu/arc700/config.mk | 7 -- arch/arc/cpu/arc700/start.S | 254 ------------------------------------------ arch/arc/cpu/arcv1/Makefile | 7 ++ arch/arc/cpu/arcv1/config.mk | 7 ++ arch/arc/cpu/arcv1/start.S | 254 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 269 insertions(+), 269 deletions(-) delete mode 100644 arch/arc/cpu/arc700/Makefile delete mode 100644 arch/arc/cpu/arc700/config.mk delete mode 100644 arch/arc/cpu/arc700/start.S create mode 100644 arch/arc/cpu/arcv1/Makefile create mode 100644 arch/arc/cpu/arcv1/config.mk create mode 100644 arch/arc/cpu/arcv1/start.S diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 6a77b8f34c9..c6b1efeb8bf 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -5,7 +5,7 @@ config SYS_ARCH default "arc" config SYS_CPU - default "arc700" + default "arcv1" choice prompt "Target select" diff --git a/arch/arc/cpu/arc700/Makefile b/arch/arc/cpu/arc700/Makefile deleted file mode 100644 index 3704ebeeaef..00000000000 --- a/arch/arc/cpu/arc700/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-y += start.o diff --git a/arch/arc/cpu/arc700/config.mk b/arch/arc/cpu/arc700/config.mk deleted file mode 100644 index 3206ff47e39..00000000000 --- a/arch/arc/cpu/arc700/config.mk +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -PLATFORM_CPPFLAGS += -mA7 diff --git a/arch/arc/cpu/arc700/start.S b/arch/arc/cpu/arc700/start.S deleted file mode 100644 index 01cfba49339..00000000000 --- a/arch/arc/cpu/arc700/start.S +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2013-2014 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 we read %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, "ax",@progbits -.align 4 -_ivt: - /* Critical system events */ - j _start /* 0 - 0x000 */ - j memory_error /* 1 - 0x008 */ - j instruction_error /* 2 - 0x010 */ - - /* Device interrupts */ -.rept 29 - j interrupt_handler /* 3:31 - 0x018:0xF8 */ -.endr - /* Exceptions */ - j EV_MachineCheck /* 0x100, Fatal Machine check (0x20) */ - j EV_TLBMissI /* 0x108, Intruction TLB miss (0x21) */ - j EV_TLBMissD /* 0x110, Data TLB miss (0x22) */ - j EV_TLBProtV /* 0x118, Protection Violation (0x23) - or Misaligned Access */ - j EV_PrivilegeV /* 0x120, Privilege Violation (0x24) */ - j EV_Trap /* 0x128, Trap exception (0x25) */ - j EV_Extension /* 0x130, Extn Intruction Excp (0x26) */ - -.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/cpu/arcv1/Makefile b/arch/arc/cpu/arcv1/Makefile new file mode 100644 index 00000000000..3704ebeeaef --- /dev/null +++ b/arch/arc/cpu/arcv1/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += start.o diff --git a/arch/arc/cpu/arcv1/config.mk b/arch/arc/cpu/arcv1/config.mk new file mode 100644 index 00000000000..3206ff47e39 --- /dev/null +++ b/arch/arc/cpu/arcv1/config.mk @@ -0,0 +1,7 @@ +# +# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +PLATFORM_CPPFLAGS += -mA7 diff --git a/arch/arc/cpu/arcv1/start.S b/arch/arc/cpu/arcv1/start.S new file mode 100644 index 00000000000..01cfba49339 --- /dev/null +++ b/arch/arc/cpu/arcv1/start.S @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2013-2014 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 we read %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, "ax",@progbits +.align 4 +_ivt: + /* Critical system events */ + j _start /* 0 - 0x000 */ + j memory_error /* 1 - 0x008 */ + j instruction_error /* 2 - 0x010 */ + + /* Device interrupts */ +.rept 29 + j interrupt_handler /* 3:31 - 0x018:0xF8 */ +.endr + /* Exceptions */ + j EV_MachineCheck /* 0x100, Fatal Machine check (0x20) */ + j EV_TLBMissI /* 0x108, Intruction TLB miss (0x21) */ + j EV_TLBMissD /* 0x110, Data TLB miss (0x22) */ + j EV_TLBProtV /* 0x118, Protection Violation (0x23) + or Misaligned Access */ + j EV_PrivilegeV /* 0x120, Privilege Violation (0x24) */ + j EV_Trap /* 0x128, Trap exception (0x25) */ + j EV_Extension /* 0x130, Extn Intruction Excp (0x26) */ + +.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] -- cgit v1.3.1