Initial revision
diff --git a/cpu/arm920t/Makefile b/cpu/arm920t/Makefile
new file mode 100644
index 0000000..e5ec81d
--- /dev/null
+++ b/cpu/arm920t/Makefile
@@ -0,0 +1,43 @@
+#
+# (C) Copyright 2000, 2001, 2002
+# 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	= serial.o interrupts.o cpu.o speed.o
+
+all:	.depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+.depend:	Makefile $(START:.o=.S) $(OBJS:.o=.c)
+		$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/cpu/arm920t/interrupts.c b/cpu/arm920t/interrupts.c
new file mode 100644
index 0000000..963ccbd
--- /dev/null
+++ b/cpu/arm920t/interrupts.c
@@ -0,0 +1,304 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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 <arm920t.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include <asm/proc-armv/ptrace.h>
+
+extern void reset_cpu(ulong addr);
+int timer_load_val = 0;
+
+/* macro to read the 16 bit timer */
+#define READ_TIMER (rTCNTO4 & 0xffff)
+
+#ifdef CONFIG_USE_IRQ
+/* enable IRQ interrupts */
+void enable_interrupts (void)
+{
+	unsigned long temp;
+	__asm__ __volatile__("mrs %0, cpsr\n"
+			     "bic %0, %0, #0x80\n"
+			     "msr cpsr_c, %0"
+			     : "=r" (temp)
+			     :
+			     : "memory");
+}
+
+
+/*
+ * disable IRQ/FIQ interrupts
+ * returns true if interrupts had been enabled before we disabled them
+ */
+int disable_interrupts (void)
+{
+	unsigned long old,temp;
+	__asm__ __volatile__("mrs %0, cpsr\n"
+			     "orr %1, %0, #0xc0\n"
+			     "msr cpsr_c, %1"
+			     : "=r" (old), "=r" (temp)
+			     :
+			     : "memory");
+	return (old & 0x80) == 0;
+}
+#else
+void enable_interrupts (void)
+{
+	return;
+}
+int disable_interrupts (void)
+{
+	return 0;
+}
+#endif
+
+
+
+void bad_mode (void)
+{
+	panic ("Resetting CPU ...\n");
+	reset_cpu (0);
+}
+
+void show_regs (struct pt_regs *regs)
+{
+	unsigned long flags;
+	const char *processor_modes[] = {
+	"USER_26",	"FIQ_26",	"IRQ_26",	"SVC_26",
+	"UK4_26",	"UK5_26",	"UK6_26",	"UK7_26",
+	"UK8_26",	"UK9_26",	"UK10_26",	"UK11_26",
+	"UK12_26",	"UK13_26",	"UK14_26",	"UK15_26",
+	"USER_32",	"FIQ_32",	"IRQ_32",	"SVC_32",
+	"UK4_32",	"UK5_32",	"UK6_32",	"ABT_32",
+	"UK8_32",	"UK9_32",	"UK10_32",	"UND_32",
+	"UK12_32",	"UK13_32",	"UK14_32",	"SYS_32",
+	};
+
+	flags = condition_codes (regs);
+
+	printf ("pc : [<%08lx>]    lr : [<%08lx>]\n"
+		"sp : %08lx  ip : %08lx  fp : %08lx\n",
+		instruction_pointer (regs),
+		regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
+	printf ("r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+		regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
+	printf ("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+		regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
+	printf ("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+		regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
+	printf ("Flags: %c%c%c%c",
+		flags & CC_N_BIT ? 'N' : 'n',
+		flags & CC_Z_BIT ? 'Z' : 'z',
+		flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
+	printf ("  IRQs %s  FIQs %s  Mode %s%s\n",
+		interrupts_enabled (regs) ? "on" : "off",
+		fast_interrupts_enabled (regs) ? "on" : "off",
+		processor_modes[processor_mode (regs)],
+		thumb_mode (regs) ? " (T)" : "");
+}
+
+void do_undefined_instruction (struct pt_regs *pt_regs)
+{
+	printf ("undefined instruction\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_software_interrupt (struct pt_regs *pt_regs)
+{
+	printf ("software interrupt\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_prefetch_abort (struct pt_regs *pt_regs)
+{
+	printf ("prefetch abort\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_data_abort (struct pt_regs *pt_regs)
+{
+	printf ("data abort\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_not_used (struct pt_regs *pt_regs)
+{
+	printf ("not used\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_fiq (struct pt_regs *pt_regs)
+{
+	printf ("fast interrupt request\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+void do_irq (struct pt_regs *pt_regs)
+{
+	printf ("interrupt request\n");
+	show_regs (pt_regs);
+	bad_mode ();
+}
+
+static ulong timestamp;
+static ulong lastdec;
+
+int interrupt_init (void)
+{
+	/* use PWM Timer 4 because it has no output */
+	/* prescaler for Timer 4 is 16 */
+	rTCFG0 = 0x0f00;
+	if (timer_load_val == 0)
+	{
+		/*
+		 * for 10 ms clock period @ PCLK with 4 bit divider = 1/2
+		 * (default) and prescaler = 16. Should be 10390
+		 * @33.25MHz and 15625 @ 50 MHz
+		 */
+		timer_load_val = get_PCLK()/(2 * 16 * 100);
+	}
+	/* load value for 10 ms timeout */
+	lastdec = rTCNTB4 = timer_load_val;
+	/* auto load, manual update of Timer 4 */
+	rTCON = 0x600000;
+	/* auto load, start Timer 4 */
+	rTCON = 0x500000;
+	timestamp = 0;
+
+	return (0);
+}
+
+/*
+ * timer without interrupts
+ */
+
+void reset_timer (void)
+{
+	reset_timer_masked ();
+}
+
+ulong get_timer (ulong base)
+{
+	return get_timer_masked () - base;
+}
+
+void set_timer (ulong t)
+{
+	timestamp = t;
+}
+
+void udelay (unsigned long usec)
+{
+	ulong tmo;
+
+	tmo = usec / 1000;
+	tmo *= (timer_load_val * 100);
+	tmo /= 1000;
+
+	tmo += get_timer (0);
+
+	while (get_timer_masked () < tmo)
+		/*NOP*/;
+}
+
+void reset_timer_masked (void)
+{
+	/* reset time */
+	lastdec = READ_TIMER;
+	timestamp = 0;
+}
+
+ulong get_timer_masked (void)
+{
+	ulong now = READ_TIMER;
+
+	if (lastdec >= now) {
+		/* normal mode */
+		timestamp += lastdec - now;
+	} else {
+		/* we have an overflow ... */
+		timestamp += lastdec + timer_load_val - now;
+	}
+	lastdec = now;
+
+	return timestamp;
+}
+
+void udelay_masked (unsigned long usec)
+{
+	ulong tmo;
+
+	tmo = usec / 1000;
+	tmo *= (timer_load_val * 100);
+	tmo /= 1000;
+
+	reset_timer_masked ();
+
+	while (get_timer_masked () < tmo)
+		/*NOP*/;
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk (void)
+{
+	ulong tbclk;
+
+#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
+	tbclk = timer_load_val * 100;
+#elif defined(CONFIG_SMDK2410)
+	tbclk = CFG_HZ;
+#endif
+
+	return tbclk;
+}
diff --git a/cpu/arm920t/serial.c b/cpu/arm920t/serial.c
new file mode 100644
index 0000000..c32e73b
--- /dev/null
+++ b/cpu/arm920t/serial.c
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * 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>
+#if defined(CONFIG_S3C2400) || defined(CONFIG_TRAB)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+
+void serial_setbrg (void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	int i;
+	unsigned int reg = 0;
+
+	/* value is calculated so : (int)(PCLK/16./baudrate) -1 */
+	reg = get_PCLK() / (16 * gd->baudrate) - 1;
+
+#ifdef CONFIG_SERIAL1
+	/* FIFO enable, Tx/Rx FIFO clear */
+	rUFCON0 = 0x07;
+	rUMCON0 = 0x0;
+	/* Normal,No parity,1 stop,8 bit */
+	rULCON0 = 0x3;
+	/*
+	 * tx=level,rx=edge,disable timeout int.,enable rx error int.,
+	 * normal,interrupt or polling
+	 */
+	rUCON0 = 0x245;
+	rUBRDIV0 = reg;
+
+#ifdef CONFIG_HWFLOW
+	rUMCON0 = 0x1; /* RTS up */
+#endif
+	for (i = 0; i < 100; i++);
+#elif CONFIG_SERIAL2
+# if defined(CONFIG_TRAB)
+#  #error "TRAB supports only CONFIG_SERIAL1"
+# endif
+	/* FIFO enable, Tx/Rx FIFO clear */
+	rUFCON1 = 0x06;
+	rUMCON1 = 0x0;
+	/* Normal,No parity,1 stop,8 bit */
+	rULCON1 = 0x3;
+	/*
+	 * tx=level,rx=edge,disable timeout int.,enable rx error int.,
+	 * normal,interrupt or polling
+	 */
+	rUCON1 = 0x245;
+	rUBRDIV1 = reg;
+
+#ifdef CONFIG_HWFLOW
+	rUMCON1 = 0x1; /* RTS up */
+#endif
+	for (i = 0; i < 100; i++);
+#else
+#error "Bad: you didn't configure serial ..."
+#endif
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+	serial_setbrg ();
+
+	return (0);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+#ifdef CONFIG_SERIAL1
+	while (!(rUTRSTAT0 & 0x1));
+
+	return rURXH0 & 0xff;
+#elif CONFIG_SERIAL2
+	while (!(rUTRSTAT1 & 0x1));
+
+	return rURXH1 & 0xff;
+#endif
+}
+
+#ifdef CONFIG_HWFLOW
+static int hwflow = 0; /* turned off by default */
+int hwflow_onoff(int on)
+{
+	switch(on) {
+	case 0:
+	default:
+		break; /* return current */
+	case 1:
+		hwflow = 1; /* turn on */
+		break;
+	case -1:
+		hwflow = 0; /* turn off */
+		break;
+	}
+	return hwflow;
+}
+#endif
+
+#ifdef CONFIG_MODEM_SUPPORT
+static int be_quiet = 0;
+void disable_putc(void)
+{
+	be_quiet = 1;
+}
+
+void enable_putc(void)
+{
+	be_quiet = 0;
+}
+#endif
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+#ifdef CONFIG_MODEM_SUPPORT
+	if (be_quiet)
+		return;
+#endif
+
+#ifdef CONFIG_SERIAL1
+	/* wait for room in the tx FIFO on SERIAL1 */
+	while (!(rUTRSTAT0 & 0x2));
+
+#ifdef CONFIG_HWFLOW
+	/* Wait for CTS up */
+	while(hwflow && !(rUMSTAT0 & 0x1))
+		;
+#endif
+
+	rUTXH0 = c;
+#elif CONFIG_SERIAL2
+	/* wait for room in the tx FIFO on SERIAL2 */
+	while (!(rUTRSTAT1 & 0x2));
+
+#ifdef CONFIG_HWFLOW
+	/* Wait for CTS up */
+	while(hwflow && !(rUMSTAT1 & 0x1))
+		;
+#endif
+	rUTXH1 = c;
+#endif
+
+	/* If \n, also do \r */
+	if (c == '\n')
+		serial_putc ('\r');
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+int serial_tstc (void)
+{
+#ifdef CONFIG_SERIAL1
+	return rUTRSTAT0 & 0x1;
+#elif CONFIG_SERIAL2
+	return rUTRSTAT1 & 0x1;
+#endif
+}
+
+void
+serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
diff --git a/cpu/arm920t/speed.c b/cpu/arm920t/speed.c
new file mode 100644
index 0000000..1ee0c1a
--- /dev/null
+++ b/cpu/arm920t/speed.c
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 2001-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
+ *
+ * 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
+ */
+
+/* This code should work for both the S3C2400 and the S3C2410
+ * as they seem to have the same PLL and clock machinery inside.
+ * The different address mapping is handled by the s3c24xx.h files below.
+ */
+
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#define MPLL 0
+#define UPLL 1
+
+/* ------------------------------------------------------------------------- */
+/* NOTE: This describes the proper use of this file.
+ *
+ * CONFIG_PLL_INPUT_FREQ should be defined as the input frequency of the PLL.
+ *
+ * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of
+ * the specified bus in HZ.
+ */
+/* ------------------------------------------------------------------------- */
+
+static ulong get_PLLCLK(int pllreg)
+{
+    ulong r, m, p, s;
+
+    if (pllreg == MPLL)
+	r = rMPLLCON;
+    else if (pllreg == UPLL)
+	r = rUPLLCON;
+    else
+	hang();
+
+    m = ((r & 0xFF000) >> 12) + 8;
+    p = ((r & 0x003F0) >> 4) + 2;
+    s = r & 0x3;
+
+    return((CONFIG_PLL_INPUT_FREQ * m) / (p << s));
+}
+
+/* return FCLK frequency */
+ulong get_FCLK(void)
+{
+    return(get_PLLCLK(MPLL));
+}
+
+/* return HCLK frequency */
+ulong get_HCLK(void)
+{
+    ulong clkdiv = rCLKDIVN;
+
+    return((clkdiv & 0x2) ? get_FCLK()/2 : get_FCLK());
+}
+
+/* return PCLK frequency */
+ulong get_PCLK(void)
+{
+    ulong clkdiv = rCLKDIVN;
+
+    return((clkdiv & 0x1) ? get_HCLK()/2 : get_HCLK());
+}
+
+/* return UCLK frequency */
+ulong get_UCLK(void)
+{
+    return(get_PLLCLK(UPLL));
+}