--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -220,6 +220,9 @@
 	help
 	  This enables support for the Cirrus EP93xx series of CPUs.
 
+config ARCH_SL2312
+    bool "SL2312"
+
 config ARCH_FOOTBRIDGE
 	bool "FootBridge"
 	select FOOTBRIDGE
@@ -414,6 +417,8 @@
 
 source "arch/arm/mach-footbridge/Kconfig"
 
+source "arch/arm/mach-sl2312/Kconfig"
+
 source "arch/arm/mach-integrator/Kconfig"
 
 source "arch/arm/mach-iop32x/Kconfig"
@@ -549,6 +554,16 @@
 config PCI_SYSCALL
 	def_bool PCI
 
+config SL2312_LPC
+    bool "LPC Host Support"
+    depends on ARCH_SL2312
+    help
+
+config SL2312_LPC_IT8712
+    bool "IT8712 Support"
+    depends on ARCH_SL2312 && SL2312_LPC
+    help
+
 # Select the host bridge type
 config PCI_HOST_VIA82C505
 	bool
@@ -988,6 +1003,10 @@
 source "drivers/mtd/Kconfig"
 endif
 
+if ARCH_SL2312
+source "drivers/telephony/Kconfig"
+endif
+
 source "drivers/parport/Kconfig"
 
 source "drivers/pnp/Kconfig"
@@ -997,7 +1016,7 @@
 if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
 	|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
 	|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
-	|| ARCH_IXP23XX
+	|| ARCH_IXP23XX || ARCH_SL2312
 source "drivers/ide/Kconfig"
 endif
 
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -72,6 +72,7 @@
 tune-$(CONFIG_CPU_ARM922T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM925T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_FA52X)    :=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
 tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
@@ -111,6 +112,7 @@
  machine-$(CONFIG_ARCH_PXA)	   := pxa
  machine-$(CONFIG_ARCH_L7200)	   := l7200
  machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
+ machine-$(CONFIG_ARCH_SL2312)     := sl2312
  textofs-$(CONFIG_ARCH_CLPS711X)   := 0x00028000
  machine-$(CONFIG_ARCH_CLPS711X)   := clps711x
  machine-$(CONFIG_ARCH_IOP32X)	   := iop32x
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -19,6 +19,10 @@
 OBJS		+= head-shark.o ofw-shark.o
 endif
 
+ifeq ($(CONFIG_ARCH_SL2312),y)
+OBJS		+= head-sl2312.o
+endif
+
 ifeq ($(CONFIG_ARCH_L7200),y)
 OBJS		+= head-l7200.o
 endif
--- /dev/null
+++ b/arch/arm/boot/compressed/head-sl2312.S
@@ -0,0 +1,6 @@
+#include <asm/mach-types.h>
+#include <asm/arch/sl2312.h>
+
+		.section	".start", "ax"
+		mov	r7, #MACH_TYPE_SL2312
+
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -57,6 +57,17 @@
 		mov	\rb, #0x50000000
 		add	\rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
 		.endm
+/*****************************************************
+ *      for Storlink SoC
+ *****************************************************/
+#elif defined(CONFIG_ARCH_SL2312)
+		.macro	loadsp, rb
+		mov	\rb, #0x16000000
+		.endm
+		.macro	writeb, rb
+		strb	\rb, [r3, #0]
+		.endm
+/****************************************************/
 #else
 		.macro	loadsp,	rb
 		addruart \rb
@@ -116,7 +127,28 @@
 		.rept	8
 		mov	r0, r0
 		.endr
-
+/*****************************************************************************
+ *  for Storlink Soc -- on chip UART
+ *****************************************************************************/
+#ifndef CONFIG_SERIAL_IT8712		// Jason test
+@                mov     r3, #0x22000000
+                mov     r3, #0x42000000
+                mov     r11, #0x80
+                strb    r11, [r3, #0xc]
+                mov     r11, #0x0
+                strb    r11, [r3, #0x4]
+#ifndef CONFIG_SL3516_ASIC
+                mov     r11, #0x9C		/*0x9c->19200 0x4E->38400 0x34->57600 */
+#else
+		mov 	r11, #0x9C		/* 0x61 for 30MHz on GeminiA chip*/
+#endif
+                strb    r11, [r3, #0x0]
+                mov     r11, #0x03
+                strb    r11, [r3, #0xc]
+		        mov     r11, #0xFB
+                strb    r11, [r3, #0x18]
+#endif
+/*****************************************************************************/
 		b	1f
 		.word	0x016f2818		@ Magic numbers to help the loader
 		.word	start			@ absolute load/run zImage address
@@ -458,6 +490,39 @@
 		mcr	p15, 0, r0, c7, c5, 4	@ ISB
 		mov	pc, r12
 
+/*****************************************************************************
+ *  for Storlink Soc -- CPU cache
+ *****************************************************************************/
+__fa526_cache_on:
+                mov     r12, lr
+                bl      __setup_mmu
+                mov     r0, #0
+                mcr     p15, 0, r0, c7, c6, 0   @ Invalidate D cache
+                mcr     p15, 0, r0, c7, c5, 0   @ Invalidate I cache
+                mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
+                mcr     p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
+                mcr     p15, 0, r3, c2, c0, 0   @ load page table pointer
+                mov     r0, #-1
+                mcr     p15, 0, r0, c3, c0, 0   @ load domain access register
+                mrc     p15, 0, r0, c1, c0, 0
+                mov     r0, r0
+                mov     r0, r0
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+        orr     r0, r0, #0x0004                 @ .... .... .... .1..
+#endif
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+        orr     r0, r0, #0x1000                 @ ...1 .... .... ....
+#endif
+
+#ifndef DEBUG
+                orr     r0, r0, #0x0039         @ Write buffer, mmu
+#endif
+                mcr     p15, 0, r0, c1, c0
+                mov     r0, r0
+                mov     r0, r0
+                mov     pc, r12
+/********************************************************************************/
+
 __arm6_mmu_cache_on:
 		mov	r12, lr
 		bl	__setup_mmu
@@ -625,6 +690,16 @@
 
 		@ These match on the architecture ID
 
+/*****************************************************************************
+ *  for Storlink Soc -- CPU architecture ID
+ *****************************************************************************/
+        .word   0x66015261              @ FA526
+        .word   0xff01fff1
+        b       __fa526_cache_on
+        b       __fa526_cache_off
+        b       __fa526_cache_flush
+/*****************************************************************************/
+
 		.word	0x00020000		@ ARMv4T
 		.word	0x000f0000
 		b	__armv4_mmu_cache_on
@@ -712,6 +787,23 @@
 		mcr	p15, 0, r0, c8, c7, 0	@ invalidate whole TLB
 		mov	pc, r12
 
+/*****************************************************************************
+ *  for Storlink Soc -- CPU cache
+ *****************************************************************************/
+__fa526_cache_off:
+        mrc     p15, 0, r0, c1, c0
+        bic     r0, r0, #0x000d
+        mov     r1, #0
+        mcr     p15, 0, r1, c7, c14, 0  @ clean and invalidate D cache
+        mcr     p15, 0, r1, c7, c10, 4  @ drain WB
+        mcr     p15, 0, r0, c1, c0      @ turn MMU and cache off
+        mov     r0, #0
+        mcr     p15, 0, r0, c7, c5, 0   @ invalidate whole cache v4
+        mcr     p15, 0, r0, c8, c7, 0   @ invalidate whole TLB v4
+        mov     pc, lr
+/*****************************************************************************/
+
+
 __arm6_mmu_cache_off:
 		mov	r0, #0x00000030		@ ARM6 control reg.
 		b	__armv3_mmu_cache_off
@@ -759,6 +851,17 @@
 		mcr	p15, 0, ip, c7, c10, 4	@ drain WB
 		mov	pc, lr
 		
+/*****************************************************************************
+ *  for Storlink Soc -- CPU cache
+ *****************************************************************************/
+__fa526_cache_flush:
+                mov     r1, #0
+                mcr     p15, 0, r1, c7, c14, 0  @ clean and invalidate D cache
+                mcr     p15, 0, r1, c7, c5, 0   @ flush I cache
+                mcr     p15, 0, r1, c7, c10, 4  @ drain WB
+                mov     pc, lr
+/*****************************************************************************/
+
 
 __armv6_mmu_cache_flush:
 		mov	r1, #0
--- /dev/null
+++ b/arch/arm/boot/compressed/it8712.h
@@ -0,0 +1,25 @@
+
+#ifndef __IT8712_H__
+#define __IT8712_H__
+
+#include "asm/arch/sl2312.h"
+
+#define IT8712_IO_BASE			SL2312_LPC_IO_BASE
+//#define IT8712_IO_BASE			0x27000000
+// Device LDN
+#define LDN_SERIAL1				0x01
+#define LDN_SERIAL2				0x02
+#define LDN_PARALLEL			0x03
+#define LDN_KEYBOARD			0x05
+#define LDN_MOUSE				0x06
+#define LDN_GPIO				0x07
+
+#define IT8712_UART1_PORT      	0x3F8
+#define IT8712_UART2_PORT      	0x2F8
+
+#define IT8712_GPIO_BASE		0x800	// 0x800-0x804 for GPIO set1-set5
+
+void LPCSetConfig(char LdnNumber, char Index, char data);
+char LPCGetConfig(char LdnNumber, char Index);
+
+#endif
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -30,7 +30,7 @@
 #include <asm/arch/uncompress.h>
 
 #ifdef CONFIG_DEBUG_ICEDCC
-
+#include "it8712.h"
 #ifdef CONFIG_CPU_V6
 
 static void icedcc_putc(int ch)
@@ -69,6 +69,7 @@
 #define flush()	do { } while (0)
 #endif
 
+#if 0
 static void putstr(const char *ptr)
 {
 	char c;
@@ -81,11 +82,36 @@
 
 	flush();
 }
+#endif
 
 #endif
 
 #define __ptr_t void *
 
+#ifdef CONFIG_SERIAL_IT8712
+unsigned int it8712_uart_base;
+#define UART_RX         0
+#define UART_TX         0
+#define UART_DLL        0
+#define UART_TRG        0
+#define UART_DLM        1
+#define UART_IER        1
+#define UART_FCTR       1
+#define UART_IIR        2
+#define UART_FCR        2
+#define UART_EFR        2
+#define UART_LCR        3
+#define UART_MCR        4
+#define UART_LSR        5
+#define UART_MSR        6
+#define UART_SCR        7
+#define UART_EMSR       7
+void LPCEnterMBPnP(void);
+void LPCExitMBPnP(void);
+int SearchIT8712(void);
+int InitLPCInterface(void);
+#endif
+
 /*
  * Optimised C version of memzero for the ARM.
  */
@@ -346,6 +372,9 @@
 decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
 		  int arch_id)
 {
+#ifdef CONFIG_SERIAL_IT8712
+        unsigned char *addr;
+#endif
 	output_data		= (uch *)output_start;	/* Points to kernel start */
 	free_mem_ptr		= free_mem_ptr_p;
 	free_mem_ptr_end	= free_mem_ptr_end_p;
@@ -353,6 +382,33 @@
 
 	arch_decomp_setup();
 
+#ifdef CONFIG_SERIAL_IT8712
+
+        InitLPCInterface();
+        LPCSetConfig(0, 0x02, 0x01);
+        LPCSetConfig(LDN_SERIAL1, 0x30, 0x1);
+        LPCSetConfig(LDN_SERIAL1, 0x23, 0x0);
+        it8712_uart_base = IT8712_IO_BASE;
+        it8712_uart_base += ((LPCGetConfig(LDN_SERIAL1, 0x60) << 8) + LPCGetConfig(LDN_SERIAL1, 0x61));
+
+        do {
+        addr = (unsigned char *)(it8712_uart_base + UART_LCR) ;
+        *addr = 0x80;
+        // Set Baud Rate
+        addr = (unsigned char *)(it8712_uart_base+UART_DLL);
+        *addr = 0x06 ;
+        addr = (unsigned char *)(it8712_uart_base+UART_DLM);
+        *addr = 0x00 ;
+
+        addr = (unsigned char *)(it8712_uart_base+UART_LCR);    // LCR
+        *addr = 0x07 ;
+        addr = (unsigned char *)(it8712_uart_base+UART_MCR);    // MCR
+        *addr = 0x08 ;
+        addr = (unsigned char *)(it8712_uart_base+UART_FCR);    // FCR
+        *addr = 0x01 ;
+    	} while(0);
+#endif
+
 	makecrc();
 	putstr("Uncompressing Linux...");
 	gunzip();
@@ -374,4 +430,119 @@
 	return 0;
 }
 #endif
+
+#ifdef CONFIG_SERIAL_IT8712
+
+#define LPC_KEY_ADDR    (unsigned char *)(SL2312_LPC_IO_BASE + 0x2e)
+#define LPC_DATA_ADDR   (unsigned char *)(SL2312_LPC_IO_BASE + 0x2f)
+#define LPC_BUS_CTRL                    *( unsigned char*) (SL2312_LPC_HOST_BASE + 0)
+#define LPC_BUS_STATUS                  *( unsigned char*) (SL2312_LPC_HOST_BASE + 2)
+#define LPC_SERIAL_IRQ_CTRL             *( unsigned char*) (SL2312_LPC_HOST_BASE + 4)
+
+char LPCGetConfig(char LdnNumber, char Index)
+{
+        char rtn;
+        unsigned char *addr ;
+
+        LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
+
+        addr = LPC_KEY_ADDR;
+        *addr = 0x07 ;
+
+        addr = LPC_DATA_ADDR;
+        *addr = LdnNumber ;
+
+        addr = LPC_KEY_ADDR;
+        *addr = Index ;
+
+        addr = LPC_DATA_ADDR ;
+        rtn = *addr ;
+
+        LPCExitMBPnP();
+        return rtn;
+
+}
+
+void LPCSetConfig(char LdnNumber, char Index, char data)
+{
+        unsigned char *addr;
+        LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
+        addr = LPC_KEY_ADDR;
+        *addr = 0x07;
+        addr = LPC_DATA_ADDR;
+        *addr = LdnNumber;
+        addr = LPC_KEY_ADDR;
+        *addr = Index;
+        addr = LPC_DATA_ADDR;
+        *addr = data;
+
+        LPCExitMBPnP();
+}
+
+//unsigned char key[4] ;
+void LPCEnterMBPnP(void)
+{
+        unsigned char *addr;
+        addr = LPC_KEY_ADDR;
+        unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
+
+ 		do {
+ 		*addr = key[0];
+ 		*addr = key[1];
+ 		*addr = key[2];
+ 		*addr = key[3];
+ 		}while(0);
+}
+
+void LPCExitMBPnP(void)
+{
+        unsigned char *addr;
+        addr = LPC_KEY_ADDR;
+        *addr = 0x02 ;
+
+        addr = LPC_DATA_ADDR;
+        *addr = 0x02 ;
+}
+
+int InitLPCInterface(void)
+{
+        int i;
+        LPC_BUS_CTRL = 0xc0;
+        LPC_SERIAL_IRQ_CTRL = 0xc0;
+
+        for(i=0;i<0x2000;i++) ;
+
+        LPC_SERIAL_IRQ_CTRL = 0x80;
+        if (!SearchIT8712()) ;
+//			while(1);
+        return 0;
+}
+
+int SearchIT8712(void)
+{
+        unsigned char Id1, Id2;
+        unsigned short Id;
+        unsigned char *addr;
+
+        LPCEnterMBPnP();
+        addr = LPC_KEY_ADDR;
+        *addr = 0x20 ;
+        addr = LPC_DATA_ADDR;
+        Id1 = *addr ;
+
+        addr = LPC_KEY_ADDR;
+        *addr = 0x21 ;
+        addr = LPC_DATA_ADDR;
+        Id2 = *addr ;
+
+        Id = (Id1 << 8) | Id2;
+        LPCExitMBPnP();
+
+        if (Id == 0x8712)
+                return 1;
+        else
+                return 0;
+}
+
+#endif
 	
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -18,6 +18,8 @@
 #include <asm/memory.h>
 #include <asm/glue.h>
 #include <asm/vfpmacros.h>
+#include <asm/arch/irqs.h>
+#include <asm/hardware.h>
 #include <asm/arch/entry-macro.S>
 #include <asm/thread_notify.h>
 
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -40,6 +40,8 @@
 #include <asm/system.h>
 #include <asm/mach/time.h>
 
+extern int fixup_irq(unsigned int irq);
+
 /*
  * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
  */
@@ -111,8 +113,11 @@
 asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
-	struct irq_desc *desc = irq_desc + irq;
+//	struct irq_desc *desc = irq_desc + irq;
+	struct irq_desc *desc;
 
+	irq = fixup_irq(irq);
+	desc = irq_desc + irq;
 	/*
 	 * Some hardware gives randomly wrong interrupts.  Rather
 	 * than crashing, do something sensible.
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -117,7 +117,7 @@
 void (*pm_idle)(void);
 EXPORT_SYMBOL(pm_idle);
 
-void (*pm_power_off)(void);
+//void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
 void (*arm_pm_restart)(char str) = arm_machine_restart;
@@ -188,13 +188,37 @@
 
 void machine_halt(void)
 {
+	unsigned int reg_v;
+
+	printk("arch_power_off\n");
+
+	reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
+	reg_v &= ~0x00000002;
+	reg_v |= 0x1;
+	mdelay(5);
+	// Power off
+	__raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
+
 }
 
 
 void machine_power_off(void)
 {
-	if (pm_power_off)
+	unsigned int reg_v;
+
+//	if (pm_power_off)
+	if (&pm_power_off!=NULL)
 		pm_power_off();
+
+	printk("arch_power_off\n");
+
+	reg_v = readl(IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
+	reg_v &= ~0x00000002;
+	reg_v |= 0x1;
+	mdelay(5);
+	// Power off
+	__raw_writel( reg_v, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
+
 }
 
 void machine_restart(char * __unused)
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -502,8 +502,13 @@
 
 device_initcall(timer_init_sysfs);
 
+extern unsigned int rtc_get_time_second(void);
+
 void __init time_init(void)
 {
+#ifdef CONFIG_SL2312_RTC
+	xtime.tv_sec  = rtc_get_time_second() ;
+#endif
 #ifndef CONFIG_GENERIC_TIME
 	if (system_timer->offset == NULL)
 		system_timer->offset = dummy_gettimeoffset;
--- /dev/null
+++ b/arch/arm/mach-sl2312/Kconfig
@@ -0,0 +1,33 @@
+
+menu "SL2312"
+
+config SL3516_ASIC
+	bool "SL3516 ASIC version"
+	depends on ARCH_SL2312
+	help
+	  This option to select AISC or FPGA
+config PCI
+       bool "SL2312 PCI"
+       depends on ARCH_SL2312
+       help
+         This option to enable Storlink PCI controller
+
+config SL2312_LPC
+       bool "SL2312 LPC"
+       depends on ARCH_SL2312
+       help
+         This option to enable Low Pin Count controller
+
+config SL2312_USB
+       bool "SL2312 USB"
+       depends on ARCH_SL2312
+       help
+         This option to enable USB OTG host controller
+
+config GEMINI_IPI
+       bool "Gemini IPI test"
+       depends on ARCH_SL2312
+       help
+	 Enable this option to test dual cpu Inter-Processor-Interrupt
+endmenu
+
--- /dev/null
+++ b/arch/arm/mach-sl2312/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+
+obj-y			:= arch.o irq.o mm.o time.o sl3516_device.o
+obj-m			:=
+obj-n			:=
+
+
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_SL2312_LPC) += lpc.o
+obj-$(CONFIG_SL2312_USB) += sl2312-otg.o # sl2312-otg-1.o
+obj-$(CONFIG_GEMINI_XOR_ACCE) += xor.o
+obj-$(CONFIG_GEMINI_IPI)      += gemini_ipi.o
--- /dev/null
+++ b/arch/arm/mach-sl2312/Makefile.boot
@@ -0,0 +1,5 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00508100
+#params_phys-y	:= 0x00008100
+initrd_phys-y	:= 0x00800000
+
--- /dev/null
+++ b/arch/arm/mach-sl2312/arch.c
@@ -0,0 +1,72 @@
+/*
+ *  linux/arch/arm/mach-epxa10db/arch.c
+ *
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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 <linux/types.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+
+extern void sl2312_map_io(void);
+extern void sl2312_init_irq(void);
+extern unsigned long sl2312_gettimeoffset (void);
+extern void __init sl2312_time_init(void);
+
+static struct sys_timer sl2312_timer = {
+	.init		= sl2312_time_init,
+	.offset		= sl2312_gettimeoffset,
+};
+
+static void __init
+sl2312_fixup(struct machine_desc *desc, struct tag *tags,
+                 char **cmdline, struct meminfo *mi)
+{
+        mi->nr_banks      = 1;
+        mi->bank[0].start = 0;
+#ifdef CONFIG_GEMINI_IPI
+        mi->bank[0].size  = (64*1024*1024);  // 128M
+#else
+        mi->bank[0].size  = (128*1024*1024);  // 128M
+#endif
+        mi->bank[0].node  = 0;
+}
+
+/* MACHINE_START(SL2312, "GeminiA")
+	MAINTAINER("Storlink Semi")
+	BOOT_MEM(0x00000000, 0x90000000, 0xf0000000)
+        FIXUP(sl2312_fixup)
+	MAPIO(sl2312_map_io)
+	INITIRQ(sl2312_init_irq)
+	.timer = &sl2312_timer,
+MACHINE_END */
+
+MACHINE_START(SL2312, "GeminiA")
+	/* .phys_ram	= 0x00000000, */
+	.phys_io	= 0x7fffc000,
+	.io_pg_offst	= ((0xffffc000) >> 18) & 0xfffc,
+	.boot_params	= 0x100,
+	.fixup      = sl2312_fixup,
+	.map_io		= sl2312_map_io,
+	.init_irq	= sl2312_init_irq,
+	.timer		= &sl2312_timer,
+MACHINE_END
--- /dev/null
+++ b/arch/arm/mach-sl2312/gemini_ipi.c
@@ -0,0 +1,593 @@
+/*
+ * FILE NAME sl_cir.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *  IPI Driver for CPU1.
+ *
+ *  Author: StorLink, Corp.
+ *          Jason Lee
+ *
+ * Copyright 2002~2006 StorLink, Corp.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMit8712D  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE	LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMit8712D   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, writ8712  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <linux/signal.h>
+#include <asm/arch/sl2312.h>
+#include <asm/arch/int_ctrl.h>
+#include <asm/arch/ipi.h>
+#include <linux/dma-mapping.h>
+
+
+#include <linux/mm.h>
+
+#include <linux/bootmem.h>
+
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
+#include <asm/mach/map.h>
+
+
+static int sl_ipi_debug = 1 ;
+#define DEB(x)  if(sl_ipi_debug>=1) x
+
+#define SRAM_PTR		IO_ADDRESS(SL2312_SRAM_BASE)
+volatile JSCALE_REQ_T *req=(JSCALE_REQ_T*)SRAM_PTR;
+volatile JSCALE_RSP_T *rsp=(JSCALE_RSP_T*)(SRAM_PTR+0x20);
+
+unsigned int jscale_status=0;
+
+#define JSCALE_WAIT	0
+#define XXXXXX_WAIT	1
+#define MAX_WAIT_Q	8
+wait_queue_head_t gemini_ipi_wait[MAX_WAIT_Q];
+
+#define DRAMCTL_DMA_CTL		0X20
+#define DRAMCTL_DMA_SA		0X24
+#define DRAMCTL_DMA_DA		0X28
+#define DRAMCTL_DMA_CNT		0X2C
+#define MEMCPY_UNIT		0x40000
+int hw_memcpy(const void *to, const void *from, unsigned int bytes)
+{
+	unsigned int reg_a,reg_d;
+	int count = bytes,i=0;
+
+	consistent_sync((unsigned int *)to, bytes, DMA_BIDIRECTIONAL);
+	consistent_sync((unsigned int *)from,bytes, DMA_TO_DEVICE);
+
+	DEB(printk("hwmemcpy:count %d\n",count));
+	while(count>0){
+		// SA
+		reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_SA;
+		reg_d = (unsigned int )__virt_to_phys(from) + i*MEMCPY_UNIT;
+		DEB(printk("hwmemcpy:from 0x%08x\n",reg_d));
+		writel(reg_d,reg_a);
+		// DA
+		reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_DA;
+		reg_d = (unsigned int )__virt_to_phys(to) + i*MEMCPY_UNIT;
+		writel(reg_d,reg_a);
+		DEB(printk("hwmemcpy:to 0x%08x\n",reg_d));
+		// byte count
+		reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CNT;
+		reg_d = (count>=MEMCPY_UNIT)?MEMCPY_UNIT:count;
+		writel(reg_d,reg_a);
+		// start DMA
+		reg_a = IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL;
+		writel(0x80000001,reg_a);
+
+		do{
+			cond_resched();
+//			msleep(4);
+			reg_d = readl(IO_ADDRESS(SL2312_DRAM_CTRL_BASE)+DRAMCTL_DMA_CTL);
+		}while(reg_d&0x1);
+
+		count -= MEMCPY_UNIT;
+		i++;
+	}
+
+	return bytes;
+}
+
+static irqreturn_t ipi_interrupt()
+{
+	unsigned int id=getcpuid(),tmp;
+
+	//dmac_inv_range(__phys_to_virt(SL2312_SRAM_BASE),__phys_to_virt(SHAREADDR)+0x2000);
+
+
+	// Clear Interrupt
+	if(id==CPU0) {
+		tmp = readl(CPU1_STATUS);
+		tmp &= ~CPU_IPI_BIT_MASK;
+		writel(tmp,CPU1_STATUS);
+	}
+	else{
+		tmp = readl(CPU0_STATUS);
+		tmp &= ~CPU_IPI_BIT_MASK;
+		writel(tmp,CPU0_STATUS);
+	}
+
+	//
+	DEB(printk("ipi interrupt:0x%x\n",rsp->status));
+	switch(rsp->status){
+		case JSCALE_STATUS_OK:
+
+			break;
+		case JSCALE_UNKNOWN_MSG_TYPE:
+
+			break;
+		case JSCALE_FAILED_FILE_SIZE:
+
+			break;
+		case JSCALE_FAILED_MALLOC:
+
+			break;
+		case JSCALE_FAILED_FORMAT:
+
+			break;
+		case JSCALE_DECODE_ERROR:
+
+			break;
+
+	}
+	jscale_status = rsp->status;
+//	wake_up(&gemini_ipi_wait[JSCALE_WAIT]);
+
+	return IRQ_HANDLED;
+}
+
+static int gemini_ipi_open(struct inode *inode, struct file *file)
+{
+	DEB(printk("ipi open\n"));
+	return 0;
+}
+
+
+static int gemini_ipi_release(struct inode *inode, struct file *file)
+{
+	DEB(printk("ipi release\n"));
+	return 0;
+}
+
+
+static int gemini_ipi_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg)
+{
+	JSCALE_RSP_T tmp;
+
+	switch(cmd) {
+		case GEMINI_IPI_JSCALE_REQ:
+			DEB(printk("ipi:ioctl jscale request %dX%d Q:%d\n",req->ScaledImageWidth,req->ScaledImageHeight,req->ScaledImageQuality));
+			if (copy_from_user(req, (JSCALE_REQ_T *)arg, sizeof(JSCALE_REQ_T)))
+				return -EFAULT;
+			req->hdr.type = IPC_JSCALE_REQ_MSG;
+			req->hdr.length = sizeof(JSCALE_REQ_T);
+			req->input_location  = CPU_1_DATA_OFFSET;
+			req->output_location = CPU_1_DATA_OFFSET;
+			break;
+		case GEMINI_IPI_JSCALE_STAT:
+			DEB(printk("ipi:ioctl jscale stat \n"));
+			if(jscale_status==JSCALE_BUSY){						// not yet
+				tmp.status = JSCALE_BUSY;
+				if (copy_to_user((JSCALE_RSP_T *)arg,&tmp, sizeof(JSCALE_RSP_T)))
+					return -EFAULT;
+			}
+			else{												// finish or error
+				if (copy_to_user((JSCALE_RSP_T *)arg,rsp, sizeof(JSCALE_RSP_T)))
+					return -EFAULT;
+			}
+			break;
+		default:
+			printk("IPI: Error IOCTL number\n");
+			return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+#define SRAM_SIZE	0x2000
+static ssize_t gemini_ipi_write(struct file *file_p, const char *buf, size_t count, loff_t * ppos)
+{
+	int i=0,tmp=0,j;
+	const char *ptr=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
+	DEB(printk("ipi:write 0x%x to 0x%x length:%d\n",&buf,ptr,count));
+	memcpy(ptr,buf,count);
+	consistent_sync(ptr,count, DMA_TO_DEVICE);
+	//hw_memcpy(ptr,&buf,count);
+
+/*	if(count>SRAM_SIZE){
+		for(i=0;i<(count/SRAM_SIZE);i++)
+			raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,SRAM_SIZE);
+		if(count%SRAM_SIZE)
+			raid_memcpy(ptr+i*SRAM_SIZE,buf+i*SRAM_SIZE,count%SRAM_SIZE);
+	}
+	else
+		raid_memcpy(ptr,buf,count);
+*/
+
+/*	for(i=0;i<count;i++){
+		if(buf[i]!=ptr[i])
+			printk("ipi error:offset %d valud %x[should %x]\n",i,ptr[i],buf[i]);
+	}
+
+	printk("===========input buf===============\n");
+	for(i=0;i<64;i+=16){
+		for(j=0;j<16;j++)
+			printk("%02x ",buf[i+j]);
+		printk("\n");
+		cond_resched();
+	}
+	printk("===========output buf==============\n");
+	for(i=0;i<64;i+=16){
+		for(j=0;j<16;j++)
+			printk("%02x ",ptr[i+j]);
+		printk("\n");
+		cond_resched();
+	}
+*/
+	// send irq for CPU1
+	tmp |= CPU_IPI_BIT_MASK;
+	writel(tmp,CPU0_STATUS);
+	jscale_status = JSCALE_BUSY;
+
+	return count;
+}
+
+static ssize_t gemini_ipi_read(struct file * file_p, char *buf, size_t length, loff_t * ppos)
+{
+	int i=0;
+	const char *ptr=(unsigned int )__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
+
+	consistent_sync(ptr,length, DMA_FROM_DEVICE);
+	memcpy(buf,ptr,length);
+	DEB(printk("ipi:read 0x%x to 0x%x length:%d\n",ptr,buf,length));
+
+	//consistent_sync((unsigned int *)ptr,0x2000, DMA_FROM_DEVICE);		// invalid
+	//hw_memcpy(buf,ptr,length);
+
+	// need encoded file size ********
+/*	if(count>SRAM_SIZE){
+		for(i=0;i<(count/SRAM_SIZE);i++)
+			raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,SRAM_SIZE);
+		if(count%0xFFFF)
+			raid_memcpy(buf+i*SRAM_SIZE,p_mbox->message+i*SRAM_SIZE,length%SRAM_SIZE);
+	}
+	else
+		raid_memcpy(buf,p_mbox->message,length);
+*/
+	return length;
+}
+
+void do_mapping_read(struct address_space *mapping,
+			     struct file_ra_state *_ra,
+			     struct file *filp,
+			     loff_t *ppos,
+			     read_descriptor_t *desc,
+			     read_actor_t actor)
+{
+	struct inode *inode = mapping->host;
+	unsigned long index;
+	unsigned long end_index;
+	unsigned long offset;
+	unsigned long last_index;
+	unsigned long next_index;
+	unsigned long prev_index;
+	loff_t isize;
+	struct page *cached_page;
+	int error;
+	struct file_ra_state ra = *_ra;
+
+	cached_page = NULL;
+	index = *ppos >> PAGE_CACHE_SHIFT;
+	next_index = index;
+	prev_index = ra.prev_page;
+	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
+	offset = *ppos & ~PAGE_CACHE_MASK;
+
+	isize = i_size_read(inode);
+	if (!isize)
+		goto out;
+
+	end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+	for (;;) {
+		struct page *page;
+		unsigned long nr, ret;
+
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index >= end_index) {
+			if (index > end_index)
+				goto out;
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				goto out;
+			}
+		}
+		nr = nr - offset;
+
+		cond_resched();
+		if (index == next_index)
+			next_index = page_cache_readahead(mapping, &ra, filp,
+					index, last_index - index);
+
+find_page:
+		page = find_get_page(mapping, index);
+		if (unlikely(page == NULL)) {
+			handle_ra_miss(mapping, &ra, index);
+			goto no_cached_page;
+		}
+		if (!PageUptodate(page))
+			goto page_not_up_to_date;
+page_ok:
+
+		/* If users can be writing to this page using arbitrary
+		 * virtual addresses, take care about potential aliasing
+		 * before reading the page on the kernel side.
+		 */
+		if (mapping_writably_mapped(mapping))
+			flush_dcache_page(page);
+
+		/*
+		 * When (part of) the same page is read multiple times
+		 * in succession, only mark it as accessed the first time.
+		 */
+		if (prev_index != index)
+			mark_page_accessed(page);
+		prev_index = index;
+
+		/*
+		 * Ok, we have the page, and it's up-to-date, so
+		 * now we can copy it to user space...
+		 *
+		 * The actor routine returns how many bytes were actually used..
+		 * NOTE! This may not be the same as how much of a user buffer
+		 * we filled up (we may be padding etc), so we can only update
+		 * "pos" here (the actor routine has to update the user buffer
+		 * pointers and the remaining count).
+		 */
+		ret = actor(desc, page, offset, nr);
+		offset += ret;
+		index += offset >> PAGE_CACHE_SHIFT;
+		offset &= ~PAGE_CACHE_MASK;
+
+		page_cache_release(page);
+		if (ret == nr && desc->count)
+			continue;
+		goto out;
+
+page_not_up_to_date:
+		/* Get exclusive access to the page ... */
+		lock_page(page);
+
+		/* Did it get unhashed before we got the lock? */
+		if (!page->mapping) {
+			unlock_page(page);
+			page_cache_release(page);
+			continue;
+		}
+
+		/* Did somebody else fill it already? */
+		if (PageUptodate(page)) {
+			unlock_page(page);
+			goto page_ok;
+		}
+
+readpage:
+		/* Start the actual read. The read will unlock the page. */
+		error = mapping->a_ops->readpage(filp, page);
+
+		if (unlikely(error))
+			goto readpage_error;
+
+		if (!PageUptodate(page)) {
+			lock_page(page);
+			if (!PageUptodate(page)) {
+				if (page->mapping == NULL) {
+					/*
+					 * invalidate_inode_pages got it
+					 */
+					unlock_page(page);
+					page_cache_release(page);
+					goto find_page;
+				}
+				unlock_page(page);
+				error = -EIO;
+				goto readpage_error;
+			}
+			unlock_page(page);
+		}
+
+		/*
+		 * i_size must be checked after we have done ->readpage.
+		 *
+		 * Checking i_size after the readpage allows us to calculate
+		 * the correct value for "nr", which means the zero-filled
+		 * part of the page is not copied back to userspace (unless
+		 * another truncate extends the file - this is desired though).
+		 */
+		isize = i_size_read(inode);
+		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+		if (unlikely(!isize || index > end_index)) {
+			page_cache_release(page);
+			goto out;
+		}
+
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index == end_index) {
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				page_cache_release(page);
+				goto out;
+			}
+		}
+		nr = nr - offset;
+		goto page_ok;
+
+readpage_error:
+		/* UHHUH! A synchronous read error occurred. Report it */
+		desc->error = error;
+		page_cache_release(page);
+		goto out;
+
+no_cached_page:
+		/*
+		 * Ok, it wasn't cached, so we need to create a new
+		 * page..
+		 */
+		if (!cached_page) {
+			cached_page = page_cache_alloc_cold(mapping);
+			if (!cached_page) {
+				desc->error = -ENOMEM;
+				goto out;
+			}
+		}
+		error = add_to_page_cache_lru(cached_page, mapping,
+						index, GFP_KERNEL);
+		if (error) {
+			if (error == -EEXIST)
+				goto find_page;
+			desc->error = error;
+			goto out;
+		}
+		page = cached_page;
+		cached_page = NULL;
+		goto readpage;
+	}
+
+out:
+	*_ra = ra;
+
+	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
+	if (cached_page)
+		page_cache_release(cached_page);
+	if (filp)
+		file_accessed(filp);
+}
+
+int ipi_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
+{
+	ssize_t written;
+	unsigned long count = desc->count;
+	struct file *file = desc->arg.data;
+	unsigned int *ptr_to=(unsigned int)__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET) + desc->written;
+	void *ptr_from;
+
+	if (size > count)
+		size = count;
+
+	ptr_from = page_address(page)+offset;
+	written = memcpy(ptr_to,ptr_from,size);
+
+	if (written < 0) {
+		desc->error = written;
+		written = 0;
+	}
+	desc->count = count - written;
+	desc->written += written;
+	return written;
+}
+
+ssize_t gemini_ipi_sendfile(struct file *in_file, loff_t *ppos,
+			 size_t count, read_actor_t actor, void *TARGET)
+{
+	read_descriptor_t desc;
+
+	if (!count)
+		return 0;
+
+	desc.written = 0;
+	desc.count = count;
+	desc.arg.data = TARGET;
+	desc.error = 0;
+
+	do_mapping_read(in_file->f_mapping,&in_file->f_ra,in_file, ppos, &desc, ipi_send_actor);
+
+	if (desc.written)
+		return desc.written;
+	return desc.error;
+}
+static struct file_operations gemini_ipi_fops = {
+	.owner	=	THIS_MODULE,
+	.ioctl	=	gemini_ipi_ioctl,
+	.open	=	gemini_ipi_open,
+	.release=	gemini_ipi_release,
+	.write	=	gemini_ipi_write,
+	.read	=	gemini_ipi_read,
+	.sendfile = gemini_ipi_sendfile,
+};
+
+#ifndef STORLINK_IPI
+#define STORLINK_IPI	242		// Documents/devices.txt suggest to use 240~255 for local driver!!
+#endif
+
+static struct miscdevice gemini_ipi_miscdev =
+{
+	STORLINK_IPI,
+	"slave_ipc",
+	&gemini_ipi_fops
+};
+
+int __init sl_ipi_init(void)
+{
+
+	printk("Gemini IPI Driver Initialization...\n");
+	printk("REQ Head :0x%x(phy:0x%x)\n",(unsigned int)req,(unsigned int)SL2312_SRAM_BASE);
+	printk("RSP Head :0x%x(phy:0x%x)\n",(unsigned int)rsp,(unsigned int)SL2312_SRAM_BASE+0x20);
+	printk("Data buff:0x%x(phy:0x%x)\n",__phys_to_virt(CPU_1_MEM_BASE+CPU_1_DATA_OFFSET),CPU_1_MEM_BASE+CPU_1_DATA_OFFSET);
+
+	misc_register(&gemini_ipi_miscdev);
+
+	if (request_irq(IRQ_CPU0_IP_IRQ_OFFSET, ipi_interrupt, SA_INTERRUPT, "ipi", NULL))
+		printk("Error: Register IRQ for Storlink IPI failed\n");
+
+	return 0;
+}
+
+void __exit sl_ipi_exit(void)
+{
+
+}
+
+module_init(sl_ipi_init);
+module_exit(sl_ipi_exit);
+
+MODULE_AUTHOR("Jason Lee <jason@storlink.com.tw>");
+MODULE_DESCRIPTION("Storlink IPI driver");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/arch/arm/mach-sl2312/hw_xor.h
@@ -0,0 +1,573 @@
+/*
+*  linux/include/asm-arm/xor.h
+*
+*  Copyright (C) 2001 Storlink Semi.
+* 	Jason Lee <jason@storlink.com.tw>
+*
+*/
+#include <asm/arch/sl2312.h>
+#include <asm/io.h>
+//#include <linux/compatmac.h>
+
+#undef BIG_ENDIAN
+#define CPU 		0
+#define DMA 		1
+
+#define DESC_NO	8
+#define TX_DESC_NUM		DESC_NO
+#define RX_DESC_NUM		DESC_NO
+
+#define RAID_BASE_ADDR	IO_ADDRESS(SL2312_RAID_BASE)
+
+#define SRAM_PAR_0k		0
+#define SRAM_PAR_4k		1
+#define SRAM_PAR_8k		2
+#define SRAM_PAR_16k		3
+#define SRAM_PAR_SIZE	SRAM_PAR_8k
+
+#define RUNNING	 	0x1
+#define COMPLETE 	0x2
+#define ERROR 		0x4
+
+#define CMD_XOR		0x0
+#define CMD_FILL	0x1
+#define CMD_CPY		0x3
+#define CMD_CHK		0x4
+
+enum RAID_DMA_REGISTER {
+	RAID_DMA_DEVICE_ID		= 0xff00,
+	RAID_DMA_STATUS			= 0xff04,
+	RAID_FCHDMA_CTRL		= 0xff08,
+	RAID_FCHDMA_FIRST_DESC	= 0xff0C,
+	RAID_FCHDMA_CURR_DESC	= 0xff10,
+	RAID_STRDMA_CTRL		= 0xff14,
+	RAID_STRDMA_FIRST_DESC	= 0xff18,
+	RAID_STRDMA_CURR_DESC	= 0xff1C,
+	RAID_TX_FLG_REG			= 0xff24,
+	RAID_RX_FLG_REG			= 0xff34,
+	RAID_PCR				= 0xff50,
+	SMC_CMD_REG				= 0xff60,
+	SMC_STATUS_REG			= 0xff64
+	};
+
+enum RAID_FUNC_MODE {
+	RAID_XOR			= 0,
+	RAID_MIX			= 2,
+	RAID_SRAM			= 3,
+	RAID_ENDIAN			= 4,
+	RAID_MEM_BLK		= 5,
+	RAID_MEM2MEM		= 7,
+	RAID_BUF_SIZE		= 8,
+	RAID_ERR_TEST		= 9,
+	RAID_BURST			= 10,
+	RAID_BUS			= 11
+	};
+
+typedef struct reg_info {
+	int mask;
+	char err[32];
+	int offset;
+} REG_INFO;
+
+/********************************************************/
+/* 	the definition of RAID DMA Module Register      */
+/********************************************************/
+typedef union
+{
+	unsigned int bit32;
+	struct bits_ff00
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int  				: 8;
+		unsigned int teytPerr		: 4; /* define protocol error under tsPErrI*/
+		unsigned int reytPerr		: 14; /* define protocol error under rsPErrI */
+		unsigned int device_id		: 12;
+		unsigned int revision_id	: 4;
+		#else
+		unsigned int revision_id	: 4;
+		unsigned int device_id		: 12;
+		unsigned int reytPerr		: 14; /* define protocol error under rsPErrI */
+		unsigned int teytPerr		: 4; /* define protocol error under tsPErrI*/
+		unsigned int 				: 8;
+		#endif
+	} bits;
+} RAID_DMA_DEVICE_ID_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff04
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int tsFinishI		: 1; /* owner bit error interrupt */
+		unsigned int tsDErrI		: 1; /* AHB bus error interrupt */
+		unsigned int tsPErrI		: 1; /* RAID XOR fetch descriptor protocol error interrupt */
+		unsigned int tsEODI			: 1; /* RAID XOR fetch DMA end of descriptor interrupt */
+		unsigned int tsEOFI			: 1; /* RAID XOR fetch DMA end of frame interrupt */
+		unsigned int rsFinishI		: 1; /* owner bit error interrupt */
+		unsigned int rsDErrI 		: 1; /* AHB bus error while RAID XOR store interrupt */
+		unsigned int rsPErrI		: 1; /* RAID XOR store descriptor protocol error interrupt */
+		unsigned int rsEODI			: 1; /* RAID XOR store DMA end of descriptor interrupt */
+		unsigned int rsEOFI			: 1; /* RAID XOR store DMA end of frame interrupt */
+		unsigned int inter			: 8; /* pattern check error interrupt */
+		unsigned int 				: 5;
+		unsigned int Loopback		: 1; /* loopback */
+		unsigned int intEnable		: 8; /*pattern check error interrupt enable */
+		#else
+		unsigned int intEnable		: 8; /*pattern check error interrupt enable */
+		unsigned int Loopback		: 1; /* loopback */
+		unsigned int 				: 5;
+		unsigned int inter			: 8; /* pattern check error interrupt */
+		unsigned int rsEOFI			: 1; /* RAID XOR store DMA end of frame interrupt */
+		unsigned int rsEODI			: 1; /* RAID XOR store DMA end of descriptor interrupt */
+		unsigned int rsPErrI		: 1; /* RAID XOR store descriptor protocol error interrupt */
+		unsigned int rsDErrI 		: 1; /* AHB bus error while RAID XOR store interrupt */
+		unsigned int rsFinishI		: 1; /* owner bit error interrupt */
+		unsigned int tsEOFI			: 1; /* RAID XOR fetch DMA end of frame interrupt */
+		unsigned int tsEODI			: 1; /* RAID XOR fetch DMA end of descriptor interrupt */
+		unsigned int tsPErrI		: 1; /* RAID XOR fetch descriptor protocol error interrupt */
+		unsigned int tsDErrI		: 1; /* AHB bus error interrupt */
+		unsigned int tsFinishI		: 1; /* owner bit error interrupt */
+		#endif
+	} bits;
+} RAID_DMA_STATUS_T;
+
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff08
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int td_start		:  1;	/* Start DMA transfer */
+		unsigned int td_continue	:  1;   /* Continue DMA operation */
+		unsigned int td_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int 				:  1;
+		unsigned int td_prot		:  4;	/* DMA protection control */
+		unsigned int td_burst_size  :  2;	/* DMA max burst size for every AHB request */
+		unsigned int td_bus		    :  2;	/* peripheral bus width */
+		unsigned int td_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int td_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int td_fail_en 	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int td_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int td_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int 				: 14;
+		#else
+		unsigned int 				: 14;
+		unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int td_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int td_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int td_fail_en 	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int td_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int td_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int td_bus		    :  2;	/* peripheral bus width;0 - 8 bits;1 - 16 bits */
+		unsigned int td_burst_size  :  2;	/* TxDMA max burst size for every AHB request */
+		unsigned int td_prot		:  4;	/* TxDMA protection control */
+		unsigned int 				:  1;
+		unsigned int td_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int td_continue	:  1;   /* Continue DMA operation */
+		unsigned int td_start		:  1;	/* Start DMA transfer */
+		#endif
+	} bits;
+} RAID_TXDMA_CTRL_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff0c
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int td_first_des_ptr	: 28;/* first descriptor address */
+		unsigned int td_busy			:  1;/* 1-TxDMA busy; 0-TxDMA idle */
+		unsigned int 					:  3;
+		#else
+		unsigned int 					:  3;
+		unsigned int td_busy			:  1;/* 1-TxDMA busy; 0-TxDMA idle */
+		unsigned int td_first_des_ptr	: 28;/* first descriptor address */
+		#endif
+	} bits;
+} RAID_TXDMA_FIRST_DESC_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff10
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int ndar			: 28;	/* next descriptor address */
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int    			:  1;
+		unsigned int sof_eof    	:  2;
+		#else
+		unsigned int sof_eof		:  2;
+		unsigned int 				:  1;
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int ndar			: 28;	/* next descriptor address */
+		#endif
+	} bits;
+} RAID_TXDMA_CURR_DESC_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff14
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int rd_start		:  1;	/* Start DMA transfer */
+		unsigned int rd_continue	:  1;   /* Continue DMA operation */
+		unsigned int rd_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int 				:  1;
+		unsigned int rd_prot		:  4;	/* DMA protection control */
+		unsigned int rd_burst_size  :  2;	/* DMA max burst size for every AHB request */
+		unsigned int rd_bus		    :  2;	/* peripheral bus width;0 - 8 bits;1 - 16 bits */
+		unsigned int rd_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int rd_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_fail_en  	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int 				: 14;
+		#else
+		unsigned int 				: 14;
+		unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int rd_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int rd_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_fail_en  	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int rd_bus		    :  2;	/* peripheral bus width;0 - 8 bits;1 - 16 bits */
+		unsigned int rd_burst_size  :  2;	/* DMA max burst size for every AHB request */
+		unsigned int rd_prot		:  4;	/* DMA protection control */
+		unsigned int 				:  1;
+		unsigned int rd_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int rd_continue	:  1;   /* Continue DMA operation */
+		unsigned int rd_start		:  1;	/* Start DMA transfer */
+		#endif
+	} bits;
+} RAID_RXDMA_CTRL_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff18
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int rd_first_des_ptr	: 28;/* first descriptor address */
+		unsigned int rd_busy			:  1;/* 1-RxDMA busy; 0-RxDMA idle */
+		unsigned int 					:  3;
+		#else
+		unsigned int 					:  3;
+		unsigned int rd_busy			:  1;/* 1-RxDMA busy; 0-RxDMA idle */
+		unsigned int rd_first_des_ptr	: 28;/* first descriptor address */
+		#endif
+	} bits;
+} RAID_RXDMA_FIRST_DESC_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff1c
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int ndar			: 28;	/* next descriptor address */
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int dec			:  1;	/* AHB bus address increment(0)/decrement(1) */
+		unsigned int sof_eof		:  2;
+		#else
+		unsigned int sof_eof		:  2;
+		unsigned int dec			:  1;	/* AHB bus address increment(0)/decrement(1) */
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int ndar			: 28;	/* next descriptor address */
+		#endif
+	} bits;
+} RAID_RXDMA_CURR_DESC_T;
+
+typedef union
+{
+	unsigned int bit32;
+	struct bits_ff50
+	{
+		unsigned int pat			: 32; /* data for pattern check */
+	} bits;
+} RAID_PACR_T;
+
+/******************************************************/
+/*	the definition of DMA Descriptor Register     */
+/******************************************************/
+typedef struct raid_descriptor_t
+{
+	union func_ctrl_t
+	{
+		unsigned int bit32;
+		struct bits_0000
+		{
+			#ifdef BIG_ENDIAN
+			unsigned int own				: 1; /* owner bit */
+			unsigned int derr				: 1;	/* data error during processing this descriptor */
+			unsigned int perr				: 1;	/* protocol error during processing this descriptor */
+			unsigned int raid_ctrl_status	: 7; /* pass RAID XOR fetch/store control status to CPU */
+			unsigned int desc_cnt			: 6;
+			unsigned int buffer_size		: 16;	/* transfer buffer size associated with current description*/
+			#else
+			unsigned int buffer_size		: 16;	/* transfer buffer size associated with current description*/
+			unsigned int desc_cnt			: 6;
+			unsigned int raid_ctrl_status	: 7; /* pass RAID XOR fetch/store control status to CPU */
+			unsigned int perr				: 1;	/* protocol error during processing this descriptor */
+			unsigned int derr				: 1;	/* data error during processing this descriptor */
+			unsigned int own				: 1; /* owner bit */
+			#endif
+		} bits;
+	} func_ctrl;
+
+	union flg_status_t
+	{
+		unsigned int bits32;
+		struct bit_004
+		{
+			#ifdef BIG_ENDIAN
+			unsigned int bcc 		: 16;
+			unsigned int 			: 13
+			unsigned int mode		: 3;
+			#else
+			unsigned int mode		: 3;
+			unsigned int 			: 13;
+			unsigned int bcc		: 16;
+			#endif
+		} bits_cmd_status;
+	} flg_status;  //Sanders
+
+	unsigned int buf_addr;
+
+	union next_desc_addr_t
+	{
+		unsigned int bits32;
+		struct bits_000c
+		{
+			#ifdef BIG_ENDIAN
+			unsigned int ndar 		: 28; /* next descriptor address */
+			unsigned int eofie		: 1; /* end of frame interrupt enable */
+			unsigned int 			: 1;
+			unsigned int sof_eof	: 2; /* the position of the descriptor in chain */
+			#else
+			unsigned int sof_eof	: 2; /* the position of the descriptor in chain */
+			unsigned int 			: 1;
+			unsigned int eofie		: 1; /* end of frame interrupt enable */
+			unsigned int ndar 		: 28; /* next descriptor address */
+			#endif
+		} bits;
+	} next_desc_addr;
+} RAID_DESCRIPTOR_T;
+
+/******************************************************/
+/*	the offset of RAID SMC register		      */
+/******************************************************/
+enum RAID_SMC_REGISTER {
+	RAID_SMC_CMD_REG		= 0xff60,
+	RAID_SMC_STATUS_REG		= 0xff64
+	};
+
+/******************************************************/
+/*	the definition of RAID SMC module register    */
+/******************************************************/
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff60
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int pat_mode		: 2; /* partition mode selection */
+		unsigned int 				: 14;
+		unsigned int device_id		: 12;
+		unsigned int revision_id	: 4;
+		#else
+		unsigned int revision_id	: 4;
+		unsigned int device_id		: 12;
+		unsigned int 				: 14;
+		unsigned int pat_mode		: 2; /* partition mode selection */
+		#endif
+	} bits;
+} RAID_SMC_CMD;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bits_ff64
+	{
+		#ifdef BIG_ENDIAN
+		unsigned int addr_err1		: 1; /* address is out of range for controller 1 */
+		unsigned int ahb_err1		: 1; /* AHB bus error for controller 1 */
+		unsigned int 				: 14;
+		unsigned int addr_err2		: 1;	/* address is out of range for controller 2 */
+		unsigned int ahb_err2		: 1; /* AHB bus error for controller 2 */
+		unsigned int 				: 14;
+		#else
+		unsigned int 				: 14;
+		unsigned int ahb_err2		: 1; /* AHB bus error for controller 2 */
+		unsigned int addr_err2		: 1;	/* address is out of range for controller 2 */
+		unsigned int 				: 14;
+		unsigned int ahb_err1		: 1; /* AHB bus error for controller 1 */
+		unsigned int addr_err1		: 1; /* address is out of range for controller 1 */
+		#endif
+	} bits;
+} RAID_SMC_STATUS;
+
+typedef struct RAID_S
+{
+	const char *device_name;
+	wait_queue_head_t wait;
+	unsigned int busy;
+	int irq;
+	unsigned int status;
+	RAID_DESCRIPTOR_T *tx_desc;  /*   point to virtual TX descriptor address */
+	RAID_DESCRIPTOR_T *rx_desc;  /* point ot virtual RX descriptor address */
+	RAID_DESCRIPTOR_T *tx_cur_desc; /* current TX descriptor */
+	RAID_DESCRIPTOR_T *rx_cur_desc; /* current RX descriptor */
+	RAID_DESCRIPTOR_T *tx_finished_desc;
+	RAID_DESCRIPTOR_T *rx_finished_desc;
+	RAID_DESCRIPTOR_T *tx_first_desc;
+	RAID_DESCRIPTOR_T *rx_first_desc;
+
+//	unsigned int *tx_buf[TX_DESC_NUM];
+	unsigned int *rx_desc_dma;			// physical address of rx_descript
+	unsigned int *tx_desc_dma;			// physical address of tx_descript
+	unsigned int *rx_bufs_dma;
+	unsigned int *tx_bufs_dma;
+
+} RAID_T;
+
+struct reg_ioctl
+{
+	unsigned int reg_addr;
+	unsigned int val_in;
+	unsigned int val_out;
+};
+
+typedef struct dma_ctrl {
+	int sram;
+	int prot;
+	int burst;
+	int bus;
+	int endian;
+	int mode;
+} DMA_CTRL;
+
+
+#ifdef XOR_SW_FILL_IN
+
+#define __XOR(a1, a2) a1 ^= a2
+
+#define GET_BLOCK_2(dst) \
+	__asm__("ldmia	%0, {%1, %2}" \
+		: "=r" (dst), "=r" (a1), "=r" (a2) \
+		: "0" (dst))
+
+#define GET_BLOCK_4(dst) \
+	__asm__("ldmia	%0, {%1, %2, %3, %4}" \
+		: "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \
+		: "0" (dst))
+
+#define XOR_BLOCK_2(src) \
+	__asm__("ldmia	%0!, {%1, %2}" \
+		: "=r" (src), "=r" (b1), "=r" (b2) \
+		: "0" (src)); \
+	__XOR(a1, b1); __XOR(a2, b2);
+
+#define XOR_BLOCK_4(src) \
+	__asm__("ldmia	%0!, {%1, %2, %3, %4}" \
+		: "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \
+		: "0" (src)); \
+	__XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4)
+
+#define PUT_BLOCK_2(dst) \
+	__asm__ __volatile__("stmia	%0!, {%2, %3}" \
+		: "=r" (dst) \
+		: "0" (dst), "r" (a1), "r" (a2))
+
+#define PUT_BLOCK_4(dst) \
+	__asm__ __volatile__("stmia	%0!, {%2, %3, %4, %5}" \
+		: "=r" (dst) \
+		: "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4))
+
+static void
+xor_arm4regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+	unsigned int lines = bytes / sizeof(unsigned long) / 4;
+	register unsigned int a1 __asm__("r4");
+	register unsigned int a2 __asm__("r5");
+	register unsigned int a3 __asm__("r6");
+	register unsigned int a4 __asm__("r7");
+	register unsigned int b1 __asm__("r8");
+	register unsigned int b2 __asm__("r9");
+	register unsigned int b3 __asm__("ip");
+	register unsigned int b4 __asm__("lr");
+
+	do {
+		GET_BLOCK_4(p1);
+		XOR_BLOCK_4(p2);
+		PUT_BLOCK_4(p1);
+	} while (--lines);
+}
+
+static void
+xor_arm4regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3)
+{
+	unsigned int lines = bytes / sizeof(unsigned long) / 4;
+	register unsigned int a1 __asm__("r4");
+	register unsigned int a2 __asm__("r5");
+	register unsigned int a3 __asm__("r6");
+	register unsigned int a4 __asm__("r7");
+	register unsigned int b1 __asm__("r8");
+	register unsigned int b2 __asm__("r9");
+	register unsigned int b3 __asm__("ip");
+	register unsigned int b4 __asm__("lr");
+
+	do {
+		GET_BLOCK_4(p1);
+		XOR_BLOCK_4(p2);
+		XOR_BLOCK_4(p3);
+		PUT_BLOCK_4(p1);
+	} while (--lines);
+}
+
+static void
+xor_arm4regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3, unsigned long *p4)
+{
+	unsigned int lines = bytes / sizeof(unsigned long) / 2;
+	register unsigned int a1 __asm__("r8");
+	register unsigned int a2 __asm__("r9");
+	register unsigned int b1 __asm__("ip");
+	register unsigned int b2 __asm__("lr");
+
+	do {
+		GET_BLOCK_2(p1);
+		XOR_BLOCK_2(p2);
+		XOR_BLOCK_2(p3);
+		XOR_BLOCK_2(p4);
+		PUT_BLOCK_2(p1);
+	} while (--lines);
+}
+
+static void
+xor_arm4regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+	unsigned int lines = bytes / sizeof(unsigned long) / 2;
+	register unsigned int a1 __asm__("r8");
+	register unsigned int a2 __asm__("r9");
+	register unsigned int b1 __asm__("ip");
+	register unsigned int b2 __asm__("lr");
+
+	do {
+		GET_BLOCK_2(p1);
+		XOR_BLOCK_2(p2);
+		XOR_BLOCK_2(p3);
+		XOR_BLOCK_2(p4);
+		XOR_BLOCK_2(p5);
+		PUT_BLOCK_2(p1);
+	} while (--lines);
+}
+#endif	//XOR_SW_FILL_IN
+
--- /dev/null
+++ b/arch/arm/mach-sl2312/irq.c
@@ -0,0 +1,202 @@
+/*
+ *  linux/arch/arm/mach-epxa10db/irq.c
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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 <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/stddef.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/int_ctrl.h>
+
+#ifdef CONFIG_PCI
+#include <asm/arch/pci.h>
+#endif
+
+int fixup_irq(unsigned int irq)
+{
+#ifdef CONFIG_PCI
+	if (irq == IRQ_PCI) {
+		return sl2312_pci_get_int_src();
+	}
+#endif
+	return irq;
+}
+
+static void sl2312_ack_irq(unsigned int irq)
+{
+   __raw_writel(1 << irq, IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+}
+
+static void sl2312_mask_irq(unsigned int irq)
+{
+	unsigned int mask;
+
+#ifdef CONFIG_PCI
+	if (irq >= PCI_IRQ_OFFSET)
+	{
+		mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+		mask &= ~IRQ_PCI_MASK ;
+		__raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+		sl2312_pci_mask_irq(irq - PCI_IRQ_OFFSET);
+	}
+	else
+#endif
+	if(irq >= FIQ_OFFSET)
+	{
+           mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+           mask &= ~(1 << (irq - FIQ_OFFSET));
+           __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+        }
+        else
+        {
+           mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+           mask &= ~(1 << irq);
+           __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+        }
+
+}
+
+static void sl2312_unmask_irq(unsigned int irq)
+{
+	unsigned int mask;
+
+#ifdef CONFIG_PCI
+	if (irq >= PCI_IRQ_OFFSET)
+	{
+		mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+		mask |= IRQ_PCI_MASK ;
+		__raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+		sl2312_pci_unmask_irq(irq - PCI_IRQ_OFFSET);
+	}
+	else
+#endif
+	if(irq >= FIQ_OFFSET)
+        {
+          mask = __raw_readl(FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+          mask |= (1 << (irq - FIQ_OFFSET));
+          __raw_writel(mask, FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+	}
+        else
+        {
+          mask = __raw_readl(IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+          mask |= (1 << irq);
+          __raw_writel(mask, IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+        }
+}
+
+static struct irq_chip sl2312_level_irq = {
+        .ack            = sl2312_mask_irq,
+        .mask           = sl2312_mask_irq,
+        .unmask         = sl2312_unmask_irq,
+//		.set_type	= ixp4xx_set_irq_type,
+};
+
+static struct irq_chip sl2312_edge_irq = {
+        .ack            = sl2312_ack_irq,
+        .mask           = sl2312_mask_irq,
+        .unmask         = sl2312_unmask_irq,
+//		.set_type	= ixp4xx_set_irq_type,
+};
+
+static struct resource irq_resource = {
+        .name   = "irq_handler",
+        .start  = IO_ADDRESS(SL2312_INTERRUPT_BASE),
+        .end    = IO_ADDRESS(FIQ_STATUS(SL2312_INTERRUPT_BASE))+4,
+};
+
+void __init sl2312_init_irq(void)
+{
+	unsigned int i, mode, level;
+
+    request_resource(&iomem_resource, &irq_resource);
+
+	for (i = 0; i < NR_IRQS; i++)
+	{
+	    if((i>=IRQ_TIMER1 && i<=IRQ_TIMER3)||(i>=IRQ_SERIRQ0 && i<=IRQ_SERIRQ_MAX))
+        {
+	        set_irq_chip(i, &sl2312_edge_irq);
+	        set_irq_handler(i, handle_edge_irq);
+        }
+	    else
+        {
+	        set_irq_chip(i, &sl2312_level_irq);
+            set_irq_handler(i,handle_level_irq);
+        }
+        set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Disable all interrupt */
+	__raw_writel(0,IRQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+	__raw_writel(0,FIQ_MASK(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+
+	/* Set interrupt mode */
+    /* emac & ipsec type is level trigger and high active */
+    mode = __raw_readl(IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+    level = __raw_readl(IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+
+	mode &= ~IRQ_GMAC0_MASK;
+	level &= ~IRQ_GMAC0_MASK;
+
+	mode &= ~IRQ_GMAC1_MASK;
+	level &= ~IRQ_GMAC1_MASK;
+
+	mode &= ~IRQ_IPSEC_MASK;
+	level &= ~IRQ_IPSEC_MASK;
+
+	// for IDE0,1, high active and level trigger
+	mode &= ~IRQ_IDE0_MASK;
+	level &= ~IRQ_IDE0_MASK;
+	mode &= ~IRQ_IDE1_MASK;
+	level &= ~IRQ_IDE1_MASK;
+
+
+	// for PCI, high active and level trigger
+	mode &= ~IRQ_PCI_MASK;
+	level &= ~IRQ_PCI_MASK;
+
+	// for USB, high active and level trigger
+	mode &= ~IRQ_USB0_MASK;
+	level &= ~IRQ_USB0_MASK;
+
+	mode &= ~IRQ_USB1_MASK;
+	level &= ~IRQ_USB1_MASK;
+
+	// for LPC, high active and edge trigger
+	mode |= 0xffff0000;
+	level &= 0x0000ffff;
+
+	// for GPIO, high active and level trigger
+	mode &= ~(IRQ_GPIO_MASK);
+	level &= ~(IRQ_GPIO_MASK);
+
+	mode &= ~(IRQ_GPIO1_MASK);
+	level &= ~(IRQ_GPIO1_MASK);
+
+	mode &= ~(IRQ_GPIO2_MASK);
+	level &= ~(IRQ_GPIO2_MASK);
+
+	__raw_writel(mode,IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+	__raw_writel(level,IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE)));
+
+}
--- /dev/null
+++ b/arch/arm/mach-sl2312/lpc.c
@@ -0,0 +1,125 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	ITE Semi IT8712 Super I/O functions.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or source@mvista.com
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/arch/it8712.h>
+#include <linux/init.h>
+#include <asm/arch/hardware.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+// MB PnP configuration register
+#define LPC_KEY_ADDR	(IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2e)
+#define LPC_DATA_ADDR	(IO_ADDRESS(SL2312_LPC_IO_BASE) + 0x2f)
+
+#define LPC_BUS_CTRL			*(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 0)
+#define LPC_BUS_STATUS			*(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 2)
+#define LPC_SERIAL_IRQ_CTRL		*(volatile unsigned char*) (IO_ADDRESS(SL2312_LPC_HOST_BASE) + 4)
+
+int it8712_exist;
+
+static void LPCEnterMBPnP(void)
+{
+	int i;
+	unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
+
+	for (i = 0; i<4; i++)
+		outb(key[i], LPC_KEY_ADDR);
+
+}
+
+static void LPCExitMBPnP(void)
+{
+	outb(0x02, LPC_KEY_ADDR);
+	outb(0x02, LPC_DATA_ADDR);
+}
+
+void LPCSetConfig(char LdnNumber, char Index, char data)
+{
+	LPCEnterMBPnP();				// Enter IT8712 MB PnP mode
+	outb(0x07, LPC_KEY_ADDR);
+	outb(LdnNumber, LPC_DATA_ADDR);
+	outb(Index, LPC_KEY_ADDR);
+	outb(data, LPC_DATA_ADDR);
+	LPCExitMBPnP();
+}
+
+char LPCGetConfig(char LdnNumber, char Index)
+{
+	char rtn;
+
+	LPCEnterMBPnP();				// Enter IT8712 MB PnP mode
+	outb(0x07, LPC_KEY_ADDR);
+	outb(LdnNumber, LPC_DATA_ADDR);
+	outb(Index, LPC_KEY_ADDR);
+	rtn = inb(LPC_DATA_ADDR);
+	LPCExitMBPnP();
+	return rtn;
+}
+
+static int SearchIT8712(void)
+{
+	unsigned char Id1, Id2;
+	unsigned short Id;
+
+	LPCEnterMBPnP();
+	outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */
+	Id1 = inb(LPC_DATA_ADDR);
+	outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */
+	Id2 = inb(LPC_DATA_ADDR);
+	Id = (Id1 << 8) | Id2;
+	LPCExitMBPnP();
+	if (Id == 0x8712)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+int InitLPCInterface(void)
+{
+	LPC_BUS_CTRL = 0xc0;
+	LPC_SERIAL_IRQ_CTRL = 0xc0;
+	mdelay(1);		// wait for 1 serial IRQ cycle
+	LPC_SERIAL_IRQ_CTRL = 0x80;
+	it8712_exist = SearchIT8712();
+	printk("IT8712 %s exist\n", it8712_exist?"":"doesn't");
+	return 0;
+}
+
+//__initcall(InitLPCInterface);
--- /dev/null
+++ b/arch/arm/mach-sl2312/mm.c
@@ -0,0 +1,80 @@
+/*
+ *  linux/arch/arm/mach-epxa10db/mm.c
+ *
+ *  MM routines for Altera'a Epxa10db board
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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 <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/sizes.h>
+
+#include <asm/mach/map.h>
+
+/* Page table mapping for I/O region */
+static struct map_desc sl2312_io_desc[] __initdata = {
+#ifdef CONFIG_GEMINI_IPI
+{__phys_to_virt(CPU_1_MEM_BASE),         __phys_to_pfn(CPU_1_MEM_BASE),        SZ_64M,  MT_MEMORY},
+#endif
+{IO_ADDRESS(SL2312_SRAM_BASE),         __phys_to_pfn(SL2312_SRAM_BASE),        SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_DRAM_CTRL_BASE),    __phys_to_pfn(SL2312_DRAM_CTRL_BASE),   SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_GLOBAL_BASE),       __phys_to_pfn(SL2312_GLOBAL_BASE),      SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_WAQTCHDOG_BASE),    __phys_to_pfn(SL2312_WAQTCHDOG_BASE),   SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_UART_BASE),         __phys_to_pfn(SL2312_UART_BASE),        SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_TIMER_BASE),        __phys_to_pfn(SL2312_TIMER_BASE),       SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_LCD_BASE),          __phys_to_pfn(SL2312_LCD_BASE),         SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_RTC_BASE),          __phys_to_pfn(SL2312_RTC_BASE),         SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_SATA_BASE),         __phys_to_pfn(SL2312_SATA_BASE),        SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_LPC_HOST_BASE),     __phys_to_pfn(SL2312_LPC_HOST_BASE),    SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_LPC_IO_BASE),       __phys_to_pfn(SL2312_LPC_IO_BASE),      SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_INTERRUPT_BASE),    __phys_to_pfn(SL2312_INTERRUPT_BASE),   SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_INTERRUPT1_BASE),   __phys_to_pfn(SL2312_INTERRUPT1_BASE),  SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_SSP_CTRL_BASE),     __phys_to_pfn(SL2312_SSP_CTRL_BASE),    SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_POWER_CTRL_BASE),   __phys_to_pfn(SL2312_POWER_CTRL_BASE),  SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_CIR_BASE),          __phys_to_pfn(SL2312_CIR_BASE),         SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_GPIO_BASE),         __phys_to_pfn(SL2312_GPIO_BASE),        SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_GPIO_BASE1),        __phys_to_pfn(SL2312_GPIO_BASE1),       SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_GPIO_BASE2),        __phys_to_pfn(SL2312_GPIO_BASE2),       SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_PCI_IO_BASE),	   __phys_to_pfn(SL2312_PCI_IO_BASE),      SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_PCI_MEM_BASE),	   __phys_to_pfn(SL2312_PCI_MEM_BASE),	   SZ_512K,  MT_DEVICE},
+#ifdef CONFIG_NET_SL351X
+{IO_ADDRESS(SL2312_TOE_BASE),    	__phys_to_pfn(SL2312_TOE_BASE)       ,   SZ_512K,  MT_DEVICE},
+#endif
+{IO_ADDRESS(SL2312_GMAC0_BASE),	       __phys_to_pfn(SL2312_GMAC0_BASE),	   SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_GMAC1_BASE),	       __phys_to_pfn(SL2312_GMAC1_BASE),	   SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_SECURITY_BASE),     __phys_to_pfn(SL2312_SECURITY_BASE),    SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_IDE0_BASE),         __phys_to_pfn(SL2312_IDE0_BASE),        SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_IDE1_BASE),         __phys_to_pfn(SL2312_IDE1_BASE),        SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_RAID_BASE),         __phys_to_pfn(SL2312_RAID_BASE),        SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_FLASH_CTRL_BASE),   __phys_to_pfn(SL2312_FLASH_CTRL_BASE),  SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_DRAM_CTRL_BASE),    __phys_to_pfn(SL2312_DRAM_CTRL_BASE),   SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_GENERAL_DMA_BASE),  __phys_to_pfn(SL2312_GENERAL_DMA_BASE), SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_USB0_BASE),         __phys_to_pfn(SL2312_USB_BASE),         SZ_512K,  MT_DEVICE},
+{IO_ADDRESS(SL2312_USB1_BASE),         __phys_to_pfn(SL2312_USB1_BASE),        SZ_512K,  MT_DEVICE},
+{FLASH_VADDR(SL2312_FLASH_BASE),       __phys_to_pfn(SL2312_FLASH_BASE),       SZ_16M,    MT_DEVICE},
+};
+
+void __init sl2312_map_io(void)
+{
+	iotable_init(sl2312_io_desc, ARRAY_SIZE(sl2312_io_desc));
+}
--- /dev/null
+++ b/arch/arm/mach-sl2312/pci.c
@@ -0,0 +1,359 @@
+/*
+ *  linux/arch/arm/mach-sl2312/pci_sl2312.c
+ *
+ *  PCI functions for sl2312 host PCI bridge
+ *
+ *  Copyright (C) 2003 StorLink Corp.
+ *
+ * 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 <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <asm/sizes.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/pci.h>
+
+//#define DEBUG
+
+// sl2312 PCI bridge access routines
+
+#define PCI_IOSIZE_REG	(*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE)))
+#define PCI_PROT_REG	(*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x04))
+#define PCI_CTRL_REG	(*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x08))
+#define PCI_SOFTRST_REG	(*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x10))
+#define PCI_CONFIG_REG	(*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x28))
+#define PCI_DATA_REG	(*(volatile unsigned long *) (IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x2C))
+
+static spinlock_t sl2312_pci_lock = SPIN_LOCK_UNLOCKED;
+// for initialize PCI devices
+struct resource pci_ioport_resource = {
+		.name = "PCI I/O Space",
+		.start = IO_ADDRESS(SL2312_PCI_IO_BASE) + 0x100,
+		.end = IO_ADDRESS(SL2312_PCI_IO_BASE) + SZ_512K - 1,
+		.flags = IORESOURCE_IO,
+};
+struct resource pci_iomem_resource = {
+		.name = "PCI Mem Space",
+		.start = SL2312_PCI_MEM_BASE,
+		.end = SL2312_PCI_MEM_BASE + SZ_128M - 1,
+		.flags = IORESOURCE_MEM,
+};
+
+static int sl2312_read_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 *val)
+{
+	unsigned long addr,data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sl2312_pci_lock, flags);
+    addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3);
+	PCI_CONFIG_REG = addr;
+	data = PCI_DATA_REG;
+
+	switch (size) {
+	case 1:
+	    *val = (u8) (data >> ((where & 0x03) * 8));
+		break;
+	case 2:
+	    *val = (u16) (data >> ((where & 0x02) * 8));
+		break;
+	case 4:
+	    *val = data;
+    	if ((where >= 0x10) && (where <= 0x24)) {
+    		if ((*val & 0xfff00000) == SL2312_PCI_IO_BASE) {
+    			*val &= 0x000fffff;
+    			*val |= IO_ADDRESS(SL2312_PCI_IO_BASE);
+    		}
+    	}
+		break;
+	}
+	spin_unlock_irqrestore(&sl2312_pci_lock, flags);
+//	printk("READ==>slot=%d fn=%d where=%d value=%x\n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,*val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sl2312_write_config(struct pci_bus *bus, unsigned int devfn, int where,int size, u32 val)
+{
+	unsigned long addr,data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sl2312_pci_lock, flags);
+    addr = 0x80000000 | (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | (where & ~3);
+	PCI_CONFIG_REG = addr;
+	data = PCI_DATA_REG;
+
+	switch (size) {
+	case 1:
+    	data &= ~(0xff << ((where & 0x03) * 8));
+    	data |= (val << ((where & 0x03) * 8));
+    	PCI_DATA_REG = data;
+		break;
+	case 2:
+    	data &= ~(0xffff << ((where & 0x02) * 8));
+    	data |= (val << ((where & 0x02) * 8));
+    	PCI_DATA_REG = data;
+		break;
+	case 4:
+    	if ((where >= 0x10) && (where <= 0x24)) {
+    		if ((val & 0xfff00000) == IO_ADDRESS(SL2312_PCI_IO_BASE)) {
+    			val &= 0x000fffff;
+    			val |= SL2312_PCI_IO_BASE;
+    		}
+    	}
+	    PCI_DATA_REG = val;
+		break;
+	}
+	spin_unlock_irqrestore(&sl2312_pci_lock, flags);
+
+//	printk("WRITE==> slot=%d fn=%d where=%d value=%x \n",PCI_SLOT(devfn),PCI_FUNC(devfn),where,val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops sl2312_pci_ops = {
+	.read	= sl2312_read_config,
+	.write	= sl2312_write_config,
+};
+
+
+int __init sl2312_pci_setup_resources(struct resource **resource)
+{
+	PCI_IOSIZE_REG = 0;		// 1M IO size
+	PCI_CTRL_REG = 0x06;
+
+	resource[0] = &pci_ioport_resource;
+	resource[1] = &pci_iomem_resource;
+	resource[2] = NULL;
+
+	return 1;
+}
+
+//static int sl2312_pci_fault(unsigned long addr, struct pt_regs *regs)
+//{
+//	return 1;
+//}
+
+
+/**********************************************************************
+ * MASK(disable) PCI interrupt
+ *    0: PCI INTA, 1: PCI INTB, ...		// for Linux interrupt routing
+ *   16: PERR								// for PCI module internal use
+ *   17: SERR,.. respect to PCI CTRL2 REG
+ **********************************************************************/
+void sl2312_pci_mask_irq(unsigned int irq)
+{
+    struct pci_bus bus;
+	unsigned int tmp;
+
+    bus.number = 0;
+    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
+	if (irq < 16) {						// for linux int routing
+		tmp &= ~(1 << (irq + 16 + 6));
+	}
+	else {
+		tmp &= ~(1 << irq);
+	}
+    sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
+}
+
+/* UNMASK(enable) PCI interrupt */
+void sl2312_pci_unmask_irq(unsigned int irq)
+{
+    struct pci_bus bus;
+	unsigned int tmp;
+
+    bus.number = 0;
+    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
+	if (irq < 16) {						// for linux int routing
+		tmp |= (1 << (irq + 16 + 6));
+	}
+	else {
+		tmp |= (1 << irq);
+	}
+    sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
+}
+
+/* Get PCI interrupt source */
+int sl2312_pci_get_int_src(void)
+{
+    struct pci_bus bus;
+	unsigned int tmp=0;
+
+    bus.number = 0;
+    sl2312_read_config(&bus, 0, SL2312_PCI_CTRL2, 4, &tmp);
+	if (tmp & (1 << 28)) { 		// PCI INTA
+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
+		return IRQ_PCI_INTA;
+	}
+	if (tmp & (1 << 29)) {		// PCI INTB
+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
+		return IRQ_PCI_INTB;
+	}
+	if (tmp & (1 << 30)) {		// PCI INTC
+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
+		return IRQ_PCI_INTC;
+	}
+	if (tmp & (1 << 31)) {		// PCI INTD
+        sl2312_write_config(&bus, 0, SL2312_PCI_CTRL2, 4, tmp);
+		return IRQ_PCI_INTD;
+	}
+	// otherwise, it should be a PCI error
+	return IRQ_PCI;
+}
+
+static irqreturn_t sl2312_pci_irq(int irq, void *devid)
+{
+    struct irq_desc *desc;
+	struct irqaction *action;
+	int retval = 0;
+
+    return 1;
+
+	irq = sl2312_pci_get_int_src();
+	desc = &irq_desc[irq];
+	action = desc->action;
+	do {
+		retval |= action->handler(irq, devid);
+		action = action->next;
+	} while (action);
+
+    return 1;
+}
+
+//extern int (*external_fault)(unsigned long addr, struct pt_regs *regs);
+
+void __init sl2312_pci_preinit(void)
+{
+    struct pci_bus bus;
+	unsigned long flags;
+	unsigned int temp;
+	int ret;
+
+	/*
+	 * Hook in our fault handler for PCI errors
+	 */
+//	external_fault = sl2312_pci_fault;
+
+	spin_lock_irqsave(&sl2312_pci_lock, flags);
+
+	/*
+	 * Grab the PCI interrupt.
+	 */
+	ret = request_irq(IRQ_PCI, sl2312_pci_irq, 0, "sl2312 pci int", NULL);
+	if (ret)
+		printk(KERN_ERR "PCI: unable to grab PCI error "
+		       "interrupt: %d\n", ret);
+
+	spin_unlock_irqrestore(&sl2312_pci_lock, flags);
+
+	// setup pci bridge
+    bus.number = 0;   /* device 0, function 0 */
+	temp = (SL2312_PCI_DMA_MEM1_BASE & 0xfff00000) | (SL2312_PCI_DMA_MEM1_SIZE << 16);
+    sl2312_write_config(&bus, 0, SL2312_PCI_MEM1_BASE_SIZE, 4, temp);
+}
+
+/*
+ * 	No swizzle on SL2312
+ */
+static u8 __init sl2312_pci_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+	return PCI_SLOT(dev->devfn);
+}
+
+/*
+ * map the specified device/slot/pin to an IRQ.  This works out such
+ * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1.
+ */
+static int __init sl2312_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int intnr = ((slot  + (pin - 1)) & 3) + 4;  /* the IRQ number of PCI bridge */
+
+	// printk("%s : slot = %d  pin = %d \n",__func__,slot,pin);
+    switch (slot)
+    {
+        case 12:
+        	if (pin==1)
+        	{
+		    	intnr = 3;
+		    }
+		    else
+		    {
+		    	intnr = 0;
+		    }
+            break;
+        case 11:
+		    intnr = (2 + (pin - 1)) & 3;
+            break;
+        case 10:
+		    intnr = (1 + (pin - 1)) & 3;
+            break;
+        case  9:
+		    intnr = (pin - 1) & 3;
+            break;
+    }
+//	if (slot == 10)
+//		intnr = (1 + (pin - 1)) & 3;
+//	else if (slot == 9)
+//		intnr = (pin - 1) & 3;
+	return (IRQ_PCI_INTA + intnr);
+}
+
+struct pci_bus * __init sl2312_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
+{
+	return (pci_scan_bus(0, &sl2312_pci_ops, sysdata));
+
+}
+
+int __init sl2312_pci_setup(int nr, struct pci_sys_data *sys)
+{
+	int ret = 0;
+
+	if (nr == 0) {
+		ret = sl2312_pci_setup_resources(sys->resource);
+	}
+
+	return ret;
+}
+
+
+struct hw_pci sl2312_pci __initdata = {
+	.setup          =	sl2312_pci_setup,
+	.preinit		=	sl2312_pci_preinit,
+	.nr_controllers =   1,
+	.swizzle		=	sl2312_pci_swizzle,
+	.map_irq		=	sl2312_pci_map_irq,
+	.scan           =   sl2312_pci_scan_bus,
+};
+
+static int __init sl2312_pci_init(void)
+{
+	if (machine_is_sl2312())
+		pci_common_init(&sl2312_pci);
+	return 0;
+}
+
+subsys_initcall(sl2312_pci_init);
--- /dev/null
+++ b/arch/arm/mach-sl2312/sl2312-otg-1.c
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/mach-pxa/sl2312.c
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 05, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * Code specific to sl2312 aka Bulverde.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include "asm/arch/sl2312.h"
+#include "asm/arch/irqs.h"
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <linux/platform_device.h>
+
+/*
+ * device registration specific to sl2312.
+ */
+
+static u64 sl2312_dmamask_1 = 0xffffffffUL;
+
+static struct resource sl2312_otg_resources_1[] = {
+	[0] = {
+		.start  = 0x69000000,
+		.end    = 0x69000fff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_USB1,
+		.end    = IRQ_USB1,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ehci_1_device = {
+	.name		= "ehci-hcd-FOTG2XX",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &sl2312_dmamask_1,
+		.coherent_dma_mask = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(sl2312_otg_resources_1),
+	.resource       = sl2312_otg_resources_1,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&ehci_1_device,
+};
+
+static int __init sl2312_1_init(void)
+{
+	return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+subsys_initcall(sl2312_1_init);
--- /dev/null
+++ b/arch/arm/mach-sl2312/sl2312-otg.c
@@ -0,0 +1,87 @@
+/*
+ *  linux/arch/arm/mach-pxa/sl2312.c
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 05, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * Code specific to sl2312 aka Bulverde.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include "asm/arch/sl2312.h"
+#include "asm/arch/irqs.h"
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <linux/platform_device.h>
+
+/*
+ * device registration specific to sl2312.
+ */
+
+static u64 sl2312_dmamask = 0xffffffffUL;
+
+static struct resource sl2312_otg_resources_1[] = {
+	[0] = {
+		.start  = 0x68000000,
+		.end    = 0x68000fff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_USB0,
+		.end    = IRQ_USB0,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+static struct resource sl2312_otg_resources_2[] = {
+	[2] = {
+		.start  = 0x69000000,
+		.end    = 0x69000fff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[3] = {
+		.start  = IRQ_USB1,
+		.end    = IRQ_USB1,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ehci_device_1 = {
+	.name		= "ehci-hcd-FOTG2XX",
+	.id		= 1,
+	.dev		= {
+		.dma_mask = &sl2312_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(sl2312_otg_resources_1),
+	.resource       = sl2312_otg_resources_1,
+};
+
+static struct platform_device ehci_device_2 = {
+	.name		= "ehci-hcd-FOTG2XX",
+	.id		= 2,
+	.dev		= {
+		.dma_mask = &sl2312_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(sl2312_otg_resources_2),
+	.resource       = sl2312_otg_resources_2,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&ehci_device_1, /* &ehci_device_2, */
+};
+
+static int __init sl2312_init(void)
+{
+	return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+subsys_initcall(sl2312_init);
--- /dev/null
+++ b/arch/arm/mach-sl2312/sl3516_device.c
@@ -0,0 +1,89 @@
+/*
+ *  linux/arch/arm/mach-2312/sl3516_device.c
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 05, 2002
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * Code specific to sl2312 aka Bulverde.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include "asm/arch/sl2312.h"
+#include "asm/arch/irqs.h"
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+/*
+ * device registration specific to sl2312.
+ */
+
+static u64 sl3516_dmamask = 0xffffffffUL;
+
+static struct resource sl3516_sata_resources[] = {
+	[0] = {
+		.start  = 0x63400000,
+		.end    = 0x63400040,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_IDE1,
+		.end    = IRQ_IDE1,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sata_device = {
+	.name		= "lepus-sata",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &sl3516_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(sl3516_sata_resources),
+	.resource       = sl3516_sata_resources,
+};
+
+static struct resource sl3516_sata0_resources[] = {
+	[0] = {
+		.start  = 0x63000000,
+		.end    = 0x63000040,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_IDE0,
+		.end    = IRQ_IDE0,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sata0_device = {
+	.name		= "lepus-sata0",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &sl3516_dmamask,
+		.coherent_dma_mask = 0xffffffff,
+	},
+	.num_resources  = ARRAY_SIZE(sl3516_sata0_resources),
+	.resource       = sl3516_sata0_resources,
+};
+
+static struct platform_device *sata_devices[] __initdata = {
+	&sata_device,
+	&sata0_device,
+};
+
+static int __init sl3516_init(void)
+{
+	return platform_add_devices(sata_devices, ARRAY_SIZE(sata_devices));
+}
+
+subsys_initcall(sl3516_init);
--- /dev/null
+++ b/arch/arm/mach-sl2312/time.c
@@ -0,0 +1,134 @@
+/*
+ *  linux/include/asm-arm/arch-epxa10db/time.h
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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 <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/arch/hardware.h>
+#include <asm/mach/time.h>
+#define TIMER_TYPE (volatile unsigned int*)
+#include <asm/arch/timer.h>
+// #define FIQ_PLUS     1
+
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t sl2312_timer_interrupt(int irq, void *dev_id)
+{
+//        unsigned int led;
+	// ...clear the interrupt
+#ifdef FIQ_PLUS
+	*((volatile unsigned int *)FIQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
+#else
+	*((volatile unsigned int *)IRQ_CLEAR(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
+#endif
+
+#if 0
+        if(!(jiffies % HZ))
+        {
+            led = jiffies / HZ;
+//            printk("ticks %x \n", led);
+	    }
+	do_leds();
+	do_timer(regs);
+	do_profile(regs);
+#endif
+    timer_tick();
+    return IRQ_HANDLED;
+}
+
+static struct irqaction sl2312_timer_irq = {
+	.name		= "SL2312 Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.handler	= sl2312_timer_interrupt,
+};
+
+unsigned long sl2312_gettimeoffset (void)
+{
+    return 0L;
+}
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void __init sl2312_time_init(void)
+{
+	// For clock rate adjusting
+	unsigned int tick_rate=0;
+
+#ifdef CONFIG_SL3516_ASIC
+	unsigned int clock_rate_base = 130000000;
+	unsigned int reg_v=0;
+
+	//--> Add by jason for clock adjust
+	reg_v = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_STATUS)));
+	reg_v >>= 15;
+	tick_rate = (clock_rate_base + (reg_v & 0x07)*10000000);
+
+	//  FPGA use AHB bus tick rate
+	printk("Bus: %dMHz",tick_rate/1000000);
+
+	tick_rate /= 6;				// APB bus run AHB*(1/6)
+
+	switch((reg_v>>3)&3){
+		case 0:	printk("(1/1)\n") ;
+					break;
+		case 1:	printk("(3/2)\n") ;
+					break;
+		case 2:	printk("(24/13)\n") ;
+					break;
+		case 3:	printk("(2/1)\n") ;
+					break;
+	}
+	//<--
+#else
+	printk("Bus: %dMHz(1/1)\n",CLOCK_TICK_RATE/1000000);		// FPGA use 20MHz
+	tick_rate = CLOCK_TICK_RATE;
+#endif
+
+
+	/*
+	 * Make irqs happen for the system timer
+	 */
+	// initialize timer interrupt
+	// low active and edge trigger
+#ifdef FIQ_PLUS
+	*((volatile unsigned int *)FIQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
+	*((volatile unsigned int *)FIQ_LEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER1_MASK);
+	setup_irq(IRQ_TIMER1, &sl2312_timer_irq);
+	/* Start the timer */
+	*TIMER_COUNT(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ);
+	*TIMER_LOAD(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(tick_rate/HZ);
+	*TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_1_CR_ENABLE_MSK|TIMER_1_CR_INT_MSK);
+#else
+	*((volatile unsigned int *)IRQ_TMODE(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
+	*((volatile unsigned int *)IRQ_TLEVEL(IO_ADDRESS(SL2312_INTERRUPT_BASE))) |= (unsigned int)(IRQ_TIMER2_MASK);
+	setup_irq(IRQ_TIMER2, &sl2312_timer_irq);
+	/* Start the timer */
+	*TIMER_COUNT(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ);
+	*TIMER_LOAD(IO_ADDRESS(SL2312_TIMER2_BASE))=(unsigned int)(tick_rate/HZ);
+	*TIMER_CR(IO_ADDRESS(SL2312_TIMER1_BASE))=(unsigned int)(TIMER_2_CR_ENABLE_MSK|TIMER_2_CR_INT_MSK);
+#endif
+
+}
+
+
--- /dev/null
+++ b/arch/arm/mach-sl2312/xor.c
@@ -0,0 +1,1200 @@
+/*
+ * arch/arm/mach-sl2312/xor.c
+ *
+ * Support functions for the Gemini Soc. This is
+ * a HW XOR unit that is specifically designed for use with RAID5
+ * applications.  This driver provides an interface that is used by
+ * the Linux RAID stack.
+ *
+ * Original Author: Jason Lee<jason@storlink.com.tw>
+ *
+ * Contributors:Sanders<sanders@storlink.com.tw>
+ 				Jason Lee<jason@storlink.com.tw>
+ *
+ *
+ * Maintainer: Jason Lee<jason@storlink.com.tw>
+ *
+ * Copyright (C) 2005 Storlink Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * History:	(06/25/2005, DJ) Initial Creation
+ *
+ *	Versing 1.0.0	Initial version
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware.h>
+#include <asm/arch/xor.h>
+#include <asm/pci.h>
+#include <linux/version.h>
+
+/*
+ * pick up local definitions
+ */
+#define XOR_SW_FILL_IN
+#include "hw_xor.h"
+
+
+//#define XOR_DEBUG
+//#define XOR_TEST	1
+#ifdef XOR_TEST
+#define TEST_ITERATION 1000
+#define SPIN_WAIT	1
+#endif
+#ifdef XOR_DEBUG
+#define DPRINTK(s, args...) printk("Gemini XOR: " s "\n", ## args)
+#define DENTER() DPRINTK("Entered...\n");
+#define DEXIT() DPRINTK("Exited...\n");
+#else
+#define DPRINTK(s, args...)
+#define DENTER()
+#define DEXIT()
+#endif
+
+//#define SPIN_WAIT
+
+/* globals */
+static RAID_T tp;
+static RAID_TXDMA_CTRL_T 	txdma_ctrl;
+RAID_RXDMA_CTRL_T			rxdma_ctrl;
+
+//#ifndef SPIN_WAIT
+static spinlock_t	    raid_lock;
+//#endif
+
+static unsigned int     tx_desc_virtual_base;
+static unsigned int     rx_desc_virtual_base;
+RAID_DESCRIPTOR_T	*tx_desc_ptr;
+RAID_DESCRIPTOR_T	*rx_desc_ptr;
+
+/* static prototypes */
+#define DMA_MALLOC(size,handle)		pci_alloc_consistent(NULL,size,handle)
+#define DMA_MFREE(mem,size,handle)	pci_free_consistent(NULL,size,mem,handle)
+
+static int gemini_xor_init_desc(void);
+
+static unsigned int raid_read_reg(unsigned int offset)
+{
+    unsigned int    reg_val;
+
+    reg_val = readl(RAID_BASE_ADDR + offset);
+	return (reg_val);
+}
+
+static void raid_write_reg(unsigned int offset,unsigned int data,unsigned int bit_mask)
+{
+	unsigned int reg_val;
+    unsigned int *addr;
+
+	reg_val = ( raid_read_reg(offset) & (~bit_mask) ) | (data & bit_mask);
+	addr = (unsigned int *)(RAID_BASE_ADDR + offset);
+    writel(reg_val,addr);
+	return;
+}
+
+#ifndef SPIN_WAIT
+__inline__ void xor_queue_descriptor(void)
+{
+	unsigned int flags,status=1;
+
+	DPRINTK("Going to sleep");
+
+	while(status){
+		yield();
+		//schedule();
+		spin_lock_irqsave(&raid_lock,flags);
+		status = tp.busy;
+		spin_unlock_irqrestore(&raid_lock, flags);
+	}
+//	tp.status = COMPLETE;
+	DPRINTK("woken up!");
+
+}
+#endif
+
+#ifdef SPIN_WAIT
+static void gemini_xor_isr(int d_n)
+#else
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
+static void gemini_xor_isr(int irq, void *dev_id, struct pt_regs *regs)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static irqreturn_t gemini_xor_isr(int irq, void *dev_instance, struct pt_regs *regs)
+#endif
+#endif
+{
+
+	unsigned int err;
+	RAID_DMA_STATUS_T 	dma_status;
+//	RAID_DESCRIPTOR_T *rdesc,*tdesc;
+//	unsigned int *paddr;
+
+	dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
+#ifdef SPIN_WAIT
+	while( (dma_status.bits32& (1<<31) ) ==0 ){
+		udelay(1);
+		dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
+	}
+
+/*	tdesc = tp.tx_first_desc;
+	rdesc = tp.rx_first_desc;
+	for(d_n;d_n>0;d_n--){
+		if( tdesc->func_ctrl.bits.own == DMA ){
+			paddr = tdesc;
+			printk("error tx desc:0x%x\n",*paddr++);
+			printk("error tx desc:0x%x\n",*paddr++);
+			printk("error tx desc:0s%x\n",*paddr++);
+			printk("error tx desc:0x%x\n",*paddr);
+			while(1);
+		}
+		tdesc = (RAID_DESCRIPTOR_T *)((tdesc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+	}
+
+	if( rdesc->func_ctrl.bits.own == DMA ){
+		paddr = rdesc;
+		printk("error rx desc:0x%x\n",*paddr++);
+		printk("error rx desc:0x%x\n",*paddr++);
+		printk("error rx desc:0s%x\n",*paddr++);
+		printk("error rx desc:0x%x\n",*paddr);
+		while(1);
+	}
+*/
+#endif
+
+	if(dma_status.bits32 & ((1<<31)|(1<<26))){
+		// if no bug , we can turn off rx finish interrupt
+		dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
+		err = raid_read_reg(RAID_DMA_DEVICE_ID);
+		tp.busy = 0;
+
+		if(err&0x00FF0000){
+			tp.status = ERROR;
+			printk("XOR:<HW>%s error code %x\n",(err&0x00F00000)?"tx":"rx",err);
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
+			return ;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#ifndef SPIN_WAIT
+			return IRQ_RETVAL(IRQ_HANDLED);
+#endif
+#endif
+		}
+		// 16~19 rx error code
+		// 20~23 tx error codd
+
+		dma_status.bits.tsFinishI = 1;
+		dma_status.bits.rsFinishI = 1;
+		raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0x84000000);	// clear INT
+
+//		printk("xor %d\n",d_n);
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
+			return ;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#ifndef SPIN_WAIT
+			return IRQ_RETVAL(IRQ_HANDLED);
+#endif
+#endif
+	}
+
+	#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,28)
+		return ;
+	#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+	#ifndef SPIN_WAIT
+		printk("XOR: DMA status register(0x%8x)\n",dma_status.bits32);
+		return IRQ_RETVAL(IRQ_HANDLED);
+	#endif
+	#endif
+}
+
+void
+xor_gemini_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+	int status=0;
+	unsigned int flags;
+
+	if(bytes > (1<<(SRAM_PAR_SIZE+11))){
+		printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
+	}
+
+	spin_lock_irqsave(&raid_lock,flags);
+	while(tp.status != COMPLETE){
+		spin_unlock_irqrestore(&raid_lock, flags);
+		//printk("XOR yield2\n");
+#ifdef XOR_SW_FILL_IN
+		xor_arm4regs_2(bytes,p1,p2);
+		return ;
+#else
+		yield();
+#endif
+	}
+	spin_unlock_irqrestore(&raid_lock, flags);
+	tp.status = RUNNING;
+
+	// flush the cache to memory before H/W XOR touches them
+	consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
+	consistent_sync(p2, bytes, DMA_TO_DEVICE);
+
+
+	tp.tx_desc = tp.tx_first_desc;
+	tp.rx_desc = tp.rx_first_desc;
+	if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
+		// prepare tx descript
+		raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
+		tp.tx_desc->buf_addr = (unsigned int)__pa(p1);		// physical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00020000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+		wmb();
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p2);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;			// last descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00010000;
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);							// keep last descript
+
+    	wmb();
+    	// prepare rx descript
+    	raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf);
+    	tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
+    	tp.rx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+    	tp.rx_desc->flg_status.bits32 = 0;				// link data from XOR
+//    	tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.rx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+
+	}
+	else{
+	 	/* no free tx descriptor */
+	 	printk("XOR:no free tx descript");
+		return ;
+	}
+
+	// change status
+//	tp.status = RUNNING;
+	status = tp.busy = 1;
+
+	// start tx DMA
+	rxdma_ctrl.bits.rd_start = 1;
+	// start rx DMA
+	txdma_ctrl.bits.td_start = 1;
+
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
+	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
+
+#ifdef SPIN_WAIT
+	gemini_xor_isr(2);
+#else
+	xor_queue_descriptor();
+#endif
+
+	tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*2) ;
+	tp.status = COMPLETE;
+//	tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
+//	tp.rx_desc = tp.rx_first_desc ;
+//	tp.rx_desc->func_ctrl.bits.own = DMA;
+
+}
+
+void
+xor_gemini_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3)
+{
+	int status=0;
+	unsigned int flags;
+
+	if(bytes > (1<<(SRAM_PAR_SIZE+11))){
+		printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
+	}
+
+	spin_lock_irqsave(&raid_lock,flags);
+	if(tp.status != COMPLETE){
+		spin_unlock_irqrestore(&raid_lock, flags);
+		//printk("XOR yield3\n");
+#ifdef XOR_SW_FILL_IN
+		xor_arm4regs_3(bytes,p1,p2,p3);
+		return;
+#else
+		yield();
+#endif
+	}
+	spin_unlock_irqrestore(&raid_lock, flags);
+	tp.status = RUNNING;
+
+	// flush the cache to memory before H/W XOR touches them
+	consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
+	consistent_sync(p2, bytes, DMA_TO_DEVICE);
+	consistent_sync(p3, bytes, DMA_TO_DEVICE);
+
+	tp.tx_desc = tp.tx_first_desc;
+	tp.rx_desc = tp.rx_first_desc;
+	if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
+		// prepare tx descript
+		raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
+		tp.tx_desc->buf_addr = (unsigned int)__pa(p1);		// physical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00020000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p2);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x0000000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p3);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;			// last descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00010000;
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);							// keep last descript
+
+    	// prepare rx descript
+    	raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFf);
+    	tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
+    	tp.rx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+    	tp.rx_desc->flg_status.bits32 = 0;				// link data from XOR
+//    	tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.rx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+
+	}
+	else{
+	 	/* no free tx descriptor */
+	 	printk("XOR:no free tx descript \n");
+		return ;
+	}
+
+	// change status
+//	tp.status = RUNNING;
+	status = tp.busy = 1;
+
+	// start tx DMA
+	rxdma_ctrl.bits.rd_start = 1;
+	// start rx DMA
+	txdma_ctrl.bits.td_start = 1;
+	wmb();
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
+	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
+
+#ifdef SPIN_WAIT
+	gemini_xor_isr(3);
+#else
+	xor_queue_descriptor();
+#endif
+	tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*3) | 0x0B;
+	tp.status = COMPLETE;
+//	tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
+	//tp.rx_desc = tp.rx_first_desc ;
+//	tp.rx_desc->func_ctrl.bits.own = DMA;
+
+}
+
+void
+xor_gemini_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3, unsigned long *p4)
+{
+	int status=0;
+	unsigned int flags;
+
+	if(bytes > (1<<(SRAM_PAR_SIZE+11))){
+		printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
+	}
+
+	spin_lock_irqsave(&raid_lock,flags);
+	if(tp.status != COMPLETE){
+		spin_unlock_irqrestore(&raid_lock, flags);
+		//printk("S\n");
+#ifdef XOR_SW_FILL_IN
+		xor_arm4regs_4(bytes,p1,p2,p3,p4);
+		return;
+#else
+		msleep(1);
+		yield();
+#endif
+	}
+	spin_unlock_irqrestore(&raid_lock, flags);
+
+	tp.status = RUNNING;
+
+	// flush the cache to memory before H/W XOR touches them
+	consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
+	consistent_sync(p2, bytes, DMA_TO_DEVICE);
+	consistent_sync(p3, bytes, DMA_TO_DEVICE);
+	consistent_sync(p4, bytes, DMA_TO_DEVICE);
+
+	tp.tx_desc = tp.tx_first_desc;
+	tp.rx_desc = tp.rx_first_desc;
+	if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
+		// prepare tx descript
+		raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
+		tp.tx_desc->buf_addr = (unsigned int)__pa(p1);		// physical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00020000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_cur_desc->buf_addr = (unsigned int)__pa(p2);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00000000;
+    	tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p3);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00000000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p4);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;			// last descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00010000;
+//    	tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);							// keep last descript
+
+    	// prepare rx descript
+    	raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
+    	tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
+    	tp.rx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+    	tp.rx_desc->flg_status.bits32 = 0;				// link data from XOR
+//    	tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.rx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+
+	}
+	else{
+	 	/* no free tx descriptor */
+	 	printk("XOR:no free tx descript");
+		return ;
+	}
+
+	// change status
+//	tp.status = RUNNING;
+	status = tp.busy = 1;
+
+	// start tx DMA
+	rxdma_ctrl.bits.rd_start = 1;
+	// start rx DMA
+	txdma_ctrl.bits.td_start = 1;
+	wmb();
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
+	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
+
+#ifdef SPIN_WAIT
+	gemini_xor_isr(4);
+#else
+	xor_queue_descriptor();
+#endif
+
+	tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*4) | 0x0B;
+	tp.status = COMPLETE;
+//	tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
+	//tp.rx_desc = tp.rx_first_desc ;
+//	tp.rx_desc->func_ctrl.bits.own = DMA;
+
+}
+
+void
+xor_gemini_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+
+	int status=0;
+	unsigned int flags;
+
+
+	if(bytes > (1<<(SRAM_PAR_SIZE+11))){
+		printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
+	}
+
+	spin_lock_irqsave(&raid_lock,flags);
+	while(tp.status != COMPLETE){
+		spin_unlock_irqrestore(&raid_lock, flags);
+		//printk("XOR yield5\n");
+#ifdef XOR_SW_FILL_IN
+		xor_arm4regs_5(bytes,p1,p2,p3,p4,p5);
+		return;
+#else
+		msleep(1);
+		yield();
+#endif
+	}
+	spin_unlock_irqrestore(&raid_lock, flags);
+	tp.status = RUNNING;
+
+	// flush the cache to memory before H/W XOR touches them
+	consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
+	consistent_sync(p2, bytes, DMA_TO_DEVICE);
+	consistent_sync(p3, bytes, DMA_TO_DEVICE);
+	consistent_sync(p4, bytes, DMA_TO_DEVICE);
+	consistent_sync(p5, bytes, DMA_TO_DEVICE);
+
+	tp.tx_desc = tp.tx_first_desc;
+	tp.rx_desc = tp.rx_first_desc;
+	if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
+		// prepare tx descript
+		raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xffffffff);
+		tp.tx_desc->buf_addr = (unsigned int)__pa(p1);		// physical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 2;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00020000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	wmb();
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p2);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00000000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	wmb();
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p3);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00000000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	wmb();
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+		tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p4);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 0;			// first descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+		tp.tx_desc->flg_status.bits32 = 0x00000000;
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	wmb();
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+
+
+    	tp.tx_desc = tp.tx_cur_desc;
+    	tp.tx_desc->buf_addr = (unsigned int)__pa(p5);		// pysical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+//    	tp.tx_desc->flg_status.bits_cmd_status.bcc = 1;			// last descript
+//    	tp.tx_desc->flg_status.bits_cmd_status.mode = 0;		// only support XOR command
+//    	tp.tx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+		tp.tx_desc->flg_status.bits32 = 0x00010000;
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xfffffff0)+tx_desc_virtual_base);
+    	tp.tx_finished_desc = tp.tx_desc;								// keep last descript
+
+    	// prepare rx descript
+    	raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
+    	tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
+    	tp.rx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+    	tp.rx_desc->flg_status.bits32 = 0;				// link data from XOR
+//    	tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.rx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+
+	}
+	else{
+	 	/* no free tx descriptor */
+	 	printk("XOR:no free tx descript");
+		return ;
+	}
+
+	// change status
+//	tp.status = RUNNING;
+	status = tp.busy = 1;
+
+	// start tx DMA
+	rxdma_ctrl.bits.rd_start = 1;
+	// start rx DMA
+	txdma_ctrl.bits.td_start = 1;
+	wmb();
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
+	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
+
+#ifdef SPIN_WAIT
+	gemini_xor_isr(5);
+#else
+	xor_queue_descriptor();
+#endif
+
+	tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*5) | 0x0B;
+	tp.status = COMPLETE;
+//	tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) | 0x0B;
+	//tp.rx_desc = tp.rx_first_desc ;
+//	tp.rx_desc->func_ctrl.bits.own = DMA;
+
+}
+
+#ifdef XOR_TEST
+void
+raid_memset(unsigned int *p1, unsigned int pattern, unsigned int bytes)
+{
+	int status=0,i;
+
+	if(bytes > (1<<(SRAM_PAR_SIZE+11))){
+		printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
+	}
+
+	*p1 = pattern;
+
+	// flush the cache to memory before H/W XOR touches them
+	consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
+
+	while(tp.status != COMPLETE){
+		DPRINTK("XOR yield\n");
+		//schedule();
+		yield();
+	}
+	tp.status = RUNNING;
+
+	tp.tx_desc = tp.tx_first_desc;
+	tp.rx_desc = tp.rx_first_desc;
+	if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
+		// prepare tx descript
+		raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
+		tp.tx_desc->buf_addr = (unsigned int)__pa(p1);		// physical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = 4;    		/* total frame byte count */
+    	tp.tx_desc->flg_status.bits_cmd_status.bcc = bytes;			// bytes to fill
+    	tp.tx_desc->flg_status.bits_cmd_status.mode = CMD_FILL;		// only support memory FILL command
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
+//    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
+
+    	// prepare rx descript
+    	raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
+    	tp.rx_desc->buf_addr = (unsigned int)__pa(p1);
+    	tp.rx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+    	tp.rx_desc->flg_status.bits32 = 0;				// link data from XOR
+    	tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.rx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+//    	tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base);
+    	tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+    	tp.rx_finished_desc = tp.rx_desc;
+
+	}
+	else{
+	 	/* no free tx descriptor */
+	 	printk("XOR:no free tx descript");
+		return ;
+	}
+
+	// change status
+	//tp.status = RUNNING;
+	status = tp.busy = 1;
+
+	// start tx DMA
+	rxdma_ctrl.bits.rd_start = 1;
+	// start rx DMA
+	txdma_ctrl.bits.td_start = 1;
+
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
+	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
+
+#ifdef SPIN_WAIT
+	gemini_xor_isr(2);
+#else
+	xor_queue_descriptor();
+#endif
+
+	for(i=1; i<(bytes/sizeof(int)); i++) {
+		if(p1[0]!=p1[i]){
+			printk("pattern set error!\n");
+			while(1);
+		}
+	}
+
+	tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
+	tp.status = COMPLETE;
+//	tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
+	//tp.rx_desc = tp.rx_first_desc ;
+//	tp.rx_desc->func_ctrl.bits.own = DMA;
+
+}
+#endif
+
+void
+raid_memcpy(unsigned int *to, unsigned int *from, unsigned int bytes)
+{
+	int status=0,i;
+
+	if(bytes > (1<<(SRAM_PAR_SIZE+11))){
+		printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
+	}
+
+	// flush the cache to memory before H/W XOR touches them
+	consistent_sync(to, bytes, DMA_BIDIRECTIONAL);
+	consistent_sync(from,bytes, DMA_TO_DEVICE);
+
+	while(tp.status != COMPLETE){
+		DPRINTK("XOR yield\n");
+		//schedule();
+		yield();
+	}
+	tp.status = RUNNING;
+
+	tp.tx_desc = tp.tx_first_desc;
+	tp.rx_desc = tp.rx_first_desc;
+	if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
+		// prepare tx descript
+		raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
+		tp.tx_desc->buf_addr = (unsigned int)__pa(from);		// physical address
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+    	tp.tx_desc->flg_status.bits32 = CMD_CPY;		// only support memory FILL command
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
+//    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
+
+    	// prepare rx descript
+    	raid_write_reg(RAID_STRDMA_CURR_DESC,(unsigned int)tp.rx_desc-rx_desc_virtual_base,0xFFFFFFFF);
+    	tp.rx_desc->buf_addr = (unsigned int)__pa(to);
+    	tp.rx_desc->func_ctrl.bits.buffer_size = bytes;    		/* total frame byte count */
+    	tp.rx_desc->flg_status.bits32 = 0;				// link data from XOR
+    	tp.rx_cur_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.rx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+//    	tp.rx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.rx_cur_desc->next_desc_addr.bits32 & 0xfffffff0)+rx_desc_virtual_base);
+    	tp.rx_desc->next_desc_addr.bits32 = 0x0000000b;// end of descript
+
+	}
+	else{
+	 	/* no free tx descriptor */
+	 	printk("XOR:no free tx descript");
+		return ;
+	}
+
+	// change status
+	//tp.status = RUNNING;
+	status = tp.busy = 1;
+
+	// start tx DMA
+	rxdma_ctrl.bits.rd_start = 1;
+	// start rx DMA
+	txdma_ctrl.bits.td_start = 1;
+
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
+	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
+
+#ifdef SPIN_WAIT
+	gemini_xor_isr(2);
+#else
+	xor_queue_descriptor();
+#endif
+
+#ifdef XOR_TEST
+	for(i=1; i<(bytes/sizeof(int)); i++) {
+		if(to[i]!=from[i]){
+			printk("pattern check error!\n");
+			printk("offset=0x%x p1=%x p2=%x\n",i*4,to[i],from[i]);
+			while(1);
+		}
+	}
+#endif
+
+	tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
+	tp.status = COMPLETE;
+//	tp.rx_desc->next_desc_addr.bits32 = ((unsigned long)tp.rx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
+	//tp.rx_desc = tp.rx_first_desc ;
+//	tp.rx_desc->func_ctrl.bits.own = DMA;
+
+}
+EXPORT_SYMBOL(raid_memcpy);
+
+#ifdef XOR_TEST
+int
+raid_memchk(unsigned int *p1, unsigned int pattern, unsigned int bytes)
+{
+	int status=0;
+	RAID_DMA_STATUS_T 	dma_status;
+
+	if(bytes > (1<<(SRAM_PAR_SIZE+11))){
+		printk("XOR: out of SRAM partition!![0x%x]\n",(unsigned int)bytes);
+	}
+
+	status = ((pattern&0xFFFF)%bytes )/4;
+	p1[status] = pattern;
+
+	while(tp.status != COMPLETE){
+		DPRINTK("XOR yield\n");
+		//schedule();
+		yield();
+	}
+	tp.status = RUNNING;
+
+	// flush the cache to memory before H/W XOR touches them
+	consistent_sync(p1, bytes, DMA_BIDIRECTIONAL);
+
+	tp.tx_desc = tp.tx_first_desc;
+	if((tp.tx_desc->func_ctrl.bits.own == CPU)/*&&(tp.rx_desc->func_ctrl.bits.own == DMA)*/){
+		// prepare tx descript
+		raid_write_reg(RAID_FCHDMA_CURR_DESC,(unsigned int)tp.tx_desc-tx_desc_virtual_base,0xFFFFFFFF);
+		tp.tx_desc->buf_addr = (unsigned int)__pa(p1);		// physical address
+    	tp.tx_desc->func_ctrl.bits.raid_ctrl_status = 0;
+    	tp.tx_desc->func_ctrl.bits.buffer_size = bytes ;    		/* total frame byte count */
+    	tp.tx_desc->flg_status.bits32 = CMD_CHK;		// only support memory FILL command
+    	tp.tx_desc->next_desc_addr.bits.sof_eof = 0x03;          /*only one descriptor*/
+    	tp.tx_desc->func_ctrl.bits.own = DMA;	        		/* set owner bit */
+    	tp.tx_desc->next_desc_addr.bits32 = 0x0000000b;
+//    	tp.tx_cur_desc = (RAID_DESCRIPTOR_T *)((tp.tx_desc->next_desc_addr.bits32 & 0xFFFFFFF0)+tx_desc_virtual_base);
+
+	}
+	else{
+	 	/* no free tx descriptor */
+	 	printk("XOR:no free tx descript");
+		return -1;
+	}
+
+	// change status
+	//tp.status = RUNNING;
+	status = tp.busy = 1;
+
+	// start tx DMA
+	txdma_ctrl.bits.td_start = 1;
+
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0x80000000);
+//	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0x80000000);
+
+#ifdef SPIN_WAIT
+	gemini_xor_isr(2);
+#else
+	xor_queue_descriptor();
+#endif
+
+//	dma_status.bits32 = raid_read_reg(RAID_DMA_STATUS);
+//	if (dma_status.bits32 & (1<<15))	{
+
+	if((tp.tx_first_desc->func_ctrl.bits.raid_ctrl_status & 0x2)) {
+		status = 1;
+//		raid_write_reg(RAID_DMA_STATUS,0x00008000,0x00080000);
+	}
+	else{
+		status = 0;
+	}
+
+	tp.tx_desc->next_desc_addr.bits32 = ((unsigned long)tp.tx_first_desc - tx_desc_virtual_base + sizeof(RAID_DESCRIPTOR_T)*1) ;
+	tp.status = COMPLETE;
+//	tp.rx_desc->func_ctrl.bits.own = DMA;
+	return status ;
+}
+#endif
+
+int __init gemini_xor_init(void)
+{
+	unsigned int res;
+	unsigned int *paddr1,*paddr2,*paddr3,i;
+	unsigned volatile char  *charact;
+	unsigned volatile short *two_char;
+	unsigned volatile int   *four_char;
+
+	// init descript
+	res = gemini_xor_init_desc();
+	if(res) {
+		printk("Init RAID Descript Fail!!\n");
+		return -res;
+	}
+
+	tp.device_name = "Gemini XOR Acceleration";
+
+	// request irq
+#ifndef SPIN_WAIT
+	res = request_irq(IRQ_RAID, gemini_xor_isr, SA_INTERRUPT, tp.device_name, NULL);
+#endif
+	if(res){
+		printk(KERN_ERR "%s: unable to request IRQ %d for "
+		       "HW XOR %d\n", tp.device_name, IRQ_RAID, res);
+		return -EBUSY;
+	}
+
+#ifdef XOR_TEST
+
+RETEST:
+	paddr1 = kmalloc(0x1000,GFP_KERNEL);
+	paddr2 = kmalloc(0x1000,GFP_KERNEL);
+	paddr3 = kmalloc(0x1000,GFP_KERNEL);
+	for(i=0;i<TEST_ITERATION;i++) {
+		printk("XOR test round %d\n",i);
+		for(res=0;res<(0x1000)/sizeof(int);res++){		// prepare data pattern
+		 	paddr1[res]= readl(0xf62000ac);
+		 	paddr2[res]= readl(0xf62000ac);
+		}
+		for(res=0;res<0x1000/sizeof(int);res++){		// calculate xor by software
+			paddr3[res] = paddr1[res]^paddr2[res];
+		}
+		xor_gemini_2(0x1000,paddr1,paddr2);				// calculate xor by hw
+		for(res=0;res<0x1000/sizeof(int);res++){		// check error
+			if(paddr1[res]!=paddr3[res]){
+				printk("XOR ERROR\n");
+				printk("[%d][0x%x]=0x%x should be %x\n",res,&paddr1[res],paddr1[res],paddr3[res]);
+				while(1);
+			}
+		}
+	}
+	kfree(paddr1);
+	kfree(paddr2);
+	kfree(paddr3);
+
+
+	// memcpy test
+	paddr1 = kmalloc(0x4000,GFP_KERNEL);
+	for(i=0;i<TEST_ITERATION;i++) {
+		for(res=0;res<(0x4000)/sizeof(int);res++)
+		 	paddr1[res]= readl(0xf62000ac);
+
+		printk("MEMCOPY round %d\n",i);
+		paddr2 = kmalloc(0x4000,GFP_KERNEL);
+		raid_memcpy(paddr2,paddr1,0x4000);
+		kfree(paddr2);
+	}
+	kfree(paddr1);
+
+	// memset test
+	for(i=0;i<TEST_ITERATION;i++) {
+		raid_memset(paddr1,0xFFFFFFFF,0x4000);
+		res = readl(0xf62000ac);
+		printk("MEMFILL fill 0x%x round %d\n",res,i);
+		paddr1 = kmalloc(0x4000,GFP_KERNEL);
+		raid_memset(paddr1,res,0x4000);
+		raid_memset(paddr1,0x0,0x4000);
+		kfree(paddr1);
+	}
+
+	paddr1 = kmalloc(0x4000,GFP_KERNEL);
+	for(i=0;i<TEST_ITERATION;i++){
+		raid_memset(paddr1, i,0x4000);
+		printk("Pattern check same ? ");
+		res = raid_memchk(paddr1, i,0x4000);
+		printk("%s\n",res?"Fail":"OK");
+		if(res)	while(1);
+
+		printk("Pattern check diff ? ");
+		res = raid_memchk(paddr1,readl(0xf62000ac),0x4000);
+		printk("%s\n",res?"OK":"Fail");
+		if(!res)	while(1);
+	}
+	kfree(paddr1);
+
+	// SRAM test
+	raid_write_reg(RAID_PCR, 0,0x00000003);
+	for(i=0;i<TEST_ITERATION;i++) {
+		printk("SRAM test %d\n",i);
+		charact = 0xF7000000;
+		two_char = 0xF7000000;
+		four_char = 0xF7000000;
+		for(res=0;res<(16*1024)/sizeof(char);res++) {		// 8-bit access
+			*charact++ = (unsigned char)res;
+		}
+		charact = 0xF7000000;
+		for(res=0;res<(16*1024)/sizeof(char);res++) {
+			if(*charact++ != (unsigned char)res){
+				printk("SRAM data error(8)\n");
+				while(1);
+			}
+		}
+
+		for(res=0;res<(16*1024)/sizeof(short);res++) {		// 16-bit access
+			*two_char++ = (unsigned short)res;
+		}
+		two_char = 0xF7000000;
+		for(res=0;res<(16*1024)/sizeof(short);res++) {
+			if(*two_char++ != (unsigned short)res){
+				printk("SRAM data error(16)\n");
+				while(1);
+			}
+		}
+
+		for(res=0;res<(16*1024)/sizeof(int);res++) {		// 32-bit access
+			*four_char++ = (unsigned int)res;
+		}
+		four_char = 0xF7000000;
+		for(res=0;res<(16*1024)/sizeof(int);res++) {
+			if(*four_char++ != (unsigned int)res){
+				printk("SRAM data error(32)\n");
+				while(1);
+			}
+		}
+	}
+	raid_write_reg(RAID_PCR, SRAM_PAR_SIZE,0x00000003);
+
+#endif
+	return 0;
+}
+
+void __exit gemini_xor_exit(void)
+{
+	DMA_MFREE(tp.tx_desc, TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(unsigned int)tp.tx_desc_dma);
+	DMA_MFREE(tp.rx_desc, RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(unsigned int)tp.rx_desc_dma);
+	free_irq(IRQ_RAID, NULL);
+}
+
+
+static int gemini_xor_init_desc(void)
+{
+	unsigned int i;
+	dma_addr_t          tx_first_desc_dma;
+	dma_addr_t          rx_first_desc_dma;
+	RAID_DMA_STATUS_T 	dma_status;
+
+	printk("Initial RAID Descripter...\n");
+
+	tp.tx_desc = (RAID_DESCRIPTOR_T*)DMA_MALLOC(TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t *)&tp.tx_desc_dma);
+    tx_desc_virtual_base = (unsigned int)tp.tx_desc - (unsigned int)tp.tx_desc_dma;
+    memset(tp.tx_desc,0x00,TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T));
+
+	tp.rx_desc = (RAID_DESCRIPTOR_T*)DMA_MALLOC(RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t *)&tp.rx_desc_dma);
+    rx_desc_virtual_base = (unsigned int)tp.rx_desc - (unsigned int)tp.rx_desc_dma;
+    memset(tp.rx_desc,0x00,RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T));
+	printk("XOR:tx_desc = %08x\n",(unsigned int)tp.tx_desc);
+    printk("XOR:rx_desc = %08x\n",(unsigned int)tp.rx_desc);
+	printk("XOR:tx_desc_dma = %08x\n",(unsigned int)tp.tx_desc_dma);
+	printk("XOR:rx_desc_dma = %08x\n",(unsigned int)tp.rx_desc_dma);
+
+	if ((tp.tx_desc == NULL) || (tp.rx_desc == NULL)) {
+		if (tp.tx_desc)
+			DMA_MFREE(tp.tx_desc, TX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t)tp.tx_desc_dma);
+		if (tp.rx_desc)
+			DMA_MFREE(tp.rx_desc, RX_DESC_NUM*sizeof(RAID_DESCRIPTOR_T),(dma_addr_t)tp.rx_desc_dma);
+		return -ENOMEM;
+	}
+
+	tp.tx_cur_desc = tp.tx_desc;  /* virtual address */
+	tp.tx_finished_desc = tp.tx_desc; /* virtual address */
+	tx_first_desc_dma = (dma_addr_t)tp.tx_desc_dma; /* physical address */
+	for (i = 1; i < TX_DESC_NUM; i++) {
+		tp.tx_desc->func_ctrl.bits.own = CPU;
+		tp.tx_desc->func_ctrl.bits.buffer_size = 0;
+		tp.tx_desc_dma = tp.tx_desc_dma + sizeof(RAID_DESCRIPTOR_T);
+//		tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tp.tx_desc_dma | 0x0B;
+		tp.tx_desc->next_desc_addr.bits32 = ((unsigned int)tx_first_desc_dma | 0x0B) + i*0x10;
+		tp.tx_desc = &tp.tx_desc[1];
+	}
+	tp.tx_desc->func_ctrl.bits.own = DMA;
+	tp.tx_desc->next_desc_addr.bits32 = (unsigned int)tx_first_desc_dma|0x0b;
+	tp.tx_desc = tp.tx_cur_desc;
+	tp.tx_desc_dma = (unsigned int*)tx_first_desc_dma;
+	tp.tx_first_desc = tp.tx_desc ;
+
+	tp.rx_cur_desc = tp.rx_desc;  /* virtual address */
+	tp.rx_finished_desc = tp.rx_desc; /* virtual address */
+	rx_first_desc_dma = (dma_addr_t)tp.rx_desc_dma; /* physical address */
+	for (i = 1; i < RX_DESC_NUM; i++) {
+		tp.rx_desc->func_ctrl.bits.own = DMA;
+		tp.rx_desc->func_ctrl.bits.buffer_size = 0;
+		tp.rx_desc_dma = tp.rx_desc_dma + sizeof(RAID_DESCRIPTOR_T);
+//		tp.rx_desc->next_desc_addr.bits32 = (unsigned int)tp.rx_desc_dma | 0x0B;
+		tp.rx_desc->next_desc_addr.bits32 = ((unsigned int)rx_first_desc_dma | 0x0B) + i*0x10;
+		tp.rx_desc = &tp.rx_desc[1];
+	}
+	tp.rx_desc->func_ctrl.bits.own = DMA;
+	tp.rx_desc->next_desc_addr.bits32 = rx_first_desc_dma|0x0b;
+	tp.rx_desc = tp.rx_cur_desc;
+	tp.rx_desc_dma = (unsigned int*)rx_first_desc_dma;
+	tp.rx_first_desc = tp.rx_desc ;
+	tp.busy = 0;
+	tp.status = COMPLETE;
+
+	// Partition SRAM size
+	raid_write_reg(RAID_PCR, SRAM_PAR_SIZE,0x00000003);
+
+	// config tx DMA controler
+	txdma_ctrl.bits32 = 0;
+	txdma_ctrl.bits.td_start = 0;
+	txdma_ctrl.bits.td_continue = 1;
+	txdma_ctrl.bits.td_chain_mode = 1;
+	txdma_ctrl.bits.td_prot = 0;
+	txdma_ctrl.bits.td_burst_size = 1;
+	txdma_ctrl.bits.td_bus = 3;
+	txdma_ctrl.bits.td_endian = 0;
+	txdma_ctrl.bits.td_finish_en = 1;
+	txdma_ctrl.bits.td_fail_en = 1;
+	txdma_ctrl.bits.td_perr_en = 1;
+	txdma_ctrl.bits.td_eod_en = 0;	// enable tx descript
+	txdma_ctrl.bits.td_eof_en = 0;
+	raid_write_reg(RAID_FCHDMA_CTRL, txdma_ctrl.bits32,0xFFFFFFFF);
+
+	// config rx DMA controler
+	rxdma_ctrl.bits32 = 0;
+	rxdma_ctrl.bits.rd_start = 0;
+	rxdma_ctrl.bits.rd_continue = 1;
+	rxdma_ctrl.bits.rd_chain_mode = 1;
+	rxdma_ctrl.bits.rd_prot = 0;
+	rxdma_ctrl.bits.rd_burst_size = 1;
+	rxdma_ctrl.bits.rd_bus = 3;
+	rxdma_ctrl.bits.rd_endian = 0;
+	rxdma_ctrl.bits.rd_finish_en = 0;
+	rxdma_ctrl.bits.rd_fail_en = 1;
+	rxdma_ctrl.bits.rd_perr_en = 1;
+	rxdma_ctrl.bits.rd_eod_en = 0;
+	rxdma_ctrl.bits.rd_eof_en = 0;
+	raid_write_reg(RAID_STRDMA_CTRL, rxdma_ctrl.bits32,0xFFFFFFFF);
+
+	// enable interrupt
+	dma_status.bits32 = 3;	// enable RpInt
+	raid_write_reg(RAID_DMA_STATUS, dma_status.bits32,0xFFFFFFFF);
+
+	return 0;
+}
+
+module_init(gemini_xor_init);
+module_exit(gemini_xor_exit);
+
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -187,6 +187,26 @@
 	  Say Y if you want support for the ARM926T processor.
 	  Otherwise, say N.
 
+###### for Storlink SoC ######
+config CPU_FA526
+	bool "FA526 processor"
+	depends on ARCH_SL2312
+	default y
+	select CPU_32v4
+	select CPU_ABRT_EV4
+	select CPU_CACHE_FA
+	select CPU_CACHE_VIVT
+	select CPU_CP15_MMU
+	select CPU_COPY_FA
+	select CPU_TLB_FA
+	select CPU_FA_BTB
+	help
+	  The FA526 is a version of the ARM9 compatible processor, but with smaller
+	  instruction and data caches. It is used in Storlink Sword device family.
+
+	  Say Y if you want support for the FA526 processor.
+	  Otherwise, say N.
+
 # ARM940T
 config CPU_ARM940T
 	bool "Support ARM940T processor" if ARCH_INTEGRATOR
@@ -461,6 +481,9 @@
 config CPU_CACHE_VIPT
 	bool
 
+config CPU_CACHE_FA
+	bool
+
 if MMU
 # The copy-page model
 config CPU_COPY_V3
@@ -475,6 +498,12 @@
 config CPU_COPY_V6
 	bool
 
+config CPU_COPY_FA
+	bool
+
+config CPU_FA_BTB
+	bool
+
 # This selects the TLB model
 config CPU_TLB_V3
 	bool
@@ -534,6 +563,14 @@
 config IO_36
 	bool
 
+config CPU_TLB_FA
+	bool
+	help
+	  //TODO
+	  Faraday ARM FA526 architecture, unified TLB with writeback cache
+	  and invalidate instruction cache entry. Branch target buffer is also
+	  supported.
+
 comment "Processor Features"
 
 config ARM_THUMB
@@ -600,7 +637,7 @@
 
 config CPU_DCACHE_WRITETHROUGH
 	bool "Force write through D-cache"
-	depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
+	depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FA526) && !CPU_DCACHE_DISABLE
 	default y if CPU_ARM925T
 	help
 	  Say Y here to use the data cache in writethrough mode. Unless you
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -32,6 +32,7 @@
 obj-$(CONFIG_CPU_CACHE_V4WB)	+= cache-v4wb.o
 obj-$(CONFIG_CPU_CACHE_V6)	+= cache-v6.o
 obj-$(CONFIG_CPU_CACHE_V7)	+= cache-v7.o
+obj-$(CONFIG_CPU_CACHE_FA)	+= cache-fa.o
 
 obj-$(CONFIG_CPU_COPY_V3)	+= copypage-v3.o
 obj-$(CONFIG_CPU_COPY_V4WT)	+= copypage-v4wt.o
@@ -40,6 +41,7 @@
 obj-$(CONFIG_CPU_SA1100)	+= copypage-v4mc.o
 obj-$(CONFIG_CPU_XSCALE)	+= copypage-xscale.o
 obj-$(CONFIG_CPU_XSC3)		+= copypage-xsc3.o
+obj-$(CONFIG_CPU_COPY_FA)	+= copypage-fa.o
 
 obj-$(CONFIG_CPU_TLB_V3)	+= tlb-v3.o
 obj-$(CONFIG_CPU_TLB_V4WT)	+= tlb-v4.o
@@ -47,6 +49,7 @@
 obj-$(CONFIG_CPU_TLB_V4WBI)	+= tlb-v4wbi.o
 obj-$(CONFIG_CPU_TLB_V6)	+= tlb-v6.o
 obj-$(CONFIG_CPU_TLB_V7)	+= tlb-v7.o
+obj-$(CONFIG_CPU_TLB_FA)	+= tlb-fa.o
 
 obj-$(CONFIG_CPU_ARM610)	+= proc-arm6_7.o
 obj-$(CONFIG_CPU_ARM710)	+= proc-arm6_7.o
@@ -60,6 +63,7 @@
 obj-$(CONFIG_CPU_ARM926T)	+= proc-arm926.o
 obj-$(CONFIG_CPU_ARM940T)	+= proc-arm940.o
 obj-$(CONFIG_CPU_ARM946E)	+= proc-arm946.o
+obj-$(CONFIG_CPU_FA526)		+= proc-fa526.o
 obj-$(CONFIG_CPU_ARM1020)	+= proc-arm1020.o
 obj-$(CONFIG_CPU_ARM1020E)	+= proc-arm1020e.o
 obj-$(CONFIG_CPU_ARM1022)	+= proc-arm1022.o
--- /dev/null
+++ b/arch/arm/mm/cache-fa.S
@@ -0,0 +1,400 @@
+/*
+ *  linux/arch/arm/mm/cache-fa.S
+ *
+ *  Copyright (C) 2005 Faraday Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Processors: FA520 FA526 FA626	
+ * 03/31/2005 :	Luke Lee created, modified from cache-v4wb.S
+ * 04/06/2005 :	1. Read CR0-1 and determine the cache size dynamically,
+ *		   to suit all Faraday CPU series
+ *	        2. Fixed all functions
+ * 04/08/2005 :	insert CONFIG_CPU_ICACHE_DISABLE and CONFIG_CPU_DCACHE_DISABLE
+ * 04/12/2005 :	TODO: make this processor dependent or a self-modifying code to 
+ *	        inline cache len/size info into the instructions, as reading cache 
+ *	        size and len info in memory could cause another cache miss.
+ * 05/05/2005 :	Modify fa_flush_user_cache_range to comply APCS.
+ * 05/19/2005 :	Adjust for boundary conditions.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include "proc-macros.S"
+
+#define CACHE_DLINESIZE	   16
+#ifdef CONFIG_SL3516_ASIC
+#define CACHE_DSIZE	   8192
+#else
+#define CACHE_DSIZE	   16384 
+#endif 
+#define CACHE_ILINESIZE	   16
+#define CACHE_ISIZE	   16384
+
+/* Luke Lee 04/06/2005 ins begin */
+/*
+ *	initialize_cache_info()
+ *
+ *	Automatic detection of DSIZE, DLEN, ISIZE, ILEN variables according to 
+ *	system register CR0-1
+ *	Destroyed register: r0, r1, r2, r3, ip
+ */
+	.align
+ENTRY(fa_initialize_cache_info)
+	mov	r3, #1				@ r3 always = 1
+	adr	ip, __fa_cache_ilen
+	
+	mrc	p15, 0, r0, c0, c0, 1
+	/* ILEN */
+	and	r1, r0, #3			@ bits [1:0]
+	add	r1, r1, #3			@ cache line size is at least 8 bytes (2^3)
+	mov	r2, r3, lsl r1			@ r2 = 1<<r1
+	str	r2, [ip], #4
+	/* ISIZE */
+	mov	r1, r0, lsr #6			@ bits [8:6]
+	and	r1, r1, #7
+	add	r1, r1, #9			@ cache size is at least 512 bytes (2^9)
+	mov	r2, r3, lsl r1
+	str	r2, [ip], #4
+	/* DLEN */
+	mov	r1, r0, lsr #12
+	and	r1, r1, #3			@ bits [13:12]
+	add	r1, r1, #3			@ cache line size is at least 8 bytes (2^3)
+	mov	r2, r3, lsl r1			@ r2 = 1<<r1
+	str	r2, [ip], #4
+	/* DSIZE */
+	mov	r1, r0, lsr #18			@ bits [20:18]
+	and	r1, r1, #7
+	add	r1, r1, #9			@ cache size is at least 512 bytes (2^9)
+	mov	r2, r3, lsl r1
+	str	r2, [ip]
+	mov	pc, lr
+
+	/* Warning : Do not change the order ! Successive codes depends on this */
+	.align
+	.globl __fa_cache_ilen, __fa_cache_isize, __fa_cache_dlen, __fa_cache_dsize
+__fa_cache_ilen:
+	.word	0				@ instruction cache line length
+__fa_cache_isize:
+	.word	0				@ instruction cache size
+__fa_cache_dlen:
+	.word	0				@ data cahce line length	
+__fa_cache_dsize:
+	.word	0				@ data cache size
+
+/* Luke Lee 04/06/2005 ins end */
+
+/*
+ *	flush_user_cache_all()
+ *
+ *	Clean and invalidate all cache entries in a particular address
+ *	space.
+ */
+ENTRY(fa_flush_user_cache_all)
+	/* FALLTHROUGH */
+/*
+ *	flush_kern_cache_all()
+ *
+ *	Clean and invalidate the entire cache.
+ */
+ENTRY(fa_flush_kern_cache_all)
+/* Luke Lee 04/06/2005 mod ok */
+	mov	ip, #0
+	
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+#endif
+	
+__flush_whole_cache:
+	
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+	mov	ip, #0
+#  ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+#  else
+	mcr	p15, 0, ip, c7,c14, 0		@ clean/invalidate D cache
+#  endif
+#endif /*CONFIG_CPU_DCACHE_DISABLE*/
+	
+#ifndef CONFIG_CPU_FA_WB_DISABLE	
+	mcr	p15, 0, ip, c7, c10, 4		@ drain write buffer
+#endif
+	
+#ifdef CONFIG_CPU_FA_BTB
+	mcr	p15, 0, ip, c7, c5, 6		@ invalidate BTB
+	nop
+	nop
+#endif
+	
+/* Luke Lee 04/06/2005 que todo tofix : should iscratchpad and dscratchpad be invalidated ? */
+	mov	pc, lr
+
+/*
+ *	flush_user_cache_range(start, end, flags)
+ *
+ *	Invalidate a range of cache entries in the specified
+ *	address space.
+ *
+ *	- start - start address (inclusive, page aligned)
+ *	- end	- end address (exclusive, page aligned)
+ *	- flags	- vma_area_struct flags describing address space
+ */
+ENTRY(fa_flush_user_cache_range)
+
+/* Luke Lee 04/06/2005 mod ok */
+	/* Luke Lee 04/07/2005 ins 1 */
+	mov	ip, #0
+	sub	r3, r1, r0			@ calculate total size
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	tst	r2, #VM_EXEC			@ executable region?
+	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+#endif
+
+#ifndef CONFIG_CPU_DCACHE_DISABLE	
+	/* Luke Lee 04/06/2005 ins 2 mod 1 */
+	cmp	r3, #CACHE_DSIZE		@ total size >= limit?
+	bhs	__flush_whole_cache		@ flush whole D cache
+
+	//debug_Aaron
+        bic     r0, r0, #CACHE_DLINESIZE-1  
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate boundary D entry
+        bic     r1, r1, #CACHE_DLINESIZE-1  
+	mcr	p15, 0, r1, c7, c14, 1		@ clean and invalidate boundary D entry
+
+
+1:	/* Luke Lee 04/06/2005 del 2 ins 5 */
+	
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+#else
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+#endif
+	/* Luke Lee 04/06/2005 mod 1 */
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	bls	1b				@ Luke Lee 05/19/2005
+#endif	/* CONFIG_CPU_DCACHE_DISABLE */
+	
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	tst	r2, #VM_EXEC
+	/* Luke Lee 04/06/2005 mod 1 tofix todo : ne->eq */
+	mcreq	p15, 0, r4, c7, c10, 4		@ drain write buffer
+#endif
+
+	/* Luke Lee 04/06/2005 ins block */
+#ifdef CONFIG_CPU_FA_BTB
+        tst     r2, #VM_EXEC
+	mov	ip, #0
+	mcrne	p15, 0, ip, c7, c5, 6		@ invalidate BTB
+	nop
+	nop
+#endif
+	mov	pc, lr
+
+/*
+ *	flush_kern_dcache_page(void *page)
+ *
+ *	Ensure no D cache aliasing occurs, either with itself or
+ *	the I cache
+ *
+ *	- addr	- page aligned address
+ */
+ENTRY(fa_flush_kern_dcache_page)
+	add	r1, r0, #PAGE_SZ
+	/* fall through */
+
+/*
+ *	coherent_kern_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_coherent_kern_range)
+	/* fall through */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_coherent_user_range)
+
+/* Luke Lee 04/06/2005 mod ok */
+	/* Luke Lee 04/06/2005 ins 3 mod 1 */
+	bic	r0, r0, #CACHE_DLINESIZE-1
+
+ //debug_Aaron
+        bic     r0, r0, #CACHE_DLINESIZE-1
+        mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate boundary D entry
+        bic     r1, r1, #CACHE_DLINESIZE-1
+        mcr     p15, 0, r1, c7, c14, 1          @ clean and invalidate boundary D entry
+
+#if !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE))
+1:	/* Luke Lee 04/06/2005 del 2 ins 5 mod 1 */
+#ifndef CONFIG_CPU_DCACHE_DISABLE	
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+#else
+	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+#endif
+#endif /* CONFIG_CPU_DCACHE_DISABLE */
+	
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
+#endif
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	bls	1b				@ Luke Lee 05/19/2005 blo->bls	
+#endif /* !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) */
+
+	mov	ip, #0
+#ifdef CONFIG_CPU_FA_BTB
+	mcr	p15, 0, ip, c7, c5, 6		@ invalidate BTB
+	nop
+	nop
+#endif
+
+/* Luke Lee 04/08/2005 ins 1 skp 1 ins 1 */
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+#endif
+
+	mov	pc, lr
+
+/*
+ *	dma_inv_range(start, end)
+ *
+ *	Invalidate (discard) the specified virtual address range.
+ *	May not write back any entries.  If 'start' or 'end'
+ *	are not cache line aligned, those lines must be written
+ *	back.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_dma_inv_range)
+
+/* Luke Lee 04/06/2005 mod ok */
+
+#ifndef CONFIG_CPU_DCACHE_DISABLE	
+
+ //debug_Aaron
+        bic     r0, r0, #CACHE_DLINESIZE-1
+        mcr     p15, 0, r0, c7, c6, 1          @ invalidate boundary D entry
+        bic     r1, r1, #CACHE_DLINESIZE-1
+        mcr     p15, 0, r1, c7, c6, 1          @ invalidate boundary D entry
+
+	/* Luke Lee 04/06/2005 ins 4 mod 2 */
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	tst	r0, #CACHE_DLINESIZE -1
+	bic	r0, r0, #CACHE_DLINESIZE -1
+
+//debug_Aaron
+	//mcrne	p15, 0, r0, c7, c10, 1		@ clean boundary D entry
+
+	/* Luke Lee 04/06/2005 mod 1 */
+	/* Luke Lee 05/19/2005 always clean the end-point boundary mcrne->mcr */
+	////tst	r1, #CACHE_DLINESIZE -1
+	//mcr	p15, 0, r1, c7, c10, 1		@ clean boundary D entry
+	/* Luke Lee 04/06/2005 ins 1 */
+#else
+	bic	r0, r0, #CACHE_DLINESIZE -1	
+#endif
+
+//debug_Aaron	
+1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
+//1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
+
+	/* Luke Lee 04/06/2005 mod 1 */	
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	bls	1b				@ Luke Lee 05/19/2005 blo->bls
+#endif /* CONFIG_CPU_DCACHE_DISABLE */
+
+	/* Luke Lee 04/06/2005 ins 1 */		
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+#endif	
+
+	mov	pc, lr
+
+/*
+ *	dma_clean_range(start, end)
+ *
+ *	Clean (write back) the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(fa_dma_clean_range)
+
+/* Luke Lee 04/06/2005 mod ok */
+#ifndef CONFIG_CPU_DCACHE_DISABLE	
+
+ //debug_Aaron
+        bic     r0, r0, #CACHE_DLINESIZE-1
+        mcr     p15, 0, r0, c7, c10, 1          @ clean boundary D entry
+        bic     r1, r1, #CACHE_DLINESIZE-1
+        mcr     p15, 0, r1, c7, c10, 1          @ clean boundary D entry
+
+	/* Luke Lee 04/06/2005 ins 4 mod 2 */
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	bic	r0, r0, #CACHE_DLINESIZE - 1
+
+//debug_Aaron
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+//1:	mcr	p15, 0, r0, c7, c14, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	cmp	r0, r1
+	bls	1b				@ Luke Lee 05/19/2005 blo->bls
+	/* Luke Lee 04/06/2005 ins 2 */
+#endif
+#endif /* CONFIG_CPU_DCACHE_DISABLE */
+
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mov	r0, #0	
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+#endif	
+
+	mov	pc, lr
+
+/*
+ *	dma_flush_range(start, end)
+ *
+ *	Clean and invalidate the specified virtual address range.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ *
+ *	This is actually the same as fa_coherent_kern_range()
+ */
+	.globl	fa_dma_flush_range
+	.set	fa_dma_flush_range, fa_coherent_kern_range
+
+	__INITDATA
+
+	.type	fa_cache_fns, #object
+ENTRY(fa_cache_fns)
+	.long	fa_flush_kern_cache_all
+	.long	fa_flush_user_cache_all
+	.long	fa_flush_user_cache_range
+	.long	fa_coherent_kern_range
+	.long	fa_coherent_user_range
+	.long	fa_flush_kern_dcache_page
+	.long	fa_dma_inv_range
+	.long	fa_dma_clean_range
+	.long	fa_dma_flush_range
+	.size	fa_cache_fns, . - fa_cache_fns
--- /dev/null
+++ b/arch/arm/mm/copypage-fa.S
@@ -0,0 +1,106 @@
+/*
+ *  linux/arch/arm/lib/copypage-fa.S
+ *
+ *  Copyright (C) 2005 Faraday Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  ASM optimised string functions
+ * 05/18/2005 :	Luke Lee created, modified from copypage-v4wb.S
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+
+	.text
+/*
+ * ARMv4 optimised copy_user_page for Faraday processors
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address.  Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ *
+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
+ * instruction.  If your processor does not supply this, you have to write your
+ * own copy_user_page that does the right thing.
+ *
+ * copy_user_page(to,from,vaddr)
+ */
+	.align	4
+ENTRY(fa_copy_user_page)
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	/* Write through */
+	stmfd	sp!, {r4, lr}			@ 2
+	mov	r2, #PAGE_SZ/32			@ 1
+
+	ldmia	r1!, {r3, r4, ip, lr}		@ 4
+1:	stmia	r0!, {r3, r4, ip, lr}		@ 4
+	ldmia	r1!, {r3, r4, ip, lr}		@ 4+1
+	subs	r2, r2, #1			@ 1
+	stmia	r0!, {r3, r4, ip, lr}		@ 4
+	ldmneia	r1!, {r3, r4, ip, lr}		@ 4
+	bne	1b				@ 1
+
+	mcr	p15, 0, r2, c7, c7, 0		@ flush ID cache
+	ldmfd	sp!, {r4, pc}			@ 3
+#else
+	/* Write back */
+	stmfd	sp!, {r4, lr}			@ 2
+	mov	r2, #PAGE_SZ/32			@ 1
+
+1:	ldmia	r1!, {r3, r4, ip, lr}		@ 4
+	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line
+	stmia	r0!, {r3, r4, ip, lr}		@ 4
+	ldmia	r1!, {r3, r4, ip, lr}		@ 4
+	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line
+	stmia	r0!, {r3, r4, ip, lr}		@ 4
+	subs	r2, r2, #1			@ 1
+	bne	1b
+	mcr	p15, 0, r2, c7, c10, 4		@ 1   drain WB
+	ldmfd	sp!, {r4, pc}			@ 3
+#endif
+
+/*
+ * ARMv4 optimised clear_user_page
+ *
+ * Same story as above.
+ */
+	.align	4
+ENTRY(fa_clear_user_page)
+	str	lr, [sp, #-4]!
+	mov	r1, #PAGE_SZ/32			@ 1
+	mov	r2, #0				@ 1
+	mov	r3, #0				@ 1
+	mov	ip, #0				@ 1
+	mov	lr, #0				@ 1
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	/* Write through */
+1:	stmia	r0!, {r2, r3, ip, lr}		@ 4
+	stmia	r0!, {r2, r3, ip, lr}		@ 4
+	subs	r1, r1, #1			@ 1
+	bne	1b				@ 1
+
+	mcr	p15, 0, r1, c7, c7, 0		@ flush ID cache
+	ldr	pc, [sp], #4
+#else
+	/* Write back */
+1:	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line
+	stmia	r0!, {r2, r3, ip, lr}		@ 4
+	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line
+	stmia	r0!, {r2, r3, ip, lr}		@ 4
+	subs	r1, r1, #1			@ 1
+	bne	1b				@ 1
+	mcr	p15, 0, r1, c7, c10, 4		@ 1   drain WB
+	ldr	pc, [sp], #4
+#endif
+
+	__INITDATA
+
+	.type	fa_user_fns, #object
+ENTRY(fa_user_fns)
+	.long	fa_clear_user_page
+	.long	fa_copy_user_page
+	.size	fa_user_fns, . - fa_user_fns
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -23,6 +23,7 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/arch/ipi.h>
 
 #include "mm.h"
 
@@ -252,6 +253,11 @@
 		initrd_end = initrd_start + phys_initrd_size;
 	}
 #endif
+#ifdef CONFIG_GEMINI_IPI
+	printk("CPU ID:%d\n",getcpuid());
+//	reserve_bootmem_node(NODE_DATA(0), 0x400000, 0x400000);		//CPU0 space
+//	reserve_bootmem_node(NODE_DATA(0), SHAREADDR, SHARE_MEM_SIZE);		//share memory
+#endif
 
 	/*
 	 * Finally, reserve any node zero regions.
--- /dev/null
+++ b/arch/arm/mm/proc-fa526.S
@@ -0,0 +1,407 @@
+/*
+ *  linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526
+ *
+ *  Copyright (C) 2005 Faraday Corp.
+ *
+ * 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
+ *
+ *
+ * These are the low level assembler for performing cache and TLB
+ * functions on the fa526.
+ *
+ *  Written by : Luke Lee
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/pgtable.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/elf.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include "proc-macros.S"
+
+#define CACHE_DLINESIZE	   16
+
+	.text
+/*
+ * cpu_fa526_proc_init()
+ */
+ENTRY(cpu_fa526_proc_init)
+	/* MMU is already ON here, ICACHE, DCACHE conditionally disabled */
+
+        mov     r0, #1
+	nop
+	nop
+        mcr     p15, 0, r0, c1, c1, 0		@ turn-on ECR
+	nop
+	nop
+
+	mrc	p15, 0, r0, c1, c0, 0		@ read ctrl register
+
+#ifdef CONFIG_CPU_FA_BTB
+	orr	r0, r0, #CR_Z
+#else
+	bic	r0, r0, #CR_Z
+#endif
+#ifdef CONFIG_CPU_FA_WB_DISABLE
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4		@ drain write buffer
+	nop
+	nop
+	bic	r0, r0, #CR_W
+#else
+	orr	r0, r0, #CR_W
+#endif
+#ifdef CONFIG_CPU_DCACHE_DISABLE
+	bic	r0, r0, #CR_C
+#else
+	orr	r0, r0, #CR_C
+#endif
+#ifdef CONFIG_CPU_ICACHE_DISABLE
+	bic	r0, r0, #CR_I
+#else
+	orr	r0, r0, #CR_I
+#endif
+
+	nop
+	nop
+    	mcr	p15, 0, r0, c1, c0, 0
+	nop
+	nop
+
+	mov	r5, lr
+	bl	fa_initialize_cache_info	@ destroy r0~r4
+	mov	pc, r5				@ return
+
+
+/*
+ * cpu_fa526_proc_fin()
+ */
+ENTRY(cpu_fa526_proc_fin)
+	stmfd	sp!, {lr}
+	mov	ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
+	msr	cpsr_c, ip
+
+	bl	fa_flush_kern_cache_all
+	mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
+	bic	r0, r0, #0x1000			@ ...i............
+	bic	r0, r0, #0x000e			@ ............wca.
+	mcr	p15, 0, r0, c1, c0, 0		@ disable caches
+
+	nop
+	nop
+	ldmfd	sp!, {pc}
+
+/*
+ * cpu_fa526_reset(loc)
+ *
+ * Perform a soft reset of the system.  Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * loc: location to jump to for soft reset
+ */
+	.align	4
+ENTRY(cpu_fa526_reset)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0		@ invalidate I,D caches
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+#endif
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate I & D TLBs
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x000f			@ ............wcam
+	bic	ip, ip, #0x1100			@ ...i...s........
+
+	bic	ip, ip, #0x0800			@ BTB off
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
+	nop
+	nop
+	mov	pc, r0
+
+/*
+ * cpu_fa526_do_idle()
+ */
+	.align	4
+ENTRY(cpu_fa526_do_idle)
+
+#ifdef CONFIG_CPU_FA_IDLE
+	nop
+	nop
+	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt (IDLE mode)
+#endif
+	mov	pc, lr
+
+
+ENTRY(cpu_fa526_dcache_clean_area)
+
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+	add	r0, r0, #CACHE_DLINESIZE
+	subs	r1, r1, #CACHE_DLINESIZE
+	bhi	1b
+#endif
+#endif
+	mov	pc, lr
+
+
+/* =============================== PageTable ============================== */
+
+/*
+ * cpu_fa526_switch_mm(pgd)
+ *
+ * Set the translation base pointer to be as described by pgd.
+ *
+ * pgd: new page tables
+ */
+	.align	4
+
+	.globl	fault_address
+fault_address:
+	.long	0
+
+ENTRY(cpu_fa526_switch_mm)
+
+	mov	ip, #0
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+#else
+	mcr	p15, 0, ip, c7, c14, 0		@ Clean and invalidate whole DCache
+#endif
+#endif /*CONFIG_CPU_DCACHE_DISABLE*/
+
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
+#endif
+
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
+#endif
+
+#ifdef CONFIG_CPU_FA_BTB
+	mcr	p15, 0, ip, c7, c5, 6		@ invalidate BTB since mm changed
+	nop
+	nop
+#endif
+	bic	r0, r0, #0xff			@ clear bits [7:0]
+	bic	r0, r0, #0x3f00			@ clear bits [13:8]
+	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
+	mcr	p15, 0, ip, c8, c7, 0		@ invalidate UTLB
+	nop
+	nop
+	mov	pc, lr
+
+/*
+ * cpu_fa526_set_pte_ext(ptep, pte, ext)
+ *
+ * Set a PTE and flush it out
+ */
+	.align	4
+ENTRY(cpu_fa526_set_pte_ext)
+	str	r1, [r0], #-2048		@ linux version
+
+	eor	r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+
+	bic	r2, r1, #PTE_SMALL_AP_MASK
+	bic	r2, r2, #PTE_TYPE_MASK
+	orr	r2, r2, #PTE_TYPE_SMALL
+
+	tst	r1, #L_PTE_USER			@ User?
+	orrne	r2, r2, #PTE_SMALL_AP_URO_SRW
+
+	tst	r1, #L_PTE_WRITE | L_PTE_DIRTY	@ Write and Dirty?
+	orreq	r2, r2, #PTE_SMALL_AP_UNO_SRW
+
+	tst	r1, #L_PTE_PRESENT | L_PTE_YOUNG	@ Present and Young?
+	movne	r2, #0
+
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	eor	r3, r2, #0x0a			@ C & small page?  1010
+	tst	r3, #0x0b			@		   1011
+	biceq	r2, r2, #4
+#endif
+	str	r2, [r0]			@ hardware version
+
+	mov	r2, #0
+	mcr	p15, 0, r2, c7, c10, 0		@ clean D cache	all
+
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mcr	p15, 0, r2, c7, c10, 4		@ drain WB
+#endif
+#ifdef CONFIG_CPU_FA_BTB
+	mcr	p15, 0, r2, c7, c5, 6		@ invalidate BTB
+	nop
+	nop
+#endif
+	mov	pc, lr
+
+	__INIT
+
+	.type	__fa526_setup, #function
+__fa526_setup:
+	/* On return of this routine, r0 must carry correct flags for CFG register */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7		@ invalidate I,D caches on v4
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
+	mcr	p15, 0, r0, c8, c7		@ invalidate I,D TLBs on v4
+
+	mcr	p15, 0, r0, c7, c5, 5		@ invalidate IScratchpad RAM
+
+        mov     r0, #1
+        mcr     p15, 0, r0, c1, c1, 0		@ turn-on ECR
+
+	mrc	p15, 0, r0, c9, c1, 0		@ DScratchpad
+	bic	r0, r0, #1
+	mcr	p15, 0, r0, c9, c1, 0
+	mrc	p15, 0, r0, c9, c1, 1		@ IScratchpad
+	bic	r0, r0, #1
+	mcr	p15, 0, r0, c9, c1, 1
+
+	mov	r0, #0
+	mcr	p15, 0, r0, c1, c1, 0		@ turn-off ECR
+
+#ifdef CONFIG_CPU_FA_BTB
+	mcr	p15, 0, r0, c7, c5, 6		@ invalidate BTB All
+	nop
+	nop
+#endif
+
+	mov	r0, #0x1f			@ Domains 0, 1 = manager, 2 = client
+	mcr	p15, 0, r0, c3, c0		@ load domain access register
+
+	mrc	p15, 0, r0, c1, c0		@ get control register v4
+	ldr	r5, fa526_cr1_clear
+	bic	r0, r0, r5
+	ldr	r5, fa526_cr1_set
+	orr	r0, r0, r5
+
+#ifdef CONFIG_CPU_FA_BTB
+	orr	r0, r0, #CR_Z
+#else
+	bic	r0, r0, #CR_Z
+#endif
+#ifdef CONFIG_CPU_FA_WB_DISABLE
+	mov	r12, #0
+	mcr	p15, 0, r12, c7, c10, 4		@ drain write buffer
+	nop
+	nop
+	bic	r0, r0, #CR_W			@ .... .... .... 1...
+#else
+	orr	r0, r0, #CR_W
+#endif
+
+	mov	pc, lr
+	.size	__fa526_setup, . - __fa526_setup
+
+	/*
+	 * .RVI ZFRS BLDP WCAM
+	 * ..11 0001 .111 1101
+	 *
+	 */
+	.type	fa526_cr1_clear, #object
+	.type	fa526_cr1_set, #object
+fa526_cr1_clear:
+	.word	0x3f3f
+fa526_cr1_set:
+	.word	0x317D
+
+	__INITDATA
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *	     come through these
+ */
+	.type	fa526_processor_functions, #object
+fa526_processor_functions:
+	.word	v4_early_abort
+	.word	cpu_fa526_proc_init
+	.word	cpu_fa526_proc_fin
+	.word	cpu_fa526_reset
+	.word   cpu_fa526_do_idle
+	.word	cpu_fa526_dcache_clean_area
+	.word	cpu_fa526_switch_mm
+	.word	cpu_fa526_set_pte_ext
+	.size	fa526_processor_functions, . - fa526_processor_functions
+
+	.section ".rodata"
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv4"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v4"
+	.size	cpu_elf_name, . - cpu_elf_name
+
+	.type	cpu_fa526_name, #object
+cpu_fa526_name:
+	.ascii	"FA526"
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	.ascii	"i"
+#endif
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+	.ascii	"d"
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	.ascii	"(wt)"
+#else
+	.ascii	"(wb)"
+#endif
+#endif
+	.ascii	"\0"
+	.size	cpu_fa526_name, . - cpu_fa526_name
+
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+#define __PMD_SECT_BUFFERABLE	0
+#else
+#define __PMD_SECT_BUFFERABLE	PMD_SECT_BUFFERABLE
+#endif
+
+	.type	__fa526_proc_info,#object
+__fa526_proc_info:
+	.long	0x66015261
+	.long	0xff01fff1
+	.long   PMD_TYPE_SECT | \
+		__PMD_SECT_BUFFERABLE | \
+		PMD_SECT_CACHEABLE | \
+		PMD_BIT4 | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	.long   PMD_TYPE_SECT | \
+		PMD_BIT4 | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	b	__fa526_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP | HWCAP_HALF
+	.long	cpu_fa526_name
+	.long	fa526_processor_functions
+	.long	fa_tlb_fns
+	.long	fa_user_fns
+	.long	fa_cache_fns
+	.size	__fa526_proc_info, . - __fa526_proc_info
+
+
--- /dev/null
+++ b/arch/arm/mm/tlb-fa.S
@@ -0,0 +1,96 @@
+/*
+ *  linux/arch/arm/mm/tlb-fa.S
+ *
+ *  Copyright (C) 2005 Faraday Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  ARM architecture version 4, Faraday variation.
+ *  This assume an unified TLBs, with a write buffer, and branch target buffer (BTB)
+ *
+ *  Processors: FA520 FA526 FA626
+ *  03/31/2005 : Created by Luke Lee, modified from tlb-v4wbi.S
+ *  05/06/2005 : Fixed buggy CPU versions that did not invalidate the associated
+ *               data cache entries when invalidating TLB entries.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+
+/*
+ *	flush_user_tlb_range(start, end, mm)
+ *
+ *	Invalidate a range of TLB entries in the specified address space.
+ *
+ *	- start - range start address
+ *	- end   - range end address
+ *	- mm    - mm_struct describing address space
+ */
+	.align	4
+ENTRY(fa_flush_user_tlb_range)
+
+	vma_vm_mm ip, r2
+	act_mm	r3				@ get current->active_mm
+	eors	r3, ip, r3			@ == mm ?
+	movne	pc, lr				@ no, we dont do anything
+	mov	r3, #0
+
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
+#endif
+
+	vma_vm_flags r2, r2
+	bic	r0, r0, #0x0ff
+	bic	r0, r0, #0xf00
+
+1:	mcr	p15, 0, r0, c8, c7, 1		@ invalidate UTLB entry
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	bls	1b				@ Luke Lee 05/19/2005 blo -> bls
+
+#ifdef CONFIG_CPU_FA_BTB
+	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB
+	nop
+	nop
+#endif
+	mov	pc, lr
+
+
+ENTRY(fa_flush_kern_tlb_range)
+	mov	r3, #0
+
+	mcr	p15, 0, r3, c7, c10, 0		@ clean Dcache all 06/03/2005
+
+#ifndef CONFIG_CPU_FA_WB_DISABLE
+	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
+#endif
+
+	bic	r0, r0, #0x0ff
+	bic	r0, r0, #0xf00
+1:
+	mcr	p15, 0, r0, c8, c7, 1		@ invalidate UTLB entry
+	add	r0, r0, #PAGE_SZ
+	cmp	r0, r1
+	bls	1b				@ Luke Lee 05/19/2005 blo -> bls
+
+#ifdef CONFIG_CPU_FA_BTB
+	mcr	p15, 0, r3, c7, c5, 6		@ invalidate BTB
+	nop
+	nop
+#endif
+	mov	pc, lr
+
+
+	__INITDATA
+
+	.type	fa_tlb_fns, #object
+ENTRY(fa_tlb_fns)
+	.long	fa_flush_user_tlb_range
+	.long	fa_flush_kern_tlb_range
+	.long	fa_tlb_flags
+	.size	fa_tlb_fns, . - fa_tlb_fns
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -208,7 +208,8 @@
 fester			SA1100_FESTER		FESTER			191
 gpi			ARCH_GPI		GPI			192
 smdk2410		ARCH_SMDK2410		SMDK2410		193
-i519			ARCH_I519		I519			194
+#i519			ARCH_I519		I519			194
+sl2312          ARCH_SL2312         SL2312          194
 nexio			SA1100_NEXIO		NEXIO			195
 bitbox			SA1100_BITBOX		BITBOX			196
 g200			SA1100_G200		G200			197
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/SL_gpio.h
@@ -0,0 +1,59 @@
+#define GPIO_MINOR_LAST 31
+#define GPIO_MAJOR	120	// Experiemental
+
+#define GPIO_IRQ_NBR	12
+
+#define GPIOBASEADDR		(IO_ADDRESS(0x021000000))
+
+#define GPIODATAOUTOFF		0x00
+#define GPIODATAINOFF		0x04
+#define GPIOPINDIROFF		0x08
+#define GPIOPINBYPASSOFF	0x0C
+#define GPIODATASETOFF		0x10
+#define GPIODATACLEAROFF	0x14
+#define GPIOPINPULLENBOFF	0x18
+#define GPIOPINPULLTPOFF	0x1C
+#define GPIOINTRENBOFF		0x20
+#define GPIOINTRRAWSOFF		0x24
+#define GPIOINTRMASKEDSTATEOFF	0x28
+#define GPIOINTRMASKOFF		0x2C
+#define GPIOINTRCLEAROFF	0x30
+#define GPIOINTRTRIGGEROFF	0x34
+#define GPIOINTRBOTHOFF		0x38
+#define GPIOINTRRISENEGOFF	0x3C
+#define GPIOBNCEENBOFF		0x40
+#define GPIOBNCEPRESOFF		0x44
+
+#define GPIO_IOCTRL_SETDIR	0x20
+#define GPIO_IOCTRL_SET		0x40
+#define GPIO_IOCTRL_CLEAR	0x50
+#define GPIO_IOCTRL_ENBINT	0x60
+#define GPIO_IOCTRL_MASKINT	0x70
+#define GPIO_IOCTRL_LVLTRIG	0x75
+#define GPIO_IOCTRL_EDGINT	0x77
+#define GPIO_IOCTRL_EDGPOLINT	0x78
+#define GPIO_IOCTRL_BYPASS	0x30
+#define GPIO_IOCTRL_PRESCLK	0x80
+#define GPIO_IOCTRL_CLKVAL	0x90
+#define GPIO_IOCTRL_PULLENB	0xA0
+#define GPIO_IOCTRL_PULLTYPE	0xA8
+
+
+#define GPIO_MAJOR	120	/* experimental MAJOR number */
+				// Minor - 0 : 31 gpio pins
+
+#define GPIO_SET	0x01
+#define GPIO_CLEAR	0x01
+
+#define GPIO_INPUT	0
+#define GPIO_OUTPUT	1
+#define GPIO_EDGEINTR 	0
+#define GPIO_EDGESINGL	0
+#define GPIO_EDGEBOTH	1
+#define GPIO_POSITIVE	0
+#define GPIO_ENBINT	1
+#define GPIO_DISABLEMASK	1
+#define GPIO_PULLDOWN	0
+#define GPIO_PULLUP	1
+#define GPIO_ENABLEPULL	1
+#define GPIO_DISABLEPULL	0
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/debug-macro.S
@@ -0,0 +1,20 @@
+/* linux/include/asm-arm/arch-ebsa110/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+**/
+
+		.macro	addruart,rx
+		mov	\rx, #0x42000000
+		.endm
+
+#define UART_SHIFT	2
+#define FLOW_CONTROL
+#include <asm/hardware/debug-8250.S>
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/dma.h
@@ -0,0 +1,28 @@
+/*
+ *  linux/include/asm-arm/arch-camelot/dma.h
+ *
+ *  Copyright (C) 1997,1998 Russell King
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS		0xffffffff
+
+#define MAX_DMA_CHANNELS	0
+
+#endif /* _ASM_ARCH_DMA_H */
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/entry-macro.S
@@ -0,0 +1,42 @@
+/*
+ * include/asm-arm/arch-arm/entry-macro.S
+ *
+ * Low-level IRQ helper macros for ebsa110 platform.
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <asm/arch/platform.h>
+#include <asm/arch/int_ctrl.h>
+
+
+                .macro  disable_fiq
+                .endm
+
+                .macro  get_irqnr_preamble, base, tmp
+                .endm
+
+                .macro  arch_ret_to_user, tmp1, tmp2
+                .endm
+
+                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+                ldr     \irqstat, =IRQ_STATUS(IO_ADDRESS(SL2312_INTERRUPT_BASE))
+                ldr     \irqnr,[\irqstat]
+                cmp     \irqnr,#0
+                beq     2313f
+                mov     \tmp,\irqnr
+                mov     \irqnr,#0
+2312:
+                tst     \tmp, #1
+                bne     2313f
+                add     \irqnr, \irqnr, #1
+                mov     \tmp, \tmp, lsr #1
+                cmp     \irqnr, #31
+                bcc     2312b
+2313:
+                .endm
+
+                .macro  irq_prio_table
+                .endm
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/flash.h
@@ -0,0 +1,83 @@
+#ifndef __ASM_ARM_ARCH_FLASH_H
+#define __ASM_ARM_ARCH_FLASH_H
+
+#define FLASH_START                                     SL2312_FLASH_BASE
+#define SFLASH_SIZE                      		0x00400000
+#define SPAGE_SIZE                       		0x200
+#define BLOCK_ERASE                     		0x50
+#define BUFFER1_READ                    		0x54
+#define BUFFER2_READ                    		0x56
+#define PAGE_ERASE                      		0x81
+#define MAIN_MEMORY_PAGE_READ           		0x52
+#define MAIN_MEMORY_PROGRAM_BUFFER1     		0x82
+#define MAIN_MEMORY_PROGRAM_BUFFER2     		0x85
+#define BUFFER1_TO_MAIN_MEMORY          		0x83
+#define BUFFER2_TO_MAIN_MEMORY          		0x86
+#define MAIN_MEMORY_TO_BUFFER1          		0x53
+#define MAIN_MEMORY_TO_BUFFER2          		0x55
+#define BUFFER1_WRITE                   		0x84
+#define BUFFER2_WRITE                   		0x87
+#define AUTO_PAGE_REWRITE_BUFFER1       		0x58
+#define AUTO_PAGE_REWRITE_BUFFER2       		0x59
+#define READ_STATUS                     		0x57
+
+#define MAIN_MEMORY_PAGE_READ_SPI       		0xD2
+#define BUFFER1_READ_SPI                		0xD4
+#define BUFFER2_READ_SPI                		0xD6
+#define READ_STATUS_SPI                 		0xD7
+
+#define	FLASH_ACCESS_OFFSET	        		0x00000010
+#define	FLASH_ADDRESS_OFFSET            		0x00000014
+#define	FLASH_WRITE_DATA_OFFSET         		0x00000018
+#define	FLASH_READ_DATA_OFFSET          		0x00000018
+#define SERIAL_FLASH_CHIP1_EN            0x00010000  // 16th bit = 1
+#define SERIAL_FLASH_CHIP0_EN            0x00000000  // 16th bit = 0
+#define AT45DB321_PAGE_SHIFT		         0xa
+#define AT45DB642_PAGE_SHIFT		         0xb
+#define CONTINUOUS_MODE		         0x00008000
+
+#define FLASH_ACCESS_ACTION_OPCODE                      0x0000
+#define FLASH_ACCESS_ACTION_OPCODE_DATA                 0x0100
+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS               0x0200
+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA          0x0300
+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_X_DATA          0x0400
+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_2X_DATA         0x0500
+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_3X_DATA         0x0600
+#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA         0x0700
+//#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_X_DATA        0x0600
+//#define FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA       0x0700
+
+#define M25P80_PAGE_SIZE  0x100
+#define M25P80_SECTOR_SIZE  0x10000
+
+
+//#define M25P80_BULK_ERASE                                      1
+//#define M25P80_SECTOR_ERASE                                    2
+//#define M25P80_SECTOR_SIZE                                     0x10000
+
+#define M25P80_WRITE_ENABLE                  		0x06
+#define M25P80_WRITE_DISABLE                 		0x04
+#define M25P80_READ_STATUS                   		0x05
+#define M25P80_WRITE_STATUS              		0x01
+#define M25P80_READ                      		0x03
+#define M25P80_FAST_READ                 		0x0B
+#define M25P80_PAGE_PROGRAM              		0x02
+#define M25P80_SECTOR_ERASE              		0xD8
+#define M25P80_BULK_ERASE                		0xC7
+#define FLASH_ERR_OK							0x0
+
+extern void address_to_page(__u32, __u16 *, __u16 *);
+extern void main_memory_page_read(__u8, __u16, __u16, __u8 *);
+extern void buffer_to_main_memory(__u8, __u16);
+extern void main_memory_to_buffer(__u8, __u16);
+extern void main_memory_page_program(__u8, __u16, __u16, __u8);
+extern void atmel_flash_read_page(__u32, __u8 *, __u32);
+extern void atmel_erase_page(__u8, __u16);
+extern void atmel_read_status(__u8, __u8 *);
+extern void atmel_flash_program_page(__u32, __u8 *, __u32);
+extern void atmel_buffer_write(__u8, __u16, __u8);
+extern void flash_delay(void);
+
+extern int m25p80_sector_erase(__u32 address, __u32 schip_en);
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/gemini_cir.h
@@ -0,0 +1,102 @@
+#ifndef _ASM_ARCH_CIR_H
+#define _ASM_ARCH_CIR_H
+#include <linux/ioctl.h>
+
+#define VCR_KEY_POWER		0x613E609F
+#define TV1_KEY_POWER		0x40040100
+#define TV1_KEY_POWER_EXT	0xBCBD
+#define RC5_KER_POWER		0x0CF3
+
+#define VCC_H_ACT_PER		(16-1)
+#define VCC_L_ACT_PER		(8-1)
+#define VCC_DATA_LEN		(32-1)
+#define TV1_H_ACT_PER		(8-1)
+#define TV1_L_ACT_PER		(4-1)
+#define TV1_DATA_LEN		(48-1)
+
+#define VCC_BAUD		540
+#define TV1_BAUD		430
+#ifdef  CONFIG_SL3516_ASIC
+#define	EXT_CLK			60
+#else
+#define	EXT_CLK			20
+#endif
+
+#define	NEC_PROTOCOL	0x0
+#define	RC5_PROTOCOL	0x1
+#define VCC_PROTOCOL	0x0
+#define TV1_PROTOCOL	0x01
+
+#ifndef	SL2312_CIR_BASE
+#define	SL2312_CIR_BASE		0x4C000000
+#endif
+#define	CIR_BASE_ADDR		IO_ADDRESS(SL2312_CIR_BASE)
+#define STORLINK_CIR_ID		0x00010400
+
+#define	CIR_IP_ID		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x00)
+#define	CIR_CTR_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x04)
+#define	CIR_STATUS_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x08)
+#define	CIR_RX_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x0C)
+#define	CIR_RX_EXT_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x10)
+#define	CIR_PWR_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x14)
+#define	CIR_PWR_EXT_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x18)
+#define	CIR_TX_CTR_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x1C)
+#define	CIR_TX_FEQ_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x20)
+#define	CIR_TX_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x24)
+#define	CIR_TX_EXT_REG		*(volatile unsigned int *)(CIR_BASE_ADDR + 0x28)
+
+
+#ifndef	SL2312_POWER_CTRL_BASE
+#define	SL2312_POWER_CTRL_BASE		0x4B000000
+#endif
+
+#ifndef PWR_BASE_ADDR
+#define	PWR_BASE_ADDR		IO_ADDRESS(SL2312_POWER_CTRL_BASE)
+#endif
+#define	PWR_CTRL_ID		*(unsigned int*)(PWR_BASE_ADDR+0x00)
+#define	PWR_CTRL_REG		*(unsigned int*)(PWR_BASE_ADDR+0x04)
+#define	PWR_STATUS_REG		*(unsigned int*)(PWR_BASE_ADDR+0x08)
+
+
+#define BIT(x)			(1<<x)
+#define TX_STATUS		BIT(3)
+
+#define	PWR_STAT_CIR		0x10
+#define	PWR_STAT_RTC		0x20
+#define	PWR_STAT_PUSH		0x40
+#define	PWR_SHUTDOWN		0x01
+
+#define CARR_FREQ		38000
+
+struct cir_ioctl_data {
+	__u32 data;
+};
+struct cir_ioctl_data48 {
+	__u32 timeout;
+	__u32 length;
+	__u8  ret;
+	__u32 data;
+	__u32 data_ext;
+};
+#define OLD_DATA			0
+#define NEW_RECEIVE			1
+
+#define	CIR_IOCTL_BASE		('I'|'R')
+#define CIR_SET_BAUDRATE			_IOW (CIR_IOCTL_BASE,  0, struct cir_ioctl_data)
+#define CIR_SET_HIGH_PERIOD			_IOW (CIR_IOCTL_BASE,  1, struct cir_ioctl_data)
+#define CIR_SET_LOW_PERIOD			_IOW (CIR_IOCTL_BASE,  2, struct cir_ioctl_data)
+#define CIR_SET_PROTOCOL			_IOW (CIR_IOCTL_BASE,  3, struct cir_ioctl_data)
+#define CIR_SET_ENABLE_COMPARE		_IOW (CIR_IOCTL_BASE,  4, struct cir_ioctl_data)
+#define CIR_SET_ENABLE_DEMOD		_IOW (CIR_IOCTL_BASE,  5, struct cir_ioctl_data)
+#define CIR_SET_POWER_KEY			_IOW (CIR_IOCTL_BASE,  6, struct cir_ioctl_data)
+#define CIR_GET_BAUDRATE			_IOR (CIR_IOCTL_BASE,  7, struct cir_ioctl_data)
+#define CIR_GET_HIGH_PERIOD			_IOR (CIR_IOCTL_BASE,  8 ,struct cir_ioctl_data)
+#define CIR_GET_LOW_PERIOD			_IOR (CIR_IOCTL_BASE,  9 ,struct cir_ioctl_data)
+#define CIR_GET_PROTOCOL			_IOR (CIR_IOCTL_BASE, 10, struct cir_ioctl_data)
+#define CIR_GET_ENABLE_COMPARE		_IOR (CIR_IOCTL_BASE, 11, struct cir_ioctl_data)
+#define CIR_GET_ENABLE_DEMOD		_IOR (CIR_IOCTL_BASE, 12, struct cir_ioctl_data)
+#define CIR_GET_POWER_KEY			_IOR (CIR_IOCTL_BASE, 13, struct cir_ioctl_data)
+#define CIR_GET_DATA				_IOWR (CIR_IOCTL_BASE, 14, struct cir_ioctl_data48)
+#define CIR_WAIT_INT_DATA			_IOWR (CIR_IOCTL_BASE, 15, struct cir_ioctl_data48)
+
+#endif //_ASM_ARCH_CIR_H
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/gemini_gpio.h
@@ -0,0 +1,77 @@
+/*
+ * FILE NAME gemini_gpio.h
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Generic Gemini GPIO
+ *
+ *  Author: Storlink Software [Device driver]
+ *          Jason Lee <jason@storlink.com.tw>
+ *
+ * Copyright 2005 Storlink Inc.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __GEMINI_GPIO_H
+#define __GEMINI_GPIO_H
+
+#include <linux/ioctl.h>
+
+#define STATUS_HIGH	1
+#define STATUS_LOW	0
+#define DIRECT_OUT	1
+#define DIRECT_IN	0
+
+#define EDGE_TRIG	0
+#define RISING_EDGE	0
+#define FALL_EDGE	1
+#define SINGLE_EDGE	0
+#define BOTH_EDGE	1
+
+#define LEVEL_TRIG	1
+#define HIGH_ACTIVE	0
+#define LOW_ACTIVE	1
+
+struct gemini_gpio_ioctl_data {
+	__u32 pin;
+	__u8 status;			// status or pin direction
+					// 0: status low or Input
+					// 1: status high or Output
+
+	/* these member are used to config GPIO interrupt parameter */
+	__u8	use_default;		// if not sure ,set this argument 1
+	__u8	trig_type;		// 0/1:edge/level triger ?
+	__u8	trig_polar;		// 0/1:rising/falling high/low active ?
+	__u8	trig_both;		// 0/1:single/both detect both ?
+};
+
+#define GEMINI_GPIO_IOCTL_BASE	'Z'
+
+#define GEMINI_SET_GPIO_PIN_DIR		_IOW (GEMINI_GPIO_IOCTL_BASE,16, struct gemini_gpio_ioctl_data)
+#define	GEMINI_SET_GPIO_PIN_STATUS	_IOW (GEMINI_GPIO_IOCTL_BASE,17, struct gemini_gpio_ioctl_data)
+#define	GEMINI_GET_GPIO_PIN_STATUS	_IOWR(GEMINI_GPIO_IOCTL_BASE,18, struct gemini_gpio_ioctl_data)
+#define GEMINI_WAIT_GPIO_PIN_INT	_IOWR(GEMINI_GPIO_IOCTL_BASE,19, struct gemini_gpio_ioctl_data)
+
+
+extern void init_gpio_int(__u32 pin,__u8 trig_type,__u8 trig_polar,__u8 trig_both);
+extern int request_gpio_irq(int bit,void (*handler)(int),char level,char high,char both);
+extern int free_gpio_irq(int bit);
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/gemini_i2s.h
@@ -0,0 +1,169 @@
+#ifndef __GEMINI_I2S_H__
+#define __GEMINI_I2S_H__
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <asm/arch-sl2312/irqs.h>
+
+typedef __u16 UINT16;
+typedef __u32 UINT32;
+typedef __u8 UINT8;
+typedef __u8 BOOL;
+
+/***************************************/
+/* define GPIO module base address     */
+/***************************************/
+#define DMA_CONTROL_PHY_BASE  (IO_ADDRESS(SL2312_GENERAL_DMA_BASE))
+#define DMA_CONTROL_SSP_BASE  (IO_ADDRESS(SL2312_SSP_CTRL_BASE))
+#define SSP_INT				IRQ_SSP
+#define GPIO_BASE_ADDR      (IO_ADDRESS(SL2312_GPIO_BASE))
+#define GPIO_BASE_ADDR1      (IO_ADDRESS(SL2312_GPIO_BASE1))
+#define GLOBAL_BASE      (IO_ADDRESS(SL2312_GLOBAL_BASE))
+
+/* define read/write register utility */
+#define READ_SSP_REG(offset)			(__raw_readl(offset+DMA_CONTROL_SSP_BASE))
+#define WRITE_SSP_REG(offset,val) 	(__raw_writel(val,offset+DMA_CONTROL_SSP_BASE))
+
+#define READ_GPIO_REG(offset)			(__raw_readl(offset+GPIO_BASE_ADDR))
+#define WRITE_GPIO_REG(offset,val) 	(__raw_writel(val,offset+GPIO_BASE_ADDR))
+
+#define READ_GPIO1_REG(offset)			(__raw_readl(offset+GPIO_BASE_ADDR1))
+#define WRITE_GPIO1_REG(offset,val) 	(__raw_writel(val,offset+GPIO_BASE_ADDR1))
+
+#define READ_DMA_REG(offset)			(__raw_readl(offset+DMA_CONTROL_PHY_BASE))
+#define WRITE_DMA_REG(offset,val) 	(__raw_writel(val,offset+DMA_CONTROL_PHY_BASE))
+
+#define READ_GLOBAL_REG(offset)			(__raw_readl(offset+GLOBAL_BASE))
+#define WRITE_GLOBAL_REG(offset,val) 	(__raw_writel(val,offset+GLOBAL_BASE))
+
+#define SSP_GPIO_INT       	IRQ_GPIO
+
+#ifndef CONFIG_SL3516_ASIC
+#define SSP_GPIO_INT_BIT    0x00000400				//GPIO[10] : SLIC interrupt pin
+
+#define GPIO_EECK	     0x00000040         /*   SCK: GPIO[06]   */
+#define GPIO_EECS	     0x00000080			/*   SCS: GPIO[07]   */
+#define GPIO_MISO	     0x00000200         /*   SDO: GPIO[09]   receive from 6996*/
+#define GPIO_MOSI	     0x00000100         /*   SDI: GPIO[08]   send to 6996*/
+#define GPIO_MISO_BIT	 9
+#else
+#define SSP_GPIO_INT_BIT    0x00000001				//GPIO[0] : SLIC interrupt pin
+
+//#if 0
+//#define GPIO_EECK	     0x80000000         /*   SCK: GPIO1[31]   */
+//#define GPIO_EECS	     0x40000000			/*   SCS: GPIO1[30]   */
+//#define GPIO_MISO	     0x20000000         /*   SDO: GPIO1[29]   receive from 6996*/
+//#define GPIO_MOSI	     0x10000000         /*   SDI: GPIO1[28]   send to 6996*/
+//#define GPIO_MISO_BIT	29
+//#else
+//#define GPIO_EECK	     0x00000100         /*   SCK: GPIO1[08]   */
+//#define GPIO_EECS	     0x08000000			/*   SCS: GPIO1[27]   */
+//#define GPIO_MISO	     0x00000080         /*   SDO: GPIO1[07]   receive from 6996*/
+//#define GPIO_MOSI	     0x00000200         /*   SDI: GPIO1[09]   send to 6996*/
+//#define GPIO_MISO_BIT	7
+//#endif
+#endif
+
+
+enum GPIO_REG
+{
+	GPIO_DATA_OUT   	= 0x00,
+	GPIO_DATA_IN    	= 0x04,
+	GPIO_PIN_DIR    	= 0x08,
+	GPIO_BY_PASS    	= 0x0c,
+	GPIO_DATA_SET   	= 0x10,
+	GPIO_DATA_CLEAR 	= 0x14,
+	GPIO_INT_ENABLE     = 0x20,
+	GPIO_INT_RAWSTATE   = 0x24,
+	GPIO_INT_MASKSTATE  = 0x28,
+	GPIO_INT_MASK       = 0x2C,
+	GPIO_INT_CLEAR      = 0x30,
+	GPIO_INT_TRIGGER    = 0x34,
+	GPIO_INT_BOTH       = 0x38,
+	GPIO_INT_POLARITY   = 0x3C
+};
+
+typedef struct
+{
+	UINT32 src_addr;
+	UINT32 dst_addr;
+	UINT32 llp;
+	UINT32 ctrl_size;
+	UINT32 owner;
+}DMA_LLP_t;
+
+typedef struct
+{
+	UINT32 owner;
+	UINT32 src_addr;
+	UINT32 ctrl_size;
+}IOCTL_LLP_t;
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+/* DMA Registers */
+#define	DMA_INT 		   		0x00000000
+#define	DMA_INT_TC 		   		0x00000004
+#define	DMA_CFG 		   		0x00000024
+#define	DMA_INT_TC_CLR				0x00000008
+#define	DMA_TC						0x00000014
+#define	DMA_CSR						0x00000024
+#define	DMA_SYNC					0x00000028
+
+#define	DMA_CH2_CSR    				0x00000140
+#define	DMA_CH2_CFG    				0x00000144
+#define	DMA_CH2_SRC_ADDR    		0x00000148
+#define	DMA_CH2_DST_ADDR    		0x0000014c
+#define	DMA_CH2_LLP    				0x00000150
+#define	DMA_CH2_SIZE    			0x00000154
+
+#define	DMA_CH3_CSR    				0x00000160
+#define	DMA_CH3_CFG    				0x00000164
+#define	DMA_CH3_SRC_ADDR    		0x00000168
+#define	DMA_CH3_DST_ADDR    		0x0000016c
+#define	DMA_CH3_LLP    				0x00000170
+#define	DMA_CH3_SIZE    			0x00000174
+
+#define    SSP_DEVICE_ID   			0x00
+#define    SSP_CTRL_STATUS 			0x04
+#define	   SSP_FRAME_CTRL           0x08
+#define    SSP_BAUD_RATE            0x0c
+#define    SSP_FRAME_CTRL2          0x10
+#define    SSP_FIFO_CTRL            0x14
+#define    SSP_TX_SLOT_VALID0       0x18
+#define    SSP_TX_SLOT_VALID1       0x1c
+#define    SSP_TX_SLOT_VALID2       0x20
+#define    SSP_TX_SLOT_VALID3       0x24
+#define    SSP_RX_SLOT_VALID0       0x28
+#define    SSP_RX_SLOT_VALID1       0x2c
+#define    SSP_RX_SLOT_VALID2       0x30
+#define    SSP_RX_SLOT_VALID3       0x34
+#define    SSP_SLOT_SIZE0           0x38
+#define    SSP_SLOT_SIZE1           0x3c
+#define    SSP_SLOT_SIZE2           0x40
+#define    SSP_SLOT_SIZE3           0x44
+#define    SSP_READ_PORT            0x48
+#define    SSP_WRITE_PORT           0x4c
+
+
+
+#define SSP_I2S_INIT_BUF			_IO  ('q', 0x00)
+#define SSP_I2S_STOP_DMA			_IO  ('q', 0x01)
+#define SSP_I2S_FILE_LEN			_IOW  ('q', 0x2, int)
+/*
+#define SSP_GET_HOOK_STATUS			_IOR  ('q', 0xC0, int)
+#define SSP_GET_LINEFEED			_IOR  ('q', 0xC1, int)
+#define SSP_SET_LINEFEED			_IOW  ('q', 0xC2, int)
+#define SSP_GET_REG                 _IOWR ('q', 0xC3, struct Ssp_reg *)
+#define SSP_SET_REG                 _IOWR ('q', 0xC4, struct Ssp_reg *)
+#define SSP_GEN_OFFHOOK_TONE		_IO   ('q', 0xC5)
+#define SSP_GEN_BUSY_TONE			_IO   ('q', 0xC6)
+#define SSP_GEN_RINGBACK_TONE		_IO   ('q', 0xC7)
+#define SSP_GEN_CONGESTION_TONE		_IO   ('q', 0xC8)
+#define SSP_DISABLE_DIALTONE		_IO   ('q', 0xC9)
+#define SSP_PHONE_RING_START		_IO   ('q', 0xCA)
+*/
+
+
+#endif //__GEMINI_I2S_H__
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/gemini_ssp.h
@@ -0,0 +1,263 @@
+/******************************************************************************
+ *    gemini_ssp.h
+ *
+ *
+ *****************************************************************************/
+
+#include <linux/types.h>
+#include <asm/arch-sl2312/irqs.h>
+#include <linux/phonedev.h>
+#include <linux/telephony.h>
+//#include "proslic.h"
+
+typedef __u16 UINT16;
+typedef __u32 UINT32;
+typedef __u8 UINT8;
+typedef __u8 BOOL;
+
+#define TRUE 1
+#define FALSE 0
+
+/***************************************/
+/* define GPIO module base address     */
+/***************************************/
+#define DMA_CONTROL_PHY_BASE  (IO_ADDRESS(SL2312_GENERAL_DMA_BASE))
+#define DMA_CONTROL_SSP_BASE  (IO_ADDRESS(SL2312_SSP_CTRL_BASE))
+#define SSP_INT				IRQ_SSP
+#define GPIO_BASE_ADDR      (IO_ADDRESS(SL2312_GPIO_BASE))
+#define GPIO_BASE_ADDR1      (IO_ADDRESS(SL2312_GPIO_BASE1))
+#define GLOBAL_BASE      (IO_ADDRESS(SL2312_GLOBAL_BASE))
+
+/* define read/write register utility */
+#define READ_SSP_REG(offset)			(__raw_readl(offset+DMA_CONTROL_SSP_BASE))
+#define WRITE_SSP_REG(offset,val) 	(__raw_writel(val,offset+DMA_CONTROL_SSP_BASE))
+
+#define READ_GPIO_REG(offset)			(__raw_readl(offset+GPIO_BASE_ADDR))
+#define WRITE_GPIO_REG(offset,val) 	(__raw_writel(val,offset+GPIO_BASE_ADDR))
+
+#define READ_GPIO1_REG(offset)			(__raw_readl(offset+GPIO_BASE_ADDR1))
+#define WRITE_GPIO1_REG(offset,val) 	(__raw_writel(val,offset+GPIO_BASE_ADDR1))
+
+#define READ_DMA_REG(offset)			(__raw_readl(offset+DMA_CONTROL_PHY_BASE))
+#define WRITE_DMA_REG(offset,val) 	(__raw_writel(val,offset+DMA_CONTROL_PHY_BASE))
+
+#define READ_GLOBAL_REG(offset)			(__raw_readl(offset+GLOBAL_BASE))
+#define WRITE_GLOBAL_REG(offset,val) 	(__raw_writel(val,offset+GLOBAL_BASE))
+
+
+#define SSP_GPIO_INT       	IRQ_GPIO
+
+#ifndef CONFIG_SL3516_ASIC
+#define SSP_GPIO_INT_BIT    0x00000400				//GPIO[10] : SLIC interrupt pin
+
+#define GPIO_EECK	     0x00000040         /*   SCK: GPIO[06]   */
+#define GPIO_EECS	     0x00000080			/*   SCS: GPIO[07]   */
+#define GPIO_MISO	     0x00000200         /*   SDO: GPIO[09]   receive from 6996*/
+#define GPIO_MOSI	     0x00000100         /*   SDI: GPIO[08]   send to 6996*/
+#define GPIO_MISO_BIT	 9
+#else
+#define SSP_GPIO_INT_BIT    0x00000001				//GPIO[0] : SLIC interrupt pin
+
+//#if 0
+//#define GPIO_EECK	     0x80000000         /*   SCK: GPIO1[31]   */
+//#define GPIO_EECS	     0x40000000			/*   SCS: GPIO1[30]   */
+//#define GPIO_MISO	     0x20000000         /*   SDO: GPIO1[29]   receive from 6996*/
+//#define GPIO_MOSI	     0x10000000         /*   SDI: GPIO1[28]   send to 6996*/
+//#define GPIO_MISO_BIT	29
+//#else
+//#define GPIO_EECK	     0x00000100         /*   SCK: GPIO1[08]   */
+//#define GPIO_EECS	     0x08000000			/*   SCS: GPIO1[27]   */
+//#define GPIO_MISO	     0x00000080         /*   SDO: GPIO1[07]   receive from 6996*/
+//#define GPIO_MOSI	     0x00000200         /*   SDI: GPIO1[09]   send to 6996*/
+//#define GPIO_MISO_BIT	7
+//#endif
+#endif
+
+
+enum GPIO_REG
+{
+	GPIO_DATA_OUT   	= 0x00,
+	GPIO_DATA_IN    	= 0x04,
+	GPIO_PIN_DIR    	= 0x08,
+	GPIO_BY_PASS    	= 0x0c,
+	GPIO_DATA_SET   	= 0x10,
+	GPIO_DATA_CLEAR 	= 0x14,
+	GPIO_INT_ENABLE     = 0x20,
+	GPIO_INT_RAWSTATE   = 0x24,
+	GPIO_INT_MASKSTATE  = 0x28,
+	GPIO_INT_MASK       = 0x2C,
+	GPIO_INT_CLEAR      = 0x30,
+	GPIO_INT_TRIGGER    = 0x34,
+	GPIO_INT_BOTH       = 0x38,
+	GPIO_INT_POLARITY   = 0x3C
+};
+
+
+#define SPI_ADD_LEN	     7			// bits of Address
+#define SPI_DAT_LEN	     8			// bits of Data
+
+
+
+//#ifdef MIDWAY_DIAG
+#define	DAISY_MODE	1
+#if (DAISY_MODE==1)
+#define NUMBER_OF_CHAN	2
+#else
+#define NUMBER_OF_CHAN	1
+#endif
+#define LLP_SIZE   8
+#define SBUF_SIZE  512 //0xff0 //2560
+#define DBUF_SIZE  SBUF_SIZE*NUMBER_OF_CHAN //0xff0 //2560
+#define TBUF_SIZE  (LLP_SIZE)*DBUF_SIZE
+#define DESC_NUM   1
+#define DTMF_NUM   20
+
+/* define owner bit of SSP */
+//data into SSP and transfer to AP==> SSP_Rx
+//data out of SSP and transfer to SLIC==> SSP_Tx
+#define CPU		0
+#define DMA		1
+
+#define DMA_DEMO   0
+#define DMA_NDEMO  1
+//#define DMA_NONE   2
+
+enum exceptions {
+	PROSLICiNSANE,
+	TIMEoUTpOWERuP,
+	TIMEoUTpOWERdOWN,
+	POWERlEAK,
+	TIPoRrINGgROUNDsHORT,
+	POWERaLARMQ1,
+	POWERaLARMQ2,
+	POWERaLARMQ3,
+	POWERaLARMQ4,
+	POWERaLARMQ5,
+	OWERaLARMQ6,
+	CM_CAL_ERR
+};
+
+typedef struct
+{
+	UINT32 src_addr;
+	UINT32 dst_addr;
+	UINT32 llp;
+	UINT32 ctrl_size;
+}DMA_LLP_t;
+
+typedef struct {
+	unsigned int own ;
+	char  *tbuf;
+	//UINT32 *LinkAddrT;
+	DMA_LLP_t LLPT[LLP_SIZE];
+}DMA_Tx_t;
+
+typedef struct {
+	unsigned int own ;
+	char  *rbuf;
+	//UINT32 *LinkAddrR;
+	DMA_LLP_t LLPR[LLP_SIZE];
+}DMA_Rx_t;
+
+//typedef struct {
+//	//UINT32 init_stat;
+//	struct chipStruct chipData ; /* Represents a proslics state, cached information, and timers */
+//	struct phone_device p;
+//
+//
+//}SSP_SLIC;
+
+
+
+/* DMA Registers */
+#define	DMA_INT 		   		0x00000000
+#define	DMA_INT_TC 		   		0x00000004
+#define	DMA_CFG 		   		0x00000024
+#define	DMA_INT_TC_CLR				0x00000008
+#define	DMA_TC						0x00000014
+#define	DMA_CSR						0x00000024
+#define	DMA_SYNC					0x00000028
+
+#define	DMA_CH2_CSR    				0x00000140
+#define	DMA_CH2_CFG    				0x00000144
+#define	DMA_CH2_SRC_ADDR    		0x00000148
+#define	DMA_CH2_DST_ADDR    		0x0000014c
+#define	DMA_CH2_LLP    				0x00000150
+#define	DMA_CH2_SIZE    			0x00000154
+
+#define	DMA_CH3_CSR    				0x00000160
+#define	DMA_CH3_CFG    				0x00000164
+#define	DMA_CH3_SRC_ADDR    		0x00000168
+#define	DMA_CH3_DST_ADDR    		0x0000016c
+#define	DMA_CH3_LLP    				0x00000170
+#define	DMA_CH3_SIZE    			0x00000174
+
+#define    SSP_DEVICE_ID   			0x00
+#define    SSP_CTRL_STATUS 			0x04
+#define	   SSP_FRAME_CTRL           0x08
+#define    SSP_BAUD_RATE            0x0c
+#define    SSP_FRAME_CTRL2          0x10
+#define    SSP_FIFO_CTRL            0x14
+#define    SSP_TX_SLOT_VALID0       0x18
+#define    SSP_TX_SLOT_VALID1       0x1c
+#define    SSP_TX_SLOT_VALID2       0x20
+#define    SSP_TX_SLOT_VALID3       0x24
+#define    SSP_RX_SLOT_VALID0       0x28
+#define    SSP_RX_SLOT_VALID1       0x2c
+#define    SSP_RX_SLOT_VALID2       0x30
+#define    SSP_RX_SLOT_VALID3       0x34
+#define    SSP_SLOT_SIZE0           0x38
+#define    SSP_SLOT_SIZE1           0x3c
+#define    SSP_SLOT_SIZE2           0x40
+#define    SSP_SLOT_SIZE3           0x44
+#define    SSP_READ_PORT            0x48
+#define    SSP_WRITE_PORT           0x4c
+
+
+void printFreq_Revision(int num);
+void SLIC_SPI_write(int num, UINT8 ,UINT8);
+UINT8 SLIC_SPI_read(int num, UINT8);
+void SLIC_SPI_write_bit(char);
+void SLIC_SPI_ind_write(int num, UINT8, UINT16);
+UINT16 SLIC_SPI_ind_read(int num, UINT8);
+void SLIC_SPI_CS_enable(UINT8);
+unsigned int SLIC_SPI_read_bit(void);
+void SLIC_SPI_pre_st(void);
+UINT32 ssp_init(void);
+UINT16 SLIC_SPI_get_identifier(int num);
+int selfTest(int num);
+void exception (int num, enum exceptions e);
+int SLIC_init(int num);
+UINT8 version(int num);
+UINT8 chipType (int num);
+void SLIC_init_ind_reg_set(int num);
+UINT8 powerUp(int num);
+UINT8 powerLeakTest(int num);
+void SLIC_init_reg_set(int num);
+int calibrate(int num);
+void goActive(int num);
+void clearInterrupts(int num);
+void setState(int num, int);
+UINT8 loopStatus(int num);
+int verifyIndirectRegisters(int num);
+int verifyIndirectReg(int num, UINT8 , UINT16);
+void sendProSLICID(int num);
+void disableOscillators(int num);
+UINT8 checkSum(int num, char * string );
+void fskInitialization (int num);
+void fskByte(int num, UINT8 c);
+void waitForInterrupt (int num);
+//void findNumber(void);
+UINT8 dtmfAction(int num);
+UINT8 digit(int num);
+void interrupt_init(void);
+//void gemini_slic_isr (int );
+int groundShort(int num);
+void clearAlarmBits(int num);
+void stopRinging(int num);
+void activateRinging(int num);
+void initializeLoopDebounceReg(int num);
+void busyJapan(int num) ;
+void ringBackJapan(int num) ;
+void stateMachine(int num);
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/hardware.h
@@ -0,0 +1,47 @@
+/*
+ *  linux/include/asm-arm/arch-epxa10/hardware.h
+ *
+ *  This file contains the hardware definitions of the Integrator.
+ *
+ *  Copyright (C) 1999 ARM Limited.
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/arch/platform.h>
+
+#define pcibios_assign_all_busses()	1
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ *
+ * macro to get at IO space when running virtually
+*/
+
+#define IO_ADDRESS(x)      (((x&0xfff00000)>>4)|(x & 0x000fffff)|0xF0000000)
+#define FLASH_VBASE         0xFE000000
+#define FLASH_SIZE 0x1000000// 8M
+#define FLASH_START         SL2312_FLASH_BASE
+#define FLASH_VADDR(x)      ((x & 0x00ffffff)|0xFE000000)       // flash virtual address
+
+#define PCIBIOS_MIN_IO					0x100		// 0x000-0x100 AHB reg and PCI config, data
+#define PCIBIOS_MIN_MEM					0
+
+#endif
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/int_ctrl.h
@@ -0,0 +1,171 @@
+/*
+ *
+ *  This file contains the register definitions for the Excalibur
+ *  Timer TIMER00.
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+
+#ifndef __INT_CTRL_H
+#define __INT_CTRL_H
+
+#define PCI_IRQ_OFFSET			  64    /* PCI start IRQ number */
+#define FIQ_OFFSET                32
+
+#define IRQ_SOURCE(base_addr)   (INT_CTRL_TYPE(base_addr  + 0x00))
+#define IRQ_MASK(base_addr)     (INT_CTRL_TYPE (base_addr  + 0x04 ))
+#define IRQ_CLEAR(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x08 ))
+#define IRQ_TMODE(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x0C ))
+#define IRQ_TLEVEL(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x10 ))
+#define IRQ_STATUS(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x14 ))
+#define FIQ_SOURCE(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x20 ))
+#define FIQ_MASK(base_addr)     (INT_CTRL_TYPE (base_addr  + 0x24 ))
+#define FIQ_CLEAR(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x28 ))
+#define FIQ_TMODE(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x2C ))
+#define FIQ_LEVEL(base_addr)    (INT_CTRL_TYPE (base_addr  + 0x30 ))
+#define FIQ_STATUS(base_addr)   (INT_CTRL_TYPE (base_addr  + 0x34 ))
+
+#ifdef CONFIG_SL3516_ASIC
+#define	IRQ_SERIRQ0_OFFSET                 	30
+#define	IRQ_PCID_OFFSET	                 	29
+#define	IRQ_PCIC_OFFSET	                 	28
+#define	IRQ_PCIB_OFFSET	                 	27
+#define IRQ_PWR_OFFSET				    	26
+#define IRQ_CIR_OFFSET						25
+#define	IRQ_GPIO2_OFFSET                   	24
+#define	IRQ_GPIO1_OFFSET                   	23
+#define	IRQ_GPIO_OFFSET	                	22
+#define	IRQ_SSP_OFFSET                     	21
+#define IRQ_LPC_OFFSET                      20
+#define IRQ_LCD_OFFSET                      19
+#define	IRQ_UART_OFFSET                		18
+#define	IRQ_RTC_OFFSET             			17
+#define	IRQ_TIMER3_OFFSET                  	16
+#define	IRQ_TIMER2_OFFSET                  	15
+#define	IRQ_TIMER1_OFFSET                  	14
+#define IRQ_FLASH_OFFSET					12
+#define	IRQ_USB1_OFFSET                    	11
+#define IRQ_USB0_OFFSET						10
+#define	IRQ_DMA_OFFSET                     	9
+#define	IRQ_PCI_OFFSET                 		8
+#define	IRQ_IPSEC_OFFSET            		7
+#define	IRQ_RAID_OFFSET                     6
+#define	IRQ_IDE1_OFFSET                    	5
+#define	IRQ_IDE0_OFFSET                		4
+#define	IRQ_WATCHDOG_OFFSET                 3
+#define	IRQ_GMAC1_OFFSET                    2
+#define IRQ_GMAC0_OFFSET					1
+#define	IRQ_CPU0_IP_IRQ_OFFSET              0
+
+#define	IRQ_SERIRQ0_MASK                 	(1<<30)
+#define IRQ_PCID_MASK				    	(1<<29)
+#define IRQ_PCIC_MASK				    	(1<<28)
+#define IRQ_PCIB_MASK				    	(1<<27)
+#define IRQ_PWR_MASK				    	(1<<26)
+#define IRQ_CIR_MASK						(1<<25)
+#define	IRQ_GPIO2_MASK                   	(1<<24)
+#define	IRQ_GPIO1_MASK                    	(1<<23)
+#define	IRQ_GPIO_MASK	                    (1<<22)
+#define	IRQ_SSP_MASK                        (1<<21)
+#define IRQ_LPC_MASK                        (1<<20)
+#define IRQ_LCD_MASK                        (1<<19)
+#define	IRQ_UART_MASK                	    (1<<18)
+#define	IRQ_RTC_MASK             		    (1<<17)
+#define	IRQ_TIMER3_MASK                     (1<<16)
+#define	IRQ_TIMER2_MASK                     (1<<15)
+#define	IRQ_TIMER1_MASK                     (1<<14)
+#define IRQ_FLASH_MASK					    (1<<12)
+#define	IRQ_USB1_MASK                       (1<<11)
+#define IRQ_USB0_MASK					    (1<<10)
+#define	IRQ_DMA_MASK                        (1<< 9)
+#define	IRQ_PCI_MASK                 	    (1<< 8)
+#define	IRQ_IPSEC_MASK            		    (1<< 7)
+#define	IRQ_RAID_MASK                       (1<< 6)
+#define	IRQ_IDE1_MASK                       (1<< 5)
+#define	IRQ_IDE0_MASK                 	    (1<< 4)
+#define	IRQ_WATCHDOG_MASK                   (1<< 3)
+#define	IRQ_GMAC1_MASK                      (1<< 2)
+#define IRQ_GMAC0_MASK					    (1<< 1)
+#define	IRQ_CPU0_IP_IRQ_MASK                (1<< 0)
+#else
+#define	IRQ_SERIRQ0_OFFSET                 	30
+#define	IRQ_PCID_OFFSET	                 	29
+#define	IRQ_PCIC_OFFSET	                 	28
+#define	IRQ_PCIB_OFFSET	                 	27
+#define IRQ_PWR_OFFSET				    	26
+#define IRQ_CIR_OFFSET						25
+#define	IRQ_GPIO2_OFFSET                   	24
+#define	IRQ_GPIO1_OFFSET                   	23
+#define	IRQ_GPIO_OFFSET	                	22
+#define	IRQ_SSP_OFFSET                     	21
+#define IRQ_LPC_OFFSET                      20
+#define IRQ_LCD_OFFSET                      19
+#define	IRQ_UART_OFFSET                		18
+#define	IRQ_RTC_OFFSET             			17
+#define	IRQ_TIMER3_OFFSET                  	16
+#define	IRQ_TIMER2_OFFSET                  	15
+#define	IRQ_TIMER1_OFFSET                  	14
+#define IRQ_FLASH_OFFSET					12
+#define	IRQ_USB1_OFFSET                    	11
+#define IRQ_USB0_OFFSET						10
+#define	IRQ_DMA_OFFSET                     	9
+#define	IRQ_PCI_OFFSET                 		8
+#define	IRQ_IPSEC_OFFSET            		7
+#define	IRQ_RAID_OFFSET                     6
+#define	IRQ_IDE1_OFFSET                    	5
+#define	IRQ_IDE0_OFFSET                		4
+#define	IRQ_WATCHDOG_OFFSET                 3
+#define	IRQ_GMAC1_OFFSET                    2
+#define IRQ_GMAC0_OFFSET					1
+#define	IRQ_CPU0_IP_IRQ_OFFSET              0
+
+#define	IRQ_SERIRQ0_MASK                 	(1<<30)
+#define IRQ_PCID_MASK				    	(1<<29)
+#define IRQ_PCIC_MASK				    	(1<<28)
+#define IRQ_PCIB_MASK				    	(1<<27)
+#define IRQ_PWR_MASK				    	(1<<26)
+#define IRQ_CIR_MASK						(1<<25)
+#define	IRQ_GPIO2_MASK                   	(1<<24)
+#define	IRQ_GPIO1_MASK                    	(1<<23)
+#define	IRQ_GPIO_MASK	                    (1<<22)
+#define	IRQ_SSP_MASK                        (1<<21)
+#define IRQ_LPC_MASK                        (1<<20)
+#define IRQ_LCD_MASK                        (1<<19)
+#define	IRQ_UART_MASK                	    (1<<18)
+#define	IRQ_RTC_MASK             		    (1<<17)
+#define	IRQ_TIMER3_MASK                     (1<<16)
+#define	IRQ_TIMER2_MASK                     (1<<15)
+#define	IRQ_TIMER1_MASK                     (1<<14)
+#define IRQ_FLASH_MASK					    (1<<12)
+#define	IRQ_USB1_MASK                       (1<<11)
+#define IRQ_USB0_MASK					    (1<<10)
+#define	IRQ_DMA_MASK                        (1<< 9)
+#define	IRQ_PCI_MASK                 	    (1<< 8)
+#define	IRQ_IPSEC_MASK            		    (1<< 7)
+#define	IRQ_RAID_MASK                       (1<< 6)
+#define	IRQ_IDE1_MASK                       (1<< 5)
+#define	IRQ_IDE0_MASK                 	    (1<< 4)
+#define	IRQ_WATCHDOG_MASK                   (1<< 3)
+#define	IRQ_GMAC1_MASK                      (1<< 2)
+#define IRQ_GMAC0_MASK					    (1<< 1)
+#define	IRQ_CPU0_IP_IRQ_MASK                (1<< 0)
+#endif
+
+
+#endif /* __INT_CTRL_H */
+
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/io.h
@@ -0,0 +1,50 @@
+/*
+ *  linux/include/asm-arm/arch-epxa10db/io.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+
+/*
+ * Generic virtual read/write
+ */
+/*
+#define __arch_getw(a)		(*(volatile unsigned short *)(a))
+#define __arch_putw(v,a)	(*(volatile unsigned short *)(a) = (v))
+*/
+/*#define outsw   __arch_writesw
+#define outsl   __arch_writesl
+#define outsb   __arch_writesb
+#define insb    __arch_readsb
+#define insw    __arch_readsw
+#define insl    __arch_readsl*/
+
+#define __io(a)			(a)
+#define __mem_pci(a)            (a)
+/*
+#define __arch_getw(a)			(*(volatile unsigned short  *)(a))
+#define __arch_putw(v,a)		(*(volatile unsigned short *)(a) = (v))
+*/
+#define iomem_valid_addr(off,size) (1)
+#define iomem_to_phys(off) (off)
+
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/ipi.h
@@ -0,0 +1,189 @@
+/*
+ *  linux/include/asm-arm/arch-sl2312/system.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_IPI_H
+#define __ASM_ARCH_IPI_H
+#include <asm/io.h>
+
+//#define spin_lock(x)	spin_lock_dt(x)
+//#define spin_unlock(x)	spin_unlock_dt(x)
+
+#define SWAP_OFFSET							0x400000
+#define SWAP_SIZE							0x400000
+
+#define SHARE_MEM_ADDR						0x2000000
+#define SHARE_MEM_SIZE						1024*1024
+
+
+//--> Add by jason for IPI testing
+// memory layout for maste & slave bin
+#define MASTERTEXT      0x8000
+#define SLAVETEXT		0x108000
+#define SHARESIZE		0x4000
+#define SHAREADDR		SHARE_MEM_ADDR // starting 8M
+
+// CPU1 reset release
+#define GLOBAL_BASE		IO_ADDRESS(0x40000000)
+#define GLOBAL_SOFTRESET	(GLOBAL_BASE + 0x0C)
+#define CPU1_RESET_BIT_MASK     0x40000000
+
+// IPI , need to redefine the folliwing,  bug
+#define CPU0_STATUS			(GLOBAL_BASE + 0x0038)
+#define CPU1_STATUS			(GLOBAL_BASE + 0x003C)
+#define CPU_IPI_BIT_MASK    0x80000000
+
+/* Your basic SMP spinlocks, allowing only a single CPU anywhere
+*/
+typedef struct {
+       volatile unsigned int lock;
+} spinlock_dt;
+
+
+#define         MASTER_BIT      0x01
+#define         SLAVE_BIT       0x02
+#define         HEART_BIT       0x04
+#define         IPI0_IRQ_BIT    0x08
+#define         IPI0_FIQ_BIT    0x10
+#define         IPI1_IRQ_BIT    0x20
+#define         IPI1_FIQ_BIT    0x40
+
+#define IRQ     0
+#define FIQ     1
+#define DONE    0xff
+
+#define         CPU0            0x0
+#define         CPU1            0x1
+
+#define         MAXCHAR         128*1024
+typedef struct  {
+       int flag;
+       int uart_flag;
+       int cnt;
+       spinlock_dt lk;
+       char message[MAXCHAR];
+}s_mailbox;
+
+// JScale proj definition
+typedef struct {
+	u16		type;				// message Type
+	u16		length;				// message length, including message header
+} IPC_MSG_HDR_T;
+
+typedef struct{
+	IPC_MSG_HDR_T	hdr;
+	u32				input_location;
+	u32				input_size;
+	u32				output_location;
+	u16  			ScaledImageWidth;
+	u16  			ScaledImageHeight;
+	u8  			ScaledImageQuality;
+	u8  			MaintainResultionRatio;
+	u8  			TwoStepScaling;
+	u8  			InputFormat;
+	u8				verbose;
+	u8				reserved[3];
+} JSCALE_REQ_T;
+
+typedef struct{
+	IPC_MSG_HDR_T	hdr;
+	u32				status;
+	u32				code;
+	u32				output_size;
+} JSCALE_RSP_T;
+
+#define IPC_JSCALE_REQ_MSG			0	// JScale request from CPU-0 to CPU-1
+#define IPC_JSCALE_RSP_MSG			1	// JScale response from CPU-1 to CPU-0
+
+enum {
+	JSCALE_STATUS_OK = 0,
+	JSCALE_UNKNOWN_MSG_TYPE,
+	JSCALE_FAILED_FILE_SIZE,
+	JSCALE_FAILED_MALLOC,
+	JSCALE_FAILED_FORMAT,
+	JSCALE_DECODE_ERROR,
+	JSCALE_BUSY,
+};
+// <-- JScale
+
+#define GEMINI_IPI_IOCTL_BASE	'Z'
+#define GEMINI_IPI_JSCALE_REQ		_IOW (GEMINI_IPI_IOCTL_BASE,0,JSCALE_REQ_T)
+#define GEMINI_IPI_JSCALE_STAT		_IOR (GEMINI_IPI_IOCTL_BASE,1,JSCALE_RSP_T)
+
+
+/*
+* Simple spin lock operations.
+*
+*/
+
+#define spin_is_locked_dt(x)((x)->lock != 0)
+
+static inline int test_and_set_dt(spinlock_dt *lock)
+{
+unsigned long tmp;
+__asm__ __volatile__(
+"swp     %0, %2, [%1]\n"
+: "=&r" (tmp)
+: "r" (&lock->lock), "r" (1)
+: "cc", "memory");
+
+return tmp;
+}
+
+static inline void spin_lock_dt(spinlock_dt *lock)
+{
+
+unsigned long tmp;
+__asm__ __volatile__(
+"1:     ldr   %0, [%1]\n"
+"teq     %0, #0\n"
+"swpeq   %0, %2, [%1]\n"
+"       teqeq   %0, #0\n"
+"       bne     1b"
+       : "=&r" (tmp)
+       : "r" (&lock->lock), "r" (1)
+       : "cc", "memory");
+}
+
+static inline void spin_unlock_dt(spinlock_dt *lock)
+{
+       __asm__ __volatile__(
+"       str     %1, [%0]"
+       :
+       : "r" (&lock->lock), "r" (0)
+       : "cc", "memory");
+}
+
+static inline int getcpuid(void)
+{
+       int cpuid;
+
+      __asm__(
+"mrc p8, 0, r0, c0, c0, 0\n"
+"mov %0, r0"
+       :"=r"(cpuid)
+       :
+       :"r0");
+       return (cpuid & 0x07);
+}
+
+
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/irq.h
@@ -0,0 +1,23 @@
+/*
+ *  linux/include/asm-arm/arch-sl2312/irq.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+
+ // Since we have PCI interrupt which the interrupt line is pseudo
+ // we need do some fixup
+int fixup_irq(int irq);
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/irqs.h
@@ -0,0 +1,102 @@
+/*
+ *  linux/include/asm-arm/arch-camelot/irqs.h
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+
+/* Use the Excalibur chip definitions */
+#define INT_CTRL_TYPE
+#include "asm/arch/int_ctrl.h"
+
+#ifdef CONFIG_SL3516_ASIC
+#define	IRQ_SERIRQ_MAX					31
+#define	IRQ_SERIRQ1						31
+#define	IRQ_SERIRQ0                  	30
+#define	IRQ_PCID 	                  	29
+#define	IRQ_PCIC    	             	28
+#define	IRQ_PCIB        	         	27
+#define IRQ_PWR							26
+#define IRQ_CIR							25
+#define	IRQ_GPIO2                   	24
+#define	IRQ_GPIO1                   	23
+#define	IRQ_GPIO	                	22
+#define	IRQ_SSP                     	21
+#define IRQ_LPC                         20
+#define IRQ_LCD                         19
+#define	IRQ_UART                  		18
+#define	IRQ_RTC                			17
+#define	IRQ_TIMER3                  	16
+#define	IRQ_TIMER2                    	15
+#define	IRQ_TIMER1                    	14
+#define IRQ_FLASH						12
+#define	IRQ_USB1                    	11
+#define IRQ_USB0						10
+#define	IRQ_DMA                     	9
+#define	IRQ_PCI                    		8
+#define	IRQ_IPSEC              			7
+#define	IRQ_RAID                        6
+#define	IRQ_IDE1                    	5
+#define	IRQ_IDE0                   		4
+#define	IRQ_WATCHDOG                    3
+#define	IRQ_GMAC1                       2
+#define IRQ_GMAC0						1
+#define	IRQ_CPU0_IP_IRQ                 0
+#else
+#define	IRQ_SERIRQ_MAX					31
+#define	IRQ_SERIRQ1						31
+#define	IRQ_SERIRQ0                  	30
+#define	IRQ_PCID 	                  	29
+#define	IRQ_PCIC    	             	28
+#define	IRQ_PCIB        	         	27
+#define IRQ_PWR							26
+#define IRQ_CIR							25
+#define	IRQ_GPIO2                   	24
+#define	IRQ_GPIO1                   	23
+#define	IRQ_GPIO	                	22
+#define	IRQ_SSP                     	21
+#define IRQ_LPC                         20
+#define IRQ_LCD                         19
+#define	IRQ_UART                  		18
+#define	IRQ_RTC                			17
+#define	IRQ_TIMER3                  	16
+#define	IRQ_TIMER2                    	15
+#define	IRQ_TIMER1                    	14
+#define IRQ_FLASH						12
+#define	IRQ_USB1                    	11
+#define IRQ_USB0						10
+#define	IRQ_DMA                     	9
+#define	IRQ_PCI                    		8
+#define	IRQ_IPSEC              			7
+#define	IRQ_RAID                        6
+#define	IRQ_IDE1                    	5
+#define	IRQ_IDE0                   		4
+#define	IRQ_WATCHDOG                    3
+#define	IRQ_GMAC1                       2
+#define IRQ_GMAC0						1
+#endif
+
+#define ARCH_TIMER_IRQ		               IRQ_TIMER2   /* for MV 4.0 */
+
+#define IRQ_PCI_INTA				       PCI_IRQ_OFFSET + 0
+#define IRQ_PCI_INTB				       PCI_IRQ_OFFSET + 1
+#define IRQ_PCI_INTC				       PCI_IRQ_OFFSET + 2
+#define IRQ_PCI_INTD				       PCI_IRQ_OFFSET + 3
+
+#define NR_IRQS                           (IRQ_PCI_INTD + 4)
+
+
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/it8712.h
@@ -0,0 +1,24 @@
+
+#ifndef __IT8712_H__
+#define __IT8712_H__
+
+#include "asm/arch/sl2312.h"
+
+#define IT8712_IO_BASE			SL2312_LPC_IO_BASE
+// Device LDN
+#define LDN_SERIAL1				0x01
+#define LDN_SERIAL2				0x02
+#define LDN_PARALLEL			0x03
+#define LDN_KEYBOARD			0x05
+#define LDN_MOUSE				0x06
+#define LDN_GPIO				0x07
+
+#define IT8712_UART1_PORT      	0x3F8
+#define IT8712_UART2_PORT      	0x2F8
+
+#define IT8712_GPIO_BASE		0x800	// 0x800-0x804 for GPIO set1-set5
+
+void LPCSetConfig(char LdnNumber, char Index, char data);
+char LPCGetConfig(char LdnNumber, char Index);
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/memory.h
@@ -0,0 +1,38 @@
+/*
+ *  linux/include/asm-arm/arch-sl2312/memory.h
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	UL(0x00000000)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ */
+#define __virt_to_bus(x)	(x - PAGE_OFFSET + /*SDRAM_BASE*/0)
+#define __bus_to_virt(x)	(x - /*SDRAM_BASE*/0 + PAGE_OFFSET)
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/param.h
@@ -0,0 +1,20 @@
+/*
+ *  linux/include/asm-arm/arch-epxa10db/param.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * 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
+ */
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/pci.h
@@ -0,0 +1,18 @@
+
+#ifndef __SL2312_PCI_H__
+#define __SL2312_PCI_H__
+
+#define SL2312_PCI_PMC				0x40
+#define SL2312_PCI_PMCSR			0x44
+#define SL2312_PCI_CTRL1			0x48
+#define SL2312_PCI_CTRL2			0x4c
+#define SL2312_PCI_MEM1_BASE_SIZE	0x50
+#define SL2312_PCI_MEM2_BASE_SIZE	0x54
+#define SL2312_PCI_MEM3_BASE_SIZE	0x58
+
+
+void sl2312_pci_mask_irq(unsigned int irq);
+void sl2312_pci_unmask_irq(unsigned int irq);
+int sl2312_pci_get_int_src(void);
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/platform.h
@@ -0,0 +1,7 @@
+#ifndef PLATFORM_H
+#define PLATFORM_H
+#include "sl2312.h"
+
+#define MAXIRQNUM 68
+#endif
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/preempt.h
@@ -0,0 +1,63 @@
+/*
+ * include/asm-arm/arch-sl2312/preempt.h
+ *
+ * Timing support for preempt-stats, kfi, ilatency patches
+ *
+ * Author: dsingleton <dsingleton@mvista.com>
+ *
+ * 2001-2004 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _ASM_ARCH_PREEMT_H
+#define _ASM_ARCH_PREEMT_H
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/sl2312.h>
+
+static inline unsigned long clock_diff(unsigned long start, unsigned long stop)
+{
+        return (start - stop);
+}
+
+static inline unsigned int readclock(void)
+{
+	unsigned int	x;
+
+	x = readl(IO_ADDRESS(SL2312_TIMER2_BASE));
+	return x;
+}
+
+static inline unsigned __ticks_per_usec(void)
+{
+#ifdef CONFIG_SL3516_ASIC
+	unsigned int ahb_clock_rate_base=130;  /* unit = MHz*/
+	unsigned int reg_v=0;
+	unsigned int ticks_usec;
+
+	reg_v = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+4)));
+	reg_v >>=15;
+	ticks_usec = (ahb_clock_rate_base + (reg_v & 0x07)*10)>>2;
+
+#else
+	unsigned int ticks_usec=20;
+#endif
+
+    return ticks_usec;
+}
+
+/*
+ * timer 1 runs @ 6Mhz  6 ticks = 1 microsecond
+ * and is configed as a count down timer.
+ */
+#define TICKS_PER_USEC		    __ticks_per_usec()
+#define ARCH_PREDEFINES_TICKS_PER_USEC
+
+#define clock_to_usecs(x)	    ((x) / TICKS_PER_USEC)
+
+#define INTERRUPTS_ENABLED(x)   (!(x & PSR_I_BIT))
+
+#endif
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/sl2312.h
@@ -0,0 +1,254 @@
+#ifndef __sl2312_h
+#define __sl2312_h
+
+/****************************************************************************
+ * Copyright  Storlink Corp 2002-2003.  All rights reserved.                *
+ *--------------------------------------------------------------------------*
+ * Name:board.s                                                             *
+ * Description:  SL231x specfic define                                      *
+ * Author: Plus Chen                                                        *
+ * Version: 0.9 Create
+ ****************************************************************************/
+
+/*
+  CPE address map;
+
+               +====================================================
+    0x00000000 | FLASH
+    0x0FFFFFFF |
+               |====================================================
+    0x10000000 | SDRAM
+    0x1FFFFFFF |
+               |====================================================
+    0x20000000 | Global Registers        0x20000000-0x20FFFFFF
+               | EMAC and DMA            0x21000000-0x21FFFFFF
+               | UART Module             0x22000000-0x22FFFFFF
+               | Timer Module            0x23000000-0x23FFFFFF
+               | Interrupt Module        0x24000000-0x24FFFFFF
+               | RTC Module              0x25000000-0x25FFFFFF
+               | LPC Host Controller     0x26000000-0x26FFFFFF
+               | LPC Peripherial IO      0x27000000-0x27FFFFFF
+               | WatchDog Timer          0x28000000-0x28FFFFFF
+    0x2FFFFFFF | Reserved                0x29000000-0x29FFFFFF
+               |=====================================================
+    0x30000000 | PCI IO, Configuration Registers
+    0x3FFFFFFF |
+               |=====================================================
+    0x40000000 | PCI Memory
+    0x4FFFFFFF |
+               |=====================================================
+    0x50000000 | Ethernet MAC and DMA    0x50000000-0x50FFFFFF
+               | Security and DMA        0x51000000-0x51FFFFFF
+               | IDE Channel 0 Register  0x52000000-0x527FFFFF
+               | IDE Channel 1 Register  0x52800000-0x52FFFFFF
+               | USB Register            0x53000000-0x53FFFFFF
+               | Flash Controller        0x54000000-0x54FFFFFF
+               | DRAM Controller         0x55000000-0x55FFFFFF
+    0x5FFFFFFF | Reserved                0x56000000-0x5FFFFFFF
+               |=====================================================
+    0x60000000 | Reserved
+    0x6FFFFFFF |
+               |=====================================================
+    0x70000000 | FLASH shadow Memory
+    0x7FFFFFFF |
+               |=====================================================
+    0x80000000 | Big Endian of memory    0x00000000-0x7FFFFFFF
+    0xFFFFFFFF |
+               +=====================================================
+*/
+
+
+
+/*-------------------------------------------------------------------------------
+ Memory Map definitions
+-------------------------------------------------------------------------------- */
+#define TEST		1
+#if 0
+
+static inline int GETCPUID()
+{
+       int cpuid;
+      __asm__(
+"mrc p8, 0, r0, c0, c0, 0\n"
+"mov %0, r0"
+       :"=r"(cpuid)
+       :
+       :"r0");
+       return (cpuid & 0x07);
+}
+#endif
+#define SL2312_SRAM_BASE                0x70000000       //  SRAM base after remap
+#define SL2312_DRAM_BASE                0x00000000       //  DRAM base after remap
+#define SL2312_RAM_BASE                 0x10000000       //  RAM code base before remap
+#define SL2312_FLASH_BASE         	    0x30000000
+#define SL2312_ROM_BASE                 0x30000000
+#define SL2312_GLOBAL_BASE              0x40000000
+#define SL2312_WAQTCHDOG_BASE           0x41000000
+#define SL2312_UART_BASE                0x42000000
+#define SL2312_TIMER_BASE               0x43000000
+#define SL2312_LCD_BASE                 0x44000000
+#define SL2312_RTC_BASE                 0x45000000
+#define SL2312_SATA_BASE                0x46000000
+#define SL2312_LPC_HOST_BASE            0x47000000
+#define SL2312_LPC_IO_BASE              0x47800000
+// #define SL2312_INTERRUPT_BASE           0x48000000
+#define SL2312_INTERRUPT0_BASE          0x48000000
+#define SL2312_INTERRUPT1_BASE          0x49000000
+//#define SL2312_INTERRUPT_BASE		((getcpuid()==0)?SL2312_INTERRUPT0_BASE:SL2312_INTERRUPT1_BASE)
+#define SL2312_INTERRUPT_BASE		    0x48000000
+#define SL2312_SSP_CTRL_BASE            0x4A000000
+#define SL2312_POWER_CTRL_BASE          0x4B000000
+#define SL2312_CIR_BASE                 0x4C000000
+#define SL2312_GPIO_BASE                0x4D000000
+#define SL2312_GPIO_BASE1               0x4E000000
+#define SL2312_GPIO_BASE2               0x4F000000
+#define SL2312_PCI_IO_BASE              0x50000000
+#define SL2312_PCI_MEM_BASE             0x58000000
+#ifdef  CONFIG_NET_SL351X
+#define SL2312_TOE_BASE                 0x60000000
+#define SL2312_GMAC0_BASE               0x6000A000
+#define SL2312_GMAC1_BASE               0x6000E000
+#else
+#define SL2312_GMAC0_BASE               0x60000000
+#define SL2312_GMAC1_BASE               0x61000000
+#endif
+#define SL2312_SECURITY_BASE            0x62000000
+#define SL2312_IDE0_BASE                0x63000000
+#define SL2312_IDE1_BASE		        0x63400000
+#define SL2312_RAID_BASE                0x64000000
+#define SL2312_FLASH_CTRL_BASE          0x65000000
+#define SL2312_DRAM_CTRL_BASE           0x66000000
+#define SL2312_GENERAL_DMA_BASE         0x67000000
+#define SL2312_USB_BASE                 0x68000000
+#define SL2312_USB0_BASE                0x68000000
+#define SL2312_USB1_BASE                0x69000000
+#define SL2312_FLASH_SHADOW             0x30000000
+#define SL2312_BIG_ENDIAN_BASE			0x80000000
+
+#ifdef CONFIG_GEMINI_IPI
+#define CPU_1_MEM_BASE			0x4000000				// 64 MB
+#define CPU_1_DATA_OFFSET		0x4000000-0x300000		// Offset 61 MB
+#endif
+
+#define SL2312_TIMER1_BASE              SL2312_TIMER_BASE
+#define SL2312_TIMER2_BASE              (SL2312_TIMER_BASE + 0x10)
+#define SL2312_TIMER3_BASE              (SL2312_TIMER_BASE + 0x20)
+
+#define SL2312_PCI_DMA_MEM1_BASE		0x00000000
+#define SL2312_PCI_DMA_MEM2_BASE		0x00000000
+#define SL2312_PCI_DMA_MEM3_BASE		0x00000000
+#define SL2312_PCI_DMA_MEM1_SIZE		7
+#define SL2312_PCI_DMA_MEM2_SIZE		6
+#define SL2312_PCI_DMA_MEM3_SIZE		6
+
+/*-------------------------------------------------------------------------------
+ Global Module
+---------------------------------------------------------------------------------*/
+#define GLOBAL_ID                       0x00
+#define GLOBAL_CHIP_ID                  0x002311
+#define GLOBAL_CHIP_REV                 0xA0
+#define GLOBAL_STATUS                   0x04
+#define GLOBAL_CONTROL                  0x1C
+#define GLOBAL_REMAP_BIT                0x01
+#define GLOBAL_RESET_REG		0x0C
+#define GLOBAL_MISC_REG					0x30
+#define PFLASH_SHARE_BIT				0x02
+
+#define GLOBAL_RESET		(1<<31)
+#define RESET_CPU1			(1<<30)
+#define RESET_SATA1			(1<<27)
+#define RESET_SATA0			(1<<26)
+#define RESET_CIR			(1<<25)
+#define RESET_EXT_DEV		(1<<24)
+#define RESET_WD			(1<<23)
+#define RESET_GPIO2			(1<<22)
+#define RESET_GPIO1			(1<<21)
+#define RESET_GPIO0			(1<<20)
+#define RESET_SSP			(1<<19)
+#define RESET_UART			(1<<18)
+#define RESET_TIMER			(1<<17)
+#define RESET_RTC			(1<<16)
+#define RESET_INT0			(1<<15)
+#define RESET_INT1			(1<<14)
+#define RESET_LCD			(1<<13)
+#define RESET_LPC			(1<<12)
+#define RESET_APB			(1<<11)
+#define RESET_DMA			(1<<10)
+#define RESET_USB1			(1<<9 )
+#define RESET_USB0			(1<<8 )
+#define RESET_PCI			(1<<7 )
+#define RESET_GMAC1			(1<<6 )
+#define RESET_GMAC0			(1<<5 )
+#define RESET_IPSEC			(1<<4 )
+#define RESET_RAID			(1<<3 )
+#define RESET_IDE			(1<<2 )
+#define RESET_FLASH			(1<<1 )
+#define RESET_DRAM			(1<<0 )
+
+
+
+
+
+
+
+
+/*-------------------------------------------------------------------------------
+ DRAM Module
+---------------------------------------------------------------------------------*/
+#define DRAM_SIZE_32M                   0x2000000
+#define DRAM_SIZE_64M                   0x4000000
+#define DRAM_SIZE_128M                  0x8000000
+
+#define DRAM_SIZE                       DRAM_SIZE_128M
+
+#define DRAM_SDRMR                      0x00
+#define SDRMR_DISABLE_DLL               0x80010000
+
+/*------------------------------------------------------------------------------
+ Share Pin Flag
+--------------------------------------------------------------------------------*/
+#ifdef CONFIG_SL2312_SHARE_PIN
+#define FLASH_SHARE_BIT                    0
+#define UART_SHARE_BIT                     1
+#define EMAC_SHARE_BIT                     2
+#define IDE_RW_SHARE_BIT                   3
+#define IDE_CMD_SHARE_BIT                  4
+#endif
+/*-------------------------------------------------------------------------------
+ System Clock
+---------------------------------------------------------------------------------*/
+
+#ifndef SYS_CLK
+#ifdef CONFIG_SL3516_ASIC
+#define SYS_CLK                         150000000
+#else
+#define SYS_CLK                     	20000000
+#endif
+#endif
+
+#define AHB_CLK                     	SYS_CLK
+#define MAX_TIMER                   	3
+#ifndef APB_CLK
+#ifdef CONFIG_SL3516_ASIC
+#define APB_CLK                     	(SYS_CLK / 6)
+#else
+#define APB_CLK				SYS_CLK
+#endif
+#endif
+
+#ifdef CONFIG_SL3516_ASIC
+#define UART_CLK                        48000000	// 30000000 for GeminiA chip, else 48000000
+#else
+#define UART_CLK			48000000
+#endif
+
+#define SL2312_BAUD_115200              (UART_CLK / 1843200)
+#define SL2312_BAUD_57600               (UART_CLK / 921600)
+#define SL2312_BAUD_38400		        (UART_CLK / 614400)
+#define SL2312_BAUD_19200               (UART_CLK / 307200)
+#define SL2312_BAUD_14400               (UART_CLK / 230400)
+#define SL2312_BAUD_9600                (UART_CLK / 153600)
+
+#endif
+
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/sl2312_ipsec.h
@@ -0,0 +1,684 @@
+#ifndef _IPSEC_DIAG_H
+#define _IPSEC_DIAG_H
+
+#include <linux/scatterlist.h>
+
+#define BIG_ENDIAN    0
+
+#define IPSEC_TEST    0
+#define ZERO_COPY     1
+
+#define UINT unsigned int
+#define BYTE unsigned char
+
+/* define cipher algorithm */
+enum CIPHER {
+	DES_ECB_E	=20,
+	TDES_ECB_E	=21,
+	AES_ECB_E	=22,
+	DES_CBC_E	=24,
+	TDES_CBC_E	=25,
+	AES_CBC_E	=26,
+
+	DES_ECB_D	=27,
+	TDES_ECB_D	=28,
+	AES_ECB_D	=29,
+	DES_CBC_D	=31,
+	TDES_CBC_D	=32,
+	AES_CBC_D	=33,
+	A_SHA1      =12,
+	A_HMAC_SHA1 =13,
+	A_MD5       =14,
+	A_HMAC_MD5  =15,
+};
+
+// opMode
+#define CIPHER_ENC    0x1
+#define CIPHER_DEC    0x3
+#define AUTH          0x4
+#define ENC_AUTH      0x5
+#define AUTH_DEC      0x7
+
+// cipherAlgorithm
+#define CBC_DES       0x4
+#define CBC_3DES      0x5
+#define CBC_AES       0x6
+#define ECB_DES       0x0
+#define ECB_3DES      0x1
+#define ECB_AES       0x2
+
+// authAlgorithm
+#define SHA1         0
+#define MD5          1
+#define HMAC_SHA1    2
+#define HMAC_MD5     3
+#define FCS          4
+
+//cipher mode
+#define ECB          0
+#define CBC          1
+
+// authMode
+#define AUTH_APPEND  0
+#define AUTH_CHKVAL  1
+
+/******************************************************/
+/*          the offset of IPSEC DMA register          */
+/******************************************************/
+enum IPSEC_DMA_REGISTER {
+	IPSEC_DMA_DEVICE_ID		= 0xff00,
+	IPSEC_DMA_STATUS		= 0xff04,
+	IPSEC_TXDMA_CTRL 	 	= 0xff08,
+	IPSEC_TXDMA_FIRST_DESC 	= 0xff0c,
+	IPSEC_TXDMA_CURR_DESC	= 0xff10,
+	IPSEC_RXDMA_CTRL		= 0xff14,
+	IPSEC_RXDMA_FIRST_DESC	= 0xff18,
+	IPSEC_RXDMA_CURR_DESC	= 0xff1c,
+	IPSEC_TXDMA_BUF_ADDR    = 0xff28,
+	IPSEC_RXDMA_BUF_ADDR    = 0xff38,
+	IPSEC_RXDMA_BUF_SIZE		= 0xff30,
+};
+
+#define IPSEC_STATUS_REG    0x00a8
+#define IPSEC_RAND_NUM_REG  0x00ac
+
+/******************************************************/
+/* the field definition of IPSEC DMA Module Register  */
+/******************************************************/
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff00
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int p_wclk 		:  4;	/* DMA_APB write clock period */
+		unsigned int p_rclk 		:  4;	/* DMA_APB read clock period */
+		unsigned int 				:  8;
+		unsigned int device_id		: 12;
+		unsigned int revision_id	:  4;
+#else
+		unsigned int revision_id	:  4;
+		unsigned int device_id		: 12;
+		unsigned int 				:  8;
+		unsigned int p_rclk 		:  4;	/* DMA_APB read clock period */
+		unsigned int p_wclk	    	:  4;	/* DMA_APB write clock period */
+#endif
+	} bits;
+} IPSEC_DMA_DEVICE_ID_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff04
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int ts_finish		:  1;	/* finished tx interrupt */
+		unsigned int ts_derr		:  1;   /* AHB Bus Error while tx */
+		unsigned int ts_perr		:  1;   /* Tx Descriptor protocol error */
+		unsigned int ts_eodi		:  1;	/* TxDMA end of descriptor interrupt */
+		unsigned int ts_eofi		:  1;   /* TxDMA end of frame interrupt */
+		unsigned int rs_finish		:  1;   /* finished rx interrupt */
+		unsigned int rs_derr		:  1;   /* AHB Bus Error while rx */
+		unsigned int rs_perr		:  1;   /* Rx Descriptor protocol error */
+		unsigned int rs_eodi		:  1;	/* RxDMA end of descriptor interrupt */
+		unsigned int rs_eofi		:  1;	/* RxDMA end of frame interrupt */
+        unsigned int intr           :  8;   /* Peripheral interrupt */
+		unsigned int dma_reset 		:  1;	/* write 1 to this bit will cause DMA HClk domain soft reset */
+		unsigned int peri_reset    	:  1;   /* write 1 to this bit will cause DMA PClk domain soft reset */
+		unsigned int 				:  3;
+		unsigned int loop_back		:  1;	/* loopback TxDMA to RxDMA */
+        unsigned int intr_enable    :  8;   /* Peripheral Interrupt Enable */
+#else
+        unsigned int intr_enable    :  8;   /* Peripheral Interrupt Enable */
+		unsigned int loop_back		:  1;	/* loopback TxDMA to RxDMA */
+		unsigned int 				:  3;
+		unsigned int peri_reset    	:  1;   /* write 1 to this bit will cause DMA PClk domain soft reset */
+		unsigned int dma_reset 		:  1;	/* write 1 to this bit will cause DMA HClk domain soft reset */
+        unsigned int intr           :  8;   /* Peripheral interrupt */
+		unsigned int rs_eofi		:  1;	/* RxDMA end of frame interrupt */
+		unsigned int rs_eodi		:  1;	/* RxDMA end of descriptor interrupt */
+		unsigned int rs_perr		:  1;   /* Rx Descriptor protocol error */
+		unsigned int rs_derr		:  1;   /* AHB Bus Error while rx */
+		unsigned int rs_finish		:  1;   /* finished rx interrupt */
+		unsigned int ts_eofi		:  1;   /* TxDMA end of frame interrupt */
+		unsigned int ts_eodi		:  1;	/* TxDMA end of descriptor interrupt */
+		unsigned int ts_perr		:  1;   /* Tx Descriptor protocol error */
+		unsigned int ts_derr		:  1;   /* AHB Bus Error while tx */
+		unsigned int ts_finish		:  1;	/* finished tx interrupt */
+#endif
+	} bits;
+} IPSEC_DMA_STATUS_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff08
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int td_start		:  1;	/* Start DMA transfer */
+		unsigned int td_continue	:  1;   /* Continue DMA operation */
+		unsigned int td_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int 				:  1;
+		unsigned int td_prot		:  4;	/* TxDMA protection control */
+		unsigned int td_burst_size  :  2;	/* TxDMA max burst size for every AHB request */
+		unsigned int td_bus		    :  2;	/* peripheral bus width;0 - 8 bits;1 - 16 bits */
+		unsigned int td_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int td_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int td_fail_en 	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int td_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int td_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int 				: 14;
+#else
+		unsigned int 				: 14;
+		unsigned int td_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int td_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int td_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int td_fail_en 	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int td_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int td_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int td_bus		    :  2;	/* peripheral bus width;0 - 8 bits;1 - 16 bits */
+		unsigned int td_burst_size  :  2;	/* TxDMA max burst size for every AHB request */
+		unsigned int td_prot		:  4;	/* TxDMA protection control */
+		unsigned int 				:  1;
+		unsigned int td_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int td_continue	:  1;   /* Continue DMA operation */
+		unsigned int td_start		:  1;	/* Start DMA transfer */
+#endif
+	} bits;
+} IPSEC_TXDMA_CTRL_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff0c
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int td_first_des_ptr	: 28;/* first descriptor address */
+		unsigned int td_busy			:  1;/* 1-TxDMA busy; 0-TxDMA idle */
+		unsigned int 					:  3;
+#else
+		unsigned int 					:  3;
+		unsigned int td_busy			:  1;/* 1-TxDMA busy; 0-TxDMA idle */
+		unsigned int td_first_des_ptr	: 28;/* first descriptor address */
+#endif
+	} bits;
+} IPSEC_TXDMA_FIRST_DESC_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff10
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int ndar			: 28;	/* next descriptor address */
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int dec			:  1;	/* AHB bus address increment(0)/decrement(1) */
+		unsigned int sof_eof		:  2;
+#else
+		unsigned int sof_eof		:  2;
+		unsigned int dec			:  1;	/* AHB bus address increment(0)/decrement(1) */
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int ndar			: 28;	/* next descriptor address */
+#endif
+	} bits;
+} IPSEC_TXDMA_CURR_DESC_T;
+
+
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff14
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int rd_start		:  1;	/* Start DMA transfer */
+		unsigned int rd_continue	:  1;   /* Continue DMA operation */
+		unsigned int rd_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int 				:  1;
+		unsigned int rd_prot		:  4;	/* DMA protection control */
+		unsigned int rd_burst_size  :  2;	/* DMA max burst size for every AHB request */
+		unsigned int rd_bus		    :  2;	/* peripheral bus width;0 - 8 bits;1 - 16 bits */
+		unsigned int rd_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int rd_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_fail_en  	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int 				: 14;
+#else
+		unsigned int 				: 14;
+		unsigned int rd_eof_en      :  1;   /* End of frame interrupt Enable;1-enable;0-mask */
+		unsigned int rd_eod_en  	:  1;	/* End of Descriptor interrupt Enable;1-enable;0-mask */
+		unsigned int rd_perr_en 	:  1;	/* Protocol Failure Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_fail_en  	:  1;	/* DMA Fail Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_finish_en   :  1;	/* DMA Finish Event Interrupt Enable;1-enable;0-mask */
+		unsigned int rd_endian		:  1;	/* AHB Endian. 0-little endian; 1-big endian */
+		unsigned int rd_bus		    :  2;	/* peripheral bus width;0 - 8 bits;1 - 16 bits */
+		unsigned int rd_burst_size  :  2;	/* DMA max burst size for every AHB request */
+		unsigned int rd_prot		:  4;	/* DMA protection control */
+		unsigned int 				:  1;
+		unsigned int rd_chain_mode	:  1;	/* Descriptor Chain Mode;1-Descriptor Chain mode, 0-Direct DMA mode*/
+		unsigned int rd_continue	:  1;   /* Continue DMA operation */
+		unsigned int rd_start		:  1;	/* Start DMA transfer */
+#endif
+	} bits;
+} IPSEC_RXDMA_CTRL_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff18
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int rd_first_des_ptr	: 28;/* first descriptor address */
+		unsigned int rd_busy			:  1;/* 1-RxDMA busy; 0-RxDMA idle */
+		unsigned int 					:  3;
+#else
+		unsigned int 					:  3;
+		unsigned int rd_busy			:  1;/* 1-RxDMA busy; 0-RxDMA idle */
+		unsigned int rd_first_des_ptr	: 28;/* first descriptor address */
+#endif
+	} bits;
+} IPSEC_RXDMA_FIRST_DESC_T;
+
+typedef union
+{
+	unsigned int bits32;
+	struct bit2_ff1c
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int ndar			: 28;	/* next descriptor address */
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int dec			:  1;	/* AHB bus address increment(0)/decrement(1) */
+		unsigned int sof_eof		:  2;
+#else
+		unsigned int sof_eof		:  2;
+		unsigned int dec			:  1;	/* AHB bus address increment(0)/decrement(1) */
+		unsigned int eofie			:  1;	/* end of frame interrupt enable */
+		unsigned int ndar			: 28;	/* next descriptor address */
+#endif
+	} bits;
+} IPSEC_RXDMA_CURR_DESC_T;
+
+
+
+/******************************************************/
+/*    the field definition of IPSEC module Register   */
+/******************************************************/
+typedef union
+{
+	unsigned int id;
+	struct bit_0000
+	{
+#if (BIG_ENDIAN==1)
+		unsigned int device_id		: 28;
+		unsigned int revision_id	:  4;
+#else
+		unsigned int revision_id	:  4;
+		unsigned int device_id		: 28;
+#endif
+	} bits;
+} IPSEC_ID_T;
+
+typedef union
+{
+    unsigned int control;
+    struct bit_0004
+    {
+#if (BIG_ENDIAN==1)
+        unsigned int op_mode            :  4; /* Operation Mode for the IPSec Module */
+        unsigned int                    :  1;
+        unsigned int cipher_algorithm   :  3;
+        unsigned int aesnk              :  4; /* AES Key Size */
+        unsigned int mix_key_sel        :  1; /* 0:use rCipherKey0-3  1:use Key Mixer */
+        unsigned int                    :  2;
+        unsigned int fcs_stream_copy    :  1; /* enable authentication stream copy */
+        unsigned int auth_mode          :  1; /* 0-Append or 1-Check Authentication Result */
+        unsigned int auth_algorithm     :  3;
+        unsigned int                    :  1;
+        unsigned int auth_check_len     :  3; /* Number of 32-bit words to be check or appended */
+                                              /* by the authentication module */
+        unsigned int process_id         :  8; /* Used to identify process.This number will be */
+                                              /* copied to the descriptor status of received packet*/
+#else
+        unsigned int process_id         :  8; /* Used to identify process.This number will be */
+                                              /* copied to the descriptor status of received packet*/
+        unsigned int auth_check_len     :  3; /* Number of 32-bit words to be check or appended */
+                                              /* by the authentication module */
+        unsigned int                    :  1;
+        unsigned int auth_algorithm     :  3;
+        unsigned int auth_mode          :  1; /* 0-Append or 1-Check Authentication Result */
+        unsigned int fcs_stream_copy    :  1; /* enable authentication stream copy */
+        unsigned int                    :  2;
+        unsigned int mix_key_sel        :  1; /* 0:use rCipherKey0-3  1:use Key Mixer */
+        unsigned int aesnk              :  4; /* AES Key Size */
+        unsigned int cipher_algorithm   :  3;
+        unsigned int                    :  1;
+        unsigned int op_mode            :  4; /* Operation Mode for the IPSec Module */
+#endif
+    } bits;
+} IPSEC_CONTROL_T;
+
+
+typedef union
+{
+    unsigned int cipher_packet;
+    struct bit_0008
+    {
+#if (BIG_ENDIAN==1)
+        unsigned int cipher_header_len    : 16; /* The header length to be skipped by the cipher */
+        unsigned int cipher_algorithm_len : 16; /* The length of message body to be encrypted/decrypted */
+#else
+        unsigned int cipher_algorithm_len : 16; /* The length of message body to be encrypted/decrypted */
+        unsigned int cipher_header_len    : 16; /* The header length to be skipped by the cipher */
+#endif
+    } bits;
+} IPSEC_CIPHER_PACKET_T;
+
+typedef union
+{
+    unsigned int auth_packet;
+    struct bit_000c
+    {
+#if (BIG_ENDIAN==1)
+        unsigned int auth_header_len    : 16; /* The header length that is to be skipped by the authenticator */
+        unsigned int auth_algorithm_len : 16; /* The length of message body that is to be authenticated */
+#else
+        unsigned int auth_algorithm_len : 16; /* The length of message body that is to be authenticated */
+        unsigned int auth_header_len    : 16; /* The header length that is to be skipped by the authenticator */
+#endif
+    } bits;
+} IPSEC_AUTH_PACKET_T;
+
+typedef union
+{
+    unsigned int status;
+    struct bit_00a8
+    {
+#if (BIG_ENDIAN==1)
+        unsigned int auth_cmp_rslt  :  1; /* Authentication Compare result */
+        unsigned int wep_crc_ok     :  1; /* WEP ICV compare result */
+        unsigned int tkip_mic_ok    :  1; /* TKIP Mic compare result */
+        unsigned int ccm_mic_ok     :  1; /* CCM Mic compare result */
+        unsigned int                : 16;
+        unsigned int parser_err_code:  4; /* Authentication Compare result */
+        unsigned int auth_err_code  :  4; /* Authentication module error code */
+        unsigned int cipher_err_code:  4; /* Cipher module erroe code */
+#else
+        unsigned int cipher_err_code:  4; /* Cipher module erroe code */
+        unsigned int auth_err_code  :  4; /* Authentication module error code */
+        unsigned int parser_err_code:  4; /* Authentication Compare result */
+        unsigned int                : 16;
+        unsigned int ccm_mic_ok     :  1; /* CCM Mic compare result */
+        unsigned int tkip_mic_ok    :  1; /* TKIP Mic compare result */
+        unsigned int wep_crc_ok     :  1; /* WEP ICV compare result */
+        unsigned int auth_cmp_rslt  :  1; /* Authentication Compare result */
+#endif
+    } bits;
+} IPSEC_STATUS_T;
+
+
+
+/************************************************************************/
+/*              IPSec Descriptor Format                                 */
+/************************************************************************/
+typedef struct descriptor_t
+{
+	union frame_control_t
+	{
+		unsigned int bits32;
+		struct bits_0000
+		{
+#if (BIG_ENDIAN==1)
+			unsigned int own 		: 1;	/* owner bit. 0-CPU, 1-DMA */
+			unsigned int derr		: 1;	/* data error during processing this descriptor */
+			unsigned int perr		: 1;	/* protocol error during processing this descriptor */
+			unsigned int            : 1;    /* authentication compare result */
+			unsigned int            : 6;    /* checksum[15:8] */
+			unsigned int desc_count : 6;	/* number of descriptors used for the current frame */
+			unsigned int buffer_size:16;	/* transfer buffer size associated with current description*/
+#else
+			unsigned int buffer_size:16;	/* transfer buffer size associated with current description*/
+			unsigned int desc_count : 6;	/* number of descriptors used for the current frame */
+			unsigned int            : 6;    /* checksum[15:8] */
+			unsigned int            : 1;    /* authentication compare result */
+			unsigned int perr		: 1;	/* protocol error during processing this descriptor */
+			unsigned int derr		: 1;	/* data error during processing this descriptor */
+			unsigned int own 		: 1;	/* owner bit. 0-CPU, 1-DMA */
+#endif
+		} bits;
+	} frame_ctrl;
+
+	union flag_status_t
+	{
+		unsigned int bits32;
+		struct bits_0004
+		{
+#if (BIG_ENDIAN==1)
+//            unsigned int checksum   : 8; /* checksum[7:0] */
+			unsigned int            : 4;
+			unsigned int auth_result: 1;
+			unsigned int wep_crc_ok : 1;
+			unsigned int tkip_mic_ok: 1;
+			unsigned int ccmp_mic_ok: 1;
+			unsigned int process_id : 8;
+			unsigned int frame_count:16;
+#else
+			unsigned int frame_count:16;
+			unsigned int process_id : 8;
+			unsigned int ccmp_mic_ok: 1;
+			unsigned int tkip_mic_ok: 1;
+			unsigned int wep_crc_ok : 1;
+			unsigned int auth_result: 1;
+			unsigned int            : 4;
+//            unsigned int checksum   : 8; /* checksum[7:0] */
+#endif
+		} bits_rx_status;
+
+		struct bits_0005
+		{
+#if (BIG_ENDIAN==1)
+            unsigned int            : 8;
+			unsigned int process_id : 8;
+			unsigned int frame_count:16;
+#else
+			unsigned int frame_count:16;
+			unsigned int process_id : 8;
+            unsigned int            : 8;
+#endif
+		} bits_tx_status;
+
+		struct bits_0006
+		{
+#if (BIG_ENDIAN==1)
+			unsigned int            :22;
+			unsigned int tqflag     :10;
+#else
+			unsigned int tqflag     :10;
+			unsigned int            :22;
+#endif
+		} bits_tx_flag;
+	} flag_status;
+
+	unsigned int buf_adr;	/* data buffer address */
+
+	union next_desc_t
+	{
+		unsigned int next_descriptor;
+		struct bits_000c
+		{
+#if (BIG_ENDIAN==1)
+			unsigned int ndar		:28;	/* next descriptor address */
+			unsigned int eofie		: 1;	/* end of frame interrupt enable */
+			unsigned int dec   		: 1;	/* AHB bus address. 0-increment; 1-decrement */
+			unsigned int sof_eof	: 2;	/* 00-the linking descriptor   01-the last descriptor of a frame*/
+			                                /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
+#else
+			unsigned int sof_eof	: 2;	/* 00-the linking descriptor   01-the last descriptor of a frame*/
+			                                /* 10-the first descriptor of a frame    11-only one descriptor for a frame*/
+			unsigned int dec   		: 1;	/* AHB bus address. 0-increment; 1-decrement */
+			unsigned int eofie		: 1;	/* end of frame interrupt enable */
+			unsigned int ndar		:28;	/* next descriptor address */
+#endif
+		} bits;
+	} next_desc;
+} IPSEC_DESCRIPTOR_T;
+
+
+typedef struct IPSEC_S
+{
+    unsigned char       *tx_bufs;
+    unsigned char       *rx_bufs;
+	IPSEC_DESCRIPTOR_T	*tx_desc;	    /* point to virtual TX descriptor address*/
+	IPSEC_DESCRIPTOR_T	*rx_desc;	    /* point to virtual RX descriptor address*/
+	IPSEC_DESCRIPTOR_T	*tx_cur_desc;	/* point to current TX descriptor */
+	IPSEC_DESCRIPTOR_T	*rx_cur_desc;	/* point to current RX descriptor */
+	IPSEC_DESCRIPTOR_T  *tx_finished_desc;
+	IPSEC_DESCRIPTOR_T  *rx_finished_desc;
+	dma_addr_t          rx_desc_dma;	/* physical RX descriptor address */
+	dma_addr_t          tx_desc_dma;    /* physical TX descriptor address */
+	dma_addr_t          rx_bufs_dma;    /* physical RX descriptor address */
+	dma_addr_t          tx_bufs_dma;    /* physical TX descriptor address */
+} IPSEC_T;
+
+
+/*=====================================================================================================*/
+/*  Data Structure of IPSEC Control Packet  */
+/*=====================================================================================================*/
+typedef struct IPSEC_ECB_AUTH_S
+{
+    IPSEC_CONTROL_T         control; /* control parameter */
+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
+    unsigned char           cipher_key[8*4];
+    unsigned char           auth_check_val[5*4];
+} IPSEC_ECB_AUTH_T;
+
+typedef struct IPSEC_CBC_AUTH_S
+{
+    IPSEC_CONTROL_T         control; /* control parameter */
+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
+    unsigned char           cipher_iv[4*4];
+    unsigned char           cipher_key[8*4];
+    unsigned char           auth_check_val[5*4];
+} IPSEC_CBC_AUTH_T;
+
+typedef struct IPSEC_ECB_HMAC_AUTH_S
+{
+    IPSEC_CONTROL_T         control; /* control parameter */
+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
+    unsigned char           cipher_key[8*4];
+    unsigned char           auth_key[16*4];
+    unsigned char           auth_check_val[5*4];
+} IPSEC_ECB_AUTH_HMAC_T;
+
+typedef struct IPSEC_CBC_HMAC_AUTH_S
+{
+    IPSEC_CONTROL_T         control; /* control parameter */
+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
+    unsigned char           cipher_iv[4*4];
+    unsigned char           cipher_key[8*4];
+    unsigned char           auth_key[16*4];
+    unsigned char           auth_check_val[5*4];
+} IPSEC_CBC_AUTH_HMAC_T;
+
+typedef struct IPSEC_HMAC_AUTH_S
+{
+    IPSEC_CONTROL_T         control; /* control parameter */
+    IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter */
+    unsigned char           auth_key[16*4];
+    unsigned char           auth_check_val[5*4];
+} IPSEC_HMAC_AUTH_T;
+
+typedef union
+{
+    unsigned char auth_pkt[28];
+
+    struct IPSEC_AUTH_S
+    {
+        IPSEC_CONTROL_T         control; /* control parameter(4-byte) */
+        IPSEC_AUTH_PACKET_T     auth;   /* authentication packet parameter(4-byte) */
+        unsigned char           auth_check_val[5*4];
+    } var;
+} IPSEC_AUTH_T;
+
+typedef struct IPSEC_CIPHER_CBC_S
+{
+    IPSEC_CONTROL_T         control; /* control parameter */
+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
+    unsigned char           cipher_iv[4*4];
+    unsigned char           cipher_key[8*4];
+} IPSEC_CIPHER_CBC_T;
+
+typedef struct IPSEC_CIPHER_ECB_S
+{
+    IPSEC_CONTROL_T         control; /* control parameter */
+    IPSEC_CIPHER_PACKET_T   cipher; /* cipher packet parameter */
+    unsigned char           cipher_key[8*4];
+} IPSEC_CIPHER_ECB_T;
+
+
+/****************************************************************************
+ *                          Structure Definition                            *
+ ****************************************************************************/
+struct IPSEC_PACKET_S
+{
+    unsigned int    op_mode;            /* CIPHER_ENC(1),CIPHER_DEC(3),AUTH(4),ENC_AUTH(5),AUTH_DEC(7) */
+    unsigned int    cipher_algorithm;   /* ECB_DES(0),ECB_3DES(1),ECB_AES(2),CBC_DES(4),CBC_3DES(5),CBC_AES(6) */
+    unsigned int    auth_algorithm;     /* SHA1(0),MD5(1),HMAC_SHA1(2),HMAC_MD5(3),FCS(4) */
+    unsigned int    auth_result_mode;   /* AUTH_APPEND(0),AUTH_CHKVAL(1) */
+    unsigned int    process_id;         /* Used to identify the process */
+    unsigned int    auth_header_len;    /* Header length to be skipped by the authenticator */
+    unsigned int    auth_algorithm_len; /* Length of message body that is to be authenticated */
+    unsigned int    cipher_header_len;  /* Header length to be skipped by the cipher */
+    unsigned int    cipher_algorithm_len;   /* Length of message body to be encrypted or decrypted */
+    unsigned char   iv[16];             /* Initial vector used for DES,3DES,AES */
+    unsigned int    iv_size;            /* Initial vector size */
+    unsigned char   auth_key[64];       /* authentication key */
+    unsigned int    auth_key_size;      /* authentication key size */
+    unsigned char   cipher_key[32];     /* cipher key */
+    unsigned int    cipher_key_size;    /* cipher key size */
+    struct scatterlist *in_packet;         /* input_packet buffer pointer */
+    //unsigned char		*in_packet;         /* input_packet buffer pointer */
+    unsigned int    pkt_len;            /* input total packet length */
+    unsigned char   auth_checkval[20];  /* Authentication check value/FCS check value */
+    struct IPSEC_PACKET_S *next,*prev;        /* pointer to next/previous operation to perform on buffer */
+    void (*callback)(struct IPSEC_PACKET_S *); /* function to call when done authentication/cipher */
+    unsigned char   *out_packet;        /* output_packet buffer pointer */
+    //struct scatterlist *out_packet;        /* output_packet buffer pointer */
+    unsigned int    out_pkt_len;        /* output total packet length */
+    unsigned int    auth_cmp_result;    /* authentication compare result */
+    unsigned int    checksum;           /* checksum value */
+    unsigned int    status;             /* ipsec return status. 0:success, others:fail */
+#if (IPSEC_TEST == 1)
+    unsigned char    *sw_packet;         /* for test only */
+    unsigned int    sw_pkt_len;         /* for test only */
+#endif
+} ;
+
+/*****************************************************************************
+ * Function    : ipsec_crypto_hw_process
+ * Description : This function processes H/W authentication and cipher.
+ *       Input : op_info - the authentication and cipher information for IPSec module.
+ *      Output : none.
+ *      Return : 0 - success, others - failure.
+ *****************************************************************************/
+int ipsec_crypto_hw_process(struct IPSEC_PACKET_S  *op_info);
+
+int ipsec_get_cipher_algorithm(unsigned char *alg_name,unsigned int alg_mode);
+int ipsec_get_auth_algorithm(unsigned char *alg_name,unsigned int alg_mode);
+#if 0
+void ipsec_sw_authentication(char *data,unsigned int data_len,char *authkey,char authAlgorithm,char *auth_result);
+void ipsec_sw_cipher(unsigned char *pt,unsigned int pt_len, unsigned char *cipher_key, unsigned int key_size,
+                            unsigned char *iv,unsigned int cipherAlgorithm,unsigned char *ct);
+void ipsec_sw_auth_cipher(unsigned int op_mode,char *data,unsigned int data_len,
+                                BYTE *auth_key,char authAlgorithm,char *auth_result,
+                                char *pt, unsigned int pt_len,char *cipher_key, int key_size,
+                                char *iv, char cipherAlgorithm,char *ct);
+#endif
+
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/sl_random.h
@@ -0,0 +1,2 @@
+#define RANDOM_ADD		(IO_ADDRESS (0x051000000) + 0x0AC)
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/system.h
@@ -0,0 +1,54 @@
+/*
+ *  linux/include/asm-arm/arch-sl2312/system.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/arch/platform.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/it8712.h>
+#include <asm/io.h>
+
+static void arch_idle(void)
+{
+	/*
+	 * This should do all the clock switching
+	 * and wait for interrupt tricks
+	 */
+	cpu_do_idle();
+}
+
+extern __inline__ void arch_reset(char mode)
+{
+	__raw_writel( (int) GLOBAL_RESET|RESET_CPU1, IO_ADDRESS(SL2312_GLOBAL_BASE) + GLOBAL_RESET_REG);
+}
+
+
+void (*pm_power_off)(void);
+//{
+//	printk("arch_power_off\n");
+
+	// Power off
+//	__raw_writel( (int) 0x00000001, IO_ADDRESS(SL2312_POWER_CTRL_BASE) + 0x04);
+
+//}
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/timer.h
@@ -0,0 +1,53 @@
+/*
+ *
+ *  This file contains the register definitions for the Excalibur
+ *  Timer TIMER00.
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+#ifndef __TIMER_H
+#define __TIMER_H
+
+/*
+ * Register definitions for the timers
+ */
+
+#define TIMER_COUNT(BASE_ADDR)          (TIMER_TYPE (BASE_ADDR  + 0x00 ))
+#define TIMER_LOAD(BASE_ADDR)           (TIMER_TYPE (BASE_ADDR  + 0x04 ))
+#define TIMER_MATCH1(BASE_ADDR)         (TIMER_TYPE (BASE_ADDR  + 0x08 ))
+#define TIMER_MATCH2(BASE_ADDR)         (TIMER_TYPE (BASE_ADDR  + 0x0C ))
+#define TIMER_CR(BASE_ADDR)             (TIMER_TYPE (BASE_ADDR  + 0x30 ))
+#define TIMER_1_CR_ENABLE_MSK 		    (0x00000001)
+#define TIMER_1_CR_ENABLE_OFST 		    (0)
+#define TIMER_1_CR_CLOCK_MSK  		    (0x00000002)
+#define TIMER_1_CR_CLOCK_OFST 		    (1)
+#define TIMER_1_CR_INT_MSK 		        (0x00000004)
+#define TIMER_1_CR_INT_OFST 		    (2)
+#define TIMER_2_CR_ENABLE_MSK 		    (0x00000008)
+#define TIMER_2_CR_ENABLE_OFST 		    (3)
+#define TIMER_2_CR_CLOCK_MSK  		    (0x00000010)
+#define TIMER_2_CR_CLOCK_OFST 		    (4)
+#define TIMER_2_CR_INT_MSK 		        (0x00000020)
+#define TIMER_2_CR_INT_OFST 		    (5)
+#define TIMER_3_CR_ENABLE_MSK 		    (0x00000040)
+#define TIMER_3_CR_ENABLE_OFST 		    (6)
+#define TIMER_3_CR_CLOCK_MSK  		    (0x00000080)
+#define TIMER_3_CR_CLOCK_OFST 		    (7)
+#define TIMER_3_CR_INT_MSK 		        (0x00000100)
+#define TIMER_3_CR_INT_OFST 		    (8)
+
+#endif /* __TIMER00_H */
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/timex.h
@@ -0,0 +1,29 @@
+/*
+ *  linux/include/asm-arm/arch-epxa10db/timex.h
+ *
+ *  Excalibur timex specifications
+ *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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/arch/sl2312.h>
+
+#define CLOCK_TICK_RATE		APB_CLK
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/uart.h
@@ -0,0 +1,100 @@
+/* *
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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
+ */
+#ifndef __UART_H
+#define __UART_H
+
+/*
+ * Register definitions for the UART
+ */
+
+#define UART_TX_FIFO_SIZE      (15)
+
+#define UART_RBR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x00))  // read
+#define UART_THR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x00))  // write
+#define UART_IER(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x04))
+#define UART_IER_MS                                 (0x08)
+#define UART_IER_RLS                                (0x04)
+#define UART_IER_TE                                 (0x02)
+#define UART_IER_DR                                 (0x01)
+#define UART_IIR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x08))   // read
+#define UART_IIR_NONE                		    (0x01)	/* No interrupt pending */
+#define UART_IIR_RLS                 		    (0x06)	/* Receive Line Status */
+#define UART_IIR_DR                  		    (0x04)	/* Receive Data Ready */
+#define UART_IIR_TIMEOUT             		    (0x0c)	/* Receive Time Out */
+#define UART_IIR_TE                  		    (0x02)	/* THR Empty */
+#define UART_IIR_MODEM               		    (0x00)	/* Modem Status */
+#define UART_FCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x08))  // write
+#define UART_FCR_FE                  		    (0x01) 	/* FIFO Enable */
+#define UART_FCR_RXFR                		    (0x02) 	/* Rx FIFO Reset */
+#define UART_FCR_TXFR               		    (0x04) 	/* Tx FIFO Reset */
+#define UART_FCR_FIFO_1C                            (0x00)
+#define UART_FCR_FIFO_4C                            (0x40)
+#define UART_FCR_FIFO_8C                            (0x80)
+#define UART_FCR_FIFO_14C                           (0xC0)
+#define UART_LCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x0C))
+#define UART_LCR_MSK                                (0x03)
+#define UART_LCR_LEN5                		    (0x00)
+#define UART_LCR_LEN6                		    (0x01)
+#define UART_LCR_LEN7                		    (0x02)
+#define UART_LCR_LEN8                		    (0x03)
+#define UART_LCR_STOP                		    (0x04)
+#define UART_LCR_EVEN                		    (0x18) 	/* Even Parity */
+#define UART_LCR_ODD                 		    (0x08)     	/* Odd Parity */
+#define UART_LCR_PE                  		    (0x08)	/* Parity Enable */
+#define UART_LCR_SETBREAK            		    (0x40)	/* Set Break condition */
+#define UART_LCR_STICKPARITY         		    (0x20)	/* Stick Parity Enable */
+#define UART_LCR_DLAB                		    (0x80)     	/* Divisor Latch Access Bit */
+#define UART_MCR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x10))
+#define UART_MCR_DTR                 		    (0x1)	/* Data Terminal Ready */
+#define UART_MCR_RTS                 		    (0x2)	/* Request to Send */
+#define UART_MCR_OUT1                		    (0x4)	/* output	1 */
+#define UART_MCR_OUT2                		    (0x8)	/* output2 or global interrupt enable */
+#define UART_MCR_LPBK                		    (0x10)	/* loopback mode */
+#define UART_MCR_MASK                               (0xE3)
+#define UART_LSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x14))
+#define UART_LSR_DR                  		    (0x01)     	/* Data Ready */
+#define UART_LSR_OE                  		    (0x02)     	/* Overrun Error */
+#define UART_LSR_PE                  		    (0x04)     	/* Parity Error */
+#define UART_LSR_FE                  		    (0x08)     	/* Framing Error */
+#define UART_LSR_BI                                 (0x10)     	/* Break Interrupt */
+#define UART_LSR_THRE                               (0x20)     	/* THR Empty */
+#define UART_LSR_TE                                 (0x40)     	/* Transmitte Empty */
+#define UART_LSR_DE                                 (0x80)     	/* FIFO Data Error */
+#define UART_MSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x18))
+#define UART_MSR_DELTACTS            		    (0x01)	/* Delta CTS */
+#define UART_MSR_DELTADSR            		    (0x02)	/* Delta DSR */
+#define UART_MSR_TERI                		    (0x04)	/* Trailing Edge RI */
+#define UART_MSR_DELTACD             		    (0x08)	/* Delta CD */
+#define UART_MSR_CTS                 		    (0x10)	/* Clear To Send */
+#define UART_MSR_DSR                 		    (0x20)	/* Data Set Ready */
+#define UART_MSR_RI                  		    (0x40)	/* Ring Indicator */
+#define UART_MSR_DCD                 		    (0x80)	/* Data Carrier Detect */
+#define UART_SPR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x1C))
+#define UART_DIV_LO(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x0))
+#define UART_DIV_HI(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x4))
+#define UART_PSR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x8))
+#define UART_MDR(BASE_ADDR) (UART_TYPE (BASE_ADDR  + 0x20))
+#define UART_MDR_SERIAL                             (0x0)
+
+#define UART_MSR_DDCD	0x08	/* Delta DCD */
+#define UART_MSR_DDSR	0x02	/* Delta DSR */
+#define UART_MSR_DCTS	0x01	/* Delta CTS */
+#define UART_MSR_ANY_DELTA 0x0F	/* Any of the delta bits! */
+
+
+#endif /* __UART_H */
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/uncompress.h
@@ -0,0 +1,94 @@
+/*
+ *  linux/include/asm-arm/arch-epxa10db/uncompress.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2001 Altera Corporation
+ *
+ * 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/arch/platform.h"
+#include "asm/arch/hardware.h"
+#define UART_TYPE (volatile unsigned int*)
+#ifndef CONFIG_SERIAL_IT8712
+#include "asm/arch/uart.h"
+#endif
+extern unsigned int it8712_uart_base;
+
+/*
+ * This does not append a newline
+ */
+static void putstr(const char *s)
+{
+
+#ifdef CONFIG_SERIAL_IT8712
+
+	unsigned char *base,*status,stat;
+	int i ;
+
+	status = (unsigned char*)it8712_uart_base + 5;
+	base = (unsigned char*)it8712_uart_base ;
+
+	while (*s) {
+
+		stat = *status;
+		while (!(stat&0x20)) {				// check status
+			for(i=0;i<0x10;i++)	;
+			status = (unsigned char*)it8712_uart_base + 5;
+			stat = *status ;
+		}
+
+		*base = *s;
+		barrier();
+
+		if (*s == '\n') {
+			stat = *status;
+			while (!(stat&0x20)) {			// check status
+				for(i=0;i<0x10;i++)	;
+				status = (unsigned char*)it8712_uart_base + 5;
+				stat = *status ;
+		}
+
+			barrier();
+			*base = '\r';
+		}
+		s++;
+	}
+
+#else
+	while (*s) {
+		while (!(*UART_LSR(SL2312_UART_BASE) &
+		         UART_LSR_THRE));
+		       barrier();
+
+		*UART_THR(SL2312_UART_BASE) = *s;
+
+		if (*s == '\n') {
+			while (!(*UART_LSR(SL2312_UART_BASE) &
+			         UART_LSR_THRE));
+				barrier();
+
+			*UART_THR(SL2312_UART_BASE) = '\r';
+		}
+		s++;
+	}
+#endif
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/vmalloc.h
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/arch-epxa10db/vmalloc.h
+ *
+ *  Copyright (C) 2000 Russell King.
+ *
+ * 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
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET	  (8*1024*1024)
+#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+
+//#define MODULE_START    (PAGE_OFFSET - 16*1048576)
+//#define MODULE_END      (PAGE_OFFSET)
+
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/watchdog.h
@@ -0,0 +1,58 @@
+#ifndef __WATCHDOG_H
+#define __WATCHDOG_H
+
+#define WATCHDOG_BASE		          (IO_ADDRESS (SL2312_WAQTCHDOG_BASE))
+#define WATCHDOG_COUNTER                  (WATCHDOG_BASE + 0x00)
+#define WATCHDOG_LOAD                     (WATCHDOG_BASE + 0x04)
+#define WATCHDOG_RESTART                  (WATCHDOG_BASE + 0x08)
+#define WATCHDOG_CR                       (WATCHDOG_BASE + 0x0C)
+#define WATCHDOG_STATUS                   (WATCHDOG_BASE + 0x10)
+#define WATCHDOG_CLEAR                    (WATCHDOG_BASE + 0x14)
+#define WATCHDOG_INTRLEN                  (WATCHDOG_BASE + 0x18)
+
+#define WATCHDOG_WDENABLE_MSK 		  (0x00000001)
+#define WATCHDOG_WDENABLE_OFST 		  (0)
+#define WATCHDOG_WDRST_MSK  		  (0x00000002)
+#define WATCHDOG_WDRST_OFST 		  (1)
+#define WATCHDOG_WDINTR_MSK 		  (0x00000004)
+#define WATCHDOG_WDINTR_OFST 		  (2)
+#define WATCHDOG_WDEXT_MSK 		  (0x00000008)
+#define WATCHDOG_WDEXT_OFST 		  (3)
+#define WATCHDOG_WDCLOCK_MSK 		  (0x00000010)
+#define WATCHDOG_WDCLOCK_OFST 		  (4)
+#define WATCHDOG_CR_MASK                  (0x0000001F)
+
+#define WATCHDOG_CLEAR_STATUS             0x1
+#define WATCHDOG_ENABLE                   1
+#define WATCHDOG_DISABLE                  0
+#define WATCHDOG_RESTART_VALUE            0x5AB9
+
+#define WATCHDOG_MINOR	                  130
+
+#define WATCHDOG_IOCTRL_DISABLE	          0x01
+#define WATCHDOG_IOCTRL_SETTIME	          0x02
+#define WATCHDOG_IOCTRL_ENABLE	          0x03
+#define WATCHDOG_IOCTRL_RESTART	          0x04
+
+#define WATCHDOG_TIMEOUT_SCALE            APB_CLK
+#define WATCHDOG_TIMEOUT_MARGIN           30
+#define WATCHDOG_DRIVER_OPEN              1
+#define WATCHDOG_DRIVER_CLOSE             0
+
+
+static void     watchdog_disable(void);
+static void     watchdog_enable(void);
+static int      watchdog_open(struct inode *, struct file *);
+static int      watchdog_release(struct inode *, struct file *);
+static ssize_t  watchdog_read(struct file *, char *, size_t, loff_t *);
+static ssize_t  watchdog_write(struct file *, const char *, size_t, loff_t *);
+static int      watchdog_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+#ifdef WATCHDOG_TEST
+static void watchdog_fire(int, void *, struct pt_regs *);
+#endif
+
+
+
+
+
+#endif
--- /dev/null
+++ b/include/asm-arm/arch-sl2312/xor.h
@@ -0,0 +1,29 @@
+/*
+ * include/asm-arm/arch-sl2312/xor.h
+ *
+ * Copyright (C) 2005 Storlink Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ASM_ARCH_XOR_H
+#define _ASM_ARCH_XOR_H
+
+/*
+ * Function prototypes
+ */
+void xor_gemini_2(unsigned long bytes, unsigned long *p1, unsigned long *p2);
+
+void xor_gemini_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		             unsigned long *p3);
+
+void xor_gemini_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		             unsigned long *p3, unsigned long *p4);
+
+void xor_gemini_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+		             unsigned long *p3, unsigned long *p4, unsigned long *p5);
+
+#endif /* _ASM_ARCH_XOR_H */
+
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -46,6 +46,18 @@
 # define MULTI_CACHE 1
 #endif
 
+/***********************************************************************
+ *             Storlink SoC -- Cache
+ ***********************************************************************/
+#if defined(CONFIG_CPU_FA526)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE fa
+# endif
+#endif
+/***********************************************************************/
+
 #if defined(CONFIG_CPU_ARM926T)
 # ifdef _CACHE
 #  define MULTI_CACHE 1
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -74,6 +74,18 @@
 # endif
 #endif
 
+/***********************************************************************
+ *             Storlink SoC -- flash
+ ***********************************************************************/
+#ifdef CONFIG_CPU_COPY_FA
+# ifdef _USER
+#  define MULTI_USER 1
+# else
+#  define _USER fa
+# endif
+#endif
+/***********************************************************************/
+
 #ifdef CONFIG_CPU_SA1100
 # ifdef _USER
 #  define MULTI_USER 1
--- a/include/asm-arm/proc-fns.h
+++ b/include/asm-arm/proc-fns.h
@@ -89,6 +89,14 @@
 #   define CPU_NAME cpu_arm922
 #  endif
 # endif
+# ifdef CONFIG_CPU_FA526
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_fa526
+#  endif
+# endif
 # ifdef CONFIG_CPU_ARM925T
 #  ifdef CPU_NAME
 #   undef  MULTI_CPU
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -39,6 +39,8 @@
 #define TLB_V6_D_ASID	(1 << 17)
 #define TLB_V6_I_ASID	(1 << 18)
 
+#define TLB_DINVAL      (1 << 28)
+#define TLB_BTB         (1 << 29)
 #define TLB_DCLEAN	(1 << 30)
 #define TLB_WB		(1 << 31)
 
@@ -52,6 +54,7 @@
  *	  v4wb  - ARMv4 with write buffer without I TLB flush entry instruction
  *	  v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
  *	  v6wbi - ARMv6 with write buffer with I TLB flush entry instruction
+ *    fa    - ARMv4 with write buffer with UTLB and branch target buffer (BTB)
  */
 #undef _TLB
 #undef MULTI_TLB
@@ -86,6 +89,44 @@
 # define v4_always_flags	(-1UL)
 #endif
 
+#ifdef CONFIG_CPU_FA_BTB
+#define __TLB_BTB      TLB_BTB
+#else
+#define __TLB_BTB      0
+#endif
+
+#ifdef CONFIG_CPU_FA_WB_DISABLE
+#define __TLB_WB       0
+#else
+#define __TLB_WB       TLB_WB
+#endif
+
+/* Fix buggy CPU which doesn't invalidate Dcache properly */
+#ifdef CONFIG_CPU_FA520
+#define __TLB_DINVAL   TLB_DINVAL
+#elif defined(CONFIG_CPU_FA526)
+//#define __TLB_DINVAL   TLB_DINVAL
+#define __TLB_DINVAL   0
+#else
+#define __TLB_DINVAL   0
+#endif
+
+#define fa_tlb_flags	(__TLB_WB | __TLB_BTB | __TLB_DINVAL | TLB_DCLEAN | \
+                         TLB_V4_U_FULL | TLB_V4_U_PAGE)
+
+#ifdef CONFIG_CPU_TLB_FA
+# define fa_possible_flags	fa_tlb_flags
+# define fa_always_flags	fa_tlb_flags
+# ifdef _TLB
+#  define MULTI_TLB 1
+# else
+#  define _TLB fa
+# endif
+#else
+# define fa_possible_flags	0
+# define fa_always_flags	(-1UL)
+#endif
+
 #define v4wbi_tlb_flags	(TLB_WB | TLB_DCLEAN | \
 			 TLB_V4_I_FULL | TLB_V4_D_FULL | \
 			 TLB_V4_I_PAGE | TLB_V4_D_PAGE)
@@ -246,12 +287,14 @@
 				 v4_possible_flags | \
 				 v4wbi_possible_flags | \
 				 v4wb_possible_flags | \
+                 fa_possible_flags | \
 				 v6wbi_possible_flags)
 
 #define always_tlb_flags	(v3_always_flags & \
 				 v4_always_flags & \
 				 v4wbi_always_flags & \
 				 v4wb_always_flags & \
+                 fa_always_flags & \
 				 v6wbi_always_flags)
 
 #define tlb_flag(f)	((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
@@ -261,6 +304,9 @@
 	const int zero = 0;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
+	if (tlb_flag(TLB_DINVAL))
+	        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
+
 	if (tlb_flag(TLB_WB))
 		dsb();
 
@@ -281,6 +327,13 @@
 		dsb();
 		isb();
 	}
+
+	if (tlb_flag(TLB_BTB))
+	{
+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
+		asm("mov r0, r0" : : );
+		asm("mov r0, r0" : : );
+	}
 }
 
 static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -289,6 +342,9 @@
 	const int asid = ASID(mm);
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
+	if (tlb_flag(TLB_DINVAL))
+	        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
+
 	if (tlb_flag(TLB_WB))
 		dsb();
 
@@ -317,6 +373,14 @@
 		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
 		dsb();
 	}
+
+	if (tlb_flag(TLB_BTB))
+	{
+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
+		asm("mov r0, r0" : : );
+		asm("mov r0, r0" : : );
+	}
+
 }
 
 static inline void
@@ -327,6 +391,9 @@
 
 	uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
 
+	if (tlb_flag(TLB_DINVAL))
+        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero)); // clean & invalidate data cache all
+
 	if (tlb_flag(TLB_WB))
 		dsb();
 
@@ -357,6 +424,13 @@
 		asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
 		dsb();
 	}
+
+	if (tlb_flag(TLB_BTB))
+	{
+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
+		asm("mov r0, r0" : : );
+		asm("mov r0, r0" : : );
+	}
 }
 
 static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -366,6 +440,9 @@
 
 	kaddr &= PAGE_MASK;
 
+	if (tlb_flag(TLB_DINVAL))
+        asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero));
+
 	if (tlb_flag(TLB_WB))
 		dsb();
 
@@ -386,6 +463,12 @@
 		asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
 	if (tlb_flag(TLB_V6_I_PAGE))
 		asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
+	if (tlb_flag(TLB_BTB))
+	{
+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
+		asm("mov r0, r0" : : );
+		asm("mov r0, r0" : : );
+	}
 
 	if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
 		     TLB_V6_I_PAGE | TLB_V6_D_PAGE |
@@ -412,6 +495,7 @@
  */
 static inline void flush_pmd_entry(pmd_t *pmd)
 {
+	const unsigned int zero = 0;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_DCLEAN))
@@ -419,15 +503,30 @@
 			: : "r" (pmd) : "cc");
 	if (tlb_flag(TLB_WB))
 		dsb();
+
+	if (tlb_flag(TLB_BTB)) // Luke Lee 05/16/2005
+	{
+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
+		asm("mov r0, r0" : : );
+		asm("mov r0, r0" : : );
+	}
 }
 
 static inline void clean_pmd_entry(pmd_t *pmd)
 {
+    const unsigned int zero = 0; // Luke Lee 05/16/2005 ins 1
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 
 	if (tlb_flag(TLB_DCLEAN))
 		asm("mcr	p15, 0, %0, c7, c10, 1	@ flush_pmd"
 			: : "r" (pmd) : "cc");
+
+	if (tlb_flag(TLB_BTB)) // Luke Lee 05/16/2005
+	{
+        asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero));
+		asm("mov r0, r0" : : );
+		asm("mov r0, r0" : : );
+	}
 }
 
 #undef tlb_flag
--- a/include/asm-arm/xor.h
+++ b/include/asm-arm/xor.h
@@ -139,3 +139,18 @@
 		xor_speed(&xor_block_8regs);	\
 		xor_speed(&xor_block_32regs);	\
 	} while (0)
+
+#ifdef CONFIG_GEMINI_XOR_ACCE
+#include <asm/arch/xor.h>
+static struct xor_block_template xor_block_gemini = {
+	.name	= "gemini xor acceleration",
+	.do_2	= xor_gemini_2,
+	.do_3	= xor_gemini_3,
+	.do_4	= xor_gemini_4,
+	.do_5	= xor_gemini_5,};
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES			\
+	do {					\
+	xor_speed(&xor_block_gemini); \
+	} while (0)
+#endif
--- a/include/linux/apm_bios.h
+++ b/include/linux/apm_bios.h
@@ -217,4 +217,24 @@
 #define APM_IOC_STANDBY		_IO('A', 1)
 #define APM_IOC_SUSPEND		_IO('A', 2)
 
+// add by jason for power control
+struct pwc_ioctl_data {
+	unsigned int action;	// sword struct
+	unsigned int data;	// stand shutdown time for PWC_SET_SHUT_TIME
+				// stand shutdown source for PWC_WAIT_BTN
+};
+
+#define POWEROFF		0x01
+#define RESTORE_DEFAULT	0x02
+#define SYSTEM_REBOOT	0x04
+
+#define PWR_SRC_CIR		0x10
+#define PWR_SRC_RTC		0x20
+#define PWR_SRC_BTN		0x40
+
+#define	PWC_IOCTL_BASE			'A'				// use linux APM ioctl
+#define PWC_SET_SHUT_TIME		_IOW('A', 16, struct pwc_ioctl_data)
+#define PWC_WAIT_BTN			_IOR('A', 17, struct pwc_ioctl_data)
+#define PWC_SHUTDOWN			_IO ('A', 18)
+
 #endif	/* LINUX_APM_H */
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -76,6 +76,7 @@
  * why not move it into the appropriate arch directory (for those
  * architectures that need it).
  */
+extern void rtc_set_time_second(unsigned int second);
  
 asmlinkage long sys_stime(time_t __user *tptr)
 {
@@ -87,6 +88,10 @@
 
 	tv.tv_nsec = 0;
 
+#ifdef CONFIG_SL2312_RTC
+    rtc_set_time_second(tv.tv_sec);
+#endif
+
 	err = security_settime(&tv, NULL);
 	if (err)
 		return err;