summaryrefslogtreecommitdiff
path: root/cpu/mips
diff options
context:
space:
mode:
authorwdenk <wdenk>2003-03-27 12:09:35 +0000
committerwdenk <wdenk>2003-03-27 12:09:35 +0000
commitc021880ac5837154ca51b9d84e6b75f39b64aabe (patch)
tree5f9c3cce4dd7b49e69ec5007f58c9b9a2f215c15 /cpu/mips
parentac6dbb85b7f080d923013bff4e1d5267cb6f8a5a (diff)
* Add support for MIPS32 4Kc CPUs
* Add support for INCA-IP Board
Diffstat (limited to 'cpu/mips')
-rw-r--r--cpu/mips/Makefile44
-rw-r--r--cpu/mips/cache.S265
-rw-r--r--cpu/mips/config.mk25
-rw-r--r--cpu/mips/cpu.c41
-rw-r--r--cpu/mips/incaip_clock.c107
-rw-r--r--cpu/mips/incaip_wdt.S73
-rw-r--r--cpu/mips/interrupts.c34
-rw-r--r--cpu/mips/serial.c282
-rw-r--r--cpu/mips/serial.h178
-rw-r--r--cpu/mips/start.S350
10 files changed, 1399 insertions, 0 deletions
diff --git a/cpu/mips/Makefile b/cpu/mips/Makefile
new file mode 100644
index 0000000000..91008bfe1b
--- /dev/null
+++ b/cpu/mips/Makefile
@@ -0,0 +1,44 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# 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 = lib$(CPU).a
+
+START = start.o
+OBJS = interrupts.o cpu.o incaip_clock.o serial.o
+SOBJS = incaip_wdt.o cache.o
+
+all: .depend $(START) $(LIB)
+
+$(LIB): $(OBJS) $(SOBJS)
+ $(AR) crv $@ $(OBJS) $(SOBJS)
+
+#########################################################################
+
+.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/mips/cache.S b/cpu/mips/cache.S
new file mode 100644
index 0000000000..aeb04b3790
--- /dev/null
+++ b/cpu/mips/cache.S
@@ -0,0 +1,265 @@
+/*
+ * Cache-handling routined for MIPS 4K CPUs
+ *
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * 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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+
+
+ /* 16KB is the maximum size of instruction and data caches on
+ * MIPS 4K.
+ */
+#define MIPS_MAX_CACHE_SIZE 0x4000
+
+
+/*
+ * cacheop macro to automate cache operations
+ * first some helpers...
+ */
+#define _mincache(size, maxsize) \
+ bltu size,maxsize,9f ; \
+ move size,maxsize ; \
+9:
+
+#define _align(minaddr, maxaddr, linesize) \
+ .set noat ; \
+ subu AT,linesize,1 ; \
+ not AT ; \
+ and minaddr,AT ; \
+ addu maxaddr,-1 ; \
+ and maxaddr,AT ; \
+ .set at
+
+/* general operations */
+#define doop1(op1) \
+ cache op1,0(a0)
+#define doop2(op1, op2) \
+ cache op1,0(a0) ; \
+ nop ; \
+ cache op2,0(a0)
+
+/* specials for cache initialisation */
+#define doop1lw(op1) \
+ lw zero,0(a0)
+#define doop1lw1(op1) \
+ cache op1,0(a0) ; \
+ lw zero,0(a0) ; \
+ cache op1,0(a0)
+#define doop121(op1,op2) \
+ cache op1,0(a0) ; \
+ nop; \
+ cache op2,0(a0) ; \
+ nop; \
+ cache op1,0(a0)
+
+#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
+ .set noreorder ; \
+10: doop##tag##ops ; \
+ bne minaddr,maxaddr,10b ; \
+ add minaddr,linesize ; \
+ .set reorder
+
+/* finally the cache operation macros */
+#define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
+ blez n,11f ; \
+ addu n,kva ; \
+ _align(kva, n, cacheLineSize) ; \
+ _oploopn(kva, n, cacheLineSize, tag, ops) ; \
+11:
+
+#define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
+ _mincache(n, cacheSize); \
+ blez n,11f ; \
+ addu n,kva ; \
+ _align(kva, n, cacheLineSize) ; \
+ _oploopn(kva, n, cacheLineSize, tag, ops) ; \
+11:
+
+#define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
+ vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
+
+#define icacheop(kva, n, cacheSize, cacheLineSize, op) \
+ icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
+
+/*******************************************************************************
+*
+* mips_cache_reset - low level initialisation of the primary caches
+*
+* This routine initialises the primary caches to ensure that they
+* have good parity. It must be called by the ROM before any cached locations
+* are used to prevent the possibility of data with bad parity being written to
+* memory.
+* To initialise the instruction cache it is essential that a source of data
+* with good parity is available. This routine
+* will initialise an area of memory starting at location zero to be used as
+* a source of parity.
+*
+* RETURNS: N/A
+*
+*/
+ .globl mips_cache_reset
+ .ent mips_cache_reset
+mips_cache_reset:
+
+ li t2, CFG_ICACHE_SIZE
+ li t3, CFG_DCACHE_SIZE
+ li t4, CFG_CACHELINE_SIZE
+ move t5, t4
+
+
+ li v0, MIPS_MAX_CACHE_SIZE
+
+ /* Now clear that much memory starting from zero.
+ */
+
+ li a0, KSEG1
+ addu a1, a0, v0
+
+2: sw zero, 0(a0)
+ sw zero, 4(a0)
+ sw zero, 8(a0)
+ sw zero, 12(a0)
+ sw zero, 16(a0)
+ sw zero, 20(a0)
+ sw zero, 24(a0)
+ sw zero, 28(a0)
+ addu a0, 32
+ bltu a0, a1, 2b
+
+ /* Set invalid tag.
+ */
+
+ mtc0 zero, CP0_TAGLO
+
+ /*
+ * The caches are probably in an indeterminate state,
+ * so we force good parity into them by doing an
+ * invalidate, load/fill, invalidate for each line.
+ */
+
+ /* Assume bottom of RAM will generate good parity for the cache.
+ */
+
+ li a0, K0BASE
+ move a2, t2 # icacheSize
+ move a3, t4 # icacheLineSize
+ move a1, a2
+ icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
+
+ /* To support Orion/R4600, we initialise the data cache in 3 passes.
+ */
+
+ /* 1: initialise dcache tags.
+ */
+
+ li a0, K0BASE
+ move a2, t3 # dcacheSize
+ move a3, t5 # dcacheLineSize
+ move a1, a2
+ icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
+
+ /* 2: fill dcache.
+ */
+
+ li a0, K0BASE
+ move a2, t3 # dcacheSize
+ move a3, t5 # dcacheLineSize
+ move a1, a2
+ icacheopn(a0,a1,a2,a3,1lw,(dummy))
+
+ /* 3: clear dcache tags.
+ */
+
+ li a0, K0BASE
+ move a2, t3 # dcacheSize
+ move a3, t5 # dcacheLineSize
+ move a1, a2
+ icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
+
+ j ra
+ .end mips_cache_reset
+
+
+/*******************************************************************************
+*
+* dcache_status - get cache status
+*
+* RETURNS: 0 - cache disabled; 1 - cache enabled
+*
+*/
+ .globl dcache_status
+ .ent dcache_status
+dcache_status:
+
+ mfc0 v0, CP0_CONFIG
+ andi v0, v0, 1
+ j ra
+
+ .end dcache_status
+
+/*******************************************************************************
+*
+* dcache_disable - disable cache
+*
+* RETURNS: N/A
+*
+*/
+ .globl dcache_disable
+ .ent dcache_disable
+dcache_disable:
+
+ mfc0 t0, CP0_CONFIG
+ li t1, -8
+ and t0, t0, t1
+ ori t0, t0, CONF_CM_UNCACHED
+ mtc0 t0, CP0_CONFIG
+ j ra
+
+ .end dcache_disable
+
+
+/*******************************************************************************
+*
+* mips_cache_lock - lock RAM area pointed to by a0 in cache.
+*
+* RETURNS: N/A
+*
+*/
+ .globl mips_cache_lock
+ .ent mips_cache_lock
+mips_cache_lock:
+ li a1, K0BASE - CFG_DCACHE_SIZE
+ addu a0, a1
+ li a2, CFG_DCACHE_SIZE
+ li a3, CFG_CACHELINE_SIZE
+ move a1, a2
+ icacheop(a0,a1,a2,a3,0x1d)
+
+ j ra
+ .end mips_cache_lock
+
diff --git a/cpu/mips/config.mk b/cpu/mips/config.mk
new file mode 100644
index 0000000000..4ea66172d1
--- /dev/null
+++ b/cpu/mips/config.mk
@@ -0,0 +1,25 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+#
+# 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
+#
+
+PLATFORM_CPPFLAGS += -mcpu=4kc -EB -mabicalls
+
diff --git a/cpu/mips/cpu.c b/cpu/mips/cpu.c
new file mode 100644
index 0000000000..3fc3916b4e
--- /dev/null
+++ b/cpu/mips/cpu.c
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * 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 <command.h>
+#include <asm/inca-ip.h>
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+#ifdef CONFIG_INCA_IP
+ *INCA_IP_WDT_RST_REQ = 0x3f;
+#endif
+ fprintf(stderr, "*** reset failed ***\n");
+ return 0;
+}
+
+void flush_cache (ulong start_addr, ulong size)
+{
+
+}
+
diff --git a/cpu/mips/incaip_clock.c b/cpu/mips/incaip_clock.c
new file mode 100644
index 0000000000..7fc6eb0351
--- /dev/null
+++ b/cpu/mips/incaip_clock.c
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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 <asm/inca-ip.h>
+
+
+
+/*******************************************************************************
+*
+* get_cpuclk - returns the frequency of the CPU.
+*
+* Gets the value directly from the INCA-IP hardware.
+*
+* RETURNS:
+* 150.000.000 for 150 MHz
+* 130.000.000. for 130 Mhz
+* 100.000.000. for 100 Mhz
+* NOTE:
+* This functions should be used by the hardware driver to get the correct
+* frequency of the CPU. Don't use the macros, which are set to init the CPU
+* frequency in the ROM code.
+*/
+uint incaip_get_cpuclk(void)
+{
+ /*-------------------------------------------------------------------------*/
+ /* CPU Clock Input Multiplexer (MUX I) */
+ /* Multiplexer MUX I selects the maximum input clock to the CPU. */
+ /*-------------------------------------------------------------------------*/
+ if (*((volatile ulong*)INCA_IP_CGU_CGU_MUXCR) & INCA_IP_CGU_CGU_MUXCR_MUXI)
+ {
+ /* MUX I set to 150 MHz clock */
+ return 150000000;
+ }
+ else
+ {
+ /* MUX I set to 100/133 MHz clock */
+ if (*((volatile ulong*)INCA_IP_CGU_CGU_DIVCR) & 0x40)
+ {
+ /* Division value is 1/3, maximum CPU operating */
+ /* frequency is 133.3 MHz */
+ return 130000000;
+ }
+ else
+ {
+ /* Division value is 1/4, maximum CPU operating */
+ /* frequency is 100 MHz */
+ return 100000000;
+ }
+ }
+}
+
+/*******************************************************************************
+*
+* get_fpiclk - returns the frequency of the FPI bus.
+*
+* Gets the value directly from the INCA-IP hardware.
+*
+* RETURNS: Frquency in Hz
+*
+* NOTE:
+* This functions should be used by the hardware driver to get the correct
+* frequency of the CPU. Don't use the macros, which are set to init the CPU
+* frequency in the ROM code.
+* The calculation for the
+*/
+uint incaip_get_fpiclk(void)
+{
+ uint clkCPU;
+
+ clkCPU = incaip_get_cpuclk();
+
+ switch (*((volatile ulong*)INCA_IP_CGU_CGU_DIVCR) & 0xC)
+ {
+ case 0x4:
+ return clkCPU >> 1; /* devided by 2 */
+ break;
+ case 0x8:
+ return clkCPU >> 2; /* devided by 4 */
+ break;
+ default:
+ return clkCPU;
+ break;
+ }
+}
+
+
diff --git a/cpu/mips/incaip_wdt.S b/cpu/mips/incaip_wdt.S
new file mode 100644
index 0000000000..9455569f52
--- /dev/null
+++ b/cpu/mips/incaip_wdt.S
@@ -0,0 +1,73 @@
+/*
+ * INCA-IP Watchdog timer management code.
+ *
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * 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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+
+
+#define WD_BASE 0xb8000000
+#define WD_CON0(value) 0x0020(value)
+#define WD_CON1(value) 0x0024(value)
+#define WD_DISABLE 0x00000008
+#define WD_ENABLE 0x00000000
+#define WD_WRITE_PW 0xFFFC00F8
+#define WD_WRITE_ENDINIT 0xFFFC00F3
+#define WD_WRITE_INIT 0xFFFC00F2
+
+
+ .globl disable_incaip_wdt
+disable_incaip_wdt:
+ li t0, WD_BASE
+
+ /* Calculate password.
+ */
+ lw t2, WD_CON1(t0)
+ and t2, 0xC
+
+ lw t3, WD_CON0(t0)
+ and t3, 0xFFFFFF01
+
+ or t3, t2
+ or t3, 0xF0
+
+ sw t3, WD_CON0(t0) /* write password */
+
+ /* Clear ENDINIT.
+ */
+ li t1, WD_WRITE_INIT
+ sw t1, WD_CON0(t0)
+
+
+ li t1, WD_DISABLE
+ sw t1, WD_CON1(t0) /* disable watchdog */
+ li t1, WD_WRITE_PW
+ sw t1, WD_CON0(t0) /* write password */
+ li t1, WD_WRITE_ENDINIT
+ sw t1, WD_CON0(t0) /* end command */
+
+ j ra
+ nop
+
diff --git a/cpu/mips/interrupts.c b/cpu/mips/interrupts.c
new file mode 100644
index 0000000000..0490a7661a
--- /dev/null
+++ b/cpu/mips/interrupts.c
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * 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>
+
+void enable_interrupts(void)
+{
+}
+
+int disable_interrupts(void)
+{
+ return 0;
+}
+
diff --git a/cpu/mips/serial.c b/cpu/mips/serial.c
new file mode 100644
index 0000000000..ebda509b11
--- /dev/null
+++ b/cpu/mips/serial.c
@@ -0,0 +1,282 @@
+/*
+ * (INCA) ASC UART support
+ */
+
+#include <common.h>
+#include <asm/inca-ip.h>
+#include "serial.h"
+
+#define SET_BIT(reg, mask) reg |= (mask)
+#define CLEAR_BIT(reg, mask) reg &= (~mask)
+#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
+#define SET_BITS(reg, mask) SET_BIT(reg, mask)
+#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
+
+extern uint incaip_get_fpiclk(void);
+
+static int serial_setopt (void);
+
+/* pointer to ASC register base address */
+static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
+
+/******************************************************************************
+*
+* serial_init - initialize a INCAASC channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+ /* we have to set PMU.EN13 bit to enable an ASC device*/
+ INCAASC_PMU_ENABLE(13);
+
+ /* and we have to set CLC register*/
+ CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
+ SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
+
+ /* initialy we are in async mode */
+ pAsc->asc_con = ASCCON_M_8ASYNC;
+
+ /* select input port */
+ pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
+
+ /* TXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
+ ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
+ /* enable TXFIFO */
+ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
+
+ /* RXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
+ ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
+ /* enable RXFIFO */
+ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
+
+ /* enable error signals */
+ SET_BIT(pAsc->asc_con, ASCCON_FEN);
+ SET_BIT(pAsc->asc_con, ASCCON_OEN);
+
+ /* acknowledge ASC interrupts */
+ ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
+
+ /* disable ASC interrupts */
+ ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
+
+ /* set FIFOs into the transparent mode */
+ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
+ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
+
+ /* set baud rate */
+ serial_setbrg();
+
+ /* set the options */
+ serial_setopt();
+
+ return 0;
+}
+
+void serial_setbrg (void)
+{
+ ulong uiReloadValue, fdv;
+ ulong f_ASC;
+
+ f_ASC = incaip_get_fpiclk();
+
+#ifndef INCAASC_USE_FDV
+ fdv = 2;
+ uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
+#else
+ fdv = INCAASC_FDV_HIGH_BAUDRATE;
+ uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
+#endif /* INCAASC_USE_FDV */
+
+ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
+ {
+#ifndef INCAASC_USE_FDV
+ fdv = 3;
+ uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
+#else
+ fdv = INCAASC_FDV_LOW_BAUDRATE;
+ uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
+#endif /* INCAASC_USE_FDV */
+
+ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
+ {
+ return; /* can't impossibly generate that baud rate */
+ }
+ }
+
+ /* Disable Baud Rate Generator; BG should only be written when R=0 */
+ CLEAR_BIT(pAsc->asc_con, ASCCON_R);
+
+#ifndef INCAASC_USE_FDV
+ /*
+ * Disable Fractional Divider (FDE)
+ * Divide clock by reload-value + constant (BRS)
+ */
+ /* FDE = 0 */
+ CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
+
+ if ( fdv == 2 )
+ CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
+ else
+ SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
+
+#else /* INCAASC_USE_FDV */
+
+ /* Enable Fractional Divider */
+ SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
+
+ /* Set fractional divider value */
+ pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
+
+#endif /* INCAASC_USE_FDV */
+
+ /* Set reload value in BG */
+ pAsc->asc_bg = uiReloadValue;
+
+ /* Enable Baud Rate Generator */
+ SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
+}
+
+/*******************************************************************************
+*
+* serial_setopt - set the serial options
+*
+* Set the channel operating mode to that specified. Following options
+* are supported: CREAD, CSIZE, PARENB, and PARODD.
+*
+* Note, this routine disables the transmitter. The calling routine
+* may have to re-enable it.
+*
+* RETURNS:
+* Returns 0 to indicate success, otherwise -1 is returned
+*/
+
+static int serial_setopt (void)
+{
+ ulong con;
+
+ switch ( ASC_OPTIONS & ASCOPT_CSIZE )
+ {
+ /* 7-bit-data */
+ case ASCOPT_CS7:
+ con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
+ break;
+
+ /* 8-bit-data */
+ case ASCOPT_CS8:
+ if ( ASC_OPTIONS & ASCOPT_PARENB )
+ con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
+ else
+ con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
+ break;
+
+ /*
+ * only 7 and 8-bit frames are supported
+ * if we don't use IOCTL extensions
+ */
+ default:
+ return -1;
+ }
+
+ if ( ASC_OPTIONS & ASCOPT_STOPB )
+ SET_BIT(con, ASCCON_STP); /* 2 stop bits */
+ else
+ CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
+
+ if ( ASC_OPTIONS & ASCOPT_PARENB )
+ SET_BIT(con, ASCCON_PEN); /* enable parity checking */
+ else
+ CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
+
+ if ( ASC_OPTIONS & ASCOPT_PARODD )
+ SET_BIT(con, ASCCON_ODD); /* odd parity */
+ else
+ CLEAR_BIT(con, ASCCON_ODD); /* even parity */
+
+ if ( ASC_OPTIONS & ASCOPT_CREAD )
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
+
+ pAsc->asc_con |= con;
+
+ return 0;
+}
+
+void serial_putc (const char c)
+{
+ uint txFl = 0;
+
+ if (c == '\n') serial_putc ('\r');
+
+ /* check do we have a free space in the TX FIFO */
+ /* get current filling level */
+ do
+ {
+ txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
+ }
+ while ( txFl == INCAASC_TXFIFO_FULL );
+
+ pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
+ /* check for errors */
+ if ( pAsc->asc_con & ASCCON_OE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
+ return;
+ }
+}
+
+void serial_puts (const char *s)
+{
+ while (*s)
+ {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ ulong symbol_mask;
+ char c;
+
+ while (!serial_tstc());
+
+ symbol_mask =
+ ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
+
+ c = (char)(pAsc->asc_rbuf & symbol_mask);
+
+ return c;
+}
+
+int serial_tstc (void)
+{
+ int res = 1;
+
+ if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
+ {
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_FE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_PE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_OE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
+ res = 0;
+ }
+
+ return res;
+}
diff --git a/cpu/mips/serial.h b/cpu/mips/serial.h
new file mode 100644
index 0000000000..ee63360e63
--- /dev/null
+++ b/cpu/mips/serial.h
@@ -0,0 +1,178 @@
+/* incaAscSio.h - (INCA) ASC UART tty driver header */
+
+#ifndef __INCincaAscSioh
+#define __INCincaAscSioh
+
+#include <asm/inca-ip.h>
+
+/* channel operating modes */
+#define ASCOPT_CSIZE 0x00000003
+#define ASCOPT_CS7 0x00000001
+#define ASCOPT_CS8 0x00000002
+#define ASCOPT_PARENB 0x00000004
+#define ASCOPT_STOPB 0x00000008
+#define ASCOPT_PARODD 0x00000010
+#define ASCOPT_CREAD 0x00000020
+
+#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8)
+
+/* ASC input select (0 or 1) */
+#define CONSOLE_TTY 0
+
+/* use fractional divider for baudrate settings */
+#define INCAASC_USE_FDV
+
+#ifdef INCAASC_USE_FDV
+ #define INCAASC_FDV_LOW_BAUDRATE 71
+ #define INCAASC_FDV_HIGH_BAUDRATE 453
+#endif /*INCAASC_USE_FDV*/
+
+
+#define INCAASC_TXFIFO_FL 1
+#define INCAASC_RXFIFO_FL 1
+#define INCAASC_TXFIFO_FULL 16
+
+/* interrupt lines masks for the ASC device interrupts*/
+/* change these macroses if it's necessary */
+#define INCAASC_IRQ_LINE_ALL 0x000F0000 /* all IRQs */
+
+#define INCAASC_IRQ_LINE_TIR 0x00010000 /* TIR - Tx */
+#define INCAASC_IRQ_LINE_RIR 0x00020000 /* RIR - Rx */
+#define INCAASC_IRQ_LINE_EIR 0x00040000 /* EIR - Err */
+#define INCAASC_IRQ_LINE_TBIR 0x00080000 /* TBIR - Tx Buf*/
+
+/* interrupt controller access macros */
+#define ASC_INTERRUPTS_ENABLE(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) |= X;
+#define ASC_INTERRUPTS_DISABLE(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) &= ~X;
+#define ASC_INTERRUPTS_CLEAR(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_ISR) = X;
+
+/* CLC register's bits and bitfields */
+#define ASCCLC_DISR 0x00000001
+#define ASCCLC_DISS 0x00000002
+#define ASCCLC_RMCMASK 0x0000FF00
+#define ASCCLC_RMCOFFSET 8
+
+/* CON register's bits and bitfields */
+#define ASCCON_MODEMASK 0x0007
+ #define ASCCON_M_8SYNC 0x0
+ #define ASCCON_M_8ASYNC 0x1
+ #define ASCCON_M_8IRDAASYNC 0x2
+ #define ASCCON_M_7ASYNCPAR 0x3
+ #define ASCCON_M_9ASYNC 0x4
+ #define ASCCON_M_8WAKEUPASYNC 0x5
+ #define ASCCON_M_8ASYNCPAR 0x7
+#define ASCCON_STP 0x0008
+#define ASCCON_REN 0x0010
+#define ASCCON_PEN 0x0020
+#define ASCCON_FEN 0x0040
+#define ASCCON_OEN 0x0080
+#define ASCCON_PE 0x0100
+#define ASCCON_FE 0x0200
+#define ASCCON_OE 0x0400
+#define ASCCON_FDE 0x0800
+#define ASCCON_ODD 0x1000
+#define ASCCON_BRS 0x2000
+#define ASCCON_LB 0x4000
+#define ASCCON_R 0x8000
+
+/* WHBCON register's bits and bitfields */
+#define ASCWHBCON_CLRREN 0x0010
+#define ASCWHBCON_SETREN 0x0020
+#define ASCWHBCON_CLRPE 0x0100
+#define ASCWHBCON_CLRFE 0x0200
+#define ASCWHBCON_CLROE 0x0400
+#define ASCWHBCON_SETPE 0x0800
+#define ASCWHBCON_SETFE 0x1000
+#define ASCWHBCON_SETOE 0x2000
+
+/* ABCON register's bits and bitfields */
+#define ASCABCON_ABEN 0x0001
+#define ASCABCON_AUREN 0x0002
+#define ASCABCON_ABSTEN 0x0004
+#define ASCABCON_ABDETEN 0x0008
+#define ASCABCON_FCDETEN 0x0010
+#define ASCABCON_EMMASK 0x0300
+ #define ASCABCON_EMOFF 8
+ #define ASCABCON_EM_DISAB 0x0
+ #define ASCABCON_EM_DURAB 0x1
+ #define ASCABCON_EM_ALWAYS 0x2
+#define ASCABCON_TXINV 0x0400
+#define ASCABCON_RXINV 0x0800
+
+/* FDV register mask, offset and bitfields*/
+#define ASCFDV_VALUE_MASK 0x000001FF
+
+/* WHBABCON register's bits and bitfields */
+#define ASCWHBABCON_SETABEN 0x0001
+#define ASCWHBABCON_CLRABEN 0x0002
+
+/* ABSTAT register's bits and bitfields */
+#define ASCABSTAT_FCSDET 0x0001
+#define ASCABSTAT_FCCDET 0x0002
+#define ASCABSTAT_SCSDET 0x0004
+#define ASCABSTAT_SCCDET 0x0008
+#define ASCABSTAT_DETWAIT 0x0010
+
+/* WHBABSTAT register's bits and bitfields */
+#define ASCWHBABSTAT_CLRFCSDET 0x0001
+#define ASCWHBABSTAT_SETFCSDET 0x0002
+#define ASCWHBABSTAT_CLRFCCDET 0x0004
+#define ASCWHBABSTAT_SETFCCDET 0x0008
+#define ASCWHBABSTAT_CLRSCSDET 0x0010
+#define ASCWHBABSTAT_SETSCSDET 0x0020
+#define ASCWHBABSTAT_SETSCCDET 0x0040
+#define ASCWHBABSTAT_CLRSCCDET 0x0080
+#define ASCWHBABSTAT_CLRDETWAIT 0x0100
+#define ASCWHBABSTAT_SETDETWAIT 0x0200
+
+/* TXFCON register's bits and bitfields */
+#define ASCTXFCON_TXFEN 0x0001
+#define ASCTXFCON_TXFFLU 0x0002
+#define ASCTXFCON_TXTMEN 0x0004
+#define ASCTXFCON_TXFITLMASK 0x3F00
+#define ASCTXFCON_TXFITLOFF 8
+
+/* RXFCON register's bits and bitfields */
+#define ASCRXFCON_RXFEN 0x0001
+#define ASCRXFCON_RXFFLU 0x0002
+#define ASCRXFCON_RXTMEN 0x0004
+#define ASCRXFCON_RXFITLMASK 0x3F00
+#define ASCRXFCON_RXFITLOFF 8
+
+/* FSTAT register's bits and bitfields */
+#define ASCFSTAT_RXFFLMASK 0x003F
+#define ASCFSTAT_TXFFLMASK 0x3F00
+#define ASCFSTAT_TXFFLOFF 8
+
+#define INCAASC_PMU_ENABLE(BIT) *((volatile ulong*)0xBF102000) |= (0x1 << BIT);
+
+typedef struct /* incaAsc_t */
+{
+ volatile unsigned long asc_clc; /*0x0000*/
+ volatile unsigned long asc_pisel; /*0x0004*/
+ volatile unsigned long asc_rsvd1[2]; /* for mapping */ /*0x0008*/
+ volatile unsigned long asc_con; /*0x0010*/
+ volatile unsigned long asc_bg; /*0x0014*/
+ volatile unsigned long asc_fdv; /*0x0018*/
+ volatile unsigned long asc_pmw; /* not used */ /*0x001C*/
+ volatile unsigned long asc_tbuf; /*0x0020*/
+ volatile unsigned long asc_rbuf; /*0x0024*/
+ volatile unsigned long asc_rsvd2[2]; /* for mapping */ /*0x0028*/
+ volatile unsigned long asc_abcon; /*0x0030*/
+ volatile unsigned long asc_abstat; /* not used */ /*0x0034*/
+ volatile unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0038*/
+ volatile unsigned long asc_rxfcon; /*0x0040*/
+ volatile unsigned long asc_txfcon; /*0x0044*/
+ volatile unsigned long asc_fstat; /*0x0048*/
+ volatile unsigned long asc_rsvd4; /* for mapping */ /*0x004C*/
+ volatile unsigned long asc_whbcon; /*0x0050*/
+ volatile unsigned long asc_whbabcon; /*0x0054*/
+ volatile unsigned long asc_whbabstat; /* not used */ /*0x0058*/
+
+} incaAsc_t;
+
+#endif /* __INCincaAscSioh */
+
diff --git a/cpu/mips/start.S b/cpu/mips/start.S
new file mode 100644
index 0000000000..bf11655617
--- /dev/null
+++ b/cpu/mips/start.S
@@ -0,0 +1,350 @@
+/*
+ * Startup Code for MIPS32 CPU-core
+ *
+ * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * 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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+
+#define RVECENT(f,n) \
+ b f; nop
+#define XVECENT(f,bev) \
+ b f ; \
+ li k0,bev
+
+ .set noreorder
+
+ .globl _start
+ .text
+_start:
+ RVECENT(reset,0) /* U-boot entry point */
+ RVECENT(reset,1) /* software reboot */
+#ifdef CONFIG_INCA_IP
+ .word 0x000020C4 /* EBU init code, fetched during booting */
+ .word 0x00000000 /* phase of the flash */
+#else
+ RVECENT(romReserved,2)
+#endif
+ RVECENT(romReserved,3)
+ RVECENT(romReserved,4)
+ RVECENT(romReserved,5)
+ RVECENT(romReserved,6)
+ RVECENT(romReserved,7)
+ RVECENT(romReserved,8)
+ RVECENT(romReserved,9)
+ RVECENT(romReserved,10)
+ RVECENT(romReserved,11)
+ RVECENT(romReserved,12)
+ RVECENT(romReserved,13)
+ RVECENT(romReserved,14)
+ RVECENT(romReserved,15)
+ RVECENT(romReserved,16)
+ RVECENT(romReserved,17)
+ RVECENT(romReserved,18)
+ RVECENT(romReserved,19)
+ RVECENT(romReserved,20)
+ RVECENT(romReserved,21)
+ RVECENT(romReserved,22)
+ RVECENT(romReserved,23)
+ RVECENT(romReserved,24)
+ RVECENT(romReserved,25)
+ RVECENT(romReserved,26)
+ RVECENT(romReserved,27)
+ RVECENT(romReserved,28)
+ RVECENT(romReserved,29)
+ RVECENT(romReserved,30)
+ RVECENT(romReserved,31)
+ RVECENT(romReserved,32)
+ RVECENT(romReserved,33)
+ RVECENT(romReserved,34)
+ RVECENT(romReserved,35)
+ RVECENT(romReserved,36)
+ RVECENT(romReserved,37)
+ RVECENT(romReserved,38)
+ RVECENT(romReserved,39)
+ RVECENT(romReserved,40)
+ RVECENT(romReserved,41)
+ RVECENT(romReserved,42)
+ RVECENT(romReserved,43)
+ RVECENT(romReserved,44)
+ RVECENT(romReserved,45)
+ RVECENT(romReserved,46)
+ RVECENT(romReserved,47)
+ RVECENT(romReserved,48)
+ RVECENT(romReserved,49)
+ RVECENT(romReserved,50)
+ RVECENT(romReserved,51)
+ RVECENT(romReserved,52)
+ RVECENT(romReserved,53)
+ RVECENT(romReserved,54)
+ RVECENT(romReserved,55)
+ RVECENT(romReserved,56)
+ RVECENT(romReserved,57)
+ RVECENT(romReserved,58)
+ RVECENT(romReserved,59)
+ RVECENT(romReserved,60)
+ RVECENT(romReserved,61)
+ RVECENT(romReserved,62)
+ RVECENT(romReserved,63)
+ XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */
+ RVECENT(romReserved,65)
+ RVECENT(romReserved,66)
+ RVECENT(romReserved,67)
+ RVECENT(romReserved,68)
+ RVECENT(romReserved,69)
+ RVECENT(romReserved,70)
+ RVECENT(romReserved,71)
+ RVECENT(romReserved,72)
+ RVECENT(romReserved,73)
+ RVECENT(romReserved,74)
+ RVECENT(romReserved,75)
+ RVECENT(romReserved,76)
+ RVECENT(romReserved,77)
+ RVECENT(romReserved,78)
+ RVECENT(romReserved,79)
+ XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */
+ RVECENT(romReserved,81)
+ RVECENT(romReserved,82)
+ RVECENT(romReserved,83)
+ RVECENT(romReserved,84)
+ RVECENT(romReserved,85)
+ RVECENT(romReserved,86)
+ RVECENT(romReserved,87)
+ RVECENT(romReserved,88)
+ RVECENT(romReserved,89)
+ RVECENT(romReserved,90)
+ RVECENT(romReserved,91)
+ RVECENT(romReserved,92)
+ RVECENT(romReserved,93)
+ RVECENT(romReserved,94)
+ RVECENT(romReserved,95)
+ XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */
+ RVECENT(romReserved,97)
+ RVECENT(romReserved,98)
+ RVECENT(romReserved,99)
+ RVECENT(romReserved,100)
+ RVECENT(romReserved,101)
+ RVECENT(romReserved,102)
+ RVECENT(romReserved,103)
+ RVECENT(romReserved,104)
+ RVECENT(romReserved,105)
+ RVECENT(romReserved,106)
+ RVECENT(romReserved,107)
+ RVECENT(romReserved,108)
+ RVECENT(romReserved,109)
+ RVECENT(romReserved,110)
+ RVECENT(romReserved,111)
+ XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */
+ RVECENT(romReserved,113)
+ RVECENT(romReserved,114)
+ RVECENT(romReserved,115)
+ RVECENT(romReserved,116)
+ RVECENT(romReserved,116)
+ RVECENT(romReserved,118)
+ RVECENT(romReserved,119)
+ RVECENT(romReserved,120)
+ RVECENT(romReserved,121)
+ RVECENT(romReserved,122)
+ RVECENT(romReserved,123)
+ RVECENT(romReserved,124)
+ RVECENT(romReserved,125)
+ RVECENT(romReserved,126)
+ RVECENT(romReserved,127)
+
+ /* We hope there are no more reserved vectors!
+ * 128 * 8 == 1024 == 0x400
+ * so this is address R_VEC+0x400 == 0xbfc00400
+ */
+ .align 4
+reset:
+
+ /* Clear watch registers.
+ */
+ mtc0 zero, CP0_WATCHLO
+ mtc0 zero, CP0_WATCHHI
+
+ /* STATUS register */
+ mfc0 k0, CP0_STATUS
+ li k1, ~ST0_IE
+ and k0, k1
+ mtc0 k0, CP0_STATUS
+
+ /* CAUSE register */
+ mtc0 zero, CP0_CAUSE
+
+ /* Init Timer */
+ mtc0 zero, CP0_COUNT
+ mtc0 zero, CP0_COMPARE
+
+ /* CONFIG0 register */
+ li t0, CONF_CM_UNCACHED
+ mtc0 t0, CP0_CONFIG
+
+#ifdef CONFIG_INCA_IP
+ /* Disable INCA-IP Watchdog.
+ */
+ bal disable_incaip_wdt
+ nop
+#endif
+
+ /* Initialize any external memory.
+ */
+ bal memsetup
+ nop
+
+ /* Initialize caches...
+ */
+ bal mips_cache_reset
+ nop
+
+ /* ... and enable them.
+ */
+ li t0, CONF_CM_CACHABLE_NONCOHERENT
+ mtc0 t0, CP0_CONFIG
+
+
+ /* Set up temporary stack.
+ */
+ li a0, CFG_INIT_SP_OFFSET
+ bal mips_cache_lock
+ nop
+
+ li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
+ la sp, 0(t0)
+
+ /* Initialize GOT pointer.
+ */
+ bal 1f
+ nop
+ .word _GLOBAL_OFFSET_TABLE_ - 1f + 4
+1:
+ move gp, ra
+ lw t1, 0(ra)
+ add gp, t1
+ la t9, board_init_f
+ j t9
+ nop
+
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * a0 = addr_sp
+ * a1 = gd
+ * a2 = destination address
+ */
+ .globl relocate_code
+ .ent relocate_code
+relocate_code:
+ move sp, a0 /* Set new stack pointer */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
+ */
+ move t6, gp
+ sub gp, CFG_MONITOR_BASE
+ add gp, a2 /* gp now adjusted */
+ sub t6, gp, t6 /* t6 <-- relocation offset */
+
+ li t0, CFG_MONITOR_BASE
+ add t2, t0, CFG_MONITOR_LEN
+ move t1, a2
+
+ /*
+ * t0 = source address
+ * t1 = target address
+ * t2 = source end address
+ */
+1:
+ lw t3, 0(t0)
+ sw t3, 0(t1)
+ addu t0, 4
+ ble t0, t2, 1b
+ addu t1, 4 /* delay slot */
+
+ /* If caches were enabled, we would have to flush them here.
+ */
+
+ /* Jump to where we've relocated ourselves.
+ */
+ addi t0, a2, in_ram - _start
+ j t0
+ nop
+
+ .word uboot_end_data
+ .word uboot_end
+ .word num_got_entries
+
+in_ram:
+ /* Now we want to update GOT.
+ */
+ lw t3, -4(t0) /* t3 <-- num_got_entries */
+ addi t4, gp, 8 /* Skipping first two entries. */
+ li t2, 2
+1:
+ lw t1, 0(t4)
+ beqz t1, 2f
+ add t1, t6
+ sw t1, 0(t4)
+2:
+ addi t2, 1
+ blt t2, t3, 1b
+ addi t4, 4 /* delay slot */
+
+ /* Clear BSS.
+ */
+ lw t1, -12(t0) /* t1 <-- uboot_end_data */
+ lw t2, -8(t0) /* t2 <-- uboot_end */
+ add t1, t6 /* adjust pointers */
+ add t2, t6
+
+ sub t1, 4
+1: addi t1, 4
+ bltl t1, t2, 1b
+ sw zero, 0(t1) /* delay slot */
+
+ move a0, a1
+ la t9, board_init_r
+ j t9
+ move a1, a2 /* delay slot */
+
+ .end relocate_code
+
+
+
+ /* Exception handlers.
+ */
+romReserved:
+ b romReserved
+
+romExcHandle:
+ b romExcHandle
+