config SYS_ARCH
default "arc"
+config SYS_CPU
+ default "arcv1"
+
choice
prompt "Target select"
# 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/
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
+++ /dev/null
-#
-# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
-#
-# 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 += timer.o
+++ /dev/null
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <config.h>
-#include <asm/arcregs.h>
-
-/* 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)
-
-int icache_status(void)
-{
- return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) !=
- IC_CTRL_CACHE_DISABLE;
-}
-
-void icache_enable(void)
-{
- write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) &
- ~IC_CTRL_CACHE_DISABLE);
-}
-
-void icache_disable(void)
-{
- 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)
-{
- return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) !=
- DC_CTRL_CACHE_DISABLE;
-}
-
-void dcache_enable(void)
-{
- 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)
-{
- write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) |
- DC_CTRL_CACHE_DISABLE);
-}
-
-void flush_dcache_all(void)
-{
- /* 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);
-}
+++ /dev/null
-#
-# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
-#
-# SPDX-License-Identifier: GPL-2.0+
-#
-
-PLATFORM_CPPFLAGS += -mA7
+++ /dev/null
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arcregs.h>
-#include <asm/cache.h>
-
-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;
-}
+++ /dev/null
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/arcregs.h>
-#include <asm/ptrace.h>
-
-/* 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("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);
-}
+++ /dev/null
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <command.h>
-#include <common.h>
-
-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;
-}
+++ /dev/null
-/*
- * Copyright (C) 2013-2014 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
-
- st %r0, [%sp]
- lr %r0, [%ecr]
- st %r0, [%sp, 8] /* ECR */
- st %sp, [%sp, 4]
-
- 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
-
-.align 4
-.globl _start
-_start:
- /* Critical system events */
- j reset /* 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) */
-
-memory_error:
- SAVE_ALL_SYS
- lr %r0, [%efa]
- mov %r1, %sp
- j do_memory_error
-
-instruction_error:
- SAVE_ALL_SYS
- lr %r0, [%efa]
- 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
- lr %r0, [%efa]
- 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
- lr %r0, [%efa]
- 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
-
-
-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)
- *
- * 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]
+++ /dev/null
-/*
- * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <asm/arcregs.h>
-
-#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);
-}
+++ /dev/null
-/*
- * 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)
- CPUDIR/start.o (.text*)
- *(.text*)
- }
-
- . = ALIGN(4);
- .text_end :
- {
- *(.__text_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)
- }
-}
--- /dev/null
+#
+# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += start.o
--- /dev/null
+#
+# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+PLATFORM_CPPFLAGS += -mA7
--- /dev/null
+/*
+ * Copyright (C) 2013-2014 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 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]
--- /dev/null
+/*
+ * 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)
+ }
+}
#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 */
#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 */
#include <asm-generic/sections.h>
extern ulong __text_end;
+extern ulong __ivt_start;
+extern ulong __ivt_end;
+extern ulong __image_copy_start;
#endif /* __ASM_ARC_SECTIONS_H */
# 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
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
--- /dev/null
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/arcregs.h>
+
+/* 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);
+}
--- /dev/null
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arcregs.h>
+#include <asm/cache.h>
+
+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;
+}
--- /dev/null
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arcregs.h>
+#include <asm/ptrace.h>
+
+/* 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);
+}
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 */
#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
- /* 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 */
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));
- } 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;
--- /dev/null
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <command.h>
+#include <common.h>
+
+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;
+}
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")));
--- /dev/null
+/*
+ * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/arcregs.h>
+
+#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);
+}
if TARGET_ARCANGEL4
-config SYS_CPU
- default "arc700"
-
config SYS_VENDOR
default "synopsys"
if TARGET_ARCANGEL4_BE
-config SYS_CPU
- default "arc700"
-
config SYS_VENDOR
default "synopsys"
if TARGET_AXS101
-config SYS_CPU
- default "arc700"
-
config SYS_BOARD
default "axs101"