[ARM] 3369/1: ep93xx: add core cirrus ep93xx support

Patch from Lennert Buytenhek

This patch adds support for the Cirrus ep93xx series of CPUs.  The
ep93xx is an ARM920T based CPU with two VICs, PL010 based UARTs,
IrDA, MaverickCrunch floating point coprocessor, between 24 and 64
GPIOs, ethernet, OHCI USB and, depending on the model, pcmcia, raster
engine, graphics accelerator, IDE controller and a bunch of other
stuff.

This patch adds the core ep93xx support code, and support for the
Glomation GESBC-9312-sx and the Technologic Systems TS-72xx SBCs.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6e9e8ce..0dd24eb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -108,6 +108,13 @@
 	  Ethernet interface, two PCMCIA sockets, two serial ports and a
 	  parallel port.
 
+config ARCH_EP93XX
+	bool "EP93xx-based"
+	select ARM_AMBA
+	select ARM_VIC
+	help
+	  This enables support for the Cirrus EP93xx series of CPUs.
+
 config ARCH_FOOTBRIDGE
 	bool "FootBridge"
 	select FOOTBRIDGE
@@ -250,6 +257,8 @@
 
 source "arch/arm/mach-clps711x/Kconfig"
 
+source "arch/arm/mach-ep93xx/Kconfig"
+
 source "arch/arm/mach-footbridge/Kconfig"
 
 source "arch/arm/mach-integrator/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fbfc14a..b5b1e40 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -105,6 +105,7 @@
  machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
  machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
+ machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
new file mode 100644
index 0000000..cec5a21
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -0,0 +1,21 @@
+if ARCH_EP93XX
+
+menu "Cirrus EP93xx Implementation Options"
+
+comment "EP93xx Platforms"
+
+config MACH_GESBC9312
+	bool "Support Glomation GESBC-9312-sx"
+	help
+	  Say 'Y' here if you want your kernel to support the Glomation
+	  GESBC-9312-sx board.
+
+config MACH_TS72XX
+	bool "Support Technologic Systems TS-72xx SBC"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Technologic Systems TS-72xx board.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
new file mode 100644
index 0000000..5393af9
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux kernel.
+#
+obj-y			:= core.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o
+obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot
new file mode 100644
index 0000000..d5561ad
--- /dev/null
+++ b/arch/arm/mach-ep93xx/Makefile.boot
@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
new file mode 100644
index 0000000..f831f74
--- /dev/null
+++ b/arch/arm/mach-ep93xx/core.c
@@ -0,0 +1,173 @@
+/*
+ * arch/arm/mach-ep93xx/core.c
+ * Core routines for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * Thanks go to Michael Burian and Ray Lehtiniemi for their key
+ * role in the ep93xx linux community.
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/bitops.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/delay.h>
+#include <linux/amba/bus.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware/vic.h>
+
+
+/*************************************************************************
+ * Static I/O mappings that are needed for all EP93xx platforms
+ *************************************************************************/
+static struct map_desc ep93xx_io_desc[] __initdata = {
+	{
+		.virtual	= EP93XX_AHB_VIRT_BASE,
+		.pfn		= __phys_to_pfn(EP93XX_AHB_PHYS_BASE),
+		.length		= EP93XX_AHB_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= EP93XX_APB_VIRT_BASE,
+		.pfn		= __phys_to_pfn(EP93XX_APB_PHYS_BASE),
+		.length		= EP93XX_APB_SIZE,
+		.type		= MT_DEVICE,
+	},
+};
+
+void __init ep93xx_map_io(void)
+{
+	iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc));
+}
+
+
+/*************************************************************************
+ * Timer handling for EP93xx
+ *************************************************************************
+ * The ep93xx has four internal timers.  Timers 1, 2 (both 16 bit) and
+ * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate
+ * an interrupt on underflow.  Timer 4 (40 bit) counts down at 983.04 kHz,
+ * is free-running, and can't generate interrupts.
+ *
+ * The 508 kHz timers are ideal for use for the timer interrupt, as the
+ * most common values of HZ divide 508 kHz nicely.  We pick one of the 16
+ * bit timers (timer 1) since we don't need more than 16 bits of reload
+ * value as long as HZ >= 8.
+ *
+ * The higher clock rate of timer 4 makes it a better choice than the
+ * other timers for use in gettimeoffset(), while the fact that it can't
+ * generate interrupts means we don't have to worry about not being able
+ * to use this timer for something else.  We also use timer 4 for keeping
+ * track of lost jiffies.
+ */
+static unsigned int last_jiffy_time;
+
+#define TIMER4_TICKS_PER_JIFFY		((CLOCK_TICK_RATE + (HZ/2)) / HZ)
+
+static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+
+	__raw_writel(1, EP93XX_TIMER1_CLEAR);
+	while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time
+						>= TIMER4_TICKS_PER_JIFFY) {
+		last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
+		timer_tick(regs);
+	}
+
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction ep93xx_timer_irq = {
+	.name		= "ep93xx timer",
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= ep93xx_timer_interrupt,
+};
+
+static void __init ep93xx_timer_init(void)
+{
+	/* Enable periodic HZ timer.  */
+	__raw_writel(0x48, EP93XX_TIMER1_CONTROL);
+	__raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD);
+	__raw_writel(0xc8, EP93XX_TIMER1_CONTROL);
+
+	/* Enable lost jiffy timer.  */
+	__raw_writel(0x100, EP93XX_TIMER4_VALUE_HIGH);
+
+	setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
+}
+
+static unsigned long ep93xx_gettimeoffset(void)
+{
+	int offset;
+
+	offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
+
+	/* Calculate (1000000 / 983040) * offset.  */
+	return offset + (53 * offset / 3072);
+}
+
+struct sys_timer ep93xx_timer = {
+	.init		= ep93xx_timer_init,
+	.offset		= ep93xx_gettimeoffset,
+};
+
+
+/*************************************************************************
+ * EP93xx IRQ handling
+ *************************************************************************/
+void __init ep93xx_init_irq(void)
+{
+	vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
+	vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
+}
+
+
+/*************************************************************************
+ * EP93xx peripheral handling
+ *************************************************************************/
+void __init ep93xx_init_devices(void)
+{
+	unsigned int v;
+
+	/*
+	 * Disallow access to MaverickCrunch initially.
+	 */
+	v = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG);
+	v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE;
+	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+	__raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG);
+}
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
new file mode 100644
index 0000000..d18fcb1
--- /dev/null
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -0,0 +1,40 @@
+/*
+ * arch/arm/mach-ep93xx/gesbc9312.c
+ * Glomation GESBC-9312-sx support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/physmap.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init gesbc9312_init_machine(void)
+{
+	ep93xx_init_devices();
+	physmap_configure(0x60000000, 0x00800000, 4, NULL);
+}
+
+MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.map_io		= ep93xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= gesbc9312_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
new file mode 100644
index 0000000..777e75d
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -0,0 +1,118 @@
+/*
+ * arch/arm/mach-ep93xx/ts72xx.c
+ * Technologic Systems TS72xx SBC support.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/physmap.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+static struct map_desc ts72xx_io_desc[] __initdata = {
+	{
+		.virtual	= TS72XX_MODEL_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
+		.length		= TS72XX_MODEL_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_OPTIONS_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
+		.length		= TS72XX_OPTIONS_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_OPTIONS2_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
+		.length		= TS72XX_OPTIONS2_SIZE,
+		.type		= MT_DEVICE,
+	}
+};
+
+static struct map_desc ts72xx_nand_io_desc[] __initdata = {
+	{
+		.virtual	= TS72XX_NAND_DATA_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_NAND1_DATA_PHYS_BASE),
+		.length		= TS72XX_NAND_DATA_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_NAND_CONTROL_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_NAND1_CONTROL_PHYS_BASE),
+		.length		= TS72XX_NAND_CONTROL_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_NAND_BUSY_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_NAND1_BUSY_PHYS_BASE),
+		.length		= TS72XX_NAND_BUSY_SIZE,
+		.type		= MT_DEVICE,
+	}
+};
+
+static struct map_desc ts72xx_alternate_nand_io_desc[] __initdata = {
+	{
+		.virtual	= TS72XX_NAND_DATA_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_NAND2_DATA_PHYS_BASE),
+		.length		= TS72XX_NAND_DATA_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_NAND_CONTROL_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_NAND2_CONTROL_PHYS_BASE),
+		.length		= TS72XX_NAND_CONTROL_SIZE,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= TS72XX_NAND_BUSY_VIRT_BASE,
+		.pfn		= __phys_to_pfn(TS72XX_NAND2_BUSY_PHYS_BASE),
+		.length		= TS72XX_NAND_BUSY_SIZE,
+		.type		= MT_DEVICE,
+	}
+};
+
+static void __init ts72xx_map_io(void)
+{
+	ep93xx_map_io();
+	iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc));
+
+	/*
+	 * The TS-7200 has NOR flash, the other models have NAND flash.
+	 */
+	if (!board_is_ts7200()) {
+		if (is_ts9420_installed()) {
+			iotable_init(ts72xx_alternate_nand_io_desc,
+				ARRAY_SIZE(ts72xx_alternate_nand_io_desc));
+		} else {
+			iotable_init(ts72xx_nand_io_desc,
+				ARRAY_SIZE(ts72xx_nand_io_desc));
+		}
+	}
+}
+
+static void __init ts72xx_init_machine(void)
+{
+	ep93xx_init_devices();
+	if (board_is_ts7200())
+		physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+}
+
+MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= EP93XX_APB_PHYS_BASE,
+	.io_pg_offst	= ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.map_io		= ts72xx_map_io,
+	.init_irq	= ep93xx_init_irq,
+	.timer		= &ep93xx_timer,
+	.init_machine	= ts72xx_init_machine,
+MACHINE_END
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 3b79d0e..eaaec90 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -62,7 +62,7 @@
 # ARM920T
 config CPU_ARM920T
 	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
+	depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
 	default y if ARCH_S3C2410 || ARCH_AT91RM9200
 	select CPU_32v4
 	select CPU_ABRT_EV4T
diff --git a/include/asm-arm/arch-ep93xx/debug-macro.S b/include/asm-arm/arch-ep93xx/debug-macro.S
new file mode 100644
index 0000000..397565a
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/debug-macro.S
@@ -0,0 +1,22 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/debug-macro.S
+ * Debugging macro include header
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+#include <asm/arch/ep93xx-regs.h>
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1				@ MMU enabled?
+		ldreq	\rx, =EP93XX_APB_PHYS_BASE	@ Physical base
+		ldrne	\rx, =EP93XX_APB_VIRT_BASE	@ virtual base
+		orr	\rx, \rx, #0x000c0000
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/include/asm-arm/arch-ep93xx/dma.h b/include/asm-arm/arch-ep93xx/dma.h
new file mode 100644
index 0000000..898b3ab
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/dma.h
@@ -0,0 +1,3 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/dma.h
+ */
diff --git a/include/asm-arm/arch-ep93xx/entry-macro.S b/include/asm-arm/arch-ep93xx/entry-macro.S
new file mode 100644
index 0000000..84140a2
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/entry-macro.S
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/entry-macro.S
+ * IRQ demultiplexing for EP93xx
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+#include <asm/arch/ep93xx-regs.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\base, =(EP93XX_AHB_VIRT_BASE)
+		orr	\base, \base, #0x000b0000
+		mov	\irqnr, #0
+		ldr	\irqstat, [\base]		@ lower 32 interrupts
+		cmp	\irqstat, #0
+		bne	1001f
+
+		eor	\base, \base, #0x00070000
+		ldr	\irqstat, [\base]		@ upper 32 interrupts
+		cmp	\irqstat, #0
+		beq	1002f
+		mov	\irqnr, #0x20
+
+1001:
+		movs	\tmp, \irqstat, lsl #16
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #16
+
+		movs	\tmp, \irqstat, lsl #8
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #8
+
+		movs	\tmp, \irqstat, lsl #4
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #4
+
+		movs	\tmp, \irqstat, lsl #2
+		movne	\irqstat, \tmp
+		addeq	\irqnr, \irqnr, #2
+
+		movs	\tmp, \irqstat, lsl #1
+		addeq	\irqnr, \irqnr, #1
+		orrs	\base, \base, #1
+
+1002:
+		.endm
diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
new file mode 100644
index 0000000..693f238
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
@@ -0,0 +1,114 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/ep93xx-regs.h
+ */
+
+#ifndef __ASM_ARCH_EP93XX_REGS_H
+#define __ASM_ARCH_EP93XX_REGS_H
+
+/*
+ * EP93xx linux memory map:
+ *
+ * virt		phys		size
+ * fe800000			5M		per-platform mappings
+ * fed00000	80800000	2M		APB
+ * fef00000	80000000	1M		AHB
+ */
+
+#define EP93XX_AHB_PHYS_BASE		0x80000000
+#define EP93XX_AHB_VIRT_BASE		0xfef00000
+#define EP93XX_AHB_SIZE			0x00100000
+
+#define EP93XX_APB_PHYS_BASE		0x80800000
+#define EP93XX_APB_VIRT_BASE		0xfed00000
+#define EP93XX_APB_SIZE			0x00200000
+
+
+/* AHB peripherals */
+#define EP93XX_DMA_BASE			(EP93XX_AHB_VIRT_BASE + 0x00000000)
+
+#define EP93XX_ETHERNET_BASE		(EP93XX_AHB_VIRT_BASE + 0x00010000)
+
+#define EP93XX_USB_BASE			(EP93XX_AHB_VIRT_BASE + 0x00020000)
+#define EP93XX_USB_PHYS_BASE		(EP93XX_AHB_PHYS_BASE + 0x00020000)
+
+#define EP93XX_RASTER_BASE		(EP93XX_AHB_VIRT_BASE + 0x00030000)
+
+#define EP93XX_GRAPHICS_ACCEL_BASE	(EP93XX_AHB_VIRT_BASE + 0x00040000)
+
+#define EP93XX_SDRAM_CONTROLLER_BASE	(EP93XX_AHB_VIRT_BASE + 0x00060000)
+
+#define EP93XX_PCMCIA_CONTROLLER_BASE	(EP93XX_AHB_VIRT_BASE + 0x00080000)
+
+#define EP93XX_BOOT_ROM_BASE		(EP93XX_AHB_VIRT_BASE + 0x00090000)
+
+#define EP93XX_IDE_BASE			(EP93XX_AHB_VIRT_BASE + 0x000a0000)
+
+#define EP93XX_VIC1_BASE		(EP93XX_AHB_VIRT_BASE + 0x000b0000)
+
+#define EP93XX_VIC2_BASE		(EP93XX_AHB_VIRT_BASE + 0x000c0000)
+
+
+/* APB peripherals */
+#define EP93XX_TIMER_BASE		(EP93XX_APB_VIRT_BASE + 0x00010000)
+#define EP93XX_TIMER_REG(x)		(EP93XX_TIMER_BASE + (x))
+#define EP93XX_TIMER1_LOAD		EP93XX_TIMER_REG(0x00)
+#define EP93XX_TIMER1_VALUE		EP93XX_TIMER_REG(0x04)
+#define EP93XX_TIMER1_CONTROL		EP93XX_TIMER_REG(0x08)
+#define EP93XX_TIMER1_CLEAR		EP93XX_TIMER_REG(0x0c)
+#define EP93XX_TIMER2_LOAD		EP93XX_TIMER_REG(0x20)
+#define EP93XX_TIMER2_VALUE		EP93XX_TIMER_REG(0x24)
+#define EP93XX_TIMER2_CONTROL		EP93XX_TIMER_REG(0x28)
+#define EP93XX_TIMER2_CLEAR		EP93XX_TIMER_REG(0x2c)
+#define EP93XX_TIMER4_VALUE_LOW		EP93XX_TIMER_REG(0x60)
+#define EP93XX_TIMER4_VALUE_HIGH	EP93XX_TIMER_REG(0x64)
+#define EP93XX_TIMER3_LOAD		EP93XX_TIMER_REG(0x80)
+#define EP93XX_TIMER3_VALUE		EP93XX_TIMER_REG(0x84)
+#define EP93XX_TIMER3_CONTROL		EP93XX_TIMER_REG(0x88)
+#define EP93XX_TIMER3_CLEAR		EP93XX_TIMER_REG(0x8c)
+
+#define EP93XX_I2S_BASE			(EP93XX_APB_VIRT_BASE + 0x00020000)
+
+#define EP93XX_SECURITY_BASE		(EP93XX_APB_VIRT_BASE + 0x00030000)
+
+#define EP93XX_GPIO_BASE		(EP93XX_APB_VIRT_BASE + 0x00040000)
+
+#define EP93XX_AAC_BASE			(EP93XX_APB_VIRT_BASE + 0x00080000)
+
+#define EP93XX_SPI_BASE			(EP93XX_APB_VIRT_BASE + 0x000a0000)
+
+#define EP93XX_IRDA_BASE		(EP93XX_APB_VIRT_BASE + 0x000b0000)
+
+#define EP93XX_UART1_BASE		(EP93XX_APB_VIRT_BASE + 0x000c0000)
+#define EP93XX_UART1_PHYS_BASE		(EP93XX_APB_PHYS_BASE + 0x000c0000)
+
+#define EP93XX_UART2_BASE		(EP93XX_APB_VIRT_BASE + 0x000d0000)
+#define EP93XX_UART2_PHYS_BASE		(EP93XX_APB_PHYS_BASE + 0x000d0000)
+
+#define EP93XX_UART3_BASE		(EP93XX_APB_VIRT_BASE + 0x000e0000)
+#define EP93XX_UART3_PHYS_BASE		(EP93XX_APB_PHYS_BASE + 0x000e0000)
+
+#define EP93XX_KEY_MATRIX_BASE		(EP93XX_APB_VIRT_BASE + 0x000f0000)
+
+#define EP93XX_ADC_BASE			(EP93XX_APB_VIRT_BASE + 0x00100000)
+#define EP93XX_TOUCHSCREEN_BASE		(EP93XX_APB_VIRT_BASE + 0x00100000)
+
+#define EP93XX_PWM_BASE			(EP93XX_APB_VIRT_BASE + 0x00110000)
+
+#define EP93XX_RTC_BASE			(EP93XX_APB_VIRT_BASE + 0x00120000)
+
+#define EP93XX_SYSCON_BASE		(EP93XX_APB_VIRT_BASE + 0x00130000)
+#define EP93XX_SYSCON_REG(x)		(EP93XX_SYSCON_BASE + (x))
+#define EP93XX_SYSCON_POWER_STATE	EP93XX_SYSCON_REG(0x00)
+#define EP93XX_SYSCON_CLOCK_CONTROL	EP93XX_SYSCON_REG(0x04)
+#define EP93XX_SYSCON_CLOCK_UARTBAUD	0x20000000
+#define EP93XX_SYSCON_CLOCK_USH_EN	0x10000000
+#define EP93XX_SYSCON_HALT		EP93XX_SYSCON_REG(0x08)
+#define EP93XX_SYSCON_STANDBY		EP93XX_SYSCON_REG(0x0c)
+#define EP93XX_SYSCON_DEVICE_CONFIG	EP93XX_SYSCON_REG(0x80)
+#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE	0x00800000
+#define EP93XX_SYSCON_SWLOCK		EP93XX_SYSCON_REG(0xc0)
+
+#define EP93XX_WATCHDOG_BASE		(EP93XX_APB_VIRT_BASE + 0x00140000)
+
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/gesbc9312.h b/include/asm-arm/arch-ep93xx/gesbc9312.h
new file mode 100644
index 0000000..4d0b302
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/gesbc9312.h
@@ -0,0 +1,3 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/gesbc9312.h
+ */
diff --git a/include/asm-arm/arch-ep93xx/hardware.h b/include/asm-arm/arch-ep93xx/hardware.h
new file mode 100644
index 0000000..9b69f45
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/hardware.h
@@ -0,0 +1,12 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/hardware.h
+ */
+
+#include "ep93xx-regs.h"
+
+#define pcibios_assign_all_busses()	0
+
+#include "platform.h"
+
+#include "gesbc9312.h"
+#include "ts72xx.h"
diff --git a/include/asm-arm/arch-ep93xx/io.h b/include/asm-arm/arch-ep93xx/io.h
new file mode 100644
index 0000000..7b4d25e
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/io.h
@@ -0,0 +1,8 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/io.h
+ */
+
+#define IO_SPACE_LIMIT		0xffffffff
+
+#define __io(p)			((void __iomem *)(p))
+#define __mem_pci(p)		(p)
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
new file mode 100644
index 0000000..8c10fb9
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -0,0 +1,78 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/irqs.h
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define IRQ_EP93XX_COMMRX		2
+#define IRQ_EP93XX_COMMTX		3
+#define IRQ_EP93XX_TIMER1		4
+#define IRQ_EP93XX_TIMER2		5
+#define IRQ_EP93XX_AACINTR		6
+#define IRQ_EP93XX_DMAM2P0		7
+#define IRQ_EP93XX_DMAM2P1		8
+#define IRQ_EP93XX_DMAM2P2		9
+#define IRQ_EP93XX_DMAM2P3		10
+#define IRQ_EP93XX_DMAM2P4		11
+#define IRQ_EP93XX_DMAM2P5		12
+#define IRQ_EP93XX_DMAM2P6		13
+#define IRQ_EP93XX_DMAM2P7		14
+#define IRQ_EP93XX_DMAM2P8		15
+#define IRQ_EP93XX_DMAM2P9		16
+#define IRQ_EP93XX_DMAM2M0		17
+#define IRQ_EP93XX_DMAM2M1		18
+#define IRQ_EP93XX_GPIO0MUX		20
+#define IRQ_EP93XX_GPIO1MUX		21
+#define IRQ_EP93XX_GPIO2MUX		22
+#define IRQ_EP93XX_GPIO3MUX		22
+#define IRQ_EP93XX_UART1RX		23
+#define IRQ_EP93XX_UART1TX		24
+#define IRQ_EP93XX_UART2RX		25
+#define IRQ_EP93XX_UART2TX		26
+#define IRQ_EP93XX_UART3RX		27
+#define IRQ_EP93XX_UART3TX		28
+#define IRQ_EP93XX_KEY			29
+#define IRQ_EP93XX_TOUCH		30
+#define EP93XX_VIC1_VALID_IRQ_MASK	0x7ffffffc
+
+#define IRQ_EP93XX_EXT0			32
+#define IRQ_EP93XX_EXT1			33
+#define IRQ_EP93XX_EXT2			34
+#define IRQ_EP93XX_64HZ			35
+#define IRQ_EP93XX_WATCHDOG		36
+#define IRQ_EP93XX_RTC			37
+#define IRQ_EP93XX_IRDA			38
+#define IRQ_EP93XX_ETHERNET		39
+#define IRQ_EP93XX_EXT3			40
+#define IRQ_EP93XX_PROG			41
+#define IRQ_EP93XX_1HZ			42
+#define IRQ_EP93XX_VSYNC		43
+#define IRQ_EP93XX_VIDEO_FIFO		44
+#define IRQ_EP93XX_SSP1RX		45
+#define IRQ_EP93XX_SSP1TX		46
+#define IRQ_EP93XX_GPIO4MUX		47
+#define IRQ_EP93XX_GPIO5MUX		48
+#define IRQ_EP93XX_GPIO6MUX		49
+#define IRQ_EP93XX_GPIO7MUX		50
+#define IRQ_EP93XX_TIMER3		51
+#define IRQ_EP93XX_UART1		52
+#define IRQ_EP93XX_SSP			53
+#define IRQ_EP93XX_UART2		54
+#define IRQ_EP93XX_UART3		55
+#define IRQ_EP93XX_USB			56
+#define IRQ_EP93XX_ETHERNET_PME		57
+#define IRQ_EP93XX_DSP			58
+#define IRQ_EP93XX_GPIO_AB		59
+#define IRQ_EP93XX_SAI			60
+#define EP93XX_VIC2_VALID_IRQ_MASK	0x1fffffff
+
+#define NR_EP93XX_IRQS			64
+
+#define EP93XX_BOARD_IRQ(x)		(NR_EP93XX_IRQS + (x))
+#define EP93XX_BOARD_IRQS		32
+
+#define NR_IRQS				(NR_EP93XX_IRQS + EP93XX_BOARD_IRQS)
+
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/memory.h b/include/asm-arm/arch-ep93xx/memory.h
new file mode 100644
index 0000000..4b1a5c7
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/memory.h
@@ -0,0 +1,14 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/memory.h
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET		UL(0x00000000)
+
+#define __bus_to_virt(x)	__phys_to_virt(x)
+#define __virt_to_bus(x)	__virt_to_phys(x)
+
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
new file mode 100644
index 0000000..df9cbb6
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/platform.h
@@ -0,0 +1,14 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/platform.h
+ */
+
+#ifndef __ASSEMBLY__
+
+void ep93xx_map_io(void);
+void ep93xx_init_irq(void);
+void ep93xx_init_time(unsigned long);
+void ep93xx_init_devices(void);
+extern struct sys_timer ep93xx_timer;
+
+
+#endif
diff --git a/include/asm-arm/arch-ep93xx/system.h b/include/asm-arm/arch-ep93xx/system.h
new file mode 100644
index 0000000..79b7185
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/system.h
@@ -0,0 +1,26 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/system.h
+ */
+
+#include <asm/hardware.h>
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	u32 devicecfg;
+
+	local_irq_disable();
+
+	devicecfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG);
+	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+	__raw_writel(devicecfg | 0x80000000, EP93XX_SYSCON_DEVICE_CONFIG);
+	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
+	__raw_writel(devicecfg & ~0x80000000, EP93XX_SYSCON_DEVICE_CONFIG);
+
+	while (1)
+		;
+}
diff --git a/include/asm-arm/arch-ep93xx/timex.h b/include/asm-arm/arch-ep93xx/timex.h
new file mode 100644
index 0000000..4140bdd
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/timex.h
@@ -0,0 +1,5 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/timex.h
+ */
+
+#define CLOCK_TICK_RATE		983040
diff --git a/include/asm-arm/arch-ep93xx/ts72xx.h b/include/asm-arm/arch-ep93xx/ts72xx.h
new file mode 100644
index 0000000..412215e
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/ts72xx.h
@@ -0,0 +1,90 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/ts72xx.h
+ */
+
+/*
+ * TS72xx memory map:
+ *
+ * virt		phys		size
+ * febff000	22000000	4K	model number register
+ * febfe000	22400000	4K	options register
+ * febfd000	22800000	4K	options register #2
+ * febfc000	[67]0000000	4K	NAND data register
+ * febfb000	[67]0400000	4K	NAND control register
+ * febfa000	[67]0800000	4K	NAND busy register
+ */
+
+#define TS72XX_MODEL_PHYS_BASE		0x22000000
+#define TS72XX_MODEL_VIRT_BASE		0xfebff000
+#define TS72XX_MODEL_SIZE		0x00001000
+
+#define TS72XX_MODEL_TS7200		0x00
+#define TS72XX_MODEL_TS7250		0x01
+#define TS72XX_MODEL_TS7260		0x02
+
+
+#define TS72XX_OPTIONS_PHYS_BASE	0x22400000
+#define TS72XX_OPTIONS_VIRT_BASE	0xfebfe000
+#define TS72XX_OPTIONS_SIZE		0x00001000
+
+#define TS72XX_OPTIONS_COM2_RS485	0x02
+#define TS72XX_OPTIONS_MAX197		0x01
+
+
+#define TS72XX_OPTIONS2_PHYS_BASE	0x22800000
+#define TS72XX_OPTIONS2_VIRT_BASE	0xfebfd000
+#define TS72XX_OPTIONS2_SIZE		0x00001000
+
+#define TS72XX_OPTIONS2_TS9420		0x04
+#define TS72XX_OPTIONS2_TS9420_BOOT	0x02
+
+
+#define TS72XX_NOR_PHYS_BASE		0x60000000
+#define TS72XX_NOR2_PHYS_BASE		0x62000000
+
+#define TS72XX_NAND1_DATA_PHYS_BASE	0x60000000
+#define TS72XX_NAND2_DATA_PHYS_BASE	0x70000000
+#define TS72XX_NAND_DATA_VIRT_BASE	0xfebfc000
+#define TS72XX_NAND_DATA_SIZE		0x00001000
+
+#define TS72XX_NAND1_CONTROL_PHYS_BASE	0x60400000
+#define TS72XX_NAND2_CONTROL_PHYS_BASE	0x70400000
+#define TS72XX_NAND_CONTROL_VIRT_BASE	0xfebfb000
+#define TS72XX_NAND_CONTROL_SIZE	0x00001000
+
+#define TS72XX_NAND1_BUSY_PHYS_BASE	0x60800000
+#define TS72XX_NAND2_BUSY_PHYS_BASE	0x70800000
+#define TS72XX_NAND_BUSY_VIRT_BASE	0xfebfa000
+#define TS72XX_NAND_BUSY_SIZE		0x00001000
+
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+static inline int board_is_ts7200(void)
+{
+	return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7200;
+}
+
+static inline int board_is_ts7250(void)
+{
+	return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7250;
+}
+
+static inline int board_is_ts7260(void)
+{
+	return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260;
+}
+
+static inline int is_max197_installed(void)
+{
+	return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
+					TS72XX_OPTIONS_MAX197);
+}
+
+static inline int is_ts9420_installed(void)
+{
+	return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
+					TS72XX_OPTIONS2_TS9420);
+}
+#endif
diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h
new file mode 100644
index 0000000..4410d21
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/uncompress.h
@@ -0,0 +1,53 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/uncompress.h
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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.
+ */
+
+#include <asm/arch/ep93xx-regs.h>
+
+static unsigned char __raw_readb(unsigned int ptr)
+{
+	return *((volatile unsigned char *)ptr);
+}
+
+static void __raw_writeb(unsigned char value, unsigned int ptr)
+{
+	*((volatile unsigned char *)ptr) = value;
+}
+
+
+#define PHYS_UART1_DATA		0x808c0000
+#define PHYS_UART1_FLAG		0x808c0018
+#define UART1_FLAG_TXFF		0x20
+
+static __inline__ void putc(char c)
+{
+	int i;
+
+	for (i = 0; i < 1000; i++) {
+		/* Transmit fifo not full?  */
+		if (!(__raw_readb(PHYS_UART1_FLAG) & UART1_FLAG_TXFF))
+			break;
+	}
+
+	__raw_writeb(c, PHYS_UART1_DATA);
+}
+
+static void putstr(const char *s)
+{
+	while (*s) {
+		putc(*s);
+		if (*s == '\n')
+			putc('\r');
+		s++;
+	}
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-ep93xx/vmalloc.h b/include/asm-arm/arch-ep93xx/vmalloc.h
new file mode 100644
index 0000000..205ea6b
--- /dev/null
+++ b/include/asm-arm/arch-ep93xx/vmalloc.h
@@ -0,0 +1,5 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/vmalloc.h
+ */
+
+#define VMALLOC_END	0xfe800000