From: Alexey Brodkin Date: Sat, 27 Dec 2014 23:42:12 +0000 (+0300) Subject: arc: move common sources in library X-Git-Tag: v2015.04-rc1~68^2~2 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=660d5f0d495197b4057bc1b3bdd201e500b03f1a;p=u-boot 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 --- diff --git a/arch/arc/cpu/arc700/Makefile b/arch/arc/cpu/arc700/Makefile index 021e3a2b5d..3704ebeeae 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 fa19a13b7e..0000000000 --- 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 50634b860f..0000000000 --- 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 d7cab3bb40..0000000000 --- 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 98ebf1d445..0000000000 --- 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 a0acbbc01a..0000000000 --- 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 7675f855d5..bae44199a4 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 0000000000..fa19a13b7e --- /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 0000000000..50634b860f --- /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 0000000000..d7cab3bb40 --- /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 0000000000..98ebf1d445 --- /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 0000000000..a0acbbc01a --- /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); +}