Patches by Scott McNutt, 24 Aug 2004:
- Add support for Altera Nios-II processors.
- Add support for Psyent PCI-5441 board.
- Add support for Psyent PK1C20 board.
diff --git a/cpu/nios2/Makefile b/cpu/nios2/Makefile
new file mode 100644
index 0000000..76b324a
--- /dev/null
+++ b/cpu/nios2/Makefile
@@ -0,0 +1,44 @@
+#
+# (C) Copyright 2000
+# 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
+AOBJS	= exceptions.o
+OBJS	= cpu.o interrupts.o serial.o traps.o
+
+all:	.depend $(START) $(LIB)
+
+$(LIB):	$(OBJS) $(AOBJS)
+	$(AR) crv $@ $(OBJS) $(AOBJS)
+
+#########################################################################
+
+.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) $(AOBJS:.o=.S)
+	$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) $(AOBJS:.o=.S) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/nios2/config.mk b/cpu/nios2/config.mk
new file mode 100644
index 0000000..f228d72
--- /dev/null
+++ b/cpu/nios2/config.mk
@@ -0,0 +1,24 @@
+#
+# (C) Copyright 2000
+# 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_RELFLAGS +=
diff --git a/cpu/nios2/cpu.c b/cpu/nios2/cpu.c
new file mode 100644
index 0000000..c9db127
--- /dev/null
+++ b/cpu/nios2/cpu.c
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * 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 <nios2.h>
+#include <nios2-io.h>
+
+#if defined (CFG_NIOS_SYSID_BASE)
+#include <linux/time.h>
+static void check_sysid (void)
+{
+	struct nios_sysid_t *sysid =
+		(struct nios_sysid_t *)CACHE_BYPASS(CFG_NIOS_SYSID_BASE);
+	struct tm t;
+	char asc[32];
+
+	localtime_r ((time_t *)&sysid->timestamp, &t);
+	asctime_r (&t, asc);
+	printf ("SYSID : %08x, %s", sysid->id, asc);
+
+}
+#endif /* CFG_NIOS_SYSID_BASE */
+
+int checkcpu (void)
+{
+	printf ("CPU   : Nios-II\n");
+#if !defined(CFG_NIOS_SYSID_BASE)
+	printf ("SYSID : <unknown>\n");
+#else
+	check_sysid ();
+#endif
+	return (0);
+}
+
+
+int do_reset (void)
+{
+	void (*rst)(void) = (void(*)(void))CFG_RESET_ADDR;
+	disable_interrupts ();
+	rst();
+	return(0);
+}
diff --git a/cpu/nios2/exceptions.S b/cpu/nios2/exceptions.S
new file mode 100644
index 0000000..d3b95cf
--- /dev/null
+++ b/cpu/nios2/exceptions.S
@@ -0,0 +1,152 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * 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 <asm/opcodes.h>
+
+
+	.text
+	.align	4
+
+	.global _exception
+
+_exception:
+	/* SAVE ALL REGS -- this allows trap and unimplemented
+	 * instruction handlers to be coded conveniently in C
+	 */
+	addi	sp, sp, -(33*4)
+	stw	r0, 0(sp)
+	stw	r1, 4(sp)
+	stw	r2, 8(sp)
+	stw	r3, 12(sp)
+	stw	r4, 16(sp)
+	stw	r5, 20(sp)
+	stw	r6, 24(sp)
+	stw	r7, 28(sp)
+	stw	r8, 32(sp)
+	stw	r9, 36(sp)
+	stw	r10, 40(sp)
+	stw	r11, 44(sp)
+	stw	r12, 48(sp)
+	stw	r13, 52(sp)
+	stw	r14, 56(sp)
+	stw	r15, 60(sp)
+	stw	r16, 64(sp)
+	stw	r17, 68(sp)
+	stw	r19, 72(sp)
+	stw	r19, 76(sp)
+	stw	r20, 80(sp)
+	stw	r21, 84(sp)
+	stw	r22, 88(sp)
+	stw	r23, 92(sp)
+	stw	r24, 96(sp)
+	stw	r25, 100(sp)
+	stw	r26, 104(sp)
+	stw	r27, 108(sp)
+	stw	r28, 112(sp)
+	stw	r29, 116(sp)
+	stw	r30, 120(sp)
+	stw	r31, 124(sp)
+	rdctl	et, estatus
+	stw	et, 128(sp)
+
+	/* If interrupts are disabled -- software interrupt */
+	rdctl	et, estatus
+	andi	et, et, 1
+	beq	et, r0, 0f
+
+	/* If no interrupts are pending -- software interrupt */
+	rdctl	et, ipending
+	beq	et, r0, 0f
+
+	/* HARDWARE INTERRUPT: Call interrupt handler */
+	movhi	r3, %hi(external_interrupt)
+	ori	r3, r3, %lo(external_interrupt)
+	mov	r4, sp		/* ptr to regs */
+	callr	r3
+
+	/* Return address fixup: execution resumes by re-issue of
+	 * interrupted instruction at ea-4 (ea == r29). Here we do
+	 * simple fixup to allow common exception return.
+	 */
+	ldw	r3, 116(sp)
+	addi	r3, r3, -4
+	stw	r3, 116(sp)
+	br	_exception_return
+
+0:
+	/* TRAP EXCEPTION */
+	movhi	r3, %hi(OPC_TRAP)
+	ori	r3, r3, %lo(OPC_TRAP)
+	addi	r1, ea, -4
+	ldw	r1, 0(r1)
+	bne	r1, r3, 1f
+	movhi	r3, %hi(trap_handler)
+	ori	r3, r3, %lo(trap_handler)
+	mov	r4, sp		/* ptr to regs */
+	callr	r3
+	br	_exception_return
+
+1:
+	/* UNIMPLEMENTED INSTRUCTION EXCEPTION */
+	movhi	r3, %hi(soft_emulation)
+	ori	r3, r3, %lo(soft_emulation)
+	mov	r4, sp		/* ptr to regs */
+	callr	r3
+
+	/* Restore regsisters and return from exception*/
+_exception_return:
+	ldw	r1, 4(sp)
+	ldw	r2, 8(sp)
+	ldw	r3, 12(sp)
+	ldw	r4, 16(sp)
+	ldw	r5, 20(sp)
+	ldw	r6, 24(sp)
+	ldw	r7, 28(sp)
+	ldw	r8, 32(sp)
+	ldw	r9, 36(sp)
+	ldw	r10, 40(sp)
+	ldw	r11, 44(sp)
+	ldw	r12, 48(sp)
+	ldw	r13, 52(sp)
+	ldw	r14, 56(sp)
+	ldw	r15, 60(sp)
+	ldw	r16, 64(sp)
+	ldw	r17, 68(sp)
+	ldw	r19, 72(sp)
+	ldw	r19, 76(sp)
+	ldw	r20, 80(sp)
+	ldw	r21, 84(sp)
+	ldw	r22, 88(sp)
+	ldw	r23, 92(sp)
+	ldw	r24, 96(sp)
+	ldw	r25, 100(sp)
+	ldw	r26, 104(sp)
+	ldw	r27, 108(sp)
+	ldw	r28, 112(sp)
+	ldw	r29, 116(sp)
+	ldw	r30, 120(sp)
+	ldw	r31, 124(sp)
+	addi	sp, sp, (33*4)
+	eret
+/*-------------------------------------------------------------*/
diff --git a/cpu/nios2/interrupts.c b/cpu/nios2/interrupts.c
new file mode 100644
index 0000000..4a6da58
--- /dev/null
+++ b/cpu/nios2/interrupts.c
@@ -0,0 +1,229 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * 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 <nios2.h>
+#include <nios2-io.h>
+#include <asm/ptrace.h>
+#include <common.h>
+#include <command.h>
+#include <watchdog.h>
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+
+#if defined(CFG_NIOS_TMRBASE) && !defined(CFG_NIOS_TMRIRQ)
+#error CFG_NIOS_TMRIRQ not defined (see documentation)
+#endif
+
+/****************************************************************************/
+
+struct	irq_action {
+	interrupt_handler_t *handler;
+	void *arg;
+	int count;
+};
+
+static struct irq_action vecs[32];
+
+/*************************************************************************/
+volatile ulong timestamp = 0;
+
+void reset_timer (void)
+{
+	timestamp = 0;
+}
+
+ulong get_timer (ulong base)
+{
+	WATCHDOG_RESET ();
+	return (timestamp - base);
+}
+
+void set_timer (ulong t)
+{
+	timestamp = t;
+}
+
+
+/* The board must handle this interrupt if a timer is not
+ * provided.
+ */
+#if defined(CFG_NIOS_TMRBASE)
+void tmr_isr (void *arg)
+{
+	nios_timer_t *tmr = (nios_timer_t *)arg;
+	/* Interrupt is cleared by writing anything to the
+	 * status register.
+	 */
+	tmr->status = 0;
+	timestamp += CFG_NIOS_TMRMS;
+#ifdef CONFIG_STATUS_LED
+	status_led_tick(timestamp);
+#endif
+}
+
+static void tmr_init (void)
+{
+	nios_timer_t *tmr =(nios_timer_t *)CACHE_BYPASS(CFG_NIOS_TMRBASE);
+
+	tmr->control &= ~(NIOS_TIMER_START | NIOS_TIMER_ITO);
+	tmr->control |= NIOS_TIMER_STOP;
+#if defined(CFG_NIOS_TMRCNT)
+	tmr->periodl = CFG_NIOS_TMRCNT & 0xffff;
+	tmr->periodh = (CFG_NIOS_TMRCNT >> 16) & 0xffff;
+#endif
+	tmr->control |= ( NIOS_TIMER_ITO |
+			  NIOS_TIMER_CONT |
+			  NIOS_TIMER_START );
+	irq_install_handler (CFG_NIOS_TMRIRQ, tmr_isr, (void *)tmr);
+}
+
+#endif /* CFG_NIOS_TMRBASE */
+
+/*************************************************************************/
+int disable_interrupts (void)
+{
+	int val = rdctl (CTL_STATUS);
+	wrctl (CTL_STATUS, val & ~STATUS_IE);
+	return (val & STATUS_IE);
+}
+
+void enable_interrupts( void )
+{
+	int val = rdctl (CTL_STATUS);
+	wrctl (CTL_STATUS, val | STATUS_IE);
+}
+
+void external_interrupt (struct pt_regs *regs)
+{
+	unsigned irqs;
+	struct irq_action *act;
+
+	/* Evaluate only irqs that are both enabled AND pending */
+	irqs = rdctl (CTL_IENABLE) & rdctl (CTL_IPENDING);
+	act = vecs;
+
+	/* Assume (as does the Nios2 HAL) that bit 0 is highest
+	 * priority. NOTE: There is ALWAYS a handler assigned
+	 * (the default if no other).
+	 */
+	while (irqs) {
+		if (irqs & 1) {
+			act->handler (act->arg);
+			act->count++;
+		}
+		irqs >>=1;
+		act++;
+	}
+}
+
+static void def_hdlr (void *arg)
+{
+	unsigned irqs = rdctl (CTL_IENABLE);
+
+	/* Disable the individual interrupt -- with gratuitous
+	 * warning.
+	 */
+	irqs &= ~(1 << (int)arg);
+	wrctl (CTL_IENABLE, irqs);
+	printf ("WARNING: Disabling unhandled interrupt: %d\n",
+			(int)arg);
+}
+
+/*************************************************************************/
+void irq_install_handler (int irq, interrupt_handler_t *hdlr, void *arg)
+{
+
+	int flag;
+	struct irq_action *act;
+	unsigned ena = rdctl (CTL_IENABLE);
+
+	if ((irq < 0) || (irq > 31))
+		return;
+	act = &vecs[irq];
+
+	flag = disable_interrupts ();
+	if (hdlr) {
+		act->handler = hdlr;
+		act->arg = arg;
+		ena |= (1 << irq);		/* enable */
+	} else {
+		act->handler = def_hdlr;
+		act->arg = (void *)irq;
+		ena &= ~(1 << irq);		/* disable */
+	}
+	wrctl (CTL_IENABLE, ena);
+	if (flag) enable_interrupts ();
+}
+
+
+int interrupt_init (void)
+{
+	int i;
+
+	/* Assign the default handler to all */
+	for (i = 0; i < 32; i++) {
+		vecs[i].handler = def_hdlr;
+		vecs[i].arg = (void *)i;
+		vecs[i].count = 0;
+	}
+
+#if defined(CFG_NIOS_TMRBASE)
+	tmr_init ();
+#endif
+
+	enable_interrupts ();
+	return (0);
+}
+
+
+/*************************************************************************/
+#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int i;
+	struct irq_action *act = vecs;
+
+	printf ("\nInterrupt-Information:\n\n");
+	printf ("Nr  Routine   Arg       Count\n");
+	printf ("-----------------------------\n");
+
+	for (i=0; i<32; i++) {
+		if (act->handler != def_hdlr) {
+			printf ("%02d  %08lx  %08lx  %d\n",
+				i,
+				(ulong)act->handler,
+				(ulong)act->arg,
+				act->count);
+		}
+		act++;
+	}
+	printf ("\n");
+
+	return (0);
+}
+#endif  /* CONFIG_COMMANDS & CFG_CMD_IRQ */
diff --git a/cpu/nios2/serial.c b/cpu/nios2/serial.c
new file mode 100644
index 0000000..2d08c93
--- /dev/null
+++ b/cpu/nios2/serial.c
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * 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 <watchdog.h>
+#include <nios2.h>
+#include <nios2-io.h>
+
+/*------------------------------------------------------------------
+ * JTAG acts as the serial port
+ *-----------------------------------------------------------------*/
+#if defined(CONFIG_CONSOLE_JTAG)
+
+static nios_jtag_t *jtag =
+	(nios_jtag_t *)CACHE_BYPASS(CFG_NIOS_CONSOLE);
+
+void serial_setbrg( void ){ return; }
+int serial_init( void ) { return(0);}
+
+void serial_putc (char c)
+{
+	unsigned val;
+
+	while (NIOS_JTAG_WSPACE (jtag->control) == 0)
+		WATCHDOG_RESET ();
+	jtag->data = (unsigned char)c;
+}
+
+void serial_puts (const char *s)
+{
+	while (*s != 0)
+		serial_putc (*s++);
+}
+
+int serial_tstc (void)
+{
+	return (jtag->control & NIOS_JTAG_RRDY);
+}
+
+int serial_getc (void)
+{
+	int c;
+	unsigned val;
+
+	while (1) {
+		WATCHDOG_RESET ();
+		val = jtag->data;
+		if (val & NIOS_JTAG_RVALID)
+			break;
+	}
+	c = val & 0x0ff;
+	return (c);
+}
+
+/*------------------------------------------------------------------
+ * UART the serial port
+ *-----------------------------------------------------------------*/
+#else
+
+static nios_uart_t *uart = (nios_uart_t *)
+	CACHE_BYPASS(CFG_NIOS_CONSOLE);
+
+#if defined(CFG_NIOS_FIXEDBAUD)
+
+/* Everything's already setup for fixed-baud PTF
+ * assignment
+ */
+void serial_setbrg (void){ return; }
+int serial_init (void) { return (0);}
+
+#else
+
+void serial_setbrg (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	unsigned div;
+
+	div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1;
+	uart->divisor = div;
+	return;
+}
+
+int serial_init (void)
+{
+	serial_setbrg ();
+	return (0);
+}
+
+#endif /* CFG_NIOS_FIXEDBAUD */
+
+
+/*-----------------------------------------------------------------------
+ * UART CONSOLE
+ *---------------------------------------------------------------------*/
+void serial_putc (char c)
+{
+	if (c == '\n')
+		serial_putc ('\r');
+	while ((uart->status & NIOS_UART_TRDY) == 0)
+		WATCHDOG_RESET ();
+	uart->txdata = (unsigned char)c;
+}
+
+void serial_puts (const char *s)
+{
+	while (*s != 0) {
+		serial_putc (*s++);
+	}
+}
+
+int serial_tstc (void)
+{
+	return (uart->status & NIOS_UART_RRDY);
+}
+
+int serial_getc (void)
+{
+	while (serial_tstc () == 0)
+		WATCHDOG_RESET ();
+	return( uart->rxdata & 0x00ff );
+}
+
+#endif /* CONFIG_JTAG_CONSOLE */
diff --git a/cpu/nios2/start.S b/cpu/nios2/start.S
new file mode 100644
index 0000000..281d42c
--- /dev/null
+++ b/cpu/nios2/start.S
@@ -0,0 +1,211 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * 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>
+
+/*************************************************************************
+ * RESTART
+ ************************************************************************/
+
+	.text
+	.global _start
+
+_start:
+	/* ICACHE INIT -- only the icache line at the reset address
+	 * is invalidated at reset. So the init must stay within
+	 * the cache line size (8 words). If GERMS is used, we'll
+	 * just be invalidating the cache a second time. If cache
+	 * is not implemented initi behaves as nop.
+	 */
+	movhi	r4, %hi(CFG_ICACHELINE_SIZE)
+	ori	r4, r4, %lo(CFG_ICACHELINE_SIZE)
+	movhi	r5, %hi(CFG_ICACHE_SIZE)
+	ori	r5, r5, %lo(CFG_ICACHE_SIZE)
+	mov	r6, r0
+0:	initi	r6
+	add	r6, r6, r4
+	bltu	r6, r5, 0b
+
+	/* INTERRUPTS -- for now, all interrupts masked and globally
+	 * disabled.
+	 */
+	wrctl	status, r0		/* Disable interrupts */
+	wrctl	ienable, r0		/* All disabled	*/
+
+	/* DCACHE INIT -- if dcache not implemented, initd behaves as
+	 * nop.
+	 */
+	movhi	r4, %hi(CFG_DCACHELINE_SIZE)
+	ori	r4, r4, %lo(CFG_DCACHELINE_SIZE)
+	movhi	r5, %hi(CFG_DCACHE_SIZE)
+	ori	r5, r5, %lo(CFG_DCACHE_SIZE)
+	mov	r6, r0
+1:	initd	0(r6)
+	add	r6, r6, r4
+	bltu	r6, r5, 1b
+
+	/* RELOCATE CODE, DATA & COMMAND TABLE -- the following code
+	 * assumes code, data and the command table are all
+	 * contiguous. This lets us relocate everything as a single
+	 * block. Make sure the linker script matches this ;-)
+	 */
+	nextpc	r4
+_cur:	movhi	r5, %hi(_cur - _start)
+	ori	r5, r5, %lo(_cur - _start)
+	sub	r4, r4, r5		/* r4 <- cur _start */
+	mov	r8, r4
+	movhi	r5, %hi(_start)
+	ori	r5, r5, %lo(_start)	/* r5 <- linked _start */
+	beq	r4, r5, 3f
+
+	movhi	r6, %hi(_edata)
+	ori	r6, r6, %lo(_edata)
+2:	ldwio	r7, 0(r4)
+	addi	r4, r4, 4
+	stwio	r7, 0(r5)
+	addi	r5, r5, 4
+	bne	r5, r6, 2b
+3:
+
+	/* ZERO BSS/SBSS -- bss and sbss are assumed to be adjacent
+	 * and between __bss_start and _end.
+	 */
+	 movhi	r5, %hi(__bss_start)
+	 ori	r5, r5, %lo(__bss_start)
+	 movhi	r6, %hi(_end)
+	 ori	r6, r6, %lo(_end)
+	 beq	r5, r6, 5f
+
+4:	stwio	r0, 0(r5)
+	 addi	r5, r5, 4
+	 bne	r5, r6, 4b
+5:
+
+	/* GLOBAL POINTER -- the global pointer is used to reference
+	 * "small data" (see -G switch). The linker script must
+	 * provide the gp address.
+	 */
+	 movhi	gp, %hi(_gp)
+	 ori	gp, gp, %lo(_gp)
+
+	/* JUMP TO RELOC ADDR */
+	movhi	r4, %hi(_reloc)
+	ori	r4, r4, %lo(_reloc)
+	jmp	r4
+_reloc:
+
+	/* COPY EXCEPTION TRAMPOLINE -- copy the tramp to the
+	 * exception address.
+	 */
+#if !defined(CONFIG_ROM_STUBS)
+	movhi	r4, %hi(_except_start)
+	ori	r4, r4, %lo(_except_start)
+	movhi	r5, %hi(_except_end)
+	ori	r5, r5, %lo(_except_end)
+	movhi	r6, %hi(CFG_EXCEPTION_ADDR)
+	ori	r6, r6, %lo(CFG_EXCEPTION_ADDR)
+
+6:	ldwio	r7, 0(r4)
+	stwio	r7, 0(r6)
+	addi	r4, r4, 4
+	addi	r6, r6, 4
+	bne	r4, r5, 6b
+#endif
+
+	/* STACK INIT -- zero top two words for call back chain.
+	 */
+	movhi	sp, %hi(CFG_INIT_SP)
+	ori	sp, sp, %lo(CFG_INIT_SP)
+	addi	sp, sp, -8
+	stw	r0, 0(sp)
+	stw	r0, 4(sp)
+	mov	fp, sp
+
+	/*
+	 * Call board_init -- never returns
+	 */
+	movhi	r4, %hi(board_init@h)
+	ori	r4, r4, %lo(board_init@h)
+	callr	r4
+
+	/* NEVER RETURNS -- but branch to the _start just
+	 * in case ;-)
+	 */
+	br	_start
+
+	/* EXCEPTION TRAMPOLINE -- the following gets copied
+	 * to the exception address.
+	 */
+_except_start:
+	movhi	et, %hi(_exception)
+	ori	et, et, %lo(_exception)
+	jmp	et
+_except_end:
+
+
+/*
+ * dly_clks -- Nios2 (like Nios1) doesn't have a timebase in
+ * the core. For simple delay loops, we do our best by counting
+ * instruction cycles.
+ *
+ * Instruction performance varies based on the core. For cores
+ * with icache and static/dynamic branch prediction (II/f, II/s):
+ *
+ * 	Normal ALU (e.g. add, cmp, etc):	1 cycle
+ * 	Branch (correctly predicted, taken):	2 cycles
+ *	Negative offset is predicted (II/s).
+ *
+ * For cores without icache and no branch prediction (II/e):
+ *
+ * 	Normal ALU (e.g. add, cmp, etc):	6 cycles
+ * 	Branch (no prediction):			6 cycles
+ *
+ * For simplicity, if an instruction cache is implemented we
+ * assume II/f or II/s. Otherwise, we use the II/e.
+ *
+ */
+ 	.globl dly_clks
+
+dly_clks:
+
+#if (CFG_ICACHE_SIZE > 0)
+	subi	r4, r4, 3		/* 3 clocks/loop	*/
+#else
+	subi	r4, r4, 12		/* 12 clocks/loop	*/
+#endif
+	bge	r4, r0, dly_clks
+	ret
+
+
+#if !defined(CONFIG_IDENT_STRING)
+#define CONFIG_IDENT_STRING ""
+#endif
+	.data
+	.globl	version_string
+
+version_string:
+	.ascii U_BOOT_VERSION
+	.ascii " (", __DATE__, " - ", __TIME__, ")"
+	.ascii CONFIG_IDENT_STRING, "\0"
diff --git a/cpu/nios2/traps.c b/cpu/nios2/traps.c
new file mode 100644
index 0000000..3f1517d
--- /dev/null
+++ b/cpu/nios2/traps.c
@@ -0,0 +1,42 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * 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/ptrace.h>
+#include <common.h>
+
+void trap_handler (struct pt_regs *regs)
+{
+	/* Just issue warning */
+	printf ("\n\n*** WARNING: unimplemented trap @ %08x\n\n",
+			regs->reg[29] - 4);
+}
+
+void soft_emulation (struct pt_regs *regs)
+{
+	/* TODO: Software emulation of mul/div etc. Until this is
+	 * implemented, generate warning and hang.
+	 */
+	printf ("\n\n*** ERROR: unimplemented instruction @ %08x\n",
+			regs->reg[29] - 4);
+	hang ();
+}