[U-Boot] [PATCH 3/9] openrisc: Add cpu files
Marek Vasut
marek.vasut at gmail.com
Mon Nov 21 23:50:17 CET 2011
> Signed-off-by: Stefan Kristiansson <stefan.kristiansson at saunalahti.fi>
> ---
> arch/openrisc/config.mk | 27 ++++
> arch/openrisc/cpu/Makefile | 47 ++++++
> arch/openrisc/cpu/cache.c | 157 +++++++++++++++++++
> arch/openrisc/cpu/cpu.c | 157 +++++++++++++++++++
> arch/openrisc/cpu/exceptions.c | 109 +++++++++++++
> arch/openrisc/cpu/interrupts.c | 120 ++++++++++++++
> arch/openrisc/cpu/start.S | 335
> ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 952
> insertions(+), 0 deletions(-)
> create mode 100644 arch/openrisc/config.mk
> create mode 100644 arch/openrisc/cpu/Makefile
> create mode 100644 arch/openrisc/cpu/cache.c
> create mode 100644 arch/openrisc/cpu/cpu.c
> create mode 100644 arch/openrisc/cpu/exceptions.c
> create mode 100644 arch/openrisc/cpu/interrupts.c
> create mode 100644 arch/openrisc/cpu/start.S
>
> diff --git a/arch/openrisc/config.mk b/arch/openrisc/config.mk
> new file mode 100644
> index 0000000..bea3d12
> --- /dev/null
> +++ b/arch/openrisc/config.mk
> @@ -0,0 +1,27 @@
> +#
> +# (C) Copyright 2011
> +# Julius Baxter <julius at 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
> +#
> +
> +CROSS_COMPILE ?= or32-elf-
> +
> +# r10 used for global object pointer, already set in OR32 GCC but just to
> be +# clear
> +PLATFORM_CPPFLAGS += -DCONFIG_OPENRISC -D__OR1K__ -ffixed-r10
> +
> +CONFIG_STANDALONE_LOAD_ADDR ?= 0x40000
> \ No newline at end of file
> diff --git a/arch/openrisc/cpu/Makefile b/arch/openrisc/cpu/Makefile
> new file mode 100644
> index 0000000..b3b1a24
> --- /dev/null
> +++ b/arch/openrisc/cpu/Makefile
> @@ -0,0 +1,47 @@
> +#
> +# (C) Copyright 2011
> +# Julius Baxter <julius at 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 $(TOPDIR)/config.mk
> +
> +LIB = $(obj)lib$(CPU).o
> +
> +START = start.o
> +COBJS-y = cache.o cpu.o exceptions.o interrupts.o
> +
> +SRCS := $(START:.o=.S) $(COBJS-y:.o=.c)
> +OBJS := $(addprefix $(obj),$(COBJS-y))
> +START := $(addprefix $(obj),$(START))
> +
> +all: $(obj).depend $(START) $(LIB)
> +
> +$(LIB): $(OBJS)
> + $(call cmd_link_o_target, $(OBJS))
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/arch/openrisc/cpu/cache.c b/arch/openrisc/cpu/cache.c
> new file mode 100644
> index 0000000..9dd627f
> --- /dev/null
> +++ b/arch/openrisc/cpu/cache.c
> @@ -0,0 +1,157 @@
> +/*
> + * (C) Copyright 2011, Stefan Kristiansson
> <stefan.kristiansson at saunalahti.fi> + * (C) Copyright 2011, Julius Baxter
> <julius at 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 <asm/system.h>
> +#include <common.h>
> +
> +/* cache line size can be either 16 or 32 bytes */
> +static inline unsigned long get_linesize(void)
> +{
> + return (mfspr(SPR_ICCFGR) & SPR_ICCFGR_CBS) ? 32 : 16;
What's mfspr ... if it's some register, then maybe mfspr_read() ?
> +}
> +
> +void flush_dcache_range(unsigned long addr, unsigned long stop)
> +{
> + unsigned long linesize = get_linesize();
> +
> + while (addr < stop) {
> + mtspr(SPR_DCBFR, addr);
> + addr += linesize;
> + }
> +}
> +
> +void invalidate_dcache_range(unsigned long addr, unsigned long stop)
> +{
> + unsigned long linesize = get_linesize();
> +
> + while (addr < stop) {
> + mtspr(SPR_DCBIR, addr);
> + addr += linesize;
> + }
> +}
> +
> +static void invalidate_icache_range(unsigned long addr, unsigned long
> stop) +{
> + unsigned long linesize = get_linesize();
> +
> + while (addr < stop) {
> + mtspr(SPR_ICBIR, addr);
> + addr += linesize;
> + }
> +}
> +
> +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("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("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("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
> + asm("l.nop");
Hm, maybe mtspr and those nops together need some ordering ?
> +}
> +
> +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;
> +}
> diff --git a/arch/openrisc/cpu/cpu.c b/arch/openrisc/cpu/cpu.c
> new file mode 100644
> index 0000000..3b69285
> --- /dev/null
> +++ b/arch/openrisc/cpu/cpu.c
> @@ -0,0 +1,157 @@
> +/*
> + * (C) Copyright 2011, Stefan Kristiansson
> <stefan.kristiansson at saunalahti.fi> + * (C) Copyright 2011, Julius Baxter
> <julius at 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 <asm/system.h>
> +#include <asm/openrisc_exc.h>
> +#include <common.h>
> +
> +static volatile int illegal_instruction;
> +
> +void illegal_instruction_handler(void)
> +{
> + ulong *epcr = (ulong *)mfspr(SPR_EPCR_BASE);
> +
> + /* skip over the illegal instruction */
> + mtspr(SPR_EPCR_BASE, (ulong)(++epcr));
> + illegal_instruction = 1;
> +}
> +
> +void checkinstructions(void)
> +{
> + ulong ra = 1, rb = 1, rc;
> +
> + exception_install_handler(EXC_ILLEGAL_INSTR,
> + illegal_instruction_handler);
> +
> + illegal_instruction = 0;
> + asm volatile("l.mul %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
> + printf(" Hardware multiplier: %s\n",
> + illegal_instruction ? "no" : "yes");
> +
> + illegal_instruction = 0;
> + asm volatile("l.div %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
> + printf(" Hardware divider: %s\n",
> + illegal_instruction ? "no" : "yes");
> +
> + exception_free_handler(EXC_ILLEGAL_INSTR);
> +
> +}
> +
> +int checkcpu(void)
> +{
> + ulong upr = mfspr(SPR_UPR);
> + ulong vr = mfspr(SPR_VR);
> + ulong iccfgr = mfspr(SPR_ICCFGR);
> + ulong dccfgr = mfspr(SPR_DCCFGR);
> + ulong immucfgr = mfspr(SPR_IMMUCFGR);
> + ulong dmmucfgr = mfspr(SPR_DMMUCFGR);
> + ulong cpucfgr = mfspr(SPR_CPUCFGR);
> + uint ver = (vr & SPR_VR_VER) >> 24;
> + uint rev = vr & SPR_VR_REV;
> + uint block_size;
> + uint ways;
> + uint sets;
> +
> + printf("CPU: OpenRISC-%x00 (rev %d) @ %d MHz\n",
> + ver, rev, (CONFIG_SYS_CLK_FREQ / 1000000));
The CPU won't tell you it's speed ?
> +
> + if (upr & SPR_UPR_DCP) {
> + block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16;
> + ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
> + printf(" D-Cache: %d bytes, %d bytes/line, %d way(s)\n",
> + checkdcache(), block_size, ways);
> + } else {
> + printf(" D-Cache: no\n");
> + }
> +
> + if (upr & SPR_UPR_ICP) {
> + block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16;
> + ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
> + printf(" I-Cache: %d bytes, %d bytes/line, %d way(s)\n",
> + checkicache(), block_size, ways);
> + } else {
> + printf(" I-Cache: no\n");
> + }
> +
> + if (upr & SPR_UPR_DMP) {
> + sets = 1 << ((dmmucfgr & SPR_DMMUCFGR_NTS) >> 2);
> + ways = (dmmucfgr & SPR_DMMUCFGR_NTW) + 1;
> + printf(" DMMU: %d sets, %d way(s)\n",
> + sets, ways);
> + } else {
> + printf(" DMMU: no\n");
> + }
> +
> + if (upr & SPR_UPR_IMP) {
> + sets = 1 << ((immucfgr & SPR_IMMUCFGR_NTS) >> 2);
> + ways = (immucfgr & SPR_IMMUCFGR_NTW) + 1;
> + printf(" IMMU: %d sets, %d way(s)\n",
> + sets, ways);
> + } else {
> + printf(" IMMU: no\n");
> + }
> +
> + printf(" MAC unit: %s\n",
> + (upr & SPR_UPR_MP) ? "yes" : "no");
> + printf(" Debug unit: %s\n",
> + (upr & SPR_UPR_DUP) ? "yes" : "no");
> + printf(" Performance counters: %s\n",
> + (upr & SPR_UPR_PCUP) ? "yes" : "no");
> + printf(" Power management: %s\n",
> + (upr & SPR_UPR_PMP) ? "yes" : "no");
> + printf(" Interrupt controller: %s\n",
> + (upr & SPR_UPR_PICP) ? "yes" : "no");
> + printf(" Timer: %s\n",
> + (upr & SPR_UPR_TTP) ? "yes" : "no");
> + printf(" Custom unit(s): %s\n",
> + (upr & SPR_UPR_CUP) ? "yes" : "no");
> +
> + printf(" Supported instructions:\n");
> + printf(" ORBIS32: %s\n",
> + (cpucfgr & SPR_CPUCFGR_OB32S) ? "yes" : "no");
> + printf(" ORBIS64: %s\n",
> + (cpucfgr & SPR_CPUCFGR_OB64S) ? "yes" : "no");
> + printf(" ORFPX32: %s\n",
> + (cpucfgr & SPR_CPUCFGR_OF32S) ? "yes" : "no");
> + printf(" ORFPX64: %s\n",
> + (cpucfgr & SPR_CPUCFGR_OF64S) ? "yes" : "no");
> +
> + checkinstructions();
> +
> + return 0;
> +}
> +
> +int cleanup_before_linux(void)
> +{
> + disable_interrupts();
> + return 0;
> +}
> +
> +extern void __reset(void);
> +
> +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> + disable_interrupts();
> + __reset();
> + return 0;
> +}
> diff --git a/arch/openrisc/cpu/exceptions.c
> b/arch/openrisc/cpu/exceptions.c new file mode 100644
> index 0000000..06935be
> --- /dev/null
> +++ b/arch/openrisc/cpu/exceptions.c
> @@ -0,0 +1,109 @@
> +/*
> + * (C) Copyright 2011, Stefan Kristiansson
> <stefan.kristiansson at saunalahti.fi> + * (C) Copyright 2011, Julius Baxter
> <julius at 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 <asm/system.h>
> +#include <common.h>
> +#include <stdio_dev.h>
> +
> +extern void hang(void);
> +
> +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);
> + switch (vect & 0xff00) {
> + case 0x100:
> + puts("(Reset)\n");
> + break;
> + case 0x200:
> + puts("(Bus Error)\n");
> + break;
> + case 0x300:
> + puts("(Data Page Fault)\n");
> + break;
> + case 0x400:
> + puts("(Instruction Page Fault)\n");
> + break;
> + case 0x500:
> + puts("(Tick Timer)\n");
> + break;
> + case 0x600:
> + puts("(Alignment)\n");
> + break;
> + case 0x700:
> + puts("(Illegal Instruction)\n");
> + break;
> + case 0x800:
> + puts("(External Interrupt)\n");
> + break;
> + case 0x900:
> + puts("(D-TLB Miss)\n");
> + break;
> + case 0xa00:
> + puts("(I-TLB Miss)\n");
> + break;
> + case 0xb00:
> + puts("(Range)\n");
> + break;
> + case 0xc00:
> + puts("(System Call)\n");
> + break;
> + case 0xd00:
> + puts("(Floating Point)\n");
> + break;
> + case 0xe00:
> + puts("(Trap)\n");
> + break;
> + default:
> + puts("(Unknown exception)\n");
> + break;
> + }
> + 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/interrupts.c
> b/arch/openrisc/cpu/interrupts.c new file mode 100644
> index 0000000..62d266a
> --- /dev/null
> +++ b/arch/openrisc/cpu/interrupts.c
> @@ -0,0 +1,120 @@
> +/*
> + * (C) Copyright 2011, Stefan Kristiansson
> <stefan.kristiansson at saunalahti.fi> + * (C) Copyright 2011, Julius Baxter
> <julius at 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 <asm/types.h>
> +#include <asm/ptrace.h>
> +#include <asm/system.h>
> +#include <asm/openrisc_exc.h>
> +#include <common.h>
> +
> +struct irq_action {
> + interrupt_handler_t *handler;
> + void *arg;
> + int count;
> +};
> +
> +static struct irq_action handlers[32];
> +
> +void interrupt_handler(void)
> +{
> + int irq;
> +
> + while ((irq = ffs(mfspr(SPR_PICSR)))) {
> + if (handlers[--irq].handler) {
> + handlers[irq].handler(handlers[irq].arg);
> + handlers[irq].count++;
> + } else {
> + /* disable the interrupt */
> + mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1 << irq));
> + printf("Unhandled interrupt: %d\n", irq);
> + }
> + /* clear the interrupt */
> + mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1 << irq));
> + }
> +}
> +
> +int interrupt_init(void)
> +{
> + /* install handler for external interrupt exception */
> + exception_install_handler(EXC_EXT_IRQ, interrupt_handler);
> + /* Enable interrupts in supervisor register */
> + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
> +
> + return 0;
> +}
> +
> +void enable_interrupts(void)
> +{
> + /* Set interrupt enable bit in supervisor register */
> + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
> + /* Enable timer exception */
> + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_TEE);
> +}
> +
> +int disable_interrupts(void)
> +{
> + /* Clear interrupt enable bit in supervisor register */
> + mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE);
> + /* Disable timer exception */
> + mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_TEE);
> + return 0;
> +}
> +
> +void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
> +{
> + if (irq < 0 || irq > 31)
> + return;
> +
> + handlers[irq].handler = handler;
> + handlers[irq].arg = arg;
> +}
> +
> +void irq_free_handler(int irq)
> +{
> + if (irq < 0 || irq > 31)
> + return;
> +
> + handlers[irq].handler = 0;
> + handlers[irq].arg = 0;
> +}
> +
> +#if defined(CONFIG_CMD_IRQ)
> +int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> + int i;
> +
> + printf("\nInterrupt-Information:\n\n");
> + printf("Nr Routine Arg Count\n");
> + printf("-----------------------------\n");
> +
> + for (i = 0; i < 32; i++) {
> + if (handlers[i].handler) {
> + printf("%02d %08lx %08lx %d\n",
> + i,
> + (ulong)handlers[i].handler,
> + (ulong)handlers[i].arg,
> + handlers[i].count);
> + }
> + }
> + printf("\n");
> +
> + return 0;
> +}
> +#endif
> diff --git a/arch/openrisc/cpu/start.S b/arch/openrisc/cpu/start.S
> new file mode 100644
> index 0000000..03e6a8e
> --- /dev/null
> +++ b/arch/openrisc/cpu/start.S
> @@ -0,0 +1,335 @@
> +/*
> + * (C) Copyright 2011, Stefan Kristiansson
> <stefan.kristiansson at saunalahti.fi> + * (C) Copyright 2011, Julius Baxter
> <julius at 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 <asm-offsets.h>
> +#include <asm/spr-defs.h>
> +#include <config.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 u-boot */
> + 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 */
The formating here doesn't seem right?
> +
> +#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
Please fix globally ?
> +
> + /* 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(CONFIG_SYS_INIT_SP_ADDR)
> + l.ori r1, r1, lo(CONFIG_SYS_INIT_SP_ADDR)
> + 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 board_init
> + l.nop
> +
> + .size _start, .-_start
> +
> +/*
> + * Store state onto stack and call the real exception handler
> + */
> + .section .text
> + .extern exception_handler
> + .type _exception_handler, at 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
M
More information about the U-Boot
mailing list