diff options
author | Franck Jullien <franck.jullien@gmail.com> | 2011-12-20 23:11:36 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-01-02 12:50:56 +0100 |
commit | 6fe9ee8eb4f85ff85b17024e25171d36c3f062ac (patch) | |
tree | 7d96bfb12aab32359d09b58eaedf591900138cc4 /arch/openrisc/cpu | |
parent | 6449b9cff5f330de3ce0d2ebeda9aafb40877ac7 (diff) | |
download | barebox-6fe9ee8eb4f85ff85b17024e25171d36c3f062ac.tar.gz barebox-6fe9ee8eb4f85ff85b17024e25171d36c3f062ac.tar.xz |
Add OpenRISC arch
OpenRISC is the original flagship project of the OpenCores community.
This project aims to develop a series of general purpose open source
RISC CPU architectures.
A team from OpenCores provided the first implementation, the OpenRISC
1200, written in the Verilog hardware description language.
Even though I should have created an mach-or1200 directory, it is not
necessary for now. The OpenRISC 1200 CPU is the only one available and
it will be for some time.
Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/openrisc/cpu')
-rw-r--r-- | arch/openrisc/cpu/Makefile | 5 | ||||
-rw-r--r-- | arch/openrisc/cpu/barebox.lds.S | 98 | ||||
-rw-r--r-- | arch/openrisc/cpu/cache.c | 154 | ||||
-rw-r--r-- | arch/openrisc/cpu/cpu.c | 43 | ||||
-rw-r--r-- | arch/openrisc/cpu/exceptions.c | 84 | ||||
-rw-r--r-- | arch/openrisc/cpu/start.S | 335 |
6 files changed, 719 insertions, 0 deletions
diff --git a/arch/openrisc/cpu/Makefile b/arch/openrisc/cpu/Makefile new file mode 100644 index 0000000000..1cd7506003 --- /dev/null +++ b/arch/openrisc/cpu/Makefile @@ -0,0 +1,5 @@ +obj-y += start.o +obj-y += cpu.o +obj-y += exceptions.o +obj-y += cache.o +extra-y += barebox.lds diff --git a/arch/openrisc/cpu/barebox.lds.S b/arch/openrisc/cpu/barebox.lds.S new file mode 100644 index 0000000000..d3e02a6ac0 --- /dev/null +++ b/arch/openrisc/cpu/barebox.lds.S @@ -0,0 +1,98 @@ +/* + * barebox - barebox.lds.S + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm-generic/barebox.lds.h> + +OUTPUT_FORMAT("elf32-or32", "elf32-or32", "elf32-or32") +__DYNAMIC = 0; + +MEMORY +{ + vectors : ORIGIN = 0, LENGTH = 0x2000 + ram : ORIGIN = TEXT_BASE, + LENGTH = BAREBOX_RESERVED_SIZE +} + +SECTIONS +{ + .vectors : + { + *(.vectors) + } > vectors + + . = ALIGN(4); + __start = .; + .text : AT (__start) { + _stext = .; + *(.text) + _etext = .; + *(.lit) + *(.shdata) + _endtext = .; + } > ram + + . = ALIGN(4); + .rodata : { + *(.rodata); + *(.rodata.*) + } > ram + + . = ALIGN(4); + . = .; + __barebox_cmd_start = .; + .barebox_cmd : { BAREBOX_CMDS } > ram + __barebox_cmd_end = .; + + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } > ram + __barebox_magicvar_end = .; + + __barebox_initcalls_start = .; + .barebox_initcalls : { INITCALLS } > ram + __barebox_initcalls_end = .; + + ___usymtab_start = .; + __usymtab : { BAREBOX_SYMS } > ram + ___usymtab_end = .; + + __etext = .; /* End of text and rodata section */ + + . = ALIGN(4); + .data : { + sdata = .; + _sdata = .; + *(.data) + edata = .; + _edata = .; + } > ram + + . = ALIGN(4); + .bss : + { + __bss_start = .; + _bss_start = .; + *(.shbss) + *(.bss) + *(COMMON) + _bss_end = .; + __bss_stop = .; + } > ram + __end = .; +} diff --git a/arch/openrisc/cpu/cache.c b/arch/openrisc/cpu/cache.c new file mode 100644 index 0000000000..81a0d13938 --- /dev/null +++ b/arch/openrisc/cpu/cache.c @@ -0,0 +1,154 @@ +/* + * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> + * (C) Copyright 2011, Julius Baxter <julius@opencores.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <init.h> +#include <asm/system.h> + +void flush_dcache_range(unsigned long addr, unsigned long stop) +{ + ulong block_size = (mfspr(SPR_DCCFGR) & SPR_DCCFGR_CBS) ? 32 : 16; + + while (addr < stop) { + mtspr(SPR_DCBFR, addr); + addr += block_size; + } +} + +void invalidate_dcache_range(unsigned long addr, unsigned long stop) +{ + ulong block_size = (mfspr(SPR_DCCFGR) & SPR_DCCFGR_CBS) ? 32 : 16; + + while (addr < stop) { + mtspr(SPR_DCBIR, addr); + addr += block_size; + } +} + +static void invalidate_icache_range(unsigned long addr, unsigned long stop) +{ + ulong block_size = (mfspr(SPR_ICCFGR) & SPR_ICCFGR_CBS) ? 32 : 16; + + while (addr < stop) { + mtspr(SPR_ICBIR, addr); + addr += block_size; + } +} + +void flush_cache(unsigned long addr, unsigned long size) +{ + flush_dcache_range(addr, addr + size); + invalidate_icache_range(addr, addr + size); +} + +int icache_status(void) +{ + return mfspr(SPR_SR) & SPR_SR_ICE; +} + +int checkicache(void) +{ + unsigned long iccfgr; + unsigned long cache_set_size; + unsigned long cache_ways; + unsigned long cache_block_size; + + iccfgr = mfspr(SPR_ICCFGR); + cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW); + cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3); + cache_block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16; + + return cache_set_size * cache_ways * cache_block_size; +} + +int dcache_status(void) +{ + return mfspr(SPR_SR) & SPR_SR_DCE; +} + +int checkdcache(void) +{ + unsigned long dccfgr; + unsigned long cache_set_size; + unsigned long cache_ways; + unsigned long cache_block_size; + + dccfgr = mfspr(SPR_DCCFGR); + cache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW); + cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3); + cache_block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16; + + return cache_set_size * cache_ways * cache_block_size; +} + +void dcache_enable(void) +{ + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_DCE); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); +} + +void dcache_disable(void) +{ + mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_DCE); +} + +void icache_enable(void) +{ + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_ICE); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); + asm volatile("l.nop"); +} + +void icache_disable(void) +{ + mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_ICE); +} + +int cache_init(void) +{ + if (mfspr(SPR_UPR) & SPR_UPR_ICP) { + icache_disable(); + invalidate_icache_range(0, checkicache()); + icache_enable(); + } + + if (mfspr(SPR_UPR) & SPR_UPR_DCP) { + dcache_disable(); + invalidate_dcache_range(0, checkdcache()); + dcache_enable(); + } + + return 0; +} + +core_initcall(cache_init); diff --git a/arch/openrisc/cpu/cpu.c b/arch/openrisc/cpu/cpu.c new file mode 100644 index 0000000000..48f5d032a5 --- /dev/null +++ b/arch/openrisc/cpu/cpu.c @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> + * (C) Copyright 2011, Julius Baxter <julius@opencores.org> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <init.h> +#include <asm/system.h> +#include <asm/openrisc_exc.h> + +int cleanup_before_linux(void) +{ + return 0; +} + +extern void __reset(void); + +void __noreturn reset_cpu(ulong ignored) +{ + __reset(); + /* not reached, __reset does not return */ + + /* Not reached */ + while (1); +} diff --git a/arch/openrisc/cpu/exceptions.c b/arch/openrisc/cpu/exceptions.c new file mode 100644 index 0000000000..a979258f80 --- /dev/null +++ b/arch/openrisc/cpu/exceptions.c @@ -0,0 +1,84 @@ +/* + * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> + * (C) Copyright 2011, Julius Baxter <julius@opencores.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/system.h> + +static const char * const excp_table[] = { + "Unknown exception", + "Reset", + "Bus Error", + "Data Page Fault", + "Instruction Page Fault", + "Tick Timer", + "Alignment", + "Illegal Instruction", + "External Interrupt", + "D-TLB Miss", + "I-TLB Miss", + "Range", + "System Call", + "Floating Point", + "Trap", +}; + +static void (*handlers[32])(void); + +void exception_install_handler(int exception, void (*handler)(void)) +{ + if (exception < 0 || exception > 31) + return; + + handlers[exception] = handler; +} + +void exception_free_handler(int exception) +{ + if (exception < 0 || exception > 31) + return; + + handlers[exception] = 0; +} + +static void exception_hang(int vect) +{ + printf("Unhandled exception at 0x%x ", vect & 0xff00); + + vect = ((vect >> 8) & 0xff); + if (vect < ARRAY_SIZE(excp_table)) + printf("(%s)\n", excp_table[vect]); + else + printf("(%s)\n", excp_table[0]); + + printf("EPCR: 0x%08lx\n", mfspr(SPR_EPCR_BASE)); + printf("EEAR: 0x%08lx\n", mfspr(SPR_EEAR_BASE)); + printf("ESR: 0x%08lx\n", mfspr(SPR_ESR_BASE)); + hang(); +} + +void exception_handler(int vect) +{ + int exception = vect >> 8; + + if (handlers[exception]) + handlers[exception](); + else + exception_hang(vect); +} diff --git a/arch/openrisc/cpu/start.S b/arch/openrisc/cpu/start.S new file mode 100644 index 0000000000..056f116b06 --- /dev/null +++ b/arch/openrisc/cpu/start.S @@ -0,0 +1,335 @@ +/* + * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> + * (C) Copyright 2011, Julius Baxter <julius@opencores.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <asm-generic/memory_layout.h> +#include <asm/spr-defs.h> + +#define EXCEPTION_STACK_SIZE (128+128) + +#define HANDLE_EXCEPTION \ + l.addi r1, r1, -EXCEPTION_STACK_SIZE ;\ + l.sw 0x1c(r1), r9 ;\ + l.jal _exception_handler ;\ + l.nop ;\ + l.lwz r9, 0x1c(r1) ;\ + l.addi r1, r1, EXCEPTION_STACK_SIZE ;\ + l.rfe ;\ + l.nop + + .section .vectors, "ax" + .global __reset + + /* reset */ + .org 0x100 +__reset: + /* there is no guarantee r0 is hardwired to zero, clear it here */ + l.andi r0, r0, 0 + /* reset stack and frame pointers */ + l.andi r1, r0, 0 + l.andi r2, r0, 0 + + /* set supervisor mode */ + l.ori r3,r0,SPR_SR_SM + l.mtspr r0,r3,SPR_SR + + /* Relocate barebox */ + l.movhi r3,hi(__start) /* source start address */ + l.ori r3,r3,lo(__start) + l.movhi r4,hi(_stext) /* dest start address */ + l.ori r4,r4,lo(_stext) + l.movhi r5,hi(__end) /* dest end address */ + l.ori r5,r5,lo(__end) + +.L_reloc: + l.lwz r6,0(r3) + l.sw 0(r4),r6 + l.addi r3,r3,4 + l.sfltu r4,r5 + l.bf .L_reloc + l.addi r4,r4,4 /*delay slot */ + +#ifdef CONFIG_SYS_RELOCATE_VECTORS + /* Relocate vectors from 0xf0000000 to 0x00000000 */ + l.movhi r4, 0xf000 /* source */ + l.movhi r5, 0 /* destination */ + l.addi r6, r5, CONFIG_SYS_VECTORS_LEN /* length */ +.L_relocvectors: + l.lwz r7, 0(r4) + l.sw 0(r5), r7 + l.addi r5, r5, 4 + l.sfeq r5,r6 + l.bnf .L_relocvectors + l.addi r4,r4, 4 +#endif + + l.j _start + l.nop + + /* bus error */ + .org 0x200 + HANDLE_EXCEPTION + + /* data page fault */ + .org 0x300 + HANDLE_EXCEPTION + + /* instruction page fault */ + .org 0x400 + HANDLE_EXCEPTION + + /* tick timer */ + .org 0x500 + HANDLE_EXCEPTION + + /* alignment */ + .org 0x600 + HANDLE_EXCEPTION + + /* illegal instruction */ + .org 0x700 + HANDLE_EXCEPTION + + /* external interrupt */ + .org 0x800 + HANDLE_EXCEPTION + + /* D-TLB miss */ + .org 0x900 + HANDLE_EXCEPTION + + /* I-TLB miss */ + .org 0xa00 + HANDLE_EXCEPTION + + /* range */ + .org 0xb00 + HANDLE_EXCEPTION + + /* system call */ + .org 0xc00 + HANDLE_EXCEPTION + + /* floating point */ + .org 0xd00 + HANDLE_EXCEPTION + + /* trap */ + .org 0xe00 + HANDLE_EXCEPTION + + /* reserved */ + .org 0xf00 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1100 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1200 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1300 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1400 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1500 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1600 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1700 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1800 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1900 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1a00 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1b00 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1c00 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1d00 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1e00 + HANDLE_EXCEPTION + + /* reserved */ + .org 0x1f00 + HANDLE_EXCEPTION + + /* Startup routine */ + .text + .global _start +_start: + /* Init stack and frame pointers */ + l.movhi r1, hi(STACK_BASE) + l.ori r1, r1, lo(STACK_BASE) + l.or r2, r0, r1 + + /* clear BSS segments */ + l.movhi r4, hi(_bss_start) + l.ori r4, r4, lo(_bss_start) + l.movhi r5, hi(_bss_end) + l.ori r5, r5, lo(_bss_end) +.L_clear_bss: + l.sw 0(r4), r0 + l.sfltu r4,r5 + l.bf .L_clear_bss + l.addi r4,r4,4 + + /* Reset registers before jumping to board_init */ + l.andi r3, r0, 0 + l.andi r4, r0, 0 + l.andi r5, r0, 0 + l.andi r6, r0, 0 + l.andi r7, r0, 0 + l.andi r8, r0, 0 + l.andi r9, r0, 0 + l.andi r10, r0, 0 + l.andi r11, r0, 0 + l.andi r12, r0, 0 + l.andi r13, r0, 0 + l.andi r14, r0, 0 + l.andi r15, r0, 0 + l.andi r17, r0, 0 + l.andi r18, r0, 0 + l.andi r19, r0, 0 + l.andi r20, r0, 0 + l.andi r21, r0, 0 + l.andi r22, r0, 0 + l.andi r23, r0, 0 + l.andi r24, r0, 0 + l.andi r25, r0, 0 + l.andi r26, r0, 0 + l.andi r27, r0, 0 + l.andi r28, r0, 0 + l.andi r29, r0, 0 + l.andi r30, r0, 0 + l.andi r31, r0, 0 + + l.j start_barebox + l.nop + + .size _start, .-_start + +/* + * Store state onto stack and call the real exception handler + */ + .section .text + .extern exception_handler + .type _exception_handler,@function + +_exception_handler: + /* Store state (r9 already saved)*/ + l.sw 0x00(r1), r2 + l.sw 0x04(r1), r3 + l.sw 0x08(r1), r4 + l.sw 0x0c(r1), r5 + l.sw 0x10(r1), r6 + l.sw 0x14(r1), r7 + l.sw 0x18(r1), r8 + l.sw 0x20(r1), r10 + l.sw 0x24(r1), r11 + l.sw 0x28(r1), r12 + l.sw 0x2c(r1), r13 + l.sw 0x30(r1), r14 + l.sw 0x34(r1), r15 + l.sw 0x38(r1), r16 + l.sw 0x3c(r1), r17 + l.sw 0x40(r1), r18 + l.sw 0x44(r1), r19 + l.sw 0x48(r1), r20 + l.sw 0x4c(r1), r21 + l.sw 0x50(r1), r22 + l.sw 0x54(r1), r23 + l.sw 0x58(r1), r24 + l.sw 0x5c(r1), r25 + l.sw 0x60(r1), r26 + l.sw 0x64(r1), r27 + l.sw 0x68(r1), r28 + l.sw 0x6c(r1), r29 + l.sw 0x70(r1), r30 + l.sw 0x74(r1), r31 + + /* Save return address */ + l.or r14, r0, r9 + /* Call exception handler with the link address as argument */ + l.jal exception_handler + l.or r3, r0, r14 + /* Load return address */ + l.or r9, r0, r14 + + /* Restore state */ + l.lwz r2, 0x00(r1) + l.lwz r3, 0x04(r1) + l.lwz r4, 0x08(r1) + l.lwz r5, 0x0c(r1) + l.lwz r6, 0x10(r1) + l.lwz r7, 0x14(r1) + l.lwz r8, 0x18(r1) + l.lwz r10, 0x20(r1) + l.lwz r11, 0x24(r1) + l.lwz r12, 0x28(r1) + l.lwz r13, 0x2c(r1) + l.lwz r14, 0x30(r1) + l.lwz r15, 0x34(r1) + l.lwz r16, 0x38(r1) + l.lwz r17, 0x3c(r1) + l.lwz r18, 0x40(r1) + l.lwz r19, 0x44(r1) + l.lwz r20, 0x48(r1) + l.lwz r21, 0x4c(r1) + l.lwz r22, 0x50(r1) + l.lwz r23, 0x54(r1) + l.lwz r24, 0x58(r1) + l.lwz r25, 0x5c(r1) + l.lwz r26, 0x60(r1) + l.lwz r27, 0x64(r1) + l.lwz r28, 0x68(r1) + l.lwz r29, 0x6c(r1) + l.lwz r30, 0x70(r1) + l.lwz r31, 0x74(r1) + l.jr r9 + l.nop |