diff --git a/.gitignore b/.gitignore
index 33abbd3d0783ce75b4b1d111b1ee085bc150e30f..0dfef4477f2ef2f4f091e1772ab160d06ed46742 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,4 @@ GTAGS
 *.orig
 *~
 \#*#
+uboot.img
\ No newline at end of file
diff --git a/Makefile b/Makefile
index c66bd2f7ea7aa55c71708d5308c52a585772a607..0959848bd6fc385d152516e08a1878b705a68862 100644
--- a/Makefile
+++ b/Makefile
@@ -566,12 +566,13 @@ LDPPFLAGS	+= -ansi
 endif
 
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS	+= -Os
+#KBUILD_CFLAGS	+= -Os
+KBUILD_CFLAGS	+= -Os -fno-schedule-insns -fno-schedule-insns2
 else
 KBUILD_CFLAGS	+= -O2
 endif
 
-KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
+Kbuild_CFLAGS += $(call cc-option,-fno-stack-protector)
 KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks)
 
 KBUILD_CFLAGS	+= -g
@@ -740,7 +741,7 @@ DO_STATIC_RELA =
 endif
 
 # Always append ALL so that arch config.mk's can add custom ones
-ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map u-boot.cfg binary_size_check
+ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map u-boot.cfg binary_size_check uboot.img
 
 ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
 ifeq ($(CONFIG_SPL_FSL_PBL),y)
@@ -840,6 +841,35 @@ u-boot.bin: u-boot-nodtb.bin FORCE
 	$(call if_changed,copy)
 endif
 
+# Make mediatek uimage
+DDR_CHIP=DEFAULT_DDR3_2048M
+CFG_ENV_IS=IN_NAND
+
+PHONY += mt7621_ram_init
+
+mt7621_ram_init: u-boot.bin
+	cp mt7621_stage_L2.bin nand.bin
+	cp mt7621_stage_sram.bin sram.bin
+	./mt7621_ddr.sh nand.bin nand.bin mt7621_ddr_param.txt $(DDR_CHIP) $(CFG_ENV_IS)
+	./mt7621_ddr.sh sram.bin sram.bin mt7621_ddr_param.txt $(DDR_CHIP) $(CFG_ENV_IS)
+	echo "0 10"|xxd -r|dd bs=1 count=1 seek=38 of=nand.bin conv=notrunc
+	echo "0 11"|xxd -r|dd bs=1 count=1 seek=39 of=nand.bin conv=notrunc
+	echo "0 10"|xxd -r|dd bs=1 count=1 seek=38 of=sram.bin conv=notrunc
+	echo "0 11"|xxd -r|dd bs=1 count=1 seek=39 of=sram.bin conv=notrunc
+	chmod 777 nand.bin sram.bin
+	dd if=u-boot.bin of=nand.bin bs=1 count=$(shell stat -c %s u-boot.bin) \
+	seek=$(shell echo "(($(shell stat -c %s mt7621_stage_L2.bin)+4095)/4096)*4096-64" | bc) \
+	conv=notrunc
+
+uboot.img:  mt7621_ram_init
+	./tools/mkimage_mediatek -A mips -T standalone -C none \
+		-a 0xA0200000 -e 0xa0200000 \
+		-n "NAND Flash Image" \
+		-r DDR3 -s 16 -t 256 -u 32 \
+		-y 40 \
+		-z 5000 -d nand.bin uboot.img
+	@printf "\nImage file is uboot.img.\n"
+
 %.imx: %.bin
 	$(Q)$(MAKE) $(build)=arch/arm/imx-common $@
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 21066f0fda69c1649cf981b52e2ae53c13a982d1..646f724dc78c1946cab1a79146e1b8eeaac6c987 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -39,6 +39,15 @@ config TARGET_MALTA
 	select SWAP_IO_SPACE
 	select MIPS_L1_CACHE_SHIFT_6
 
+config TARGET_EX300
+	bool "Support ex300"
+	select SUPPORTS_LITTLE_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_CPU_MIPS32_R2
+	select SWAP_IO_SPACE
+	select MIPS_L1_CACHE_SHIFT_6
+
+
 config TARGET_VCT
 	bool "Support vct"
 	select SUPPORTS_BIG_ENDIAN
@@ -77,6 +86,7 @@ endchoice
 
 source "board/dbau1x00/Kconfig"
 source "board/imgtec/malta/Kconfig"
+source "board/inteno/ex300/Kconfig"
 source "board/micronas/vct/Kconfig"
 source "board/pb1x00/Kconfig"
 source "board/qemu-mips/Kconfig"
diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
index fc6dd66aa655b9e1c7a8b25c5311e96e0ff6f4cb..c2db7422139e99e3140b56b7378d0a0e4937db97 100644
--- a/arch/mips/cpu/start.S
+++ b/arch/mips/cpu/start.S
@@ -318,3 +318,8 @@ in_ram:
 	 move	ra, zero
 
 	END(relocate_code)
+
+LEAF(debug_halt)
+1:	b 1b
+	jr      ra
+	END(debug_halt)
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
new file mode 100644
index 0000000000000000000000000000000000000000..789176099743f9fe09c23598cf08b4cbd3672e83
--- /dev/null
+++ b/arch/mips/include/asm/atomic.h
@@ -0,0 +1,818 @@
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ *
+ * But use these as seldom as possible since they are much more slower
+ * than regular operations.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 97, 99, 2000, 03, 04, 06 by Ralf Baechle
+ */
+#ifndef _ASM_ATOMIC_H
+#define _ASM_ATOMIC_H
+
+//#include <linux/irqflags.h>
+#include <linux/types.h>
+//#include <asm/barrier.h>
+#include <asm/cpu-features.h>
+//#include <asm/war.h>
+#include <asm/system.h>
+typedef struct { int counter; } atomic_t;
+
+#define R10000_LLSC_WAR 0
+#define kernel_uses_llsc 1
+#define ATOMIC_INIT(i)    { (i) }
+
+
+/*
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.
+ */
+#define atomic_read(v)		(*(volatile int *)&(v)->counter)
+
+/*
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic_set(v, i)		((v)->counter = (i))
+
+/*
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __inline__ void atomic_add(int i, atomic_t * v)
+{
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%0, %1		# atomic_add		\n"
+		"	addu	%0, %2					\n"
+		"	sc	%0, %1					\n"
+		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	} else if (kernel_uses_llsc) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%0, %1		# atomic_add		\n"
+		"	addu	%0, %2					\n"
+		"	sc	%0, %1					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	}
+#if 0
+	else {	unsigned long flags;
+
+		raw_local_irq_save(flags);
+		v->counter += i;
+		raw_local_irq_restore(flags);
+	}
+#endif
+
+}
+
+/*
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+static __inline__ void atomic_sub(int i, atomic_t * v)
+{
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%0, %1		# atomic_sub		\n"
+		"	subu	%0, %2					\n"
+		"	sc	%0, %1					\n"
+		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	} else if (kernel_uses_llsc) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%0, %1		# atomic_sub		\n"
+		"	subu	%0, %2					\n"
+		"	sc	%0, %1					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	}
+#if 0
+	else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		v->counter -= i;
+		raw_local_irq_restore(flags);
+	}
+#endif
+}
+
+/*
+ * Same as above, but return the result value
+ */
+static __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+	int result;
+
+//	smp_mb__before_llsc();
+
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%1, %2		# atomic_add_return	\n"
+		"	addu	%0, %1, %3				\n"
+		"	sc	%0, %2					\n"
+		"	beqzl	%0, 1b					\n"
+		"	addu	%0, %1, %3				\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else if (kernel_uses_llsc) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%1, %2		# atomic_add_return	\n"
+		"	addu	%0, %1, %3				\n"
+		"	sc	%0, %2					\n"
+		"	beqz	%0, 2f					\n"
+		"	addu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	}
+#if 0
+	else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		result = v->counter;
+		result += i;
+		v->counter = result;
+		raw_local_irq_restore(flags);
+	}
+
+	smp_llsc_mb();
+#endif
+	return result;
+}
+
+static __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+	int result;
+
+//	smp_mb__before_llsc();
+
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%1, %2		# atomic_sub_return	\n"
+		"	subu	%0, %1, %3				\n"
+		"	sc	%0, %2					\n"
+		"	beqzl	%0, 1b					\n"
+		"	subu	%0, %1, %3				\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else if (kernel_uses_llsc) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%1, %2		# atomic_sub_return	\n"
+		"	subu	%0, %1, %3				\n"
+		"	sc	%0, %2					\n"
+		"	beqz	%0, 2f					\n"
+		"	subu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	}
+#if 0
+	else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		result = v->counter;
+		result -= i;
+		v->counter = result;
+		raw_local_irq_restore(flags);
+	}
+
+	smp_llsc_mb();
+#endif
+	return result;
+}
+
+/*
+ * atomic_sub_if_positive - conditionally subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically test @v and subtract @i if @v is greater or equal than @i.
+ * The function returns the old value of @v minus @i.
+ */
+static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
+{
+	int result;
+
+//	smp_mb__before_llsc();
+
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
+		"	subu	%0, %1, %3				\n"
+		"	bltz	%0, 1f					\n"
+		"	sc	%0, %2					\n"
+		"	.set	noreorder				\n"
+		"	beqzl	%0, 1b					\n"
+		"	 subu	%0, %1, %3				\n"
+		"	.set	reorder					\n"
+		"1:							\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else if (kernel_uses_llsc) {
+		int temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	ll	%1, %2		# atomic_sub_if_positive\n"
+		"	subu	%0, %1, %3				\n"
+		"	bltz	%0, 1f					\n"
+		"	sc	%0, %2					\n"
+		"	.set	noreorder				\n"
+		"	beqz	%0, 2f					\n"
+		"	 subu	%0, %1, %3				\n"
+		"	.set	reorder					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"1:							\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	}
+#if 0
+	else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		result = v->counter;
+		result -= i;
+		if (result >= 0)
+			v->counter = result;
+		raw_local_irq_restore(flags);
+	}
+
+	smp_llsc_mb();
+#endif
+	return result;
+}
+#if 0
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int c, old;
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return c != (u);
+}
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+#endif
+#define atomic_dec_return(v) atomic_sub_return(1, (v))
+#define atomic_inc_return(v) atomic_add_return(1, (v))
+
+/*
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+
+/*
+ * atomic_dec_and_test - decrement by 1 and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+/*
+ * atomic_dec_if_positive - decrement by 1 if old value positive
+ * @v: pointer of type atomic_t
+ */
+#define atomic_dec_if_positive(v)	atomic_sub_if_positive(1, v)
+
+/*
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic_inc(v) atomic_add(1, (v))
+
+/*
+ * atomic_dec - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec(v) atomic_sub(1, (v))
+
+/*
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define atomic_add_negative(i, v) (atomic_add_return(i, (v)) < 0)
+
+#ifdef CONFIG_64BIT
+
+#define ATOMIC64_INIT(i)    { (i) }
+
+/*
+ * atomic64_read - read atomic variable
+ * @v: pointer of type atomic64_t
+ *
+ */
+#define atomic64_read(v)	(*(volatile long *)&(v)->counter)
+
+/*
+ * atomic64_set - set atomic variable
+ * @v: pointer of type atomic64_t
+ * @i: required value
+ */
+#define atomic64_set(v, i)	((v)->counter = (i))
+
+/*
+ * atomic64_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __inline__ void atomic64_add(long i, atomic64_t * v)
+{
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%0, %1		# atomic64_add		\n"
+		"	daddu	%0, %2					\n"
+		"	scd	%0, %1					\n"
+		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	} else if (kernel_uses_llsc) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%0, %1		# atomic64_add		\n"
+		"	daddu	%0, %2					\n"
+		"	scd	%0, %1					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	} else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		v->counter += i;
+		raw_local_irq_restore(flags);
+	}
+}
+
+/*
+ * atomic64_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+static __inline__ void atomic64_sub(long i, atomic64_t * v)
+{
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%0, %1		# atomic64_sub		\n"
+		"	dsubu	%0, %2					\n"
+		"	scd	%0, %1					\n"
+		"	beqzl	%0, 1b					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	} else if (kernel_uses_llsc) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%0, %1		# atomic64_sub		\n"
+		"	dsubu	%0, %2					\n"
+		"	scd	%0, %1					\n"
+		"	beqz	%0, 2f					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter));
+	} else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		v->counter -= i;
+		raw_local_irq_restore(flags);
+	}
+}
+
+/*
+ * Same as above, but return the result value
+ */
+static __inline__ long atomic64_add_return(long i, atomic64_t * v)
+{
+	long result;
+
+	smp_mb__before_llsc();
+
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%1, %2		# atomic64_add_return	\n"
+		"	daddu	%0, %1, %3				\n"
+		"	scd	%0, %2					\n"
+		"	beqzl	%0, 1b					\n"
+		"	daddu	%0, %1, %3				\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else if (kernel_uses_llsc) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%1, %2		# atomic64_add_return	\n"
+		"	daddu	%0, %1, %3				\n"
+		"	scd	%0, %2					\n"
+		"	beqz	%0, 2f					\n"
+		"	daddu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		result = v->counter;
+		result += i;
+		v->counter = result;
+		raw_local_irq_restore(flags);
+	}
+
+	smp_llsc_mb();
+
+	return result;
+}
+
+static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
+{
+	long result;
+
+	smp_mb__before_llsc();
+
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%1, %2		# atomic64_sub_return	\n"
+		"	dsubu	%0, %1, %3				\n"
+		"	scd	%0, %2					\n"
+		"	beqzl	%0, 1b					\n"
+		"	dsubu	%0, %1, %3				\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else if (kernel_uses_llsc) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%1, %2		# atomic64_sub_return	\n"
+		"	dsubu	%0, %1, %3				\n"
+		"	scd	%0, %2					\n"
+		"	beqz	%0, 2f					\n"
+		"	dsubu	%0, %1, %3				\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		result = v->counter;
+		result -= i;
+		v->counter = result;
+		raw_local_irq_restore(flags);
+	}
+
+	smp_llsc_mb();
+
+	return result;
+}
+
+/*
+ * atomic64_sub_if_positive - conditionally subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically test @v and subtract @i if @v is greater or equal than @i.
+ * The function returns the old value of @v minus @i.
+ */
+static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
+{
+	long result;
+
+	smp_mb__before_llsc();
+
+	if (kernel_uses_llsc && R10000_LLSC_WAR) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
+		"	dsubu	%0, %1, %3				\n"
+		"	bltz	%0, 1f					\n"
+		"	scd	%0, %2					\n"
+		"	.set	noreorder				\n"
+		"	beqzl	%0, 1b					\n"
+		"	 dsubu	%0, %1, %3				\n"
+		"	.set	reorder					\n"
+		"1:							\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else if (kernel_uses_llsc) {
+		long temp;
+
+		__asm__ __volatile__(
+		"	.set	mips3					\n"
+		"1:	lld	%1, %2		# atomic64_sub_if_positive\n"
+		"	dsubu	%0, %1, %3				\n"
+		"	bltz	%0, 1f					\n"
+		"	scd	%0, %2					\n"
+		"	.set	noreorder				\n"
+		"	beqz	%0, 2f					\n"
+		"	 dsubu	%0, %1, %3				\n"
+		"	.set	reorder					\n"
+		"	.subsection 2					\n"
+		"2:	b	1b					\n"
+		"	.previous					\n"
+		"1:							\n"
+		"	.set	mips0					\n"
+		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
+		: "Ir" (i), "m" (v->counter)
+		: "memory");
+	} else {
+		unsigned long flags;
+
+		raw_local_irq_save(flags);
+		result = v->counter;
+		result -= i;
+		if (result >= 0)
+			v->counter = result;
+		raw_local_irq_restore(flags);
+	}
+
+	smp_llsc_mb();
+
+	return result;
+}
+
+#define atomic64_cmpxchg(v, o, n) \
+	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new)))
+
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+	long c, old;
+	c = atomic64_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic64_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
+#define atomic64_dec_return(v) atomic64_sub_return(1, (v))
+#define atomic64_inc_return(v) atomic64_add_return(1, (v))
+
+/*
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic64_sub_and_test(i, v) (atomic64_sub_return((i), (v)) == 0)
+
+/*
+ * atomic64_inc_and_test - increment and test
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
+
+/*
+ * atomic64_dec_and_test - decrement by 1 and test
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+#define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
+
+/*
+ * atomic64_dec_if_positive - decrement by 1 if old value positive
+ * @v: pointer of type atomic64_t
+ */
+#define atomic64_dec_if_positive(v)	atomic64_sub_if_positive(1, v)
+
+/*
+ * atomic64_inc - increment atomic variable
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic64_inc(v) atomic64_add(1, (v))
+
+/*
+ * atomic64_dec - decrement and test
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic64_dec(v) atomic64_sub(1, (v))
+
+/*
+ * atomic64_add_negative - add and test if negative
+ * @v: pointer of type atomic64_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0)
+
+#else /* !CONFIG_64BIT */
+
+//#include <asm-generic/atomic64.h>
+
+#endif /* CONFIG_64BIT */
+
+/*
+ * atomic*_return operations are serializing but not the non-*_return
+ * versions.
+ */
+#define smp_mb__before_atomic_dec()	smp_mb__before_llsc()
+#define smp_mb__after_atomic_dec()	smp_llsc_mb()
+#define smp_mb__before_atomic_inc()	smp_mb__before_llsc()
+#define smp_mb__after_atomic_inc()	smp_llsc_mb()
+
+#include <asm-generic/atomic-long.h>
+
+#endif /* _ASM_ATOMIC_H */
diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bc5b497383f3d025989c32f6928a90d3888460c
--- /dev/null
+++ b/arch/mips/include/asm/mipsmtregs.h
@@ -0,0 +1,395 @@
+/*
+ * MT regs definitions, follows on from mipsregs.h
+ * Copyright (C) 2004 - 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Elizabeth Clarke et. al.
+ *
+ */
+#ifndef _ASM_MIPSMTREGS_H
+#define _ASM_MIPSMTREGS_H
+
+#include <asm/mipsregs.h>
+/* #include <asm/war.h> */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * C macros
+ */
+
+#define read_c0_mvpcontrol()		__read_32bit_c0_register($0, 1)
+#define write_c0_mvpcontrol(val)	__write_32bit_c0_register($0, 1, val)
+
+#define read_c0_mvpconf0()		__read_32bit_c0_register($0, 2)
+#define read_c0_mvpconf1()		__read_32bit_c0_register($0, 3)
+
+#define read_c0_vpecontrol()		__read_32bit_c0_register($1, 1)
+#define write_c0_vpecontrol(val)	__write_32bit_c0_register($1, 1, val)
+
+#define read_c0_vpeconf0()		__read_32bit_c0_register($1, 2)
+#define write_c0_vpeconf0(val)		__write_32bit_c0_register($1, 2, val)
+
+#define read_c0_tcstatus()		__read_32bit_c0_register($2, 1)
+#define write_c0_tcstatus(val)		__write_32bit_c0_register($2, 1, val)
+
+#define read_c0_tcbind()		__read_32bit_c0_register($2, 2)
+
+#define read_c0_tccontext()		__read_32bit_c0_register($2, 5)
+#define write_c0_tccontext(val)		__write_32bit_c0_register($2, 5, val)
+
+#else /* Assembly */
+/*
+ * Macros for use in assembly language code
+ */
+
+#define CP0_MVPCONTROL		$0, 1
+#define CP0_MVPCONF0		$0, 2
+#define CP0_MVPCONF1		$0, 3
+#define CP0_VPECONTROL		$1, 1
+#define CP0_VPECONF0		$1, 2
+#define CP0_VPECONF1		$1, 3
+#define CP0_YQMASK		$1, 4
+#define CP0_VPESCHEDULE	$1, 5
+#define CP0_VPESCHEFBK		$1, 6
+#define CP0_TCSTATUS		$2, 1
+#define CP0_TCBIND		$2, 2
+#define CP0_TCRESTART		$2, 3
+#define CP0_TCHALT		$2, 4
+#define CP0_TCCONTEXT		$2, 5
+#define CP0_TCSCHEDULE		$2, 6
+#define CP0_TCSCHEFBK		$2, 7
+#define CP0_SRSCONF0		$6, 1
+#define CP0_SRSCONF1		$6, 2
+#define CP0_SRSCONF2		$6, 3
+#define CP0_SRSCONF3		$6, 4
+#define CP0_SRSCONF4		$6, 5
+
+#endif
+
+/* MVPControl fields */
+#define MVPCONTROL_EVP		(_ULCAST_(1))
+
+#define MVPCONTROL_VPC_SHIFT	1
+#define MVPCONTROL_VPC		(_ULCAST_(1) << MVPCONTROL_VPC_SHIFT)
+
+#define MVPCONTROL_STLB_SHIFT	2
+#define MVPCONTROL_STLB		(_ULCAST_(1) << MVPCONTROL_STLB_SHIFT)
+
+
+/* MVPConf0 fields */
+#define MVPCONF0_PTC_SHIFT	0
+#define MVPCONF0_PTC		( _ULCAST_(0xff))
+#define MVPCONF0_PVPE_SHIFT	10
+#define MVPCONF0_PVPE		( _ULCAST_(0xf) << MVPCONF0_PVPE_SHIFT)
+#define MVPCONF0_TCA_SHIFT	15
+#define MVPCONF0_TCA		( _ULCAST_(1) << MVPCONF0_TCA_SHIFT)
+#define MVPCONF0_PTLBE_SHIFT	16
+#define MVPCONF0_PTLBE		(_ULCAST_(0x3ff) << MVPCONF0_PTLBE_SHIFT)
+#define MVPCONF0_TLBS_SHIFT	29
+#define MVPCONF0_TLBS		(_ULCAST_(1) << MVPCONF0_TLBS_SHIFT)
+#define MVPCONF0_M_SHIFT	31
+#define MVPCONF0_M		(_ULCAST_(0x1) << MVPCONF0_M_SHIFT)
+
+
+/* config3 fields */
+#define CONFIG3_MT_SHIFT	2
+#define CONFIG3_MT		(_ULCAST_(1) << CONFIG3_MT_SHIFT)
+
+
+/* VPEControl fields (per VPE) */
+#define VPECONTROL_TARGTC	(_ULCAST_(0xff))
+
+#define VPECONTROL_TE_SHIFT	15
+#define VPECONTROL_TE		(_ULCAST_(1) << VPECONTROL_TE_SHIFT)
+#define VPECONTROL_EXCPT_SHIFT	16
+#define VPECONTROL_EXCPT	(_ULCAST_(0x7) << VPECONTROL_EXCPT_SHIFT)
+
+/* Thread Exception Codes for EXCPT field */
+#define THREX_TU		0
+#define THREX_TO		1
+#define THREX_IYQ		2
+#define THREX_GSX		3
+#define THREX_YSCH		4
+#define THREX_GSSCH		5
+
+#define VPECONTROL_GSI_SHIFT	20
+#define VPECONTROL_GSI		(_ULCAST_(1) << VPECONTROL_GSI_SHIFT)
+#define VPECONTROL_YSI_SHIFT	21
+#define VPECONTROL_YSI		(_ULCAST_(1) << VPECONTROL_YSI_SHIFT)
+
+/* VPEConf0 fields (per VPE) */
+#define VPECONF0_VPA_SHIFT	0
+#define VPECONF0_VPA		(_ULCAST_(1) << VPECONF0_VPA_SHIFT)
+#define VPECONF0_MVP_SHIFT	1
+#define VPECONF0_MVP		(_ULCAST_(1) << VPECONF0_MVP_SHIFT)
+#define VPECONF0_XTC_SHIFT	21
+#define VPECONF0_XTC		(_ULCAST_(0xff) << VPECONF0_XTC_SHIFT)
+
+/* TCStatus fields (per TC) */
+#define TCSTATUS_TASID		(_ULCAST_(0xff))
+#define TCSTATUS_IXMT_SHIFT	10
+#define TCSTATUS_IXMT		(_ULCAST_(1) << TCSTATUS_IXMT_SHIFT)
+#define TCSTATUS_TKSU_SHIFT	11
+#define TCSTATUS_TKSU		(_ULCAST_(3) << TCSTATUS_TKSU_SHIFT)
+#define TCSTATUS_A_SHIFT	13
+#define TCSTATUS_A		(_ULCAST_(1) << TCSTATUS_A_SHIFT)
+#define TCSTATUS_DA_SHIFT	15
+#define TCSTATUS_DA		(_ULCAST_(1) << TCSTATUS_DA_SHIFT)
+#define TCSTATUS_DT_SHIFT	20
+#define TCSTATUS_DT		(_ULCAST_(1) << TCSTATUS_DT_SHIFT)
+#define TCSTATUS_TDS_SHIFT	21
+#define TCSTATUS_TDS		(_ULCAST_(1) << TCSTATUS_TDS_SHIFT)
+#define TCSTATUS_TSST_SHIFT	22
+#define TCSTATUS_TSST		(_ULCAST_(1) << TCSTATUS_TSST_SHIFT)
+#define TCSTATUS_RNST_SHIFT	23
+#define TCSTATUS_RNST		(_ULCAST_(3) << TCSTATUS_RNST_SHIFT)
+/* Codes for RNST */
+#define TC_RUNNING		0
+#define TC_WAITING		1
+#define TC_YIELDING		2
+#define TC_GATED		3
+
+#define TCSTATUS_TMX_SHIFT	27
+#define TCSTATUS_TMX		(_ULCAST_(1) << TCSTATUS_TMX_SHIFT)
+/* TCStatus TCU bits can use same definitions/offsets as CU bits in Status */
+
+/* TCBind */
+#define TCBIND_CURVPE_SHIFT	0
+#define TCBIND_CURVPE		(_ULCAST_(0xf))
+
+#define TCBIND_CURTC_SHIFT	21
+
+#define TCBIND_CURTC		(_ULCAST_(0xff) << TCBIND_CURTC_SHIFT)
+
+/* TCHalt */
+#define TCHALT_H		(_ULCAST_(1))
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned int dvpe(void)
+{
+	int res = 0;
+
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	noreorder					\n"
+	"	.set	noat						\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41610001		# dvpe $1		\n"
+	"	move	%0, $1						\n"
+	"	ehb							\n"
+	"	.set	pop						\n"
+	: "=r" (res));
+
+	instruction_hazard();
+
+	return res;
+}
+
+static inline void __raw_evpe(void)
+{
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	noreorder					\n"
+	"	.set	noat						\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41600021		# evpe			\n"
+	"	ehb							\n"
+	"	.set	pop						\n");
+}
+
+/* Enable virtual processor execution if previous suggested it should be.
+   EVPE_ENABLE to force */
+
+#define EVPE_ENABLE MVPCONTROL_EVP
+
+static inline void evpe(int previous)
+{
+	if ((previous & MVPCONTROL_EVP))
+		__raw_evpe();
+}
+
+static inline unsigned int dmt(void)
+{
+	int res;
+
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	mips32r2					\n"
+	"	.set	noat						\n"
+	"	.word	0x41610BC1			# dmt $1	\n"
+	"	ehb							\n"
+	"	move	%0, $1						\n"
+	"	.set	pop						\n"
+	: "=r" (res));
+
+	instruction_hazard();
+
+	return res;
+}
+
+static inline void __raw_emt(void)
+{
+	__asm__ __volatile__(
+	"	.set	noreorder					\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41600be1			# emt		\n"
+	"	ehb							\n"
+	"	.set	mips0						\n"
+	"	.set	reorder");
+}
+
+/* enable multi-threaded execution if previous suggested it should be.
+   EMT_ENABLE to force */
+
+#define EMT_ENABLE VPECONTROL_TE
+
+static inline void emt(int previous)
+{
+	if ((previous & EMT_ENABLE))
+		__raw_emt();
+}
+
+static inline void ehb(void)
+{
+	__asm__ __volatile__(
+	"	.set	mips32r2				\n"
+	"	ehb						\n"
+	"	.set	mips0					\n");
+}
+
+#define mftc0(rt,sel)							\
+({									\
+	 unsigned long  __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	# mftc0	$1, $" #rt ", " #sel "			\n"	\
+	"	.word	0x41000800 | (" #rt " << 16) | " #sel "	\n"	\
+	"	move	%0, $1					\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mftgpr(rt)							\
+({									\
+	unsigned long __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	# mftgpr $1," #rt "				\n"	\
+	"	.word	0x41000820 | (" #rt " << 16)		\n"	\
+	"	move	%0, $1					\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mftr(rt, u, sel)							\
+({									\
+	unsigned long __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	mftr	%0, " #rt ", " #u ", " #sel "		\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mttgpr(rd,v)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttgpr $1, " #rd "				\n"	\
+	"	.word	0x41810020 | (" #rd " << 11)		\n"	\
+	"	.set	pop					\n"	\
+	: : "r" (v));							\
+} while (0)
+
+#define mttc0(rd, sel, v)							\
+({									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttc0 %0," #rd ", " #sel "			\n"	\
+	"	.word	0x41810000 | (" #rd " << 11) | " #sel "	\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (v));							\
+})
+
+
+#define mttr(rd, u, sel, v)						\
+({									\
+	__asm__ __volatile__(						\
+	"mttr	%0," #rd ", " #u ", " #sel				\
+	: : "r" (v));							\
+})
+
+
+#define settc(tc)							\
+do {									\
+	write_c0_vpecontrol((read_c0_vpecontrol()&~VPECONTROL_TARGTC) | (tc)); \
+	ehb();								\
+} while (0)
+
+
+/* you *must* set the target tc (settc) before trying to use these */
+#define read_vpe_c0_vpecontrol()	mftc0(1, 1)
+#define write_vpe_c0_vpecontrol(val)	mttc0(1, 1, val)
+#define read_vpe_c0_vpeconf0()		mftc0(1, 2)
+#define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val)
+#define read_vpe_c0_count()		mftc0(9, 0)
+#define write_vpe_c0_count(val)		mttc0(9, 0, val)
+#define read_vpe_c0_status()		mftc0(12, 0)
+#define write_vpe_c0_status(val)	mttc0(12, 0, val)
+#define read_vpe_c0_cause()		mftc0(13, 0)
+#define write_vpe_c0_cause(val)		mttc0(13, 0, val)
+#define read_vpe_c0_config()		mftc0(16, 0)
+#define write_vpe_c0_config(val)	mttc0(16, 0, val)
+#define read_vpe_c0_config1()		mftc0(16, 1)
+#define write_vpe_c0_config1(val)	mttc0(16, 1, val)
+#define read_vpe_c0_config7()		mftc0(16, 7)
+#define write_vpe_c0_config7(val)	mttc0(16, 7, val)
+#define read_vpe_c0_ebase()		mftc0(15, 1)
+#define write_vpe_c0_ebase(val)		mttc0(15, 1, val)
+#define write_vpe_c0_compare(val)	mttc0(11, 0, val)
+#define read_vpe_c0_badvaddr()		mftc0(8, 0)
+#define read_vpe_c0_epc()		mftc0(14, 0)
+#define write_vpe_c0_epc(val)		mttc0(14, 0, val)
+
+
+/* TC */
+#define read_tc_c0_tcstatus()		mftc0(2, 1)
+#define write_tc_c0_tcstatus(val)	mttc0(2, 1, val)
+#define read_tc_c0_tcbind()		mftc0(2, 2)
+#define write_tc_c0_tcbind(val)		mttc0(2, 2, val)
+#define read_tc_c0_tcrestart()		mftc0(2, 3)
+#define write_tc_c0_tcrestart(val)	mttc0(2, 3, val)
+#define read_tc_c0_tchalt()		mftc0(2, 4)
+#define write_tc_c0_tchalt(val)		mttc0(2, 4, val)
+#define read_tc_c0_tccontext()		mftc0(2, 5)
+#define write_tc_c0_tccontext(val)	mttc0(2, 5, val)
+
+/* GPR */
+#define read_tc_gpr_sp()		mftgpr(29)
+#define write_tc_gpr_sp(val)		mttgpr(29, val)
+#define read_tc_gpr_gp()		mftgpr(28)
+#define write_tc_gpr_gp(val)		mttgpr(28, val)
+
+__BUILD_SET_C0(mvpcontrol)
+
+#endif /* Not __ASSEMBLY__ */
+
+#endif
diff --git a/arch/mips/include/asm/war.h b/arch/mips/include/asm/war.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa133c1bc1f962796d88ab99ff695a13a3956303
--- /dev/null
+++ b/arch/mips/include/asm/war.h
@@ -0,0 +1,244 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle
+ * Copyright (C) 2007  Maciej W. Rozycki
+ */
+#ifndef _ASM_WAR_H
+#define _ASM_WAR_H
+
+#include <war.h>
+
+/*
+ * Work around certain R4000 CPU errata (as implemented by GCC):
+ *
+ * - A double-word or a variable shift may give an incorrect result
+ *   if executed immediately after starting an integer division:
+ *   "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0",
+ *   erratum #28
+ *   "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum
+ *   #19
+ *
+ * - A double-word or a variable shift may give an incorrect result
+ *   if executed while an integer multiplication is in progress:
+ *   "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0",
+ *   errata #16 & #28
+ *
+ * - An integer division may give an incorrect result if started in
+ *   a delay slot of a taken branch or a jump:
+ *   "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0",
+ *   erratum #52
+ */
+#ifdef CONFIG_CPU_R4000_WORKAROUNDS
+#define R4000_WAR 1
+#else
+#define R4000_WAR 0
+#endif
+
+/*
+ * Work around certain R4400 CPU errata (as implemented by GCC):
+ *
+ * - A double-word or a variable shift may give an incorrect result
+ *   if executed immediately after starting an integer division:
+ *   "MIPS R4400MC Errata, Processor Revision 1.0", erratum #10
+ *   "MIPS R4400MC Errata, Processor Revision 2.0 & 3.0", erratum #4
+ */
+#ifdef CONFIG_CPU_R4400_WORKAROUNDS
+#define R4400_WAR 1
+#else
+#define R4400_WAR 0
+#endif
+
+/*
+ * Work around the "daddi" and "daddiu" CPU errata:
+ *
+ * - The `daddi' instruction fails to trap on overflow.
+ *   "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0",
+ *   erratum #23
+ *
+ * - The `daddiu' instruction can produce an incorrect result.
+ *   "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0",
+ *   erratum #41
+ *   "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum
+ *   #15
+ *   "MIPS R4400PC/SC Errata, Processor Revision 1.0", erratum #7
+ *   "MIPS R4400MC Errata, Processor Revision 1.0", erratum #5
+ */
+#ifdef CONFIG_CPU_DADDI_WORKAROUNDS
+#define DADDI_WAR 1
+#else
+#define DADDI_WAR 0
+#endif
+
+/*
+ * Another R4600 erratum.  Due to the lack of errata information the exact
+ * technical details aren't known.  I've experimentally found that disabling
+ * interrupts during indexed I-cache flushes seems to be sufficient to deal
+ * with the issue.
+ */
+#ifndef R4600_V1_INDEX_ICACHEOP_WAR
+#error Check setting of R4600_V1_INDEX_ICACHEOP_WAR for your platform
+#endif
+
+/*
+ * Pleasures of the R4600 V1.x.  Cite from the IDT R4600 V1.7 errata:
+ *
+ *  18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D,
+ *      Hit_Invalidate_D and Create_Dirty_Excl_D should only be
+ *      executed if there is no other dcache activity. If the dcache is
+ *      accessed for another instruction immeidately preceding when these
+ *      cache instructions are executing, it is possible that the dcache
+ *      tag match outputs used by these cache instructions will be
+ *      incorrect. These cache instructions should be preceded by at least
+ *      four instructions that are not any kind of load or store
+ *      instruction.
+ *
+ *      This is not allowed:    lw
+ *                              nop
+ *                              nop
+ *                              nop
+ *                              cache       Hit_Writeback_Invalidate_D
+ *
+ *      This is allowed:        lw
+ *                              nop
+ *                              nop
+ *                              nop
+ *                              nop
+ *                              cache       Hit_Writeback_Invalidate_D
+ */
+#ifndef R4600_V1_HIT_CACHEOP_WAR
+#error Check setting of R4600_V1_HIT_CACHEOP_WAR for your platform
+#endif
+
+
+/*
+ * Writeback and invalidate the primary cache dcache before DMA.
+ *
+ * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D,
+ * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Exclusive_D will only
+ * operate correctly if the internal data cache refill buffer is empty.  These
+ * CACHE instructions should be separated from any potential data cache miss
+ * by a load instruction to an uncached address to empty the response buffer."
+ * (Revision 2.0 device errata from IDT available on http://www.idt.com/
+ * in .pdf format.)
+ */
+#ifndef R4600_V2_HIT_CACHEOP_WAR
+#error Check setting of R4600_V2_HIT_CACHEOP_WAR for your platform
+#endif
+
+/*
+ * When an interrupt happens on a CP0 register read instruction, CPU may
+ * lock up or read corrupted values of CP0 registers after it enters
+ * the exception handler.
+ *
+ * This workaround makes sure that we read a "safe" CP0 register as the
+ * first thing in the exception handler, which breaks one of the
+ * pre-conditions for this problem.
+ */
+#ifndef R5432_CP0_INTERRUPT_WAR
+#error Check setting of R5432_CP0_INTERRUPT_WAR for your platform
+#endif
+
+/*
+ * Workaround for the Sibyte M3 errata the text of which can be found at
+ *
+ *   http://sibyte.broadcom.com/hw/bcm1250/docs/pass2errata.txt
+ *
+ * This will enable the use of a special TLB refill handler which does a
+ * consistency check on the information in c0_badvaddr and c0_entryhi and
+ * will just return and take the exception again if the information was
+ * found to be inconsistent.
+ */
+#ifndef BCM1250_M3_WAR
+#error Check setting of BCM1250_M3_WAR for your platform
+#endif
+
+/*
+ * This is a DUART workaround related to glitches around register accesses
+ */
+#ifndef SIBYTE_1956_WAR
+#error Check setting of SIBYTE_1956_WAR for your platform
+#endif
+
+/*
+ * Fill buffers not flushed on CACHE instructions
+ *
+ * Hit_Invalidate_I cacheops invalidate an icache line but the refill
+ * for that line can get stale data from the fill buffer instead of
+ * accessing memory if the previous icache miss was also to that line.
+ *
+ * Workaround: generate an icache refill from a different line
+ *
+ * Affects:
+ *  MIPS 4K		RTL revision <3.0, PRID revision <4
+ */
+#ifndef MIPS4K_ICACHE_REFILL_WAR
+#error Check setting of MIPS4K_ICACHE_REFILL_WAR for your platform
+#endif
+
+/*
+ * Missing implicit forced flush of evictions caused by CACHE
+ * instruction
+ *
+ * Evictions caused by a CACHE instructions are not forced on to the
+ * bus. The BIU gives higher priority to fetches than to the data from
+ * the eviction buffer and no collision detection is performed between
+ * fetches and pending data from the eviction buffer.
+ *
+ * Workaround: Execute a SYNC instruction after the cache instruction
+ *
+ * Affects:
+ *   MIPS 5Kc,5Kf	RTL revision <2.3, PRID revision <8
+ *   MIPS 20Kc		RTL revision <4.0, PRID revision <?
+ */
+#ifndef MIPS_CACHE_SYNC_WAR
+#error Check setting of MIPS_CACHE_SYNC_WAR for your platform
+#endif
+
+/*
+ * From TX49/H2 manual: "If the instruction (i.e. CACHE) is issued for
+ * the line which this instruction itself exists, the following
+ * operation is not guaranteed."
+ *
+ * Workaround: do two phase flushing for Index_Invalidate_I
+ */
+#ifndef TX49XX_ICACHE_INDEX_INV_WAR
+#error Check setting of TX49XX_ICACHE_INDEX_INV_WAR for your platform
+#endif
+
+/*
+ * On the RM9000 there is a problem which makes the CreateDirtyExclusive
+ * eache operation unusable on SMP systems.
+ */
+#ifndef RM9000_CDEX_SMP_WAR
+#error Check setting of RM9000_CDEX_SMP_WAR for your platform
+#endif
+
+/*
+ * The RM7000 processors and the E9000 cores have a bug (though PMC-Sierra
+ * opposes it being called that) where invalid instructions in the same
+ * I-cache line worth of instructions being fetched may case spurious
+ * exceptions.
+ */
+#ifndef ICACHE_REFILLS_WORKAROUND_WAR
+#error Check setting of ICACHE_REFILLS_WORKAROUND_WAR for your platform
+#endif
+
+/*
+ * On the R10000 up to version 2.6 (not sure about 2.7) there is a bug that
+ * may cause ll / sc and lld / scd sequences to execute non-atomically.
+ */
+#ifndef R10000_LLSC_WAR
+#error Check setting of R10000_LLSC_WAR for your platform
+#endif
+
+/*
+ * 34K core erratum: "Problems Executing the TLBR Instruction"
+ */
+#ifndef MIPS34K_MISSED_ITLB_WAR
+#error Check setting of MIPS34K_MISSED_ITLB_WAR for your platform
+#endif
+
+#endif /* _ASM_WAR_H */
diff --git a/board/inteno/ex300/Kconfig b/board/inteno/ex300/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..1bb23324283c2afc135a13e13831b6c4f419f52f
--- /dev/null
+++ b/board/inteno/ex300/Kconfig
@@ -0,0 +1,11 @@
+if TARGET_EX300
+
+config SYS_BOARD
+	default "ex300"
+
+config SYS_VENDOR
+	default "inteno"
+
+config SYS_CONFIG_NAME
+	default "ex300"
+endif
diff --git a/board/inteno/ex300/Makefile b/board/inteno/ex300/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c21fba5a06a94f2c8e1c7fd06395fc922a4f2f0b
--- /dev/null
+++ b/board/inteno/ex300/Makefile
@@ -0,0 +1,10 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	= board.o
+obj-y  += lowlevel_init.o
+
diff --git a/board/inteno/ex300/board.c b/board/inteno/ex300/board.c
new file mode 100644
index 0000000000000000000000000000000000000000..2fb009371b51fcf1d305427c0eb8e066076522d3
--- /dev/null
+++ b/board/inteno/ex300/board.c
@@ -0,0 +1,228 @@
+
+#include <common.h>
+#include "serial.h"
+#include "rt_mmap.h"
+
+#define RALINK_REG(x)		(*((volatile u32 *)(x)))
+
+/* running in DRAM(flash) not relocated */
+int board_early_init_f(void)
+{
+	u32 value;
+	u32 fdiv = 0, frac = 0, i;
+
+	value = le32_to_cpu(*(volatile u_long *)(RALINK_SPI_BASE + 0x3c));
+	value &= ~(0xFFF);
+	value |= 5; //work-around 3-wire SPI issue (3 for RFB, 5 for EVB)
+	*(volatile u_long *)(RALINK_SPI_BASE + 0x3c) = cpu_to_le32(value);
+
+	value = RALINK_REG(RALINK_CUR_CLK_STS_REG);
+	fdiv = ((value>>8)&0x1F);
+	frac = (unsigned long)(value&0x1F);
+
+	i = 0;
+
+	while(frac < fdiv) {
+		value = RALINK_REG(RALINK_DYN_CFG0_REG);
+		fdiv = ((value>>8)&0x0F);
+		fdiv--;
+		value &= ~(0x0F<<8);
+		value |= (fdiv<<8);
+		RALINK_REG(RALINK_DYN_CFG0_REG) = value;
+		udelay(500);
+		i++;
+		value = RALINK_REG(RALINK_CUR_CLK_STS_REG);
+		fdiv = ((value>>8)&0x1F);
+		frac = (unsigned long)(value&0x1F);
+	}
+
+ 	//change CPLL from GPLL to MEMPLL
+	value = RALINK_REG(RALINK_CLKCFG0_REG);
+	value &= ~(0x3<<30);
+	value |= (0x1<<30);
+	RALINK_REG(RALINK_CLKCFG0_REG) = value;
+
+	/* make sure DMA has access to dram */
+	value = RALINK_REG(RALINK_DMA_ARB_BASE + 0xc);
+	value &= ~(0x1);
+	RALINK_REG(RALINK_DMA_ARB_BASE + 0xc) = value;
+
+
+	return 0;
+}
+
+#define RT2880_PRGIO_ADDR       (RALINK_SYSCTL_BASE + 0x600) // Programmable I/O
+#define RT2880_REG_PIOINT       (RT2880_PRGIO_ADDR + 0x90)
+#define RT2880_REG_PIOEDGE      (RT2880_PRGIO_ADDR + 0xA0)
+#define RT2880_REG_PIORENA      (RT2880_PRGIO_ADDR + 0x50)
+#define RT2880_REG_PIOFENA      (RT2880_PRGIO_ADDR + 0x60)
+#define RT2880_REG_PIODATA      (RT2880_PRGIO_ADDR + 0x20)
+#define RT2880_REG_PIODIR       (RT2880_PRGIO_ADDR + 0x00)
+#define RT2880_REG_PIOSET       (RT2880_PRGIO_ADDR + 0x30)
+#define RT2880_REG_PIORESET     (RT2880_PRGIO_ADDR + 0x40)
+
+
+
+void _machine_restart(void)
+{
+	void __iomem *reset_base;
+
+	reset_base = (void __iomem *)CKSEG1ADDR(RT2880_RSTCTRL_REG);
+	__raw_writel(0x1, reset_base);
+	mdelay(1000);
+}
+
+
+void trigger_hw_reset(void)
+{
+
+	printf("BUG: we are supposed to do some reset here.!\n");
+
+#ifdef GPIO14_RESET_MODE
+        //set GPIO14 as output to trigger hw reset circuit
+        RALINK_REG(RT2880_REG_PIODIR)|=1<<14; //output mode
+
+        RALINK_REG(RT2880_REG_PIODATA)|=1<<14; //pull high
+	udelay(100);
+        RALINK_REG(RT2880_REG_PIODATA)&=~(1<<14); //pull low
+#endif
+}
+
+
+void config_usb_mtk_xhci(void)
+{
+        u32     regValue;
+
+        regValue = RALINK_REG(RALINK_SYSCTL_BASE + 0x10);
+        regValue = (regValue >> 6) & 0x7;
+        if(regValue >= 6) { //25Mhz Xtal
+                printf("\nConfig XHCI 25M PLL \n");
+                RALINK_REG(0xbe1d0784) = 0x20201a;
+                RALINK_REG(0xbe1d0c20) = 0x80004;
+                RALINK_REG(0xbe1d0c1c) = 0x18181819;
+                RALINK_REG(0xbe1d0c24) = 0x18000000;
+                RALINK_REG(0xbe1d0c38) = 0x25004a;
+                RALINK_REG(0xbe1d0c40) = 0x48004a;
+                RALINK_REG(0xbe1d0b24) = 0x190;
+                RALINK_REG(0xbe1d0b10) = 0x1c000000;
+                RALINK_REG(0xbe1d0b04) = 0x20000004;
+                RALINK_REG(0xbe1d0b08) = 0xf203200;
+
+                RALINK_REG(0xbe1d0b2c) = 0x1400028;
+                //RALINK_REG(0xbe1d0a30) =;
+                RALINK_REG(0xbe1d0a40) = 0xffff0001;
+                RALINK_REG(0xbe1d0a44) = 0x60001;
+        } else if (regValue >=3 ) { // 40 Mhz
+                printf("\nConfig XHCI 40M PLL \n");
+                RALINK_REG(0xbe1d0784) = 0x20201a;
+                RALINK_REG(0xbe1d0c20) = 0x80104;
+                RALINK_REG(0xbe1d0c1c) = 0x1818181e;
+                RALINK_REG(0xbe1d0c24) = 0x1e400000;
+                RALINK_REG(0xbe1d0c38) = 0x250073;
+                RALINK_REG(0xbe1d0c40) = 0x71004a;
+                RALINK_REG(0xbe1d0b24) = 0x140;
+                RALINK_REG(0xbe1d0b10) = 0x23800000;
+                RALINK_REG(0xbe1d0b04) = 0x20000005;
+                RALINK_REG(0xbe1d0b08) = 0x12203200;
+        
+                RALINK_REG(0xbe1d0b2c) = 0x1400028;
+                //RALINK_REG(0xbe1d0a30) =;
+                RALINK_REG(0xbe1d0a40) = 0xffff0001;
+                RALINK_REG(0xbe1d0a44) = 0x60001;
+        } else { //20Mhz Xtal
+
+                /* TODO */
+
+        }
+}
+
+
+
+/* just for eth driver now. */
+unsigned long mips_bus_feq;
+unsigned long mips_cpu_feq;
+
+/* running in DRAM and relocated */
+int board_early_init_r( void )
+{
+	unsigned int reg;
+
+	reg = RALINK_REG(RALINK_SYSCTL_BASE + 0x2C);
+	if( reg & ((0x1UL) << 30)) {
+		reg = RALINK_REG(RALINK_MEMCTRL_BASE + 0x648);
+		mips_cpu_feq = (((reg >> 4) & 0x7F) + 1) * 1000 * 1000;
+		reg = RALINK_REG(RALINK_SYSCTL_BASE + 0x10);
+		reg = (reg >> 6) & 0x7;
+		if(reg >= 6) { //25Mhz Xtal
+			mips_cpu_feq = mips_cpu_feq * 25;
+		} else if (reg >=3) { //40Mhz Xtal
+			mips_cpu_feq = mips_cpu_feq * 20;
+		} else { //20Mhz Xtal
+			/* TODO */
+		}
+	}else {
+		reg = RALINK_REG(RALINK_SYSCTL_BASE + 0x44);
+		mips_cpu_feq = (500 * (reg & 0x1F) / ((reg >> 8) & 0x1F)) * 1000 * 1000;
+	}
+	mips_bus_feq = mips_cpu_feq/4;
+
+#define RT2880_SYS_CNTL_BASE			(RALINK_SYSCTL_BASE)
+#define RT2880_RSTSTAT_REG			(RT2880_SYS_CNTL_BASE+0x38)
+#define RT2880_WDRST            (1<<1)
+#define RT2880_SWSYSRST         (1<<2)
+#define RT2880_SWCPURST         (1<<3)
+
+
+	reg = RALINK_REG(RT2880_RSTSTAT_REG);
+	if(reg & RT2880_WDRST ){
+		printf("***********************\n");
+		printf("Watchdog Reset Occurred\n");
+		printf("***********************\n");
+		RALINK_REG(RT2880_RSTSTAT_REG)|=RT2880_WDRST;
+		RALINK_REG(RT2880_RSTSTAT_REG)&=~RT2880_WDRST;
+		trigger_hw_reset();
+	}else if(reg & RT2880_SWSYSRST){
+		printf("******************************\n");
+		printf("Software System Reset Occurred\n");
+		printf("******************************\n");
+		RALINK_REG(RT2880_RSTSTAT_REG)|=RT2880_SWSYSRST;
+		RALINK_REG(RT2880_RSTSTAT_REG)&=~RT2880_SWSYSRST;
+		trigger_hw_reset();
+	}else if (reg & RT2880_SWCPURST){
+		printf("***************************\n");
+		printf("Software CPU Reset Occurred\n");
+		printf("***************************\n");
+		RALINK_REG(RT2880_RSTSTAT_REG)|=RT2880_SWCPURST;
+		RALINK_REG(RT2880_RSTSTAT_REG)&=~RT2880_SWCPURST;
+		trigger_hw_reset();
+	}
+
+	config_usb_mtk_xhci();
+
+	return 0;
+
+}
+
+phys_size_t initdram(int board_type)
+{
+	return CONFIG_SYS_MEM_SIZE;
+}
+
+#ifdef  CONFIG_CMD_NET
+
+int rt2880_eth_initialize(bd_t *bis);
+void setup_internal_gsw( void );
+void LANWANPartition(void);
+
+int board_eth_init(bd_t *bis)
+{
+	//enable MDIO
+	RALINK_REG(0xbe000060) &= ~(1 << 12); //set MDIO to Normal mode
+	RALINK_REG(0xbe000060) &= ~(1 << 14); //set RGMII1 to Normal mode
+	RALINK_REG(0xbe000060) &= ~(1 << 15); //set RGMII2 to Normal mode
+	setup_internal_gsw();
+	LANWANPartition();
+
+	return rt2880_eth_initialize(bis);
+}
+#endif
diff --git a/board/inteno/ex300/jtag/ex300.cmm b/board/inteno/ex300/jtag/ex300.cmm
new file mode 100644
index 0000000000000000000000000000000000000000..b9421931f794fdf579bea67c547619514ade78ff
--- /dev/null
+++ b/board/inteno/ex300/jtag/ex300.cmm
@@ -0,0 +1,99 @@
+///////////////////////////////////////////////////////////////////////////////
+// basic cpu config for lauterbach
+// 
+B::RES
+B::SYS.CPU MIPS1004KMT
+//B::sys.jc 25.mhz
+B::sys.jc 75.mhz
+B::SYS.M UP
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Make the internal sram available for the cpu core
+//
+B::DATA.OUT 0xBE100004 %LONG 0x1	//reset PSE SRAM 
+wait 20ms
+B::DATA.OUT 0xBE100004 %LONG 0x6	//full use PSE SRAM
+B::DATA.OUT 0xBE00001C %LONG 0x2	//set ICE_MODE+DDR calibration
+
+
+///////////////////////////////////////////////////////////////////////////////
+// load dram init code into sram and run 
+//
+B::D.LOAD.b ../../../../sram.bin 0xbe108800
+B::B::R.S PC 0xBE108800
+break 0xBE108008 /write /onchip
+go;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// when dram setup remove sram again
+//
+wait !state.run()
+break 0xBE108008 /disable
+DATA.OUT 0xBE100004 %LONG 0x1	//reset PSE SRAM
+
+
+///////////////////////////////////////////////////////////////////////////////
+// load u-boot into dram. 
+//
+B::D.LOAD ../../../../u-boot
+
+
+
+// manual relocate. this is a bit hard to figure out what value to use.
+// atomatic relocate below 
+//sYmbol.RELOCate -10231000
+
+go
+
+//commet this out and compile u-boot with option "#define TRACE32" set in config file.
+//then an infinite loop as added to u-boot. we break the execution and caclulate the
+// offsett to use for symbols 
+
+enddo
+
+///////////////////////////////////////////////////////////////////////////////
+// magic for calculating symbol offset after u-boot relocated itself. 
+/////////////////////////////////////////////////////////////////////
+wait 1s
+break
+
+&x=register(pc)
+&x=&x+4
+Register.Set pc &x
+
+&x=register(r4)
+print "&x"
+&x=-1*&x
+sYmbol.RELOCate &x
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+
+
+// set breakpoint on relocated sysmbols and then run as normal
+
+
+//break mtk_nand_probe
+//break.set load_fact_bbt
+//break.set nand_command
+//break.set nand_do_read_ops
+//break.set nand_scan_ident
+//break.set nand_get_flash_type
+//break.set nand_do_read_ops
+//break.set mtk_nand_read_oob
+//break.set mtk_nand_read_oob_hw
+//break.set mtk_nand_read_oob_raw
+//break.set nand_read_oob
+//break.set mtk_nand_erase
+//break.set rt2880_eth_setup
+//break.set rt2880_eth_init
+//break.set rt2880_eth_send
+//break.set rt2880_eth_recv
+//break.set rt2880_eth_halt
+
+
+
+go
+
diff --git a/board/inteno/ex300/jtag/go b/board/inteno/ex300/jtag/go
new file mode 100755
index 0000000000000000000000000000000000000000..6e0f31f708ae3079e46536a974de4a12442409e3
--- /dev/null
+++ b/board/inteno/ex300/jtag/go
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+export T32SYS=/opt/t32
+export T32TMP=/tmp
+export T32ID=T32
+export T32PDFVIEWER=/opt/t32/_pdfviewer.sh
+
+xset +fp /opt/t32/fonts
+xset fp rehash
+/opt/t32/bin/pc_linux64/t32mips
+
diff --git a/board/inteno/ex300/jtag/mt7621_ref_nand.cmm b/board/inteno/ex300/jtag/mt7621_ref_nand.cmm
new file mode 100644
index 0000000000000000000000000000000000000000..73b7d8b0a662facc7939b7e4fa9447bebe25596e
--- /dev/null
+++ b/board/inteno/ex300/jtag/mt7621_ref_nand.cmm
@@ -0,0 +1,75 @@
+B::RES
+B::SYS.CPU MIPS1004KMT
+;sys.cpu mips1004k
+;sys.config irpre 20.
+;sys.config drpre 4.
+B::SYS.O E Little
+B::sys.jc 25.mhz
+B::SYS.M UP
+
+//enddo
+
+IF 1==0
+(
+GLOBAL &BOOTSTRAP
+GLOBAL &DRAM_TYPE
+GLOBAL &DRAMSPEED
+GLOBAL &XTAL
+GLOBAL &ddr_cfg
+GLOBAL &mempll_cfg
+GLOBAL &MPLL_IN_LBK
+
+&MPLL_IN_LBK=1
+&BOOTSTRAP=D.L(D:0xBE000010)
+&DRAM_TYPE=(&BOOTSTRAP>>4)&0x01
+&XTAL=4
+//(&BOOTSTRAP>>6)&0x7
+
+&mempll_cfg="C:\T32\ICE\mt7621_asic_mpll_xtal40_200.cmm"
+//&mempll_cfg="C:\T32\ICE\mt7621_asic_mpll_xtal40_400.cmm"
+//&mempll_cfg="C:\T32\ICE\mt7621_asic_mpll_xtal40_600.cmm"
+
+IF &DRAM_TYPE==0
+(
+&DRAMSPEED=1200
+&ddr_cfg="C:\T32\ICE\mt7621_asic_ddr3.cmm"
+)
+ELSE
+(
+&DRAMSPEED=800
+&ddr_cfg="C:\T32\ICE\mt7621_asic_ddr2.cmm"
+)
+DO &mempll_cfg
+DO &ddr_cfg
+)
+ELSE
+(
+B::DATA.OUT 0xBE100004 %LONG 0x1	//reset PSE SRAM 
+wait 20ms
+B::DATA.OUT 0xBE100004 %LONG 0x6	//full use PSE SRAM
+B::DATA.OUT 0xBE00001C %LONG 0x2	//set ICE_MODE+DDR calibration
+//B::D.LOAD  x:\Uboot\mt7621_stage_sram.bin 0xbe108800
+
+//B::D.LOAD.b  /home/kenjo/proj/inteno/mediatek/Uboot/mt7621_stage_sram.bin 0xbe108800
+B::D.LOAD.b  /home/kenjo/proj/inteno/mediatek/Uboot/ken.img 0xbe108800
+
+
+
+B::B::R.S PC 0xBE108800
+break 0xBE108008 /write /onchip
+go;
+
+wait !state.run()
+break 0xBE108008 /disable
+DATA.OUT 0xBE100004 %LONG 0x1	//reset PSE SRAM
+
+)
+
+//B::D.LOAD  x:\Uboot\u-boot
+B::D.LOAD /home/kenjo/proj/inteno/mediatek/Uboot/u-boot
+//B::D.LOAD /tmp/mediatek/Uboot/u-boot
+
+go
+
+//send /home/kenjo/proj/inteno/mediatek/Uboot/uboot.img
+//sYmbol.RELOCate -18254000
diff --git a/board/inteno/ex300/lowlevel_init.S b/board/inteno/ex300/lowlevel_init.S
new file mode 100644
index 0000000000000000000000000000000000000000..d11c008fe79657adcc100c730233e7d44a44a4a4
--- /dev/null
+++ b/board/inteno/ex300/lowlevel_init.S
@@ -0,0 +1,12 @@
+
+
+
+	.set noreorder
+	.globl lowlevel_init
+	.text
+lowlevel_init:
+    jr $ra
+	/*b	__reset_vector
+	nop*/
+
+
diff --git a/board/inteno/ex300/rt_mmap.h b/board/inteno/ex300/rt_mmap.h
new file mode 100644
index 0000000000000000000000000000000000000000..8cbcc730cf4b9d2616f3745ee9456b0f10f4c755
--- /dev/null
+++ b/board/inteno/ex300/rt_mmap.h
@@ -0,0 +1,844 @@
+/**************************************************************************
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *     register definition for Ralink RT-series SoC
+ *
+ *  Copyright 2007 Ralink 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 __RALINK_MMAP__
+#define __RALINK_MMAP__
+
+#if defined (RT2880_FPGA_BOARD) || defined (RT2880_ASIC_BOARD)
+
+#ifdef RT2880_SHUTTLE
+
+#define RALINK_SYSCTL_BASE 		0xA0300000
+#define RALINK_TIMER_BASE		0xA0300100
+#define RALINK_INTCL_BASE		0xA0300200
+#define RALINK_MEMCTRL_BASE		0xA0300300
+#define RALINK_UART_BASE		0xA0300500
+#define RALINK_PIO_BASE			0xA0300600
+#define RALINK_I2C_BASE			0xA0300900
+#define RALINK_SPI_BASE			0xA0300B00
+#define RALINK_UART_LITE_BASE		0xA0300C00
+#define RALINK_FRAME_ENGINE_BASE	0xA0310000
+#define RALINK_EMBEDD_ROM_BASE		0xA0400000
+#define RALINK_PCI_BASE			0xA0500000
+#define RALINK_11N_MAC_BASE		0xA0600000
+
+#else // RT2880_MP
+
+#define RALINK_SYSCTL_BASE 		0xA0300000
+#define RALINK_TIMER_BASE		0xA0300100
+#define RALINK_INTCL_BASE		0xA0300200
+#define RALINK_MEMCTRL_BASE		0xA0300300
+#define RALINK_UART_BASE		0xA0300500
+#define RALINK_PIO_BASE			0xA0300600
+#define RALINK_I2C_BASE			0xA0300900
+#define RALINK_SPI_BASE			0xA0300B00
+#define RALINK_UART_LITE_BASE		0x00300C00
+#define RALINK_FRAME_ENGINE_BASE	0xA0400000
+#define RALINK_EMBEDD_ROM_BASE		0xA0410000
+#define RALINK_PCI_BASE			0xA0440000
+#define RALINK_11N_MAC_BASE		0xA0480000
+
+//Interrupt Controller
+#define RALINK_INTCTL_TIMER0		(1<<0)
+#define RALINK_INTCTL_WDTIMER		(1<<1)
+#define RALINK_INTCTL_UART		(1<<2)
+#define RALINK_INTCTL_PIO		(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UARTLITE		(1<<8)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<23)
+
+//Reset Control Register
+#define RALINK_TIMER_RST		(1<<1)
+#define RALINK_INTC_RST			(1<<2)
+#define RALINK_MC_RST			(1<<3)
+#define RALINK_CPU_RST			(1<<4)
+#define RALINK_UART_RST			(1<<5)
+#define RALINK_PIO_RST			(1<<6)
+#define RALINK_I2C_RST			(1<<9)
+#define RALINK_SPI_RST			(1<<11)
+#define RALINK_UART2_RST		(1<<12)
+#define RALINK_PCI_RST			(1<<16)
+#define RALINK_2860_RST			(1<<17)
+#define RALINK_FE_RST			(1<<18)
+#define RALINK_PCM_RST			(1<<19)
+
+#endif
+
+#elif defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD)
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_PCM_BASE			0xB0000400
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_GDMA_BASE		0xB0000700
+#define RALINK_NAND_CTRL_BASE		0xB0000800
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_NAND		(1<<8)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_OTG		(1<<18)
+#define RALINK_INTCTL_OTG_IRQN		18
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_CPU_RST			(1<<1)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_RT2872_RST		(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_OTG_RST			(1<<22)
+#define RALINK_SW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+
+#elif defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN		(1<<20)
+#define RALINK_UPHY0_CLK_EN		(1<<18)
+#define RALINK_GE1_CLK_EN		(1<<16)
+
+
+#elif defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_NAND_CTRL_BASE		0xB0000810
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_PCIE_BASE		0xB0140000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UHST0_RST		(1<<25)
+#define RALINK_UDEV_RST			(1<<25)
+#define RALINK_PCIE0_RST		(1<<26)
+#define RALINK_PCIE1_RST		(1<<27)
+
+//Clock Conf Register
+#define RALINK_UPHY0_CLK_EN		(1<<25)
+
+#elif defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD)
+#define RALINK_SYSCTL_BASE              0xB0000000
+#define RALINK_TIMER_BASE               0xB0000100
+#define RALINK_INTCL_BASE               0xB0000200
+#define RALINK_MEMCTRL_BASE             0xB0000300
+#define RALINK_RBUS_MATRIXCTL_BASE      0xB0000400
+#define RALINK_UART_BASE                0x10000500
+#define RALINK_PIO_BASE                 0xB0000600
+#define RALINK_NAND_CTRL_BASE           0xB0000810
+#define RALINK_I2C_BASE                 0xB0000900
+#define RALINK_I2S_BASE                 0xB0000A00
+#define RALINK_SPI_BASE                 0xB0000B00
+#define RALINK_UART_LITE_BASE           0x10000C00
+#define RALINK_MIPS_CNT_BASE            0x10000D00
+#define RALINK_PCM_BASE                 0xB0002000
+#define RALINK_GDMA_BASE                0xB0002800
+#define RALINK_CRYPTO_ENGING_BASE       0xB0004000
+#define RALINK_FRAME_ENGINE_BASE        0xB0100000
+#define RALINK_ETH_SW_BASE              0xB0110000
+#define RALINK_USB_DEV_BASE             0x10120000
+#define RALINK_MSDC_BASE                0xB0130000
+#define RALINK_PCI_BASE                 0xB0140000
+#define RALINK_11N_MAC_BASE             0xB0180000
+#define RALINK_USB_HOST_BASE            0x101C0000
+
+#define RALINK_MCNT_CFG                 0xB0000D00
+#define RALINK_COMPARE                  0xB0000D04
+#define RALINK_COUNT                    0xB0000D08
+
+#define RALINK_CPLLCFG0_REG		(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG		(RALINK_SYSCTL_BASE+0x58)
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL            (1<<0)
+#define RALINK_INTCTL_TIMER0            (1<<1)
+#define RALINK_INTCTL_WDTIMER           (1<<2)
+#define RALINK_INTCTL_ILL_ACCESS        (1<<3)
+#define RALINK_INTCTL_PCM               (1<<4)
+#define RALINK_INTCTL_UART              (1<<5)
+#define RALINK_INTCTL_PIO               (1<<6)
+#define RALINK_INTCTL_DMA               (1<<7)
+#define RALINK_INTCTL_PC                (1<<9)
+#define RALINK_INTCTL_I2S               (1<<10)
+#define RALINK_INTCTL_SPI               (1<<11)
+#define RALINK_INTCTL_UARTLITE          (1<<12)
+#define RALINK_INTCTL_CRYPTO            (1<<13)
+#define RALINK_INTCTL_ESW               (1<<17)
+#define RALINK_INTCTL_UHST              (1<<18)
+#define RALINK_INTCTL_UDEV              (1<<19)
+#define RALINK_INTCTL_GLOBAL            (1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST                  (1<<0)
+#define RALINK_TIMER_RST                (1<<8)
+#define RALINK_INTC_RST                 (1<<9)
+#define RALINK_MC_RST                   (1<<10)
+#define RALINK_PCM_RST                  (1<<11)
+#define RALINK_UART_RST                 (1<<12)
+#define RALINK_PIO_RST                  (1<<13)
+#define RALINK_DMA_RST                  (1<<14)
+#define RALINK_I2C_RST                  (1<<16)
+#define RALINK_I2S_RST                  (1<<17)
+#define RALINK_SPI_RST                  (1<<18)
+#define RALINK_UARTL_RST                (1<<19)
+#define RALINK_FE_RST                   (1<<21)
+#define RALINK_UHST_RST                 (1<<22)
+#define RALINK_ESW_RST                  (1<<23)
+#define RALINK_EPHY_RST                 (1<<24)
+#define RALINK_UDEV_RST                 (1<<25)
+#define RALINK_PCIE0_RST                (1<<26)
+#define RALINK_PCIE1_RST                (1<<27)
+#define RALINK_MIPS_CNT_RST             (1<<28)
+#define RALINK_CRYPTO_RST               (1<<29)
+
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN     (1<<22)
+#define RALINK_UPHY0_CLK_EN     (1<<25)
+
+#elif defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+
+#define RALINK_SYSCTL_BASE              0xB0000000
+#define RALINK_TIMER_BASE               0xB0000100
+#define RALINK_INTCL_BASE               0xB0000200
+#define RALINK_MEMCTRL_BASE             0xB0000300
+#define RALINK_RBUS_MATRIXCTL_BASE      0xB0000400
+#define RALINK_MIPS_CNT_BASE            0x10000500
+#define RALINK_PIO_BASE                 0xB0000600
+#define RALINK_I2C_BASE                 0xB0000900
+#define RALINK_I2S_BASE                 0xB0000A00
+#define RALINK_SPI_BASE                 0xB0000B00
+#define RALINK_UART_LITE_BASE           0x10000C00
+#define RALINK_UART_LITE2_BASE          0x10000D00
+#define RALINK_UART_LITE3_BASE          0x10000E00
+#define RALINK_PCM_BASE                 0xB0002000
+#define RALINK_GDMA_BASE                0xB0002800
+#define RALINK_AES_ENGING_BASE          0xB0004000
+#define RALINK_CRYPTO_ENGING_BASE       RALINK_AES_ENGING_BASE
+#define RALINK_RGCTRL_BASE				0xB0001000
+#define RALINK_FRAME_ENGINE_BASE        0xB0100000
+#define RALINK_ETH_SW_BASE              0xB0110000
+#define RALINK_USB_DEV_BASE             0x10120000
+#define RALINK_MSDC_BASE                0xB0130000
+#define RALINK_PCI_BASE                 0xB0140000
+#define RALINK_11N_MAC_BASE             0xB0180000
+#define RALINK_USB_HOST_BASE            0x101C0000
+
+#define RALINK_MCNT_CFG                 0xB0000D00
+#define RALINK_COMPARE                  0xB0000D04
+#define RALINK_COUNT                    0xB0000D08
+
+#define RALINK_CPLLCFG0_REG		(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG		(RALINK_SYSCTL_BASE+0x58)
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL            (1<<0)
+#define RALINK_INTCTL_TIMER0            (1<<1)
+#define RALINK_INTCTL_WDTIMER           (1<<2)
+#define RALINK_INTCTL_ILL_ACCESS        (1<<3)
+#define RALINK_INTCTL_PCM               (1<<4)
+#define RALINK_INTCTL_UART              (1<<5)
+#define RALINK_INTCTL_PIO               (1<<6)
+#define RALINK_INTCTL_DMA               (1<<7)
+#define RALINK_INTCTL_PC                (1<<9)
+#define RALINK_INTCTL_I2S               (1<<10)
+#define RALINK_INTCTL_SPI               (1<<11)
+#define RALINK_INTCTL_UARTLITE          (1<<12)
+#define RALINK_INTCTL_CRYPTO            (1<<13)
+#define RALINK_INTCTL_ESW               (1<<17)
+#define RALINK_INTCTL_UHST              (1<<18)
+#define RALINK_INTCTL_UDEV              (1<<19)
+#define RALINK_INTCTL_GLOBAL            (1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST                  (1<<0)
+#define RALINK_TIMER_RST                (1<<8)
+#define RALINK_INTC_RST                 (1<<9)
+#define RALINK_MC_RST                   (1<<10)
+#define RALINK_PCM_RST                  (1<<11)
+#define RALINK_UART_RST                 (1<<12)
+#define RALINK_PIO_RST                  (1<<13)
+#define RALINK_DMA_RST                  (1<<14)
+#define RALINK_I2C_RST                  (1<<16)
+#define RALINK_I2S_RST                  (1<<17)
+#define RALINK_SPI_RST                  (1<<18)
+#define RALINK_UARTL_RST                (1<<19)
+#define RALINK_FE_RST                   (1<<21)
+#define RALINK_UHST_RST                 (1<<22)
+#define RALINK_ESW_RST                  (1<<23)
+#define RALINK_EPHY_RST                 (1<<24)
+#define RALINK_UDEV_RST                 (1<<25)
+#define RALINK_PCIE0_RST                (1<<26)
+#define RALINK_PCIE1_RST                (1<<27)
+#define RALINK_MIPS_CNT_RST             (1<<28)
+#define RALINK_CRYPTO_RST               (1<<29)
+
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN     (1<<22)
+#define RALINK_UPHY0_CLK_EN     (1<<25)
+#define RALINK_PCIE_CLK_EN    	(1<<26)
+
+#elif defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE              0xBE000000
+#define RALINK_TIMER_BASE               0xBE000100
+#define RALINK_INTCL_BASE               0xBE000200
+#define RALINK_RBUS_MATRIXCTL_BASE      0xBE000400
+#define RALINK_MIPS_CNT_BASE            0x1E000500
+#define RALINK_PIO_BASE                 0xBE000600
+#define RALINK_SPDIF_BASE               0xBE000700
+#define RALINK_DMA_ARB_BASE             0xBE000800
+#define RALINK_I2C_BASE                 0xBE000900
+#define RALINK_I2S_BASE                 0xBE000A00
+#define RALINK_SPI_BASE                 0xBE000B00
+#define RALINK_UART_LITE_BASE           0xBE000C00
+#define RALINK_UART_LITE2_BASE          0xBE000D00
+#define RALINK_UART_LITE3_BASE          0xBE000E00
+#define RALINK_PCM_BASE                 0xBE002000
+#define RALINK_GDMA_BASE                0xBE002800
+#define RALINK_NAND_CTRL_BASE           0xBE003000
+#define RALINK_NANDECC_CTRL_BASE	0xBE003800
+#define RALINK_CRYPTO_ENGINE_BASE       0xBE004000
+#define RALINK_MEMCTRL_BASE             0xBE005000
+#define RALINK_FRAME_ENGINE_BASE        0xBE100000
+#define RALINK_ETH_GMAC_BASE            0xBE110000
+#define RALINK_ETH_SW_BASE		0xBE110000
+#define RALINK_ROM_BASE                 0xBE118000
+#define RALINK_MSDC_BASE                0xBE130000
+#define RALINK_PCI_BASE                 0xBE140000
+#define RALINK_USB_HOST_BASE            0x1E1C0000
+
+
+#define RALINK_CPLLCFG0_REG		(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG		(RALINK_SYSCTL_BASE+0x58)
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL            (1<<0)
+#define RALINK_INTCTL_TIMER0            (1<<1)
+#define RALINK_INTCTL_WDTIMER           (1<<2)
+#define RALINK_INTCTL_ILL_ACCESS        (1<<3)
+#define RALINK_INTCTL_PCM               (1<<4)
+#define RALINK_INTCTL_UART              (1<<5)
+#define RALINK_INTCTL_PIO               (1<<6)
+#define RALINK_INTCTL_DMA               (1<<7)
+#define RALINK_INTCTL_PC                (1<<9)
+#define RALINK_INTCTL_I2S               (1<<10)
+#define RALINK_INTCTL_SPI               (1<<11)
+#define RALINK_INTCTL_UARTLITE          (1<<12)
+#define RALINK_INTCTL_CRYPTO            (1<<13)
+#define RALINK_INTCTL_ESW               (1<<17)
+#define RALINK_INTCTL_UHST              (1<<18)
+#define RALINK_INTCTL_UDEV              (1<<19)
+#define RALINK_INTCTL_GLOBAL            (1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST                  (1<<0)
+#define RALINK_TIMER_RST                (1<<8)
+#define RALINK_INTC_RST                 (1<<9)
+#define RALINK_MC_RST                   (1<<10)
+#define RALINK_PCM_RST                  (1<<11)
+#define RALINK_UART_RST                 (1<<12)
+#define RALINK_PIO_RST                  (1<<13)
+#define RALINK_DMA_RST                  (1<<14)
+#define RALINK_I2C_RST                  (1<<16)
+#define RALINK_I2S_RST                  (1<<17)
+#define RALINK_SPI_RST                  (1<<18)
+#define RALINK_UARTL_RST                (1<<19)
+#define RALINK_FE_RST                   (1<<21)
+#define RALINK_UHST_RST                 (1<<22)
+#define RALINK_ESW_RST                  (1<<23)
+#define RALINK_EPHY_RST                 (1<<24)
+#define RALINK_UDEV_RST                 (1<<25)
+#define RALINK_PCIE0_RST                (1<<26)
+#define RALINK_PCIE1_RST                (1<<27)
+#define RALINK_MIPS_CNT_RST             (1<<28)
+#define RALINK_CRYPTO_RST               (1<<29)
+
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN     (1<<22)
+#define RALINK_UPHY0_CLK_EN     (1<<25)
+
+#elif defined (RT2883_FPGA_BOARD) || defined (RT2883_ASIC_BOARD)
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_PCM_BASE			0xB0000400
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_GDMA_BASE		0xB0000700
+#define RALINK_NAND_CTRL_BASE		0xB0000800
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_PCI_BASE			0xB0140000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_NAND		(1<<8)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_OTG		(1<<18)
+#define RALINK_INTCTL_OTG_IRQN		18
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_CPU_RST			(1<<1)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_OTG_RST			(1<<22)
+#define RALINK_PCIE_RST			(1<<23)
+
+
+#elif defined (RT3883_FPGA_BOARD) || defined (RT3883_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_NOR_CTRL_BASE		0xB0000700
+#define RALINK_NAND_CTRL_BASE		0xB0000810
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_CODEC1_BASE		0xB0003000
+#define RALINK_CODEC2_BASE		0xB0003800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_PCI_BASE			0xB0140000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_HOST_BASE		0xB01C0000
+#define RALINK_PCIE_BASE		0xB0200000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_NAND		(1<<8)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_NAND_RST			(1<<15)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_PCIE_RST			(1<<23)
+#define RALINK_PCI_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+#define RALINK_FLASH_RST		(1<<26)
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN		(1<<20)
+#define RALINK_UPHY0_CLK_EN		(1<<18)
+#define RALINK_GE1_CLK_EN		(1<<16)
+
+
+#elif defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_HOST_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+#define RALINK_MIPS_RST			(1<<26)
+
+//Clock Conf Register
+#define RALINK_UPHY0_CLK_EN		(1<<18)
+#define RALINK_GE1_CLK_EN		(1<<16)
+
+#elif defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xBFB00000
+#define RALINK_TIMER_BASE		0xBFBF0100
+#define RALINK_INTCL_BASE		0xBFB40000
+#define RALINK_MEMCTRL_BASE		0xBFB20000
+#define RALINK_PIO_BASE			0xBFBF0200
+#define RALINK_NAND_CTRL_BASE		0xBFBE0010
+#define RALINK_I2C_BASE			0xBFBF8000
+#define RALINK_I2S_BASE			0xBFBF8100
+#define RALINK_SPI_BASE			0xBFBC0B00
+#define RALINK_UART_LITE_BASE		0xBFBF0000
+#define RALINK_UART_LITE2_BASE		0xBFBF0300
+#define RALINK_PCM_BASE			0xBFBD0000
+#define RALINK_GDMA_BASE		0xBFB30000
+#define RALINK_FRAME_ENGINE_BASE	0xBFB50000
+#define RALINK_ETH_SW_BASE		0xBFB58000
+//#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_PCI_BASE			0xBFB80000
+//#define RALINK_USB_HOST_BASE		0xB01C0000
+#define RALINK_PCIE_BASE		0xBFB81000
+
+//Interrupt Controller
+#define RALINK_INTCTL_UARTLITE		(1<<0)
+#define RALINK_INTCTL_PIO		(1<<10)
+#define RALINK_INTCTL_PCM		(1<<11)
+#define RALINK_INTCTL_DMA		(1<<14)
+#define RALINK_INTCTL_GMAC2		(1<<15)
+#define RALINK_INTCTL_PCI		(1<<17)
+#define RALINK_INTCTL_UHST2		(1<<20)
+#define RALINK_INTCTL_GMAC1		(1<<21)
+#define RALINK_INTCTL_UHST1		(1<<23)
+#define RALINK_INTCTL_PCIE		(1<<24)
+#define RALINK_INTCTL_NAND		(1<<25)
+#define RALINK_INTCTL_SPI		(1<<27)
+
+//Reset Control Register
+//#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+//#define RALINK_MIPS_RST			(1<<26)
+
+#endif
+
+
+/*kurtis:define DDR parameter here for better performance*/
+#ifdef ON_BOARD_DDR2
+/*define ddr module here to choose proper setting or use default setting*/
+//#define W9751G6IB_25
+
+#define DDR_CFG0_REG	RALINK_MEMCTRL_BASE+0x40
+#define RAS_OFFSET	23
+#define TRFC_OFFSET	13
+#define TRFI_OFFSET	0
+#ifdef  ON_BOARD_32BIT_DRAM_BUS
+#define BL_VALUE	2//BL=4
+#else
+#define BL_VALUE	3 //BL=8
+#endif
+
+#define CAS_OFFSET	4
+#define BL_OFFSET	0
+#define AdditiveLatency_OFFSET 3
+
+#if defined (W9751G6IB_25)
+#define RAS_VALUE	7
+#define TRFC_VALUE	9
+#define TRFI_VALUE	650
+#define CAS_VALUE	3
+#define AdditiveLatency_VALUE  0
+#endif //W9751G6IB_25
+
+#endif //DDR
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+#define RALINK_SDRAM_CFG0_REG 	(RALINK_MEMCTRL_BASE)
+#define RALINK_SDRAM_CFG1_REG 	(RALINK_MEMCTRL_BASE+0x4)
+#define RALINK_DDR_CFG0		(RALINK_MEMCTRL_BASE+0x40)
+#define RALINK_DDR_CFG1		(RALINK_MEMCTRL_BASE+0x44)
+#define RALINK_DDR_CFG2		(RALINK_MEMCTRL_BASE+0x48)
+#define RALINK_DDR_CFG3		(RALINK_MEMCTRL_BASE+0x4c)
+#define RALINK_DDR_CFG4		(RALINK_MEMCTRL_BASE+0x50)
+#define RALINK_DDR_CFG9		(RALINK_MEMCTRL_BASE+0x64)
+#endif
+
+#if defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) || defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+/* CPLL related */
+#define RALINK_CPLLCFG0_REG	(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG	(RALINK_SYSCTL_BASE+0x58)
+#define CPLL_SW_CONFIG                  (0x1UL << 31)
+#define CPLL_MULT_RATIO_SHIFT           16
+#define CPLL_MULT_RATIO                 (0x7UL << CPLL_MULT_RATIO_SHIFT)
+#define CPLL_DIV_RATIO_SHIFT            10
+#define CPLL_DIV_RATIO                  (0x3UL << CPLL_DIV_RATIO_SHIFT)
+#define BASE_CLOCK                      40      /* Mhz */
+#endif
+
+/* Timer related */
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+#define RALINK_TIMER_CTL	(RALINK_TIMER_BASE + 0x00)
+#define RALINK_TIMER5_LDV	(RALINK_TIMER_BASE + 0x2C)
+#endif
+
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+#define RALINK_HIR_REG	(RALINK_SYSCTL_BASE+0x64)
+#endif
+
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+#define RALINK_PIO_BASE			0xBE000600
+#define RALINK_CLKCFG0_REG		0xBE00002C
+#define RALINK_GPIOMODE_REG		0xBE000060
+#define RALINK_CUR_CLK_STS_REG		0xBE000044
+#define RALINK_DYN_CFG0_REG		0xBE000410
+#endif
+
+#if defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+#define RALINK_CLKCFG0_REG      0xB000002C
+#define RALINK_DYN_CFG0_REG		0xB0000440
+#endif
+
+#endif // __RALINK_MMAP__
diff --git a/common/board_r.c b/common/board_r.c
index d959ad3c6f90ea2c2a422b6878c11a5437764a2c..0b5a4d66aded1affa1a7d2b64bd9ac9138d6f9c8 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -972,6 +972,8 @@ init_fnc_t init_sequence_r[] = {
 	run_main_loop,
 };
 
+void debug_halt(long addr);
+
 void board_init_r(gd_t *new_gd, ulong dest_addr)
 {
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
@@ -990,7 +992,9 @@ void board_init_r(gd_t *new_gd, ulong dest_addr)
 	for (i = 0; i < ARRAY_SIZE(init_sequence_r); i++)
 		init_sequence_r[i] += gd->reloc_off;
 #endif
-
+#ifdef TRACE32
+	debug_halt(CONFIG_SYS_TEXT_BASE - gd->relocaddr);
+#endif
 	if (initcall_run_list(init_sequence_r))
 		hang();
 
diff --git a/configs/ex300_defconfig b/configs/ex300_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..63f55dd99b249bdf35df27f801134ed3cd060918
--- /dev/null
+++ b/configs/ex300_defconfig
@@ -0,0 +1,511 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# U-Boot 2016.09-rc2 Configuration
+#
+CONFIG_HAVE_ARCH_IOREMAP=y
+# CONFIG_ARC is not set
+# CONFIG_ARM is not set
+# CONFIG_AVR32 is not set
+# CONFIG_BLACKFIN is not set
+# CONFIG_M68K is not set
+# CONFIG_MICROBLAZE is not set
+CONFIG_MIPS=y
+# CONFIG_NDS32 is not set
+# CONFIG_NIOS2 is not set
+# CONFIG_OPENRISC is not set
+# CONFIG_PPC is not set
+# CONFIG_SANDBOX is not set
+# CONFIG_SH is not set
+# CONFIG_SPARC is not set
+# CONFIG_X86 is not set
+# CONFIG_XTENSA is not set
+CONFIG_SYS_ARCH="mips"
+CONFIG_SYS_CPU="mips32"
+CONFIG_SYS_VENDOR="inteno"
+CONFIG_SYS_BOARD="ex300"
+CONFIG_SYS_CONFIG_NAME="ex300"
+
+#
+# MIPS architecture
+#
+# CONFIG_TARGET_QEMU_MIPS is not set
+# CONFIG_TARGET_MALTA is not set
+CONFIG_TARGET_EX300=y
+# CONFIG_TARGET_VCT is not set
+# CONFIG_TARGET_DBAU1X00 is not set
+# CONFIG_TARGET_PB1X00 is not set
+# CONFIG_ARCH_ATH79 is not set
+# CONFIG_MACH_PIC32 is not set
+CONFIG_SYS_TEXT_BASE=0xA0200000
+CONFIG_SYS_DCACHE_SIZE=0
+CONFIG_SYS_DCACHE_LINE_SIZE=0
+CONFIG_SYS_ICACHE_SIZE=0
+CONFIG_SYS_ICACHE_LINE_SIZE=0
+CONFIG_SYS_LITTLE_ENDIAN=y
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+
+#
+# OS boot interface
+#
+CONFIG_MIPS_BOOT_CMDLINE_LEGACY=y
+CONFIG_MIPS_BOOT_ENV_LEGACY=y
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SUPPORTS_CPU_MIPS32_R1=y
+CONFIG_SUPPORTS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_32BIT=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_SYS_CACHE_SIZE_AUTO=y
+CONFIG_MIPS_L1_CACHE_SHIFT_6=y
+CONFIG_MIPS_L1_CACHE_SHIFT=6
+# CONFIG_DM_KEYBOARD is not set
+# CONFIG_AHCI is not set
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_DISTRO_DEFAULTS is not set
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_EXPERT=y
+CONFIG_SYS_MALLOC_CLEAR_ON_INIT=y
+# CONFIG_TOOLS_DEBUG is not set
+# CONFIG_PHYS_64BIT is not set
+
+#
+# Boot images
+#
+# CONFIG_FIT is not set
+# CONFIG_OF_BOARD_SETUP is not set
+# CONFIG_OF_SYSTEM_SETUP is not set
+# CONFIG_OF_STDOUT_VIA_ALIAS is not set
+CONFIG_SYS_EXTRA_OPTIONS=""
+CONFIG_ARCH_FIXUP_FDT=y
+
+#
+# Boot timing
+#
+# CONFIG_BOOTSTAGE is not set
+CONFIG_BOOTSTAGE_USER_COUNT=20
+CONFIG_BOOTSTAGE_STASH_ADDR=0
+CONFIG_BOOTSTAGE_STASH_SIZE=4096
+
+#
+# Boot media
+#
+# CONFIG_NAND_BOOT is not set
+# CONFIG_ONENAND_BOOT is not set
+# CONFIG_QSPI_BOOT is not set
+# CONFIG_SATA_BOOT is not set
+# CONFIG_SD_BOOT is not set
+# CONFIG_SPI_BOOT is not set
+CONFIG_BOOTDELAY=2
+# CONFIG_CONSOLE_RECORD is not set
+# CONFIG_SYS_NO_FLASH is not set
+
+#
+# Command line interface
+#
+CONFIG_CMDLINE=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="ex300 -> "
+
+#
+# Autoboot options
+#
+CONFIG_AUTOBOOT=y
+# CONFIG_AUTOBOOT_KEYED is not set
+
+#
+# FASTBOOT
+#
+# CONFIG_FASTBOOT is not set
+
+#
+# Commands
+#
+
+#
+# Info commands
+#
+CONFIG_CMD_BDI=y
+CONFIG_CMD_CONSOLE=y
+# CONFIG_CMD_CPU is not set
+# CONFIG_CMD_LICENSE is not set
+
+#
+# Boot commands
+#
+CONFIG_CMD_BOOTD=y
+CONFIG_CMD_BOOTM=y
+# CONFIG_CMD_BOOTZ is not set
+CONFIG_CMD_ELF=y
+CONFIG_CMD_FDT=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_RUN=y
+CONFIG_CMD_IMI=y
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_XIMG=y
+
+#
+# Environment commands
+#
+# CONFIG_CMD_ASKENV is not set
+CONFIG_CMD_EXPORTENV=y
+CONFIG_CMD_IMPORTENV=y
+CONFIG_CMD_EDITENV=y
+# CONFIG_CMD_GREPENV is not set
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_ENV_EXISTS=y
+
+#
+# Memory commands
+#
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_CRC32=y
+# CONFIG_LOOPW is not set
+# CONFIG_CMD_MEMTEST is not set
+# CONFIG_CMD_MX_CYCLIC is not set
+# CONFIG_CMD_MEMINFO is not set
+
+#
+# Device access commands
+#
+CONFIG_CMD_DM=y
+# CONFIG_CMD_DEMO is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_FLASH=y
+# CONFIG_CMD_ARMFLASH is not set
+# CONFIG_CMD_MMC is not set
+# CONFIG_CMD_NAND is not set
+# CONFIG_CMD_SF is not set
+# CONFIG_CMD_SPI is not set
+# CONFIG_CMD_I2C is not set
+# CONFIG_CMD_USB is not set
+# CONFIG_CMD_DFU is not set
+# CONFIG_CMD_USB_MASS_STORAGE is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_GPIO is not set
+
+#
+# Shell scripting commands
+#
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_ITEST=y
+CONFIG_CMD_SOURCE=y
+# CONFIG_CMD_SETEXPR is not set
+
+#
+# Network commands
+#
+CONFIG_CMD_NET=y
+# CONFIG_CMD_TFTPPUT is not set
+# CONFIG_CMD_TFTPSRV is not set
+# CONFIG_CMD_RARP is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+# CONFIG_CMD_MII is not set
+CONFIG_CMD_PING=y
+# CONFIG_CMD_CDP is not set
+# CONFIG_CMD_SNTP is not set
+# CONFIG_CMD_DNS is not set
+# CONFIG_CMD_LINK_LOCAL is not set
+
+#
+# Misc commands
+#
+# CONFIG_CMD_CACHE is not set
+# CONFIG_CMD_TIME is not set
+CONFIG_CMD_MISC=y
+# CONFIG_CMD_TIMER is not set
+# CONFIG_CMD_QFW is not set
+
+#
+# Power commands
+#
+
+#
+# Security commands
+#
+
+#
+# Filesystem commands
+#
+# CONFIG_CMD_EXT2 is not set
+# CONFIG_CMD_EXT4 is not set
+# CONFIG_CMD_FAT is not set
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SUPPORT_OF_CONTROL=y
+
+#
+# Device Tree Control
+#
+# CONFIG_OF_CONTROL is not set
+CONFIG_NET=y
+# CONFIG_NET_RANDOM_ETHADDR is not set
+# CONFIG_NETCONSOLE is not set
+CONFIG_NET_TFTP_VARS=y
+CONFIG_BOOTP_VCI_STRING="U-Boot"
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_DM=y
+CONFIG_DM_WARN=y
+CONFIG_DM_DEVICE_REMOVE=y
+CONFIG_DM_STDIO=y
+CONFIG_DM_SEQ_ALIAS=y
+# CONFIG_SPL_DM_SEQ_ALIAS is not set
+# CONFIG_REGMAP is not set
+# CONFIG_SPL_REGMAP is not set
+# CONFIG_DEVRES is not set
+# CONFIG_ADC is not set
+# CONFIG_ADC_EXYNOS is not set
+# CONFIG_ADC_SANDBOX is not set
+# CONFIG_BLK is not set
+# CONFIG_BLOCK_CACHE is not set
+
+#
+# Clock
+#
+# CONFIG_CLK is not set
+# CONFIG_CPU is not set
+
+#
+# Hardware crypto devices
+#
+# CONFIG_FSL_CAAM is not set
+
+#
+# Demo for driver model
+#
+# CONFIG_DM_DEMO is not set
+
+#
+# DFU support
+#
+# CONFIG_DFU_TFTP is not set
+
+#
+# DMA Support
+#
+# CONFIG_DMA is not set
+# CONFIG_TI_EDMA3 is not set
+
+#
+# GPIO Support
+#
+# CONFIG_DM_GPIO is not set
+# CONFIG_INTEL_BROADWELL_GPIO is not set
+# CONFIG_LPC32XX_GPIO is not set
+# CONFIG_VYBRID_GPIO is not set
+
+#
+# I2C support
+#
+# CONFIG_DM_I2C is not set
+# CONFIG_DM_I2C_COMPAT is not set
+# CONFIG_SYS_I2C_DW is not set
+# CONFIG_CROS_EC_KEYB is not set
+
+#
+# LED Support
+#
+# CONFIG_LED is not set
+
+#
+# Mailbox Controller Support
+#
+
+#
+# Memory Controller drivers
+#
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MISC is not set
+# CONFIG_CROS_EC is not set
+# CONFIG_FSL_SEC_MON is not set
+# CONFIG_MXC_OCOTP is not set
+# CONFIG_NUVOTON_NCT6102D is not set
+# CONFIG_PWRSEQ is not set
+# CONFIG_PCA9551_LED is not set
+# CONFIG_WINBOND_W83627 is not set
+
+#
+# MMC Host controller Support
+#
+# CONFIG_DM_MMC is not set
+
+#
+# MTD Support
+#
+CONFIG_MTD=y
+# CONFIG_CFI_FLASH is not set
+# CONFIG_ALTERA_QSPI is not set
+
+#
+# NAND Device Support
+#
+# CONFIG_NAND_DENALI is not set
+# CONFIG_NAND_VF610_NFC is not set
+# CONFIG_NAND_PXA3XX is not set
+# CONFIG_NAND_ARASAN is not set
+# CONFIG_MTK_MTD_NAND is not set
+
+#
+# Generic NAND options
+#
+
+#
+# SPI Flash Support
+#
+# CONFIG_SPI_FLASH is not set
+# CONFIG_DM_ETH is not set
+CONFIG_PHYLIB=y
+# CONFIG_RTL8211X_PHY_FORCE_MASTER is not set
+CONFIG_NETDEVICES=y
+# CONFIG_E1000 is not set
+# CONFIG_ETH_DESIGNWARE is not set
+# CONFIG_ETHOC is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_RTL8169 is not set
+CONFIG_RT2880_ETH=y
+
+#
+# PCI
+#
+# CONFIG_DM_PCI is not set
+
+#
+# Pin controllers
+#
+# CONFIG_PINCTRL is not set
+
+#
+# Power
+#
+
+#
+# Power Domain Support
+#
+# CONFIG_DM_PMIC is not set
+# CONFIG_DM_REGULATOR is not set
+# CONFIG_DM_PWM is not set
+# CONFIG_RAM is not set
+
+#
+# Remote Processor drivers
+#
+
+#
+# Reset Controller Support
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_DM_RTC is not set
+
+#
+# Serial drivers
+#
+# CONFIG_DM_SERIAL is not set
+# CONFIG_DEBUG_UART is not set
+# CONFIG_DEBUG_UART_SKIP_INIT is not set
+# CONFIG_FSL_LPUART is not set
+CONFIG_SYS_NS16550=y
+
+#
+# Sound support
+#
+# CONFIG_SOUND is not set
+
+#
+# SPI Support
+#
+# CONFIG_DM_SPI is not set
+# CONFIG_FSL_ESPI is not set
+# CONFIG_TI_QSPI is not set
+
+#
+# SPMI support
+#
+# CONFIG_SPMI is not set
+
+#
+# System reset device drivers
+#
+# CONFIG_SYSRESET is not set
+# CONFIG_DM_THERMAL is not set
+
+#
+# Timer Support
+#
+# CONFIG_TIMER is not set
+
+#
+# TPM support
+#
+# CONFIG_USB is not set
+
+#
+# Graphics support
+#
+# CONFIG_DM_VIDEO is not set
+
+#
+# TrueType Fonts
+#
+# CONFIG_VIDEO_VESA is not set
+# CONFIG_VIDEO_LCD_ANX9804 is not set
+# CONFIG_VIDEO_LCD_SSD2828 is not set
+# CONFIG_VIDEO_MVEBU is not set
+# CONFIG_DISPLAY is not set
+# CONFIG_VIDEO_BRIDGE is not set
+# CONFIG_PHYS_TO_BUS is not set
+
+#
+# File systems
+#
+
+#
+# Library routines
+#
+# CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED is not set
+CONFIG_HAVE_PRIVATE_LIBGCC=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_SYS_HZ=1000
+# CONFIG_USE_TINY_PRINTF is not set
+CONFIG_REGEX=y
+# CONFIG_LIB_RAND is not set
+# CONFIG_CMD_DHRYSTONE is not set
+# CONFIG_RSA is not set
+# CONFIG_TPM is not set
+
+#
+# Hashing Support
+#
+# CONFIG_SHA1 is not set
+# CONFIG_SHA256 is not set
+# CONFIG_SHA_HW_ACCEL is not set
+
+#
+# Compression Support
+#
+# CONFIG_LZ4 is not set
+# CONFIG_ERRNO_STR is not set
+CONFIG_OF_LIBFDT=y
+# CONFIG_OF_LIBFDT_OVERLAY is not set
+# CONFIG_SPL_OF_LIBFDT is not set
+# CONFIG_UNIT_TEST is not set
diff --git a/configs/mt7621_defconfig b/configs/mt7621_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..4ab51b8bc081524ef4c93be4e7fd6a21f7713a70
--- /dev/null
+++ b/configs/mt7621_defconfig
@@ -0,0 +1,13 @@
+CONFIG_MIPS=y
+CONFIG_TARGET_MT7621=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="mt7621 # "
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_SYS_NS16550=y
+CONFIG_USE_PRIVATE_LIBGCC=y
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 5ce7d6d06cea39099c50b039727ec622d9d5ea54..e005a70149d3ccef7d97adee91d0c5508c87cf86 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -80,6 +80,9 @@ config NAND_ARASAN
 	  controller. This uses the hardware ECC for read and
 	  write operations.
 
+config MTK_MTD_NAND
+	bool "Support for MTK SoC NAND controller"
+
 comment "Generic NAND options"
 
 # Enhance depends when converting drivers to Kconfig which use this config
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1df9273cdd1114f64f161a9d987ce2ae89f590d2..3ac8536ba30c8e403dbd91b71ddc1df0c660b637 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
 obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
 obj-$(CONFIG_NAND_PLAT) += nand_plat.o
 obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
+obj-$(CONFIG_MTK_MTD_NAND) += mtk_nand.o # bmt.o
 
 else  # minimal SPL drivers
 
diff --git a/drivers/mtd/nand/bmt.c b/drivers/mtd/nand/bmt.c
new file mode 100644
index 0000000000000000000000000000000000000000..75c2ed41e0946b0b6e160d4a05a654c245c53670
--- /dev/null
+++ b/drivers/mtd/nand/bmt.c
@@ -0,0 +1,753 @@
+#include <common.h>
+#include <nand.h>
+#include "bmt.h"
+
+
+typedef struct
+{
+    char signature[3];
+    u8 version;
+    u8 bad_count;               // bad block count in pool
+    u8 mapped_count;            // mapped block count in pool
+    u8 checksum;
+    u8 reseverd[13];
+} phys_bmt_header;
+
+typedef struct
+{
+    phys_bmt_header header;
+    bmt_entry table[MAX_BMT_SIZE];
+} phys_bmt_struct;
+
+typedef struct
+{
+    char signature[3];
+} bmt_oob_data;
+
+static char MAIN_SIGNATURE[] = "BMT";
+static char OOB_SIGNATURE[] = "bmt";
+#define SIGNATURE_SIZE      (3)
+
+#define MAX_DAT_SIZE        0x1000
+#define MAX_OOB_SIZE        0x80
+
+static struct mtd_info *mtd_bmt;
+static struct nand_chip *nand_chip_bmt;
+#define BLOCK_SIZE_BMT          (1 << nand_chip_bmt->phys_erase_shift)
+#define PAGE_SIZE_BMT           (1 << nand_chip_bmt->page_shift)
+
+#define OFFSET(block)       ((block) * BLOCK_SIZE_BMT)  
+#define PAGE_ADDR(block)    ((block) * BLOCK_SIZE_BMT / PAGE_SIZE_BMT)
+
+/*********************************************************************
+* Flash is splited into 2 parts, system part is for normal system    *
+* system usage, size is system_block_count, another is replace pool  *
+*    +-------------------------------------------------+             *
+*    |     system_block_count     |   bmt_block_count  |             *
+*    +-------------------------------------------------+             *
+*********************************************************************/
+static u32 total_block_count;   // block number in flash
+static u32 system_block_count;
+static int bmt_block_count;     // bmt table size
+// static int bmt_count;               // block used in bmt
+static int page_per_block;      // page per count
+
+static u32 bmt_block_index;     // bmt block index
+static bmt_struct bmt;          // dynamic created global bmt table
+
+static u8 dat_buf[MAX_DAT_SIZE];
+static u8 oob_buf[MAX_OOB_SIZE];
+static bool pool_erased;
+
+/***************************************************************
+*                                                              
+* Interface adaptor for preloader/uboot/kernel                 
+*    These interfaces operate on physical address, read/write
+*       physical data.
+*                                                              
+***************************************************************/
+int nand_read_page_bmt(u32 page, u8 * dat, u8 * oob)
+{
+    return mtk_nand_exec_read_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob);
+}
+
+bool nand_block_bad_bmt(u32 offset)
+{
+    return mtk_nand_block_bad_hw(mtd_bmt, offset);
+}
+
+bool nand_erase_bmt(u32 offset)
+{
+    int status;
+    if (offset < 0x20000)
+    {
+        MSG(INIT, "erase offset: 0x%x\n", offset);
+    }
+
+    status = mtk_nand_erase_hw(mtd_bmt, offset / PAGE_SIZE_BMT); // as nand_chip structure doesn't have a erase function defined
+    if (status & NAND_STATUS_FAIL)
+        return false;
+    else
+        return true;
+}
+
+int mark_block_bad_bmt(u32 offset)
+{
+    return mtk_nand_block_markbad_hw(mtd_bmt, offset);   //mark_block_bad_hw(offset);
+}
+
+bool nand_write_page_bmt(u32 page, u8 * dat, u8 * oob)
+{
+    if (mtk_nand_exec_write_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob))
+        return false;
+    else
+        return true;
+}
+
+/***************************************************************
+*                                                              *
+* static internal function                                     *
+*                                                              *
+***************************************************************/
+static void dump_bmt_info(bmt_struct * bmt)
+{
+    int i;
+
+    MSG(INIT, "BMT v%d. total %d mapping:\n", bmt->version, bmt->mapped_count);
+    for (i = 0; i < bmt->mapped_count; i++)
+    {
+        MSG(INIT, "\t0x%x -> 0x%x\n", bmt->table[i].bad_index, bmt->table[i].mapped_index);
+    }
+}
+
+static bool match_bmt_signature(u8 * dat, u8 * oob)
+{
+
+    if (memcmp(dat + MAIN_SIGNATURE_OFFSET, MAIN_SIGNATURE, SIGNATURE_SIZE))
+    {
+        return false;
+    }
+
+    if (memcmp(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE))
+    {
+        MSG(INIT, "main signature match, oob signature doesn't match, but ignore\n");
+    }
+    return true;
+}
+
+static u8 cal_bmt_checksum(phys_bmt_struct * phys_table, int bmt_size)
+{
+    int i;
+    u8 checksum = 0;
+    u8 *dat = (u8 *) phys_table;
+
+    checksum += phys_table->header.version;
+    checksum += phys_table->header.mapped_count;
+
+    dat += sizeof(phys_bmt_header);
+    for (i = 0; i < bmt_size * sizeof(bmt_entry); i++)
+    {
+        checksum += dat[i];
+    }
+
+    return checksum;
+}
+
+
+static int is_block_mapped(int index)
+{
+    int i;
+    for (i = 0; i < bmt.mapped_count; i++)
+    {
+        if (index == bmt.table[i].mapped_index)
+            return i;
+    }
+    return -1;
+}
+
+static bool is_page_used(u8 * dat, u8 * oob)
+{
+    return ((oob[OOB_INDEX_OFFSET] != 0xFF) || (oob[OOB_INDEX_OFFSET + 1] != 0xFF));
+}
+
+static bool valid_bmt_data(phys_bmt_struct * phys_table)
+{
+    int i;
+    u8 checksum = cal_bmt_checksum(phys_table, bmt_block_count);
+
+    // checksum correct?
+    if (phys_table->header.checksum != checksum)
+    {
+        MSG(INIT, "BMT Data checksum error: %x %x\n", phys_table->header.checksum, checksum);
+        return false;
+    }
+
+    MSG(INIT, "BMT Checksum is: 0x%x\n", phys_table->header.checksum);
+
+    // block index correct?
+    for (i = 0; i < phys_table->header.mapped_count; i++)
+    {
+        if (phys_table->table[i].bad_index >= total_block_count || phys_table->table[i].mapped_index >= total_block_count || phys_table->table[i].mapped_index < system_block_count)
+        {
+            MSG(INIT, "index error: bad_index: %d, mapped_index: %d\n", phys_table->table[i].bad_index, phys_table->table[i].mapped_index);
+            return false;
+        }
+    }
+
+    // pass check, valid bmt.
+    MSG(INIT, "Valid BMT, version v%d\n", phys_table->header.version);
+    return true;
+}
+
+static void fill_nand_bmt_buffer(bmt_struct * bmt, u8 * dat, u8 * oob)
+{
+    phys_bmt_struct phys_bmt;
+
+    dump_bmt_info(bmt);
+
+    // fill phys_bmt_struct structure with bmt_struct
+    memset(&phys_bmt, 0xFF, sizeof(phys_bmt));
+
+    memcpy(phys_bmt.header.signature, MAIN_SIGNATURE, SIGNATURE_SIZE);
+    phys_bmt.header.version = BMT_VERSION;
+    // phys_bmt.header.bad_count = bmt->bad_count;
+    phys_bmt.header.mapped_count = bmt->mapped_count;
+    memcpy(phys_bmt.table, bmt->table, sizeof(bmt_entry) * bmt_block_count);
+
+    phys_bmt.header.checksum = cal_bmt_checksum(&phys_bmt, bmt_block_count);
+
+    memcpy(dat + MAIN_SIGNATURE_OFFSET, &phys_bmt, sizeof(phys_bmt));
+    memcpy(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE);
+}
+
+// return valid index if found BMT, else return 0
+static int load_bmt_data(int start, int pool_size)
+{
+    int bmt_index = start + pool_size - 1;  // find from the end
+    phys_bmt_struct phys_table;
+    int i;
+
+    MSG(INIT, "[%s]: begin to search BMT from block 0x%x\n", __FUNCTION__, bmt_index);
+
+    for (bmt_index = start + pool_size - 1; bmt_index >= start; bmt_index--)
+    {
+        if (nand_block_bad_bmt(OFFSET(bmt_index)))
+        {
+            MSG(INIT, "Skip bad block: %d\n", bmt_index);
+            continue;
+        }
+
+        if (!nand_read_page_bmt(PAGE_ADDR(bmt_index), dat_buf, oob_buf))
+        {
+            MSG(INIT, "Error found when read block %d\n", bmt_index);
+            continue;
+        }
+
+        if (!match_bmt_signature(dat_buf, oob_buf))
+        {
+            continue;
+        }
+
+        MSG(INIT, "Match bmt signature @ block: 0x%x\n", bmt_index);
+
+        memcpy(&phys_table, dat_buf + MAIN_SIGNATURE_OFFSET, sizeof(phys_table));
+
+        if (!valid_bmt_data(&phys_table))
+        {
+            MSG(INIT, "BMT data is not correct %d\n", bmt_index);
+            continue;
+        } else
+        {
+            bmt.mapped_count = phys_table.header.mapped_count;
+            bmt.version = phys_table.header.version;
+            // bmt.bad_count = phys_table.header.bad_count;
+            memcpy(bmt.table, phys_table.table, bmt.mapped_count * sizeof(bmt_entry));
+
+            MSG(INIT, "bmt found at block: %d, mapped block: %d\n", bmt_index, bmt.mapped_count);
+
+            for (i = 0; i < bmt.mapped_count; i++)
+            {
+                if (!nand_block_bad_bmt(OFFSET(bmt.table[i].bad_index)))
+                {
+                    MSG(INIT, "block 0x%x is not mark bad, should be power lost last time\n", bmt.table[i].bad_index);
+                    mark_block_bad_bmt(OFFSET(bmt.table[i].bad_index));
+                }
+            }
+
+            return bmt_index;
+        }
+    }
+
+    MSG(INIT, "bmt block not found!\n");
+    return 0;
+}
+
+/*************************************************************************
+* Find an available block and erase.                                     *
+* start_from_end: if true, find available block from end of flash.       *
+*                 else, find from the beginning of the pool              *
+* need_erase: if true, all unmapped blocks in the pool will be erased    *
+*************************************************************************/
+static int find_available_block(bool start_from_end)
+{
+    int i;                      // , j;
+    int block = system_block_count;
+    int direction;
+    // int avail_index = 0;
+    MSG(INIT, "Try to find_available_block, pool_erase: %d\n", pool_erased);
+
+    // erase all un-mapped blocks in pool when finding avaliable block
+    if (!pool_erased)
+    {
+        MSG(INIT, "Erase all un-mapped blocks in pool\n");
+        for (i = 0; i < bmt_block_count; i++)
+        {
+            if (block == bmt_block_index)
+            {
+                MSG(INIT, "Skip bmt block 0x%x\n", block);
+                continue;
+            }
+
+            if (nand_block_bad_bmt(OFFSET(block + i)))
+            {
+                MSG(INIT, "Skip bad block 0x%x\n", block + i);
+                continue;
+            }
+//if(block==4095)
+//{
+//  continue;
+//}
+
+            if (is_block_mapped(block + i) >= 0)
+            {
+                MSG(INIT, "Skip mapped block 0x%x\n", block + i);
+                continue;
+            }
+
+            if (!nand_erase_bmt(OFFSET(block + i)))
+            {
+                MSG(INIT, "Erase block 0x%x failed\n", block + i);
+                mark_block_bad_bmt(OFFSET(block + i));
+            }
+        }
+
+        pool_erased = 1;
+    }
+
+    if (start_from_end)
+    {
+        block = total_block_count - 1;
+        direction = -1;
+    } else
+    {
+        block = system_block_count;
+        direction = 1;
+    }
+
+    for (i = 0; i < bmt_block_count; i++, block += direction)
+    {
+        if (block == bmt_block_index)
+        {
+            MSG(INIT, "Skip bmt block 0x%x\n", block);
+            continue;
+        }
+
+        if (nand_block_bad_bmt(OFFSET(block)))
+        {
+            MSG(INIT, "Skip bad block 0x%x\n", block);
+            continue;
+        }
+
+        if (is_block_mapped(block) >= 0)
+        {
+            MSG(INIT, "Skip mapped block 0x%x\n", block);
+            continue;
+        }
+
+        MSG(INIT, "Find block 0x%x available\n", block);
+        return block;
+    }
+
+    return 0;
+}
+
+static unsigned short get_bad_index_from_oob(u8 * oob_buf)
+{
+    unsigned short index;
+    memcpy(&index, oob_buf + OOB_INDEX_OFFSET, OOB_INDEX_SIZE);
+
+    return index;
+}
+
+void set_bad_index_to_oob(u8 * oob, u16 index)
+{
+    memcpy(oob + OOB_INDEX_OFFSET, &index, sizeof(index));
+}
+
+static int migrate_from_bad(int offset, u8 * write_dat, u8 * write_oob)
+{
+    int page;
+    int error_block = offset / BLOCK_SIZE_BMT;
+    int error_page = (offset / PAGE_SIZE_BMT) % page_per_block;
+    int to_index;
+
+    memcpy(oob_buf, write_oob, MAX_OOB_SIZE);
+
+    to_index = find_available_block(false);
+
+    if (!to_index)
+    {
+        MSG(INIT, "Cannot find an available block for BMT\n");
+        return 0;
+    }
+
+    {                           // migrate error page first
+        MSG(INIT, "Write error page: 0x%x\n", error_page);
+        if (!write_dat)
+        {
+            nand_read_page_bmt(PAGE_ADDR(error_block) + error_page, dat_buf, NULL);
+            write_dat = dat_buf;
+        }
+        // memcpy(oob_buf, write_oob, MAX_OOB_SIZE);
+
+        if (error_block < system_block_count)
+            set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB.
+
+        if (!nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf))
+        {
+            MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + error_page);
+            mark_block_bad_bmt(to_index);
+            return migrate_from_bad(offset, write_dat, write_oob);
+        }
+    }
+
+    for (page = 0; page < page_per_block; page++)
+    {
+        if (page != error_page)
+        {
+            nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf);
+            if (is_page_used(dat_buf, oob_buf))
+            {
+                if (error_block < system_block_count)
+                {
+                    set_bad_index_to_oob(oob_buf, error_block);
+                }
+                MSG(INIT, "\tmigrate page 0x%x to page 0x%x\n", PAGE_ADDR(error_block) + page, PAGE_ADDR(to_index) + page);
+                if (!nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf))
+                {
+                    MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + page);
+                    mark_block_bad_bmt(to_index);
+                    return migrate_from_bad(offset, write_dat, write_oob);
+                }
+            }
+        }
+    }
+
+    MSG(INIT, "Migrate from 0x%x to 0x%x done!\n", error_block, to_index);
+
+    return to_index;
+}
+
+static bool write_bmt_to_flash(u8 * dat, u8 * oob)
+{
+    bool need_erase = true;
+    MSG(INIT, "Try to write BMT\n");
+
+    if (bmt_block_index == 0)
+    {
+        // if we don't have index, we don't need to erase found block as it has been erased in find_available_block()
+        need_erase = false;
+        if (!(bmt_block_index = find_available_block(true)))
+        {
+            MSG(INIT, "Cannot find an available block for BMT\n");
+            return false;
+        }
+    }
+
+    MSG(INIT, "Find BMT block: 0x%x\n", bmt_block_index);
+
+    // write bmt to flash
+    if (need_erase)
+    {
+        if (!nand_erase_bmt(OFFSET(bmt_block_index)))
+        {
+            MSG(INIT, "BMT block erase fail, mark bad: 0x%x\n", bmt_block_index);
+            mark_block_bad_bmt(OFFSET(bmt_block_index));
+            // bmt.bad_count++;
+
+            bmt_block_index = 0;
+            return write_bmt_to_flash(dat, oob);    // recursive call 
+        }
+    }
+
+    if (!nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob))
+    {
+        MSG(INIT, "Write BMT data fail, need to write again\n");
+        mark_block_bad_bmt(OFFSET(bmt_block_index));
+        // bmt.bad_count++;
+
+        bmt_block_index = 0;
+        return write_bmt_to_flash(dat, oob);    // recursive call 
+    }
+
+    MSG(INIT, "Write BMT data to block 0x%x success\n", bmt_block_index);
+    return true;
+}
+
+/*******************************************************************
+* Reconstruct bmt, called when found bmt info doesn't match bad 
+* block info in flash.
+* 
+* Return NULL for failure
+*******************************************************************/
+bmt_struct *reconstruct_bmt(bmt_struct * bmt)
+{
+    int i;
+    int index = system_block_count;
+    unsigned short bad_index;
+    int mapped;
+
+    // init everything in BMT struct 
+    bmt->version = BMT_VERSION;
+    bmt->bad_count = 0;
+    bmt->mapped_count = 0;
+
+    memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry));
+
+    for (i = 0; i < bmt_block_count; i++, index++)
+    {
+        if (nand_block_bad_bmt(OFFSET(index)))
+        {
+            MSG(INIT, "Skip bad block: 0x%x\n", index);
+            // bmt->bad_count++;
+            continue;
+        }
+
+        MSG(INIT, "read page: 0x%x\n", PAGE_ADDR(index));
+        nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf);
+        /* if (mtk_nand_read_page_hw(PAGE_ADDR(index), dat_buf))
+           {
+           MSG(INIT,  "Error when read block %d\n", bmt_block_index);
+           continue;
+           } */
+
+        if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count)
+        {
+            MSG(INIT, "get bad index: 0x%x\n", bad_index);
+            if (bad_index != 0xFFFF)
+                MSG(INIT, "Invalid bad index found in block 0x%x, bad index 0x%x\n", index, bad_index);
+            continue;
+        }
+
+        MSG(INIT, "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index);
+
+        if (!nand_block_bad_bmt(OFFSET(bad_index)))
+        {
+            MSG(INIT, "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index);
+            continue;           // no need to erase here, it will be erased later when trying to write BMT
+        }
+
+        if ((mapped = is_block_mapped(bad_index)) >= 0)
+        {
+            MSG(INIT, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index);
+            bmt->table[mapped].mapped_index = index;    // use new one instead.
+        } else
+        {
+            // add mapping to BMT
+            bmt->table[bmt->mapped_count].bad_index = bad_index;
+            bmt->table[bmt->mapped_count].mapped_index = index;
+            bmt->mapped_count++;
+        }
+
+        MSG(INIT, "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index);
+
+    }
+
+    MSG(INIT, "Scan replace pool done, mapped block: %d\n", bmt->mapped_count);
+    // dump_bmt_info(bmt);
+
+    // fill NAND BMT buffer
+    memset(oob_buf, 0xFF, sizeof(oob_buf));
+    fill_nand_bmt_buffer(bmt, dat_buf, oob_buf);
+
+    // write BMT back
+    if (!write_bmt_to_flash(dat_buf, oob_buf))
+    {
+        MSG(INIT, "TRAGEDY: cannot find a place to write BMT!!!!\n");
+    }
+
+    return bmt;
+}
+
+/*******************************************************************
+* [BMT Interface]
+*
+* Description:
+*   Init bmt from nand. Reconstruct if not found or data error
+*
+* Parameter:
+*   size: size of bmt and replace pool
+* 
+* Return: 
+*   NULL for failure, and a bmt struct for success
+*******************************************************************/
+bmt_struct *init_bmt(struct nand_chip * chip, int size)
+{
+    struct mtk_nand_host *host;
+
+    if (size > 0 && size < MAX_BMT_SIZE)
+    {
+        MSG(INIT, "Init bmt table, size: %d\n", size);
+        bmt_block_count = size;
+    } else
+    {
+        MSG(INIT, "Invalid bmt table size: %d\n", size);
+        return NULL;
+    }
+    nand_chip_bmt = chip;
+    system_block_count = chip->chipsize >> chip->phys_erase_shift;
+    total_block_count = bmt_block_count + system_block_count;
+    page_per_block = BLOCK_SIZE_BMT / PAGE_SIZE_BMT;
+    host = (struct mtk_nand_host *)chip->priv;
+    mtd_bmt = &host->mtd;
+
+    MSG(INIT, "mtd_bmt: %p, nand_chip_bmt: %p\n", mtd_bmt, nand_chip_bmt);
+    MSG(INIT, "bmt count: %d, system count: %d\n", bmt_block_count, system_block_count);
+
+    // set this flag, and unmapped block in pool will be erased.
+    pool_erased = 0;
+    memset(bmt.table, 0, size * sizeof(bmt_entry));
+    if ((bmt_block_index = load_bmt_data(system_block_count, size)))
+    {
+        MSG(INIT, "Load bmt data success @ block 0x%x\n", bmt_block_index);
+        dump_bmt_info(&bmt);
+        return &bmt;
+    } else
+    {
+        MSG(INIT, "Load bmt data fail, need re-construct!\n");
+#ifndef __UBOOT_NAND__            // BMT is not re-constructed in UBOOT.
+        if (reconstruct_bmt(&bmt))
+            return &bmt;
+        else
+#endif
+            return NULL;
+    }
+}
+
+/*******************************************************************
+* [BMT Interface]
+*
+* Description:
+*   Update BMT.
+*
+* Parameter:
+*   offset: update block/page offset.
+*   reason: update reason, see update_reason_t for reason.
+*   dat/oob: data and oob buffer for write fail.
+* 
+* Return: 
+*   Return true for success, and false for failure.
+*******************************************************************/
+bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob)
+{
+    int map_index;
+    int orig_bad_block = -1;
+    // int bmt_update_index;
+    int i;
+    int bad_index = offset / BLOCK_SIZE_BMT;
+
+#ifndef MTK_NAND_BMT
+	return false;
+#endif
+    if (reason == UPDATE_WRITE_FAIL)
+    {
+        MSG(INIT, "Write fail, need to migrate\n");
+        if (!(map_index = migrate_from_bad(offset, dat, oob)))
+        {
+            MSG(INIT, "migrate fail\n");
+            return false;
+        }
+    } else
+    {
+        if (!(map_index = find_available_block(false)))
+        {
+            MSG(INIT, "Cannot find block in pool\n");
+            return false;
+        }
+    }
+
+    // now let's update BMT
+    if (bad_index >= system_block_count)    // mapped block become bad, find original bad block
+    {
+        for (i = 0; i < bmt_block_count; i++)
+        {
+            if (bmt.table[i].mapped_index == bad_index)
+            {
+                orig_bad_block = bmt.table[i].bad_index;
+                break;
+            }
+        }
+        // bmt.bad_count++;
+        MSG(INIT, "Mapped block becomes bad, orig bad block is 0x%x\n", orig_bad_block);
+
+        bmt.table[i].mapped_index = map_index;
+    } else
+    {
+        bmt.table[bmt.mapped_count].mapped_index = map_index;
+        bmt.table[bmt.mapped_count].bad_index = bad_index;
+        bmt.mapped_count++;
+    }
+
+    memset(oob_buf, 0xFF, sizeof(oob_buf));
+    fill_nand_bmt_buffer(&bmt, dat_buf, oob_buf);
+    if (!write_bmt_to_flash(dat_buf, oob_buf))
+        return false;
+
+    mark_block_bad_bmt(offset);
+
+    return true;
+}
+
+/*******************************************************************
+* [BMT Interface]
+*
+* Description:
+*   Given an block index, return mapped index if it's mapped, else 
+*   return given index.
+*
+* Parameter:
+*   index: given an block index. This value cannot exceed 
+*   system_block_count.
+*
+* Return NULL for failure
+*******************************************************************/
+u16 get_mapping_block_index(int index)
+{
+    int i;
+#ifndef MTK_NAND_BMT
+	return index;
+#endif
+    if (index > system_block_count)
+    {
+        return index;
+    }
+
+    for (i = 0; i < bmt.mapped_count; i++)
+    {
+        if (bmt.table[i].bad_index == index)
+        {
+            return bmt.table[i].mapped_index;
+        }
+    }
+
+    return index;
+}
+#ifdef __KERNEL_NAND__
+EXPORT_SYMBOL_GPL(init_bmt);
+EXPORT_SYMBOL_GPL(update_bmt);
+EXPORT_SYMBOL_GPL(get_mapping_block_index);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("MediaTek");
+MODULE_DESCRIPTION("Bad Block mapping management for MediaTek NAND Flash Driver");
+#endif
diff --git a/drivers/mtd/nand/bmt.h b/drivers/mtd/nand/bmt.h
new file mode 100644
index 0000000000000000000000000000000000000000..3401be6920e728dcfd413620c57e24b082d88586
--- /dev/null
+++ b/drivers/mtd/nand/bmt.h
@@ -0,0 +1,82 @@
+#ifndef __BMT_H__
+#define __BMT_H__
+
+#include "nand_def.h"
+
+#if defined(__PRELOADER_NAND__)
+
+#include "nand.h"
+
+#elif defined(__UBOOT_NAND__)
+
+#include <linux/mtd/nand.h>
+#include "mtk_nand.h"
+
+#elif defined(__KERNEL_NAND__)
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#ifndef __UBOOT__
+#include <linux/module.h>
+#endif
+#include "mtk_nand.h"
+
+#endif
+
+
+#define MAX_BMT_SIZE        (0x80)
+#define BMT_VERSION         (1) // initial version
+
+#define MAIN_SIGNATURE_OFFSET   (0)
+#define OOB_SIGNATURE_OFFSET    (1)
+#define OOB_INDEX_OFFSET        (29)
+#define OOB_INDEX_SIZE          (2)
+#define FAKE_INDEX              (0xAAAA)
+
+typedef struct _bmt_entry_
+{
+    u16 bad_index;              // bad block index
+    u16 mapped_index;           // mapping block index in the replace pool
+} bmt_entry;
+
+typedef enum
+{
+    UPDATE_ERASE_FAIL,
+    UPDATE_WRITE_FAIL,
+    UPDATE_UNMAPPED_BLOCK,
+    UPDATE_REASON_COUNT,
+} update_reason_t;
+
+typedef struct
+{
+    bmt_entry table[MAX_BMT_SIZE];
+    u8 version;
+    u8 mapped_count;            // mapped block count in pool
+    u8 bad_count;               // bad block count in pool. Not used in V1
+} bmt_struct;
+
+/***************************************************************
+*                                                              *
+* Interface BMT need to use                                    *
+*                                                              *
+***************************************************************/
+extern bool mtk_nand_exec_read_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob);
+extern int mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs);
+extern int mtk_nand_erase_hw(struct mtd_info *mtd, int page);
+extern int mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t ofs);
+extern int mtk_nand_exec_write_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob);
+
+
+/***************************************************************
+*                                                              *
+* Different function interface for preloader/uboot/kernel      *
+*                                                              *
+***************************************************************/
+void set_bad_index_to_oob(u8 * oob, u16 index);
+
+
+bmt_struct *init_bmt(struct nand_chip *nand, int size);
+bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob);
+unsigned short get_mapping_block_index(int index);
+
+#endif                          // #ifndef __BMT_H__
diff --git a/drivers/mtd/nand/dev-nand.c b/drivers/mtd/nand/dev-nand.c
new file mode 100644
index 0000000000000000000000000000000000000000..9fb52350fc103b52809ef034a66a666b1253305f
--- /dev/null
+++ b/drivers/mtd/nand/dev-nand.c
@@ -0,0 +1,63 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "mt6575_typedefs.h"
+
+#define RALINK_NAND_CTRL_BASE               0xBE003000
+#define NFI_base    RALINK_NAND_CTRL_BASE
+#define RALINK_NANDECC_CTRL_BASE    0xBE003800
+#define NFIECC_base RALINK_NANDECC_CTRL_BASE
+#define MT7621_NFI_IRQ_ID		SURFBOARDINT_NAND
+#define MT7621_NFIECC_IRQ_ID	SURFBOARDINT_NAND_ECC
+
+#define SURFBOARDINT_NAND 22
+#define SURFBOARDINT_NAND_ECC 23
+
+static struct resource MT7621_resource_nand[] = {
+        {
+                .start          = NFI_base,
+                .end            = NFI_base + 0x1A0,
+                .flags          = IORESOURCE_MEM,
+        },
+        {
+                .start          = NFIECC_base,
+                .end            = NFIECC_base + 0x150,
+                .flags          = IORESOURCE_MEM,
+        },
+        {
+                .start          = MT7621_NFI_IRQ_ID,
+                .flags          = IORESOURCE_IRQ,
+        },
+        {
+                .start          = MT7621_NFIECC_IRQ_ID,
+                .flags          = IORESOURCE_IRQ,
+        },
+};
+
+static struct platform_device MT7621_nand_dev = {
+    .name = "MT7621-NAND",
+    .id   = 0,
+        .num_resources  = ARRAY_SIZE(MT7621_resource_nand),
+        .resource               = MT7621_resource_nand,
+    .dev            = {
+        .platform_data = &mt7621_nand_hw,
+    },
+};
+
+
+int __init mtk_nand_register(void)
+{
+
+	int retval = 0;
+
+	retval = platform_device_register(&MT7621_nand_dev);
+	if (retval != 0) {
+		printk(KERN_ERR "register nand device fail\n");
+		return retval;
+	}
+
+
+	return retval;
+}
+arch_initcall(mtk_nand_register);
diff --git a/drivers/mtd/nand/mt6575_typedefs.h b/drivers/mtd/nand/mt6575_typedefs.h
new file mode 100644
index 0000000000000000000000000000000000000000..a7b964762872c93743a5637d5769bfb2f5f17ecf
--- /dev/null
+++ b/drivers/mtd/nand/mt6575_typedefs.h
@@ -0,0 +1,340 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2008
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+#ifndef _MT6575_TYPEDEFS_H
+#define _MT6575_TYPEDEFS_H
+
+#if defined (__KERNEL_NAND__)
+#include <linux/bug.h>
+#else
+#define true 		1 
+#define false 		0  
+#define bool		u8
+#endif
+
+// ---------------------------------------------------------------------------
+//  Basic Type Definitions
+// ---------------------------------------------------------------------------
+
+typedef volatile unsigned char  *P_kal_uint8;
+typedef volatile unsigned short *P_kal_uint16;
+typedef volatile unsigned int   *P_kal_uint32;
+
+typedef long            LONG;
+typedef unsigned char   UBYTE;
+typedef short           SHORT;
+
+typedef signed char     kal_int8;
+typedef signed short    kal_int16;
+typedef signed int      kal_int32;
+typedef long long       kal_int64;
+typedef unsigned char   kal_uint8;
+typedef unsigned short  kal_uint16;
+typedef unsigned int    kal_uint32;
+typedef unsigned long long  kal_uint64;
+typedef char            kal_char;
+
+typedef unsigned int            *UINT32P;
+typedef volatile unsigned short *UINT16P;
+typedef volatile unsigned char  *UINT8P;
+typedef unsigned char           *U8P;
+
+typedef volatile unsigned char  *P_U8;
+typedef volatile signed char    *P_S8;
+typedef volatile unsigned short *P_U16;
+typedef volatile signed short   *P_S16;
+typedef volatile unsigned int   *P_U32;
+typedef volatile signed int     *P_S32;
+typedef unsigned long long      *P_U64;
+typedef signed long long        *P_S64;
+
+typedef unsigned char       U8;
+typedef signed char         S8;
+typedef unsigned short      U16;
+typedef signed short        S16;
+typedef unsigned int        U32;
+typedef signed int          S32;
+typedef unsigned long long  U64;
+typedef signed long long    S64;
+//typedef unsigned char       bool;
+
+typedef unsigned char   UINT8;
+typedef unsigned short  UINT16;
+typedef unsigned int    UINT32;
+typedef unsigned short  USHORT;
+typedef signed char     INT8;
+typedef signed short    INT16;
+typedef signed int      INT32;
+typedef unsigned int    DWORD;
+typedef void            VOID;
+typedef unsigned char   BYTE;
+typedef float           FLOAT;
+
+typedef char           *LPCSTR;
+typedef short          *LPWSTR;
+
+
+// ---------------------------------------------------------------------------
+//  Constants
+// ---------------------------------------------------------------------------
+
+#define IMPORT  EXTERN
+#ifndef __cplusplus
+  #define EXTERN  extern
+#else
+  #define EXTERN  extern "C"
+#endif
+#define LOCAL     static
+#define GLOBAL
+#define EXPORT    GLOBAL
+
+#define EQ        ==
+#define NEQ       !=
+#define AND       &&
+#define OR        ||
+#define XOR(A,B)  ((!(A) AND (B)) OR ((A) AND !(B)))
+
+#ifndef FALSE
+  #define FALSE (0)
+#endif
+
+#ifndef TRUE
+  #define TRUE  (1)
+#endif
+
+#ifndef NULL
+  #define NULL  (0)
+#endif
+
+//enum boolean {false, true};
+enum {RX, TX, NONE};
+
+#ifndef BOOL
+typedef unsigned char  BOOL;
+#endif
+
+typedef enum {
+   KAL_FALSE = 0,
+   KAL_TRUE  = 1,
+} kal_bool;
+
+
+// ---------------------------------------------------------------------------
+//  Type Casting
+// ---------------------------------------------------------------------------
+
+#define AS_INT32(x)     (*(INT32 *)((void*)x))
+#define AS_INT16(x)     (*(INT16 *)((void*)x))
+#define AS_INT8(x)      (*(INT8  *)((void*)x))
+
+#define AS_UINT32(x)    (*(UINT32 *)((void*)x))
+#define AS_UINT16(x)    (*(UINT16 *)((void*)x))
+#define AS_UINT8(x)     (*(UINT8  *)((void*)x))
+
+
+// ---------------------------------------------------------------------------
+//  Register Manipulations
+// ---------------------------------------------------------------------------
+
+#define READ_REGISTER_UINT32(reg) \
+    (*(volatile UINT32 * const)(reg))
+
+#define WRITE_REGISTER_UINT32(reg, val) \
+    (*(volatile UINT32 * const)(reg)) = (val)
+
+#define READ_REGISTER_UINT16(reg) \
+    (*(volatile UINT16 * const)(reg))
+
+#define WRITE_REGISTER_UINT16(reg, val) \
+    (*(volatile UINT16 * const)(reg)) = (val)
+
+#define READ_REGISTER_UINT8(reg) \
+    (*(volatile UINT8 * const)(reg))
+
+#define WRITE_REGISTER_UINT8(reg, val) \
+    (*(volatile UINT8 * const)(reg)) = (val)
+
+#define INREG8(x)           READ_REGISTER_UINT8((UINT8*)((void*)(x)))
+#define OUTREG8(x, y)       WRITE_REGISTER_UINT8((UINT8*)((void*)(x)), (UINT8)(y))
+#define SETREG8(x, y)       OUTREG8(x, INREG8(x)|(y))
+#define CLRREG8(x, y)       OUTREG8(x, INREG8(x)&~(y))
+#define MASKREG8(x, y, z)   OUTREG8(x, (INREG8(x)&~(y))|(z))
+
+#define INREG16(x)          READ_REGISTER_UINT16((UINT16*)((void*)(x)))
+#define OUTREG16(x, y)      WRITE_REGISTER_UINT16((UINT16*)((void*)(x)),(UINT16)(y))
+#define SETREG16(x, y)      OUTREG16(x, INREG16(x)|(y))
+#define CLRREG16(x, y)      OUTREG16(x, INREG16(x)&~(y))
+#define MASKREG16(x, y, z)  OUTREG16(x, (INREG16(x)&~(y))|(z))
+
+#define INREG32(x)          READ_REGISTER_UINT32((UINT32*)((void*)(x)))
+#define OUTREG32(x, y)      WRITE_REGISTER_UINT32((UINT32*)((void*)(x)), (UINT32)(y))
+#define SETREG32(x, y)      OUTREG32(x, INREG32(x)|(y))
+#define CLRREG32(x, y)      OUTREG32(x, INREG32(x)&~(y))
+#define MASKREG32(x, y, z)  OUTREG32(x, (INREG32(x)&~(y))|(z))
+
+
+#define DRV_Reg8(addr)              INREG8(addr)
+#define DRV_WriteReg8(addr, data)   OUTREG8(addr, data)
+#define DRV_SetReg8(addr, data)     SETREG8(addr, data)
+#define DRV_ClrReg8(addr, data)     CLRREG8(addr, data)
+
+#define DRV_Reg16(addr)             INREG16(addr)
+#define DRV_WriteReg16(addr, data)  OUTREG16(addr, data)
+#define DRV_SetReg16(addr, data)    SETREG16(addr, data)
+#define DRV_ClrReg16(addr, data)    CLRREG16(addr, data)
+
+#define DRV_Reg32(addr)             INREG32(addr)
+#define DRV_WriteReg32(addr, data)  OUTREG32(addr, data)
+#define DRV_SetReg32(addr, data)    SETREG32(addr, data)
+#define DRV_ClrReg32(addr, data)    CLRREG32(addr, data)
+
+// !!! DEPRECATED, WILL BE REMOVED LATER !!!
+#define DRV_Reg(addr)               DRV_Reg16(addr)
+#define DRV_WriteReg(addr, data)    DRV_WriteReg16(addr, data)
+#define DRV_SetReg(addr, data)      DRV_SetReg16(addr, data)
+#define DRV_ClrReg(addr, data)      DRV_ClrReg16(addr, data)
+
+
+// ---------------------------------------------------------------------------
+//  Compiler Time Deduction Macros
+// ---------------------------------------------------------------------------
+
+#define _MASK_OFFSET_1(x, n)  ((x) & 0x1) ? (n) :
+#define _MASK_OFFSET_2(x, n)  _MASK_OFFSET_1((x), (n)) _MASK_OFFSET_1((x) >> 1, (n) + 1)
+#define _MASK_OFFSET_4(x, n)  _MASK_OFFSET_2((x), (n)) _MASK_OFFSET_2((x) >> 2, (n) + 2)
+#define _MASK_OFFSET_8(x, n)  _MASK_OFFSET_4((x), (n)) _MASK_OFFSET_4((x) >> 4, (n) + 4)
+#define _MASK_OFFSET_16(x, n) _MASK_OFFSET_8((x), (n)) _MASK_OFFSET_8((x) >> 8, (n) + 8)
+#define _MASK_OFFSET_32(x, n) _MASK_OFFSET_16((x), (n)) _MASK_OFFSET_16((x) >> 16, (n) + 16)
+
+#define MASK_OFFSET_ERROR (0xFFFFFFFF)
+
+#define MASK_OFFSET(x) (_MASK_OFFSET_32(x, 0) MASK_OFFSET_ERROR)
+
+
+// ---------------------------------------------------------------------------
+//  Assertions
+// ---------------------------------------------------------------------------
+
+#ifndef ASSERT
+    #define ASSERT(expr)        BUG_ON(!(expr))
+#endif
+
+#ifndef NOT_IMPLEMENTED
+    #define NOT_IMPLEMENTED()   BUG_ON(1)
+#endif    
+
+#define STATIC_ASSERT(pred)         STATIC_ASSERT_X(pred, __LINE__)
+#define STATIC_ASSERT_X(pred, line) STATIC_ASSERT_XX(pred, line)
+#define STATIC_ASSERT_XX(pred, line) \
+    extern char assertion_failed_at_##line[(pred) ? 1 : -1]
+
+// ---------------------------------------------------------------------------
+//  Resolve Compiler Warnings
+// ---------------------------------------------------------------------------
+
+#define NOT_REFERENCED(x)   { (x) = (x); }
+
+
+// ---------------------------------------------------------------------------
+//  Utilities
+// ---------------------------------------------------------------------------
+
+#define MAXIMUM(A,B)       (((A)>(B))?(A):(B))
+#define MINIMUM(A,B)       (((A)<(B))?(A):(B))
+
+#define ARY_SIZE(x) (sizeof((x)) / sizeof((x[0])))
+#define DVT_DELAYMACRO(u4Num)                                            \
+{                                                                        \
+    UINT32 u4Count = 0 ;                                                 \
+    for (u4Count = 0; u4Count < u4Num; u4Count++ );                      \
+}                                                                        \
+
+#define    A68351B      0
+#define    B68351B      1
+#define    B68351D      2
+#define    B68351E      3
+#define    UNKNOWN_IC_VERSION   0xFF
+
+/* NAND driver */
+struct mtk_nand_host_hw {
+    unsigned int nfi_bus_width;		    /* NFI_BUS_WIDTH */ 
+	unsigned int nfi_access_timing;		/* NFI_ACCESS_TIMING */  
+	unsigned int nfi_cs_num;			/* NFI_CS_NUM */
+	unsigned int nand_sec_size;			/* NAND_SECTOR_SIZE */
+	unsigned int nand_sec_shift;		/* NAND_SECTOR_SHIFT */
+	unsigned int nand_ecc_size;
+	unsigned int nand_ecc_bytes;
+	unsigned int nand_ecc_mode;
+};
+extern struct mtk_nand_host_hw mt7621_nand_hw;
+extern unsigned int	CFG_BLOCKSIZE;
+
+#endif  // _MT6575_TYPEDEFS_H
+
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
new file mode 100644
index 0000000000000000000000000000000000000000..d870e51a5aa00102bb34472fea9109ab50e766de
--- /dev/null
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -0,0 +1,2123 @@
+/******************************************************************************
+* mtk_nand.c - MTK NAND Flash Device Driver
+ *
+* Copyright 2009-2012 MediaTek Co.,Ltd.
+ *
+* DESCRIPTION:
+* 	This file provid the other drivers nand relative functions
+ *
+* modification history
+* ----------------------------------------
+* v3.0, 11 Feb 2010, mtk
+* ----------------------------------------
+******************************************************************************/
+
+#include "nand_def.h"
+
+#ifndef __UBOOT__
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#else
+#include <common.h>
+#include <nand.h>
+#include <div64.h>
+#include <linux/compat.h>
+#include <memalign.h>
+#endif
+#include <linux/types.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include "mtk_nand.h"
+#include "nand_device_list.h"
+
+#include "bmt.h"
+#include "partition.h"
+
+
+static int shift_on_bbt = 0;
+extern void nand_bbt_set(struct mtd_info *mtd, int page, int flag);
+extern int nand_bbt_get(struct mtd_info *mtd, int page);
+static int mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page);
+
+static const char * const probe_types[] = { "cmdlinepart", "ofpart", NULL };
+
+#define NAND_CMD_STATUS_MULTI  0x71
+
+void show_stack(struct task_struct *tsk, unsigned long *sp);
+extern void mt_irq_set_sens(unsigned int irq, unsigned int sens);
+extern void mt_irq_set_polarity(unsigned int irq,unsigned int polarity);
+
+struct mtk_nand_host	mtk_nand_host;	/* include mtd_info and nand_chip structs */
+struct mtk_nand_host_hw mt7621_nand_hw = {
+    .nfi_bus_width          = 8,
+    .nfi_access_timing      = NFI_DEFAULT_ACCESS_TIMING,
+    .nfi_cs_num             = NFI_CS_NUM,
+    .nand_sec_size          = 512,
+    .nand_sec_shift         = 9,
+    .nand_ecc_size          = 2048,
+    .nand_ecc_bytes         = 32,
+    .nand_ecc_mode          = NAND_ECC_HW,
+};
+
+
+/*******************************************************************************
+ * Gloable Varible Definition
+ *******************************************************************************/
+
+#define NFI_ISSUE_COMMAND(cmd, col_addr, row_addr, col_num, row_num) \
+   do { \
+      DRV_WriteReg(NFI_CMD_REG16,cmd);\
+      while (DRV_Reg32(NFI_STA_REG32) & STA_CMD_STATE);\
+      DRV_WriteReg32(NFI_COLADDR_REG32, col_addr);\
+      DRV_WriteReg32(NFI_ROWADDR_REG32, row_addr);\
+      DRV_WriteReg(NFI_ADDRNOB_REG16, col_num | (row_num<<ADDR_ROW_NOB_SHIFT));\
+      while (DRV_Reg32(NFI_STA_REG32) & STA_ADDR_STATE);\
+   }while(0);
+
+//-------------------------------------------------------------------------------
+static struct NAND_CMD g_kCMD;
+static u32 g_u4ChipVer;
+bool g_bInitDone;
+static bool g_bcmdstatus;
+static u32 g_value = 0;
+
+BOOL g_bHwEcc = true;
+
+
+static u8 *local_buffer_16_align;   // 16 byte aligned buffer, for HW issue
+static u8 local_buffer[4096 + 512];
+
+extern void nand_release_device(struct mtd_info *mtd);
+extern int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state);
+
+#if defined(MTK_NAND_BMT)
+static bmt_struct *g_bmt;
+#endif
+struct mtk_nand_host *host;
+extern struct mtd_partition g_pasStatic_Partition[];
+int part_num = NUM_PARTITIONS;
+int manu_id;
+int dev_id;
+
+static u8 local_oob_buf[NAND_MAX_OOBSIZE];
+
+static u8 nand_badblock_offset = 0;
+
+#if 0
+static struct nand_ecclayout nand_oob_16 = {
+	.eccbytes = 8,
+	.eccpos = {8, 9, 10, 11, 12, 13, 14, 15},
+	.oobfree = {{1, 6}, {0, 0}}
+};
+#endif
+struct nand_ecclayout nand_oob_64 = {
+	.eccbytes = 32,
+	.eccpos = {32, 33, 34, 35, 36, 37, 38, 39,
+		40, 41, 42, 43, 44, 45, 46, 47,
+		48, 49, 50, 51, 52, 53, 54, 55,
+		56, 57, 58, 59, 60, 61, 62, 63},
+	.oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 6}, {0, 0}}
+};
+
+struct nand_ecclayout nand_oob_128 = {
+	.eccbytes = 64,
+	.eccpos = {
+		64, 65, 66, 67, 68, 69, 70, 71,
+		72, 73, 74, 75, 76, 77, 78, 79,
+		80, 81, 82, 83, 84, 85, 86, 86,
+		88, 89, 90, 91, 92, 93, 94, 95,
+		96, 97, 98, 99, 100, 101, 102, 103,
+		104, 105, 106, 107, 108, 109, 110, 111,
+		112, 113, 114, 115, 116, 117, 118, 119,
+		120, 121, 122, 123, 124, 125, 126, 127},
+	.oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 7}, {33, 7}, {41, 7}, {49, 7}, {57, 6}}
+};
+
+flashdev_info devinfo;
+
+void dump_nfi(void)
+{
+}
+
+void dump_ecc(void)
+{
+}
+
+static void
+ECC_Config(struct mtk_nand_host_hw *hw,u32 ecc_bit)
+{
+	u32 u4ENCODESize;
+	u32 u4DECODESize;
+	u32 ecc_bit_cfg = ECC_CNFG_ECC4;
+
+	switch(ecc_bit){
+	case 4:
+		ecc_bit_cfg = ECC_CNFG_ECC4;
+		break;
+	case 8:
+		ecc_bit_cfg = ECC_CNFG_ECC8;
+		break;
+	case 10:
+		ecc_bit_cfg = ECC_CNFG_ECC10;
+		break;
+	case 12:
+		ecc_bit_cfg = ECC_CNFG_ECC12;
+		break;
+	default:
+		break;
+	}
+	DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE);
+	do {
+	} while (!DRV_Reg16(ECC_DECIDLE_REG16));
+
+	DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE);
+	do {
+	} while (!DRV_Reg32(ECC_ENCIDLE_REG32));
+
+	/* setup FDM register base */
+	DRV_WriteReg32(ECC_FDMADDR_REG32, NFI_FDM0L_REG32);
+
+	/* Sector + FDM */
+	u4ENCODESize = (hw->nand_sec_size + 8) << 3;
+	/* Sector + FDM + YAFFS2 meta data bits */
+	u4DECODESize = ((hw->nand_sec_size + 8) << 3) + ecc_bit * 13;
+
+	/* configure ECC decoder && encoder */
+	DRV_WriteReg32(ECC_DECCNFG_REG32, ecc_bit_cfg | DEC_CNFG_NFI | DEC_CNFG_EMPTY_EN | (u4DECODESize << DEC_CNFG_CODE_SHIFT));
+
+	DRV_WriteReg32(ECC_ENCCNFG_REG32, ecc_bit_cfg | ENC_CNFG_NFI | (u4ENCODESize << ENC_CNFG_MSG_SHIFT));
+	NFI_SET_REG32(ECC_DECCNFG_REG32, DEC_CNFG_EL);
+}
+
+static void
+ECC_Decode_Start(void)
+{
+	while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE))
+		;
+	DRV_WriteReg16(ECC_DECCON_REG16, DEC_EN);
+}
+
+static void
+ECC_Decode_End(void)
+{
+	while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE))
+		;
+	DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE);
+}
+
+static void
+ECC_Encode_Start(void)
+{
+	while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE))
+		;
+	mb();
+	DRV_WriteReg16(ECC_ENCCON_REG16, ENC_EN);
+}
+
+static void
+ECC_Encode_End(void)
+{
+	/* wait for device returning idle */
+	while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ;
+	mb();
+	DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE);
+}
+
+static bool
+mtk_nand_check_bch_error(struct mtd_info *mtd, u8 * pDataBuf, u32 u4SecIndex, u32 u4PageAddr)
+{
+	bool bRet = true;
+	u16 u2SectorDoneMask = 1 << u4SecIndex;
+//	u32 u4ErrorNumDebug, i, u4ErrNum;
+	u32 i, u4ErrNum;
+	u32 timeout = 0xFFFF;
+	// int el;
+	u32 au4ErrBitLoc[6];
+	u32 u4ErrByteLoc, u4BitOffset;
+	u32 u4ErrBitLoc1th, u4ErrBitLoc2nd;
+
+	//4 // Wait for Decode Done
+	while (0 == (u2SectorDoneMask & DRV_Reg16(ECC_DECDONE_REG16))) {
+		timeout--;
+		if (0 == timeout)
+			return false;
+	}
+	/* We will manually correct the error bits in the last sector, not all the sectors of the page! */
+	memset(au4ErrBitLoc, 0x0, sizeof(au4ErrBitLoc));
+	//u4ErrorNumDebug = DRV_Reg32(ECC_DECENUM_REG32);
+	u4ErrNum = DRV_Reg32(ECC_DECENUM_REG32) >> (u4SecIndex << 2);
+	u4ErrNum &= 0xF;
+
+	if (u4ErrNum) {
+		if (0xF == u4ErrNum) {
+			mtd->ecc_stats.failed++;
+			bRet = false;
+			//printk(KERN_ERR"UnCorrectable at PageAddr=%d\n", u4PageAddr);
+		} else {
+			for (i = 0; i < ((u4ErrNum + 1) >> 1); ++i) {
+				au4ErrBitLoc[i] = DRV_Reg32(ECC_DECEL0_REG32 + i);
+				u4ErrBitLoc1th = au4ErrBitLoc[i] & 0x1FFF;
+				if (u4ErrBitLoc1th < 0x1000) {
+					u4ErrByteLoc = u4ErrBitLoc1th / 8;
+					u4BitOffset = u4ErrBitLoc1th % 8;
+					pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset);
+					mtd->ecc_stats.corrected++;
+				} else {
+					mtd->ecc_stats.failed++;
+				}
+				u4ErrBitLoc2nd = (au4ErrBitLoc[i] >> 16) & 0x1FFF;
+				if (0 != u4ErrBitLoc2nd) {
+					if (u4ErrBitLoc2nd < 0x1000) {
+						u4ErrByteLoc = u4ErrBitLoc2nd / 8;
+						u4BitOffset = u4ErrBitLoc2nd % 8;
+						pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset);
+						mtd->ecc_stats.corrected++;
+					} else {
+						mtd->ecc_stats.failed++;
+						//printk(KERN_ERR"UnCorrectable High ErrLoc=%d\n", au4ErrBitLoc[i]);
+					}
+				}
+			}
+		}
+		if (0 == (DRV_Reg16(ECC_DECFER_REG16) & (1 << u4SecIndex)))
+			bRet = false;
+	}
+	return bRet;
+}
+
+static bool
+mtk_nand_RFIFOValidSize(u16 u2Size)
+{
+	u32 timeout = 0xFFFF;
+	while (FIFO_RD_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) < u2Size) {
+		timeout--;
+		if (0 == timeout)
+			return false;
+	}
+	return true;
+}
+
+static bool
+mtk_nand_WFIFOValidSize(u16 u2Size)
+{
+	u32 timeout = 0xFFFF;
+
+	while (FIFO_WR_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) > u2Size) {
+		timeout--;
+		if (0 == timeout)
+			return false;
+	}
+	return true;
+}
+
+static bool
+mtk_nand_status_ready(u32 u4Status)
+{
+	u32 timeout = 0xFFFF;
+
+	while ((DRV_Reg32(NFI_STA_REG32) & u4Status) != 0) {
+		timeout--;
+		if (0 == timeout)
+			return false;
+	}
+	return true;
+}
+
+static bool
+mtk_nand_reset(void)
+{
+	int timeout = 0xFFFF;
+	if (DRV_Reg16(NFI_MASTERSTA_REG16)) {
+		mb();
+		DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST);
+		while (DRV_Reg16(NFI_MASTERSTA_REG16)) {
+			timeout--;
+			if (!timeout)
+				MSG(INIT, "Wait for NFI_MASTERSTA timeout\n");
+		}
+	}
+	/* issue reset operation */
+	mb();
+	DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST);
+
+	return mtk_nand_status_ready(STA_NFI_FSM_MASK | STA_NAND_BUSY) && mtk_nand_RFIFOValidSize(0) && mtk_nand_WFIFOValidSize(0);
+}
+
+static void
+mtk_nand_set_mode(u16 u2OpMode)
+{
+	u16 u2Mode = DRV_Reg16(NFI_CNFG_REG16);
+	u2Mode &= ~CNFG_OP_MODE_MASK;
+	u2Mode |= u2OpMode;
+	DRV_WriteReg16(NFI_CNFG_REG16, u2Mode);
+}
+
+static void
+mtk_nand_set_autoformat(bool bEnable)
+{
+	if (bEnable)
+		NFI_SET_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN);
+	else
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN);
+}
+
+static void
+mtk_nand_configure_fdm(u16 u2FDMSize)
+{
+	NFI_CLN_REG16(NFI_PAGEFMT_REG16, PAGEFMT_FDM_MASK | PAGEFMT_FDM_ECC_MASK);
+	NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_SHIFT);
+	NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_ECC_SHIFT);
+}
+
+static void
+mtk_nand_configure_lock(void)
+{
+	u32 u4WriteColNOB = 2;
+	u32 u4WriteRowNOB = 3;
+	u32 u4EraseColNOB = 0;
+	u32 u4EraseRowNOB = 3;
+	DRV_WriteReg16(NFI_LOCKANOB_REG16,
+		(u4WriteColNOB << PROG_CADD_NOB_SHIFT) | (u4WriteRowNOB << PROG_RADD_NOB_SHIFT) | (u4EraseColNOB << ERASE_CADD_NOB_SHIFT) | (u4EraseRowNOB << ERASE_RADD_NOB_SHIFT));
+
+	if (CHIPVER_ECO_1 == g_u4ChipVer) {
+		int i;
+		for (i = 0; i < 16; ++i) {
+			DRV_WriteReg32(NFI_LOCK00ADD_REG32 + (i << 1), 0xFFFFFFFF);
+			DRV_WriteReg32(NFI_LOCK00FMT_REG32 + (i << 1), 0xFFFFFFFF);
+		}
+		//DRV_WriteReg16(NFI_LOCKANOB_REG16, 0x0);
+		DRV_WriteReg32(NFI_LOCKCON_REG32, 0xFFFFFFFF);
+		DRV_WriteReg16(NFI_LOCK_REG16, NFI_LOCK_ON);
+	}
+}
+
+static bool
+mtk_nand_pio_ready(void)
+{
+	int count = 0;
+	while (!(DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1)) {
+		count++;
+		if (count > 0xffff) {
+			printk("PIO_DIRDY timeout\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static bool
+mtk_nand_set_command(u16 command)
+{
+	mb();
+	DRV_WriteReg16(NFI_CMD_REG16, command);
+	return mtk_nand_status_ready(STA_CMD_STATE);
+}
+
+static bool
+mtk_nand_set_address(u32 u4ColAddr, u32 u4RowAddr, u16 u2ColNOB, u16 u2RowNOB)
+{
+	mb();
+	DRV_WriteReg32(NFI_COLADDR_REG32, u4ColAddr);
+	DRV_WriteReg32(NFI_ROWADDR_REG32, u4RowAddr);
+	DRV_WriteReg16(NFI_ADDRNOB_REG16, u2ColNOB | (u2RowNOB << ADDR_ROW_NOB_SHIFT));
+	return mtk_nand_status_ready(STA_ADDR_STATE);
+}
+
+static bool
+mtk_nand_check_RW_count(u16 u2WriteSize)
+{
+	u32 timeout = 0xFFFF;
+	u16 u2SecNum = u2WriteSize >> 9;
+
+	while (ADDRCNTR_CNTR(DRV_Reg16(NFI_ADDRCNTR_REG16)) < u2SecNum) {
+		timeout--;
+		if (0 == timeout) {
+			printk(KERN_INFO "[%s] timeout\n", __FUNCTION__);
+			return false;
+		}
+	}
+	return true;
+}
+
+static bool
+mtk_nand_ready_for_read(struct nand_chip *nand, u32 u4RowAddr, u32 u4ColAddr, bool full, u8 * buf)
+{
+	/* Reset NFI HW internal state machine and flush NFI in/out FIFO */
+	bool bRet = false;
+	u16 sec_num = 1 << (nand->page_shift - 9);
+	u32 col_addr = u4ColAddr;
+	u32 colnob = 2, rownob = devinfo.addr_cycle - 2;
+	if (nand->options & NAND_BUSWIDTH_16)
+		col_addr /= 2;
+
+	if (!mtk_nand_reset())
+		goto cleanup;
+	if (g_bHwEcc)	{
+		NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+	} else	{
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+	}
+
+	mtk_nand_set_mode(CNFG_OP_READ);
+	NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN);
+	DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT);
+
+	if (full) {
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB);
+
+		if (g_bHwEcc)
+			NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		else
+			NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+	} else {
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB);
+	}
+
+	mtk_nand_set_autoformat(full);
+	if (full)
+		if (g_bHwEcc)
+			ECC_Decode_Start();
+	if (!mtk_nand_set_command(NAND_CMD_READ0))
+		goto cleanup;
+	if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob))
+		goto cleanup;
+	if (!mtk_nand_set_command(NAND_CMD_READSTART))
+		goto cleanup;
+	if (!mtk_nand_status_ready(STA_NAND_BUSY))
+		goto cleanup;
+
+	bRet = true;
+
+cleanup:
+	return bRet;
+}
+
+static bool
+mtk_nand_ready_for_write(struct nand_chip *nand, u32 u4RowAddr, u32 col_addr, bool full, u8 * buf)
+{
+	bool bRet = false;
+	u32 sec_num = 1 << (nand->page_shift - 9);
+	u32 colnob = 2, rownob = devinfo.addr_cycle - 2;
+	if (nand->options & NAND_BUSWIDTH_16)
+		col_addr /= 2;
+
+	/* Reset NFI HW internal state machine and flush NFI in/out FIFO */
+	if (!mtk_nand_reset())
+		return false;
+
+	mtk_nand_set_mode(CNFG_OP_PRGM);
+
+	NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_READ_EN);
+
+	DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT);
+
+	if (full) {
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB);
+		if (g_bHwEcc)
+			NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		else
+			NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+	} else {
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB);
+	}
+
+	mtk_nand_set_autoformat(full);
+
+	if (full)
+		if (g_bHwEcc)
+			ECC_Encode_Start();
+
+	if (!mtk_nand_set_command(NAND_CMD_SEQIN))
+		goto cleanup;
+	//1 FIXED ME: For Any Kind of AddrCycle
+	if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob))
+		goto cleanup;
+
+	if (!mtk_nand_status_ready(STA_NAND_BUSY))
+		goto cleanup;
+
+	bRet = true;
+
+cleanup:
+	return bRet;
+}
+
+static bool
+mtk_nand_check_dececc_done(u32 u4SecNum)
+{
+	u32 timeout, dec_mask;
+
+	timeout = 0xffff;
+	dec_mask = (1 << u4SecNum) - 1;
+	while ((dec_mask != DRV_Reg(ECC_DECDONE_REG16)) && timeout > 0)
+		timeout--;
+	if (timeout == 0) {
+		MSG(VERIFY, "ECC_DECDONE: timeout\n");
+		return false;
+	}
+	return true;
+}
+
+static bool
+mtk_nand_mcu_read_data(u8 * buf, u32 length)
+{
+	int timeout = 0xffff;
+	u32 i;
+	u32 *buf32 = (u32 *) buf;
+	if ((u32) buf % 4 || length % 4)
+		NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW);
+	else
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW);
+
+	//DRV_WriteReg32(NFI_STRADDR_REG32, 0);
+	mb();
+	NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BRD);
+
+	if ((u32) buf % 4 || length % 4) {
+		for (i = 0; (i < (length)) && (timeout > 0);) {
+			if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) {
+				*buf++ = (u8) DRV_Reg32(NFI_DATAR_REG32);
+				i++;
+			} else {
+				timeout--;
+			}
+			if (0 == timeout) {
+				printk(KERN_ERR "[%s] timeout\n", __FUNCTION__);
+				dump_nfi();
+				return false;
+			}
+		}
+	} else {
+		for (i = 0; (i < (length >> 2)) && (timeout > 0);) {
+			if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) {
+				*buf32++ = DRV_Reg32(NFI_DATAR_REG32);
+				i++;
+			} else {
+				timeout--;
+			}
+			if (0 == timeout) {
+				printk(KERN_ERR "[%s] timeout\n", __FUNCTION__);
+				dump_nfi();
+				return false;
+			}
+		}
+	}
+	return true;
+}
+
+static bool
+mtk_nand_read_page_data(struct mtd_info *mtd, u8 * pDataBuf, u32 u4Size)
+{
+	return mtk_nand_mcu_read_data(pDataBuf, u4Size);
+}
+
+static bool
+mtk_nand_mcu_write_data(struct mtd_info *mtd, const u8 * buf, u32 length)
+{
+	u32 timeout = 0xFFFF;
+	u32 i;
+	u32 *pBuf32;
+	NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW);
+	mb();
+	NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BWR);
+	pBuf32 = (u32 *) buf;
+
+	if ((u32) buf % 4 || length % 4)
+		NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW);
+	else
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW);
+
+	if ((u32) buf % 4 || length % 4) {
+		for (i = 0; (i < (length)) && (timeout > 0);) {
+			if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) {
+				DRV_WriteReg32(NFI_DATAW_REG32, *buf++);
+				i++;
+			} else {
+				timeout--;
+			}
+			if (0 == timeout) {
+				printk(KERN_ERR "[%s] timeout\n", __FUNCTION__);
+				dump_nfi();
+				return false;
+			}
+		}
+	} else {
+		for (i = 0; (i < (length >> 2)) && (timeout > 0);) {
+			if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) {
+				DRV_WriteReg32(NFI_DATAW_REG32, *pBuf32++);
+				i++;
+			} else {
+				timeout--;
+			}
+			if (0 == timeout) {
+				printk(KERN_ERR "[%s] timeout\n", __FUNCTION__);
+				dump_nfi();
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+static bool
+mtk_nand_write_page_data(struct mtd_info *mtd, u8 * buf, u32 size)
+{
+	return mtk_nand_mcu_write_data(mtd, buf, size);
+}
+
+static void
+mtk_nand_read_fdm_data(u8 * pDataBuf, u32 u4SecNum)
+{
+	u32 i;
+	u32 *pBuf32 = (u32 *) pDataBuf;
+
+	if (pBuf32) {
+		for (i = 0; i < u4SecNum; ++i) {
+			*pBuf32++ = DRV_Reg32(NFI_FDM0L_REG32 + (i << 1));
+			*pBuf32++ = DRV_Reg32(NFI_FDM0M_REG32 + (i << 1));
+		}
+	}
+}
+
+static u8 fdm_buf[64];
+static void
+mtk_nand_write_fdm_data(struct nand_chip *chip, u8 * pDataBuf, u32 u4SecNum)
+{
+	u32 i, j;
+	u8 checksum = 0;
+	bool empty = true;
+	struct nand_oobfree *free_entry;
+	u32 *pBuf32;
+
+	memcpy(fdm_buf, pDataBuf, u4SecNum * 8);
+
+	free_entry = chip->ecc.layout->oobfree;
+	for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free_entry[i].length; i++) {
+		for (j = 0; j < free_entry[i].length; j++) {
+			if (pDataBuf[free_entry[i].offset + j] != 0xFF)
+				empty = false;
+			checksum ^= pDataBuf[free_entry[i].offset + j];
+		}
+	}
+
+	if (!empty) {
+		fdm_buf[free_entry[i - 1].offset + free_entry[i - 1].length] = checksum;
+	}
+
+	pBuf32 = (u32 *) fdm_buf;
+	for (i = 0; i < u4SecNum; ++i) {
+		DRV_WriteReg32(NFI_FDM0L_REG32 + (i << 1), *pBuf32++);
+		DRV_WriteReg32(NFI_FDM0M_REG32 + (i << 1), *pBuf32++);
+	}
+}
+
+static void
+mtk_nand_stop_read(void)
+{
+	NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD);
+	mtk_nand_reset();
+	if (g_bHwEcc)
+		ECC_Decode_End();
+	DRV_WriteReg16(NFI_INTR_EN_REG16, 0);
+}
+
+static void
+mtk_nand_stop_write(void)
+{
+	NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR);
+	if (g_bHwEcc)
+		ECC_Encode_End();
+	DRV_WriteReg16(NFI_INTR_EN_REG16, 0);
+}
+
+bool
+mtk_nand_exec_read_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf)
+{
+	u8 *buf;
+	bool bRet = true;
+	struct nand_chip *nand = mtd->priv;
+	u32 u4SecNum = u4PageSize >> 9;
+
+	if (((u32) pPageBuf % 16) && local_buffer_16_align)
+		buf = local_buffer_16_align;
+	else
+		buf = pPageBuf;
+	if (mtk_nand_ready_for_read(nand, u4RowAddr, 0, true, buf)) {
+		int j;
+		for (j = 0 ; j < u4SecNum; j++) {
+			if (!mtk_nand_read_page_data(mtd, buf+j*512, 512))
+				bRet = false;
+			if(g_bHwEcc && !mtk_nand_check_dececc_done(j+1))
+				bRet = false;
+			if(g_bHwEcc && !mtk_nand_check_bch_error(mtd, buf+j*512, j, u4RowAddr))
+				bRet = false;
+		}
+		if (!mtk_nand_status_ready(STA_NAND_BUSY))
+			bRet = false;
+
+		mtk_nand_read_fdm_data(pFDMBuf, u4SecNum);
+		mtk_nand_stop_read();
+	}
+
+	if (buf == local_buffer_16_align)
+		memcpy(pPageBuf, buf, u4PageSize);
+
+	return bRet;
+}
+
+int
+mtk_nand_exec_write_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf)
+{
+	struct nand_chip *chip = mtd->priv;
+	u32 u4SecNum = u4PageSize >> 9;
+	u8 *buf;
+	u8 status;
+
+	MSG(WRITE, "mtk_nand_exec_write_page, page: 0x%x\n", u4RowAddr);
+
+	if (((u32) pPageBuf % 16) && local_buffer_16_align) {
+		printk(KERN_INFO "Data buffer not 16 bytes aligned: %p\n", pPageBuf);
+		memcpy(local_buffer_16_align, pPageBuf, mtd->writesize);
+		buf = local_buffer_16_align;
+	} else
+		buf = pPageBuf;
+
+	if (mtk_nand_ready_for_write(chip, u4RowAddr, 0, true, buf)) {
+		mtk_nand_write_fdm_data(chip, pFDMBuf, u4SecNum);
+		(void)mtk_nand_write_page_data(mtd, buf, u4PageSize);
+		(void)mtk_nand_check_RW_count(u4PageSize);
+		mtk_nand_stop_write();
+		(void)mtk_nand_set_command(NAND_CMD_PAGEPROG);
+		while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ;
+	}
+
+	status = chip->waitfunc(mtd, chip);
+	if (status & NAND_STATUS_FAIL)
+		return -EIO;
+	return 0;
+}
+
+static int
+get_start_end_block(struct mtd_info *mtd, int block, int *start_blk, int *end_blk)
+{
+	struct nand_chip *chip = mtd->priv;
+	int i;
+
+	*start_blk = 0;
+        for (i = 0; i <= part_num; i++)
+        {
+		if (i == part_num)
+		{
+			// try the last reset partition
+			*end_blk = (chip->chipsize >> chip->phys_erase_shift) - 1;
+			if (*start_blk <= *end_blk)
+			{
+				if ((block >= *start_blk) && (block <= *end_blk))
+					break;
+			}
+		}
+		// skip All partition entry
+		else if (g_pasStatic_Partition[i].size == MTDPART_SIZ_FULL)
+		{
+			continue;
+		}
+                *end_blk = *start_blk + (g_pasStatic_Partition[i].size >> chip->phys_erase_shift) - 1;
+                if ((block >= *start_blk) && (block <= *end_blk))
+                        break;
+                *start_blk = *end_blk + 1;
+        }
+        if (*start_blk > *end_blk)
+	{
+                return -1;
+	}
+	return 0;
+}
+
+static int
+block_remap(struct mtd_info *mtd, int block)
+{
+	struct nand_chip *chip = mtd->priv;
+	int start_blk, end_blk;
+	int j, block_offset;
+	int bad_block = 0;
+
+	if (chip->bbt == NULL) {
+		printk("ERROR!! no bbt table for block_remap\n");
+		return -1;
+	}
+
+	if (get_start_end_block(mtd, block, &start_blk, &end_blk) < 0) {
+		printk("ERROR!! can not find start_blk and end_blk\n");
+		return -1;
+	}
+
+	block_offset = block - start_blk;
+	for (j = start_blk; j <= end_blk;j++) {
+		if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) == 0x0) {
+			if (!block_offset)
+				break;
+			block_offset--;
+		} else {
+			bad_block++;
+		}
+	}
+	if (j <= end_blk) {
+		return j;
+	} else {
+		// remap to the bad block
+		for (j = end_blk; bad_block > 0; j--)
+		{
+			if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) != 0x0)
+			{
+				bad_block--;
+				if (bad_block <= block_offset)
+					return j;
+			}
+		}
+	}
+
+	printk("Error!! block_remap error\n");
+	return -1;
+}
+
+int
+check_block_remap(struct mtd_info *mtd, int block)
+{
+	if (shift_on_bbt)
+		return  block_remap(mtd, block);
+	else
+		return block;
+}
+EXPORT_SYMBOL(check_block_remap);
+
+
+static int
+write_next_on_fail(struct mtd_info *mtd, char *write_buf, int page, int * to_blk)
+{
+	struct nand_chip *chip = mtd->priv;
+	int i, j, to_page = 0, first_page;
+	char *buf, *oob;
+	int start_blk = 0, end_blk;
+	int mapped_block;
+	int page_per_block_bit = chip->phys_erase_shift - chip->page_shift;
+	int block = page >> page_per_block_bit;
+
+	// find next available block in the same MTD partition 
+	mapped_block = block_remap(mtd, block);
+	if (mapped_block == -1)
+		return NAND_STATUS_FAIL;
+
+	get_start_end_block(mtd, block, &start_blk, &end_blk);
+
+	buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL | GFP_DMA);
+	if (buf == NULL)
+		return -1;
+
+	oob = buf + mtd->writesize;
+	for ((*to_blk) = block + 1; (*to_blk) <= end_blk ; (*to_blk)++)	{
+		if (nand_bbt_get(mtd, (*to_blk) << page_per_block_bit) == 0) {
+			int status;
+			status = mtk_nand_erase_hw(mtd, (*to_blk) << page_per_block_bit);
+			if (status & NAND_STATUS_FAIL)	{
+				mtk_nand_block_markbad_hw(mtd, (*to_blk) << chip->phys_erase_shift);
+				nand_bbt_set(mtd, (*to_blk) << page_per_block_bit, 0x3);
+			} else {
+				/* good block */
+				to_page = (*to_blk) << page_per_block_bit;
+				break;
+			}
+		}
+	}
+
+	if (!to_page) {
+		kfree(buf);
+		return -1;
+	}
+
+	first_page = (page >> page_per_block_bit) << page_per_block_bit;
+	for (i = 0; i < (1 << page_per_block_bit); i++) {
+		if ((first_page + i) != page) {
+			mtk_nand_read_oob_hw(mtd, chip, (first_page+i));
+			for (j = 0; j < mtd->oobsize; j++)
+				if (chip->oob_poi[j] != (unsigned char)0xff)
+					break;
+			if (j < mtd->oobsize)	{
+				mtk_nand_exec_read_page(mtd, (first_page+i), mtd->writesize, (u8 *)buf, (u8 *)oob);
+				memset(oob, 0xff, mtd->oobsize);
+				if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)buf, (u8 *)oob) != 0) {
+					int ret, new_blk = 0;
+					nand_bbt_set(mtd, to_page, 0x3);
+					ret =  write_next_on_fail(mtd, buf, to_page + i, &new_blk);
+					if (ret) {
+						kfree(buf);
+						mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift);
+						return ret;
+					}
+					mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift);
+					*to_blk = new_blk;
+					to_page = ((*to_blk) <<  page_per_block_bit);
+				}
+			}
+		} else {
+			memset(chip->oob_poi, 0xff, mtd->oobsize);
+			if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)write_buf, chip->oob_poi) != 0) {
+				int ret, new_blk = 0;
+				nand_bbt_set(mtd, to_page, 0x3);
+				ret =  write_next_on_fail(mtd, write_buf, to_page + i, &new_blk);
+				if (ret) {
+					kfree(buf);
+					mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift);
+					return ret;
+				}
+				mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift);
+				*to_blk = new_blk;
+				to_page = ((*to_blk) <<  page_per_block_bit);
+			}
+		}
+	}
+
+	kfree(buf);
+
+	return 0;
+}
+
+static int
+mtk_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offset,
+		int data_len, const u8 * buf, int oob_required, int page, int cached, int raw)
+{
+	int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
+	int block = page / page_per_block;
+	u16 page_in_block = page % page_per_block;
+	int mapped_block = block;
+
+#if defined(MTK_NAND_BMT)
+	mapped_block = get_mapping_block_index(block);
+	// write bad index into oob
+	if (mapped_block != block)
+		set_bad_index_to_oob(chip->oob_poi, block);
+	else
+		set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX);
+#else
+	if (shift_on_bbt) {
+		mapped_block = block_remap(mtd, block);
+		if (mapped_block == -1)
+			return NAND_STATUS_FAIL;
+		if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0)
+			return NAND_STATUS_FAIL;
+	}
+#endif
+	do {
+		if (mtk_nand_exec_write_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, (u8 *)buf, chip->oob_poi)) {
+			MSG(INIT, "write fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block);
+#if defined(MTK_NAND_BMT)
+			if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, UPDATE_WRITE_FAIL, (u8 *) buf, chip->oob_poi)) {
+				MSG(INIT, "Update BMT success\n");
+				return 0;
+			} else {
+				MSG(INIT, "Update BMT fail\n");
+				return -EIO;
+			}
+#else
+			{
+				int new_blk;
+				nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3);
+				if (write_next_on_fail(mtd, (char *)buf, page_in_block + mapped_block * page_per_block, &new_blk) != 0)
+				{
+				mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift);
+				return NAND_STATUS_FAIL;
+				}
+				mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift);
+				break;
+			}
+#endif
+		} else
+			break;
+	} while(1);
+
+	return 0;
+}
+
+static void
+mtk_nand_command_bp(struct mtd_info *mtd, unsigned int command, int column, int page_addr)
+{
+	struct nand_chip *nand = mtd->priv;
+
+//	MSG(INIT, "%s: command 0x%02x col %d page %x \n", __func__, command, column, page_addr);
+
+	switch (command) {
+	case NAND_CMD_SEQIN:
+		memset(g_kCMD.au1OOB, 0xFF, sizeof(g_kCMD.au1OOB));
+		g_kCMD.pDataBuf = NULL;
+		g_kCMD.u4RowAddr = page_addr;
+		g_kCMD.u4ColAddr = column;
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		if (g_kCMD.pDataBuf || (0xFF != g_kCMD.au1OOB[nand_badblock_offset])) {
+			u8 *pDataBuf = g_kCMD.pDataBuf ? g_kCMD.pDataBuf : nand->buffers->databuf;
+			mtk_nand_exec_write_page(mtd, g_kCMD.u4RowAddr, mtd->writesize, pDataBuf, g_kCMD.au1OOB);
+			g_kCMD.u4RowAddr = (u32) - 1;
+			g_kCMD.u4OOBRowAddr = (u32) - 1;
+		}
+		break;
+
+	case NAND_CMD_READOOB:
+		g_kCMD.u4RowAddr = page_addr;
+		g_kCMD.u4ColAddr = column + mtd->writesize;
+		break;
+
+	case NAND_CMD_READ0:
+		g_kCMD.u4RowAddr = page_addr;
+		g_kCMD.u4ColAddr = column;
+		break;
+
+	case NAND_CMD_ERASE1:
+		nand->state=FL_ERASING;
+		(void)mtk_nand_reset();
+		mtk_nand_set_mode(CNFG_OP_ERASE);
+		(void)mtk_nand_set_command(NAND_CMD_ERASE1);
+		(void)mtk_nand_set_address(0, page_addr, 0, devinfo.addr_cycle - 2);
+		break;
+
+	case NAND_CMD_ERASE2:
+		(void)mtk_nand_set_command(NAND_CMD_ERASE2);
+		while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY)
+			;
+		break;
+
+	case NAND_CMD_STATUS:
+		(void)mtk_nand_reset();
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW);
+		mtk_nand_set_mode(CNFG_OP_SRD);
+		mtk_nand_set_mode(CNFG_READ_EN);
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB);
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		(void)mtk_nand_set_command(NAND_CMD_STATUS);
+		NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK);
+		mb();
+		DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD | (1 << CON_NFI_NOB_SHIFT));
+		g_bcmdstatus = true;
+		break;
+
+	case NAND_CMD_RESET:
+		(void)mtk_nand_reset();
+		DRV_WriteReg16(NFI_INTR_EN_REG16, INTR_RST_DONE_EN);
+		(void)mtk_nand_set_command(NAND_CMD_RESET);
+		DRV_WriteReg16(NFI_BASE+0x44, 0xF1);
+		while(!(DRV_Reg16(NFI_INTR_REG16)&INTR_RST_DONE_EN))
+			;
+		break;
+
+	case NAND_CMD_READID:
+		mtk_nand_reset();
+		/* Disable HW ECC */
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB);
+		NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN | CNFG_BYTE_RW);
+		(void)mtk_nand_reset();
+		mb();
+		mtk_nand_set_mode(CNFG_OP_SRD);
+		(void)mtk_nand_set_command(NAND_CMD_READID);
+//		(void)mtk_nand_set_address(0, 0, 1, 0);
+		(void)mtk_nand_set_address(column, page_addr, 1, 0);
+		DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD);
+		while (DRV_Reg32(NFI_STA_REG32) & STA_DATAR_STATE)
+			;
+		break;
+
+	default:
+		BUG();
+		break;
+	}
+}
+
+static void
+mtk_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+//	MSG(INIT, "%s:  chip = %d \n", __func__, chip);
+
+
+	/*KEN chip set ti -1 means deselect chip */
+	switch (chip) {
+	case -1:
+		break;
+	case 0:
+	case 1:
+		/*  Jun Shen, 2011.04.13  */
+		/* Note: MT6577 EVB NAND  is mounted on CS0, but FPGA is CS1  */
+		DRV_WriteReg16(NFI_CSEL_REG16, chip);
+		/*  Jun Shen, 2011.04.13 */
+		break;
+	}
+}
+
+static uint8_t
+mtk_nand_read_byte(struct mtd_info *mtd)
+{
+	uint8_t retval = 0;
+
+	if (!mtk_nand_pio_ready()) {
+		printk("pio ready timeout\n");
+		retval = false;
+	}
+
+	if (g_bcmdstatus) {
+		retval = DRV_Reg8(NFI_DATAR_REG32);
+		NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK);
+		mtk_nand_reset();
+		if (g_bHwEcc) {
+			NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		} else {
+			NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+		}
+		g_bcmdstatus = false;
+	} else
+		retval = DRV_Reg8(NFI_DATAR_REG32);
+
+	return retval;
+}
+
+static void
+mtk_nand_read_buf(struct mtd_info *mtd, uint8_t * buf, int len)
+{
+	struct nand_chip *nand = (struct nand_chip *)mtd->priv;
+	struct NAND_CMD *pkCMD = &g_kCMD;
+	u32 u4ColAddr = pkCMD->u4ColAddr;
+	u32 u4PageSize = mtd->writesize;
+
+	if (u4ColAddr < u4PageSize) {
+		if ((u4ColAddr == 0) && (len >= u4PageSize)) {
+			mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, pkCMD->au1OOB);
+			if (len > u4PageSize) {
+				u32 u4Size = min(len - u4PageSize, sizeof(pkCMD->au1OOB));
+				memcpy(buf + u4PageSize, pkCMD->au1OOB, u4Size);
+			}
+		} else {
+			mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB);
+			memcpy(buf, nand->buffers->databuf + u4ColAddr, len);
+		}
+		pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr;
+	} else {
+		u32 u4Offset = u4ColAddr - u4PageSize;
+		u32 u4Size = min(len - u4Offset, sizeof(pkCMD->au1OOB));
+		if (pkCMD->u4OOBRowAddr != pkCMD->u4RowAddr) {
+			mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB);
+			pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr;
+		}
+		memcpy(buf, pkCMD->au1OOB + u4Offset, u4Size);
+	}
+	pkCMD->u4ColAddr += len;
+}
+
+static void
+mtk_nand_write_buf(struct mtd_info *mtd, const uint8_t * buf, int len)
+{
+	struct NAND_CMD *pkCMD = &g_kCMD;
+	u32 u4ColAddr = pkCMD->u4ColAddr;
+	u32 u4PageSize = mtd->writesize;
+	int i4Size, i;
+
+	if (u4ColAddr >= u4PageSize) {
+		u32 u4Offset = u4ColAddr - u4PageSize;
+		u8 *pOOB = pkCMD->au1OOB + u4Offset;
+		i4Size = min(len, (int)(sizeof(pkCMD->au1OOB) - u4Offset));
+		for (i = 0; i < i4Size; i++) {
+			pOOB[i] &= buf[i];
+		}
+	} else {
+		pkCMD->pDataBuf = (u8 *) buf;
+	}
+
+	pkCMD->u4ColAddr += len;
+}
+
+static int
+mtk_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, int oob_required,int page)
+{
+	mtk_nand_write_buf(mtd, buf, mtd->writesize);
+	mtk_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	return 0;
+}
+
+int
+mtk_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, int oob_required, int page)
+{
+	struct NAND_CMD *pkCMD = &g_kCMD;
+	u32 u4ColAddr = pkCMD->u4ColAddr;
+	u32 u4PageSize = mtd->writesize;
+
+	if (u4ColAddr == 0) {
+		mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, chip->oob_poi);
+		pkCMD->u4ColAddr += u4PageSize + mtd->oobsize;
+	}
+
+	return 0;
+}
+
+#if 0
+static int
+mtk_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, u8 * buf, int page)
+{
+	int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
+	int block = page / page_per_block;
+	u16 page_in_block = page % page_per_block;
+	int mapped_block = block;
+
+#if defined (MTK_NAND_BMT)
+	mapped_block = get_mapping_block_index(block);
+	if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block,
+			mtd->writesize, buf, chip->oob_poi))
+		return 0;
+#else
+	if (shift_on_bbt) {
+		mapped_block = block_remap(mtd, block);
+		if (mapped_block == -1)
+			return NAND_STATUS_FAIL;
+		if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0)
+			return NAND_STATUS_FAIL;
+	}
+
+	if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, buf, chip->oob_poi))
+		return 0;
+	else
+		return -EIO;
+#endif
+}
+#endif
+int
+mtk_nand_erase_hw(struct mtd_info *mtd, int page)
+{
+	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+
+	chip->erase(mtd, page);
+
+	return chip->waitfunc(mtd, chip);
+}
+#if 0
+int
+mtk_nand_erase(struct mtd_info *mtd, int page)
+{
+	// get mapping 
+	struct nand_chip *chip = mtd->priv;
+	int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
+	int page_in_block = page % page_per_block;
+	int block = page / page_per_block;
+	int mapped_block = block;
+
+#if defined(MTK_NAND_BMT)    
+	mapped_block = get_mapping_block_index(block);
+#else
+	if (shift_on_bbt) {
+		mapped_block = block_remap(mtd, block);
+		if (mapped_block == -1)
+			return NAND_STATUS_FAIL;
+		if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0)
+			return NAND_STATUS_FAIL;
+	}
+#endif
+
+	do {
+		int status = mtk_nand_erase_hw(mtd, page_in_block + page_per_block * mapped_block);
+
+		if (status & NAND_STATUS_FAIL) {
+#if defined (MTK_NAND_BMT)    	
+			if (update_bmt( (page_in_block + mapped_block * page_per_block) << chip->page_shift,
+					UPDATE_ERASE_FAIL, NULL, NULL))
+			{
+				MSG(INIT, "Erase fail at block: 0x%x, update BMT success\n", mapped_block);
+				return 0;
+			} else {
+				MSG(INIT, "Erase fail at block: 0x%x, update BMT fail\n", mapped_block);
+				return NAND_STATUS_FAIL;
+			}
+#else
+			mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift);
+			nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3);
+			if (shift_on_bbt) {
+				mapped_block = block_remap(mtd, block);
+				if (mapped_block == -1)
+					return NAND_STATUS_FAIL;
+				if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0)
+					return NAND_STATUS_FAIL;
+			} else
+				return NAND_STATUS_FAIL;
+#endif
+		} else
+			break;
+	} while(1);
+
+	return 0;
+}
+#endif
+static int
+mtk_nand_read_oob_raw(struct mtd_info *mtd, uint8_t * buf, int page_addr, int len)
+{
+	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	u32 col_addr = 0;
+	u32 sector = 0;
+	int res = 0;
+	u32 colnob = 2, rawnob = devinfo.addr_cycle - 2;
+	int randomread = 0;
+	int read_len = 0;
+	int sec_num = 1<<(chip->page_shift-9);
+	int spare_per_sector = mtd->oobsize/sec_num;
+
+	if (len >  NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) {
+		printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf);
+		return -EINVAL;
+	}
+	if (len > spare_per_sector)
+		randomread = 1;
+	if (!randomread || !(devinfo.advancedmode & RAMDOM_READ)) {
+		while (len > 0) {
+			read_len = min(len, spare_per_sector);
+			col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); // TODO: Fix this hard-code 16
+			if (!mtk_nand_ready_for_read(chip, page_addr, col_addr, false, NULL)) {
+				printk(KERN_WARNING "mtk_nand_ready_for_read return failed\n");
+				res = -EIO;
+				goto error;
+			}
+			if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) {
+				printk(KERN_WARNING "mtk_nand_mcu_read_data return failed\n");
+				res = -EIO;
+				goto error;
+			}
+			mtk_nand_check_RW_count(read_len);
+			mtk_nand_stop_read();
+			sector++;
+			len -= read_len;
+		}
+	} else {
+		col_addr = NAND_SECTOR_SIZE;
+		if (chip->options & NAND_BUSWIDTH_16)
+			col_addr /= 2;
+		if (!mtk_nand_reset())
+			goto error;
+		mtk_nand_set_mode(0x6000);
+		NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN);
+		DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT);
+
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB);
+		NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+
+		mtk_nand_set_autoformat(false);
+
+		if (!mtk_nand_set_command(NAND_CMD_READ0))
+			goto error;
+		//1 FIXED ME: For Any Kind of AddrCycle
+		if (!mtk_nand_set_address(col_addr, page_addr, colnob, rawnob))
+			goto error;
+		if (!mtk_nand_set_command(NAND_CMD_READSTART))
+			goto error;
+		if (!mtk_nand_status_ready(STA_NAND_BUSY))
+			goto error;
+		read_len = min(len, spare_per_sector);
+		if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) {
+			printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n");
+			res = -EIO;
+			goto error;
+		}
+		sector++;
+		len -= read_len;
+		mtk_nand_stop_read();
+		while (len > 0) {
+			read_len = min(len,  spare_per_sector);
+			if (!mtk_nand_set_command(0x05))
+				goto error;
+			col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector);
+			if (chip->options & NAND_BUSWIDTH_16)
+				col_addr /= 2;
+			DRV_WriteReg32(NFI_COLADDR_REG32, col_addr);
+			DRV_WriteReg16(NFI_ADDRNOB_REG16, 2);
+			DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT);
+			if (!mtk_nand_status_ready(STA_ADDR_STATE))
+				goto error;
+			if (!mtk_nand_set_command(0xE0))
+				goto error;
+			if (!mtk_nand_status_ready(STA_NAND_BUSY))
+				goto error;
+			if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) {
+				printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n");
+				res = -EIO;
+				goto error;
+			}
+			mtk_nand_stop_read();
+			sector++;
+			len -= read_len;
+		}
+	}
+error:
+	NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD);
+	return res;
+}
+
+static int
+mtk_nand_write_oob_raw(struct mtd_info *mtd, const uint8_t * buf, int page_addr, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	u32 col_addr = 0;
+	u32 sector = 0;
+	int write_len = 0;
+	int status;
+	int sec_num = 1<<(chip->page_shift-9);
+	int spare_per_sector = mtd->oobsize/sec_num;
+
+	if (len >  NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) {
+		printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf);
+		return -EINVAL;
+	}
+
+	while (len > 0) {
+		write_len = min(len,  spare_per_sector);
+		col_addr = sector * (NAND_SECTOR_SIZE +  spare_per_sector) + NAND_SECTOR_SIZE;
+		if (!mtk_nand_ready_for_write(chip, page_addr, col_addr, false, NULL))
+			return -EIO;
+		if (!mtk_nand_mcu_write_data(mtd, buf + sector * spare_per_sector, write_len))
+			return -EIO;
+		(void)mtk_nand_check_RW_count(write_len);
+		NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR);
+		(void)mtk_nand_set_command(NAND_CMD_PAGEPROG);
+		while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY)
+			;
+		status = chip->waitfunc(mtd, chip);
+		if (status & NAND_STATUS_FAIL) {
+			printk(KERN_INFO "status: %d\n", status);
+			return -EIO;
+		}
+		len -= write_len;
+		sector++;
+	}
+
+	return 0;
+}
+
+static int
+mtk_nand_write_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page)
+{
+	int i, iter;
+	int sec_num = 1<<(chip->page_shift-9);
+	int spare_per_sector = mtd->oobsize/sec_num;
+	memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize);
+
+	// copy ecc data
+	for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
+		iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) *  spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR);
+		local_oob_buf[iter] = chip->oob_poi[chip->ecc.layout->eccpos[i]];
+	}
+
+	// copy FDM data
+	for (i = 0; i < sec_num; i++)
+		memcpy(&local_oob_buf[i * spare_per_sector], &chip->oob_poi[i * OOB_AVAI_PER_SECTOR], OOB_AVAI_PER_SECTOR);
+
+	return mtk_nand_write_oob_raw(mtd, local_oob_buf, page, mtd->oobsize);
+}
+
+static int mtk_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
+{
+	int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
+	int block = page / page_per_block;
+	u16 page_in_block = page % page_per_block;
+	int mapped_block = block;
+
+#if defined(MTK_NAND_BMT)
+	mapped_block = get_mapping_block_index(block);
+	// write bad index into oob
+	if (mapped_block != block)
+		set_bad_index_to_oob(chip->oob_poi, block);
+	else
+		set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX);
+#else
+	if (shift_on_bbt)
+	{
+		mapped_block = block_remap(mtd, block);
+		if (mapped_block == -1)
+			return NAND_STATUS_FAIL;
+		if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0)
+			return NAND_STATUS_FAIL;
+	}
+#endif
+	do {
+		if (mtk_nand_write_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block /* page */)) {
+			MSG(INIT, "write oob fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block);
+#if defined(MTK_NAND_BMT)      
+			if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift,
+					UPDATE_WRITE_FAIL, NULL, chip->oob_poi))
+			{
+				MSG(INIT, "Update BMT success\n");
+				return 0;
+			} else {
+				MSG(INIT, "Update BMT fail\n");
+				return -EIO;
+			}
+#else
+			mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift);
+			nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3);
+			if (shift_on_bbt) {
+				mapped_block = block_remap(mtd, mapped_block);
+				if (mapped_block == -1)
+					return NAND_STATUS_FAIL;
+				if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0)
+					return NAND_STATUS_FAIL;
+			} else {
+				return NAND_STATUS_FAIL;
+			}
+#endif
+		} else
+			break;
+	} while (1);
+
+	return 0;
+}
+
+int
+mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t offset)
+{
+	struct nand_chip *chip = mtd->priv;
+	int block = (int)offset >> chip->phys_erase_shift;
+	int page = block * (1 << (chip->phys_erase_shift - chip->page_shift));
+	u8 buf[8];
+	memset(buf, 0xFF, 8);
+	buf[0] = 0;
+	return  mtk_nand_write_oob_raw(mtd, buf, page, 8);
+}
+
+static int
+mtk_nand_block_markbad(struct mtd_info *mtd, loff_t offset)
+{
+	struct nand_chip *chip = mtd->priv;
+	int block = (int)offset >> chip->phys_erase_shift;
+	int ret;
+	int mapped_block = block;
+
+	nand_get_device(chip, mtd, FL_WRITING);
+
+#if defined(MTK_NAND_BMT)    
+	mapped_block = get_mapping_block_index(block);
+	ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift);
+#else
+	if (shift_on_bbt) {
+		mapped_block = block_remap(mtd, block);
+		if (mapped_block == -1) {
+			printk("NAND mark bad failed\n");
+			nand_release_device(mtd);
+			return NAND_STATUS_FAIL;
+		}
+	}
+	ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift);
+#endif
+	nand_release_device(mtd);
+
+	return ret;
+}
+
+static int
+mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page)
+{
+	int i;
+	u8 iter = 0;
+
+	int sec_num = 1<<(chip->page_shift-9);
+	int spare_per_sector = mtd->oobsize/sec_num;
+	if (mtk_nand_read_oob_raw(mtd, chip->oob_poi, page, mtd->oobsize)) {
+		printk(KERN_ERR "[%s]mtk_nand_read_oob_raw return failed\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	// adjust to ecc physical layout to memory layout
+	/*********************************************************/
+	/* FDM0 | ECC0 | FDM1 | ECC1 | FDM2 | ECC2 | FDM3 | ECC3 */
+	/*  8B  |  8B  |  8B  |  8B  |  8B  |  8B  |  8B  |  8B  */
+	/*********************************************************/
+
+	memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize);
+	// copy ecc data
+	for (i = 0; i < chip->ecc.layout->eccbytes; i++) {
+		iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) *  spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR);
+		chip->oob_poi[chip->ecc.layout->eccpos[i]] = local_oob_buf[iter];
+	}
+
+	// copy FDM data
+	for (i = 0; i < sec_num; i++) {
+		memcpy(&chip->oob_poi[i * OOB_AVAI_PER_SECTOR], &local_oob_buf[i *  spare_per_sector], OOB_AVAI_PER_SECTOR);
+	}
+	return 0;
+}
+
+static int
+mtk_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page)
+{
+	int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
+	int block = page / page_per_block;
+	u16 page_in_block = page % page_per_block;
+	int mapped_block = block;
+
+#if defined (MTK_NAND_BMT)
+	mapped_block = get_mapping_block_index(block);
+	mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block);
+#else
+	if (shift_on_bbt) {
+		mapped_block = block_remap(mtd, block);
+		if (mapped_block == -1)
+			return NAND_STATUS_FAIL;
+		// allow to read oob even if the block is bad
+	}
+	if (mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block)!=0)
+		return -1;
+#endif
+	return 0;
+}
+
+int
+mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	int page_addr = (int)(ofs >> chip->page_shift);
+	unsigned int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
+	unsigned char oob_buf[8];
+
+	page_addr &= ~(page_per_block - 1);
+	if (mtk_nand_read_oob_raw(mtd, oob_buf, page_addr, sizeof(oob_buf))) {
+		printk(KERN_WARNING "mtk_nand_read_oob_raw return error\n");
+		return 1;
+	}
+
+	if (oob_buf[0] != 0xff) {
+		printk(KERN_WARNING "Bad block detected at 0x%x, oob_buf[0] is 0x%x\n", page_addr, oob_buf[0]);
+		// dump_nfi();
+		return 1;
+	}
+
+	return 0;
+}
+
+#if 0
+static int
+mtk_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	int chipnr = 0;
+	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	int block = (int)ofs >> chip->phys_erase_shift;
+	int mapped_block = block;
+	int ret;
+
+	if (getchip) {
+		chipnr = (int)(ofs >> chip->chip_shift);
+		nand_get_device(chip, mtd, FL_READING);
+		/* Select the NAND device */
+		chip->select_chip(mtd, chipnr);
+	}
+
+#if defined(MTK_NAND_BMT)    
+	mapped_block = get_mapping_block_index(block);
+#else
+	if (shift_on_bbt) {
+		mapped_block = block_remap(mtd, block);
+		if (mapped_block == -1) {
+		if (getchip)
+			nand_release_device(mtd);
+			return NAND_STATUS_FAIL;
+		}
+	}
+#endif
+
+	ret = mtk_nand_block_bad_hw(mtd, mapped_block << chip->phys_erase_shift);
+#if defined (MTK_NAND_BMT)	
+	if (ret) {
+		MSG(INIT, "Unmapped bad block: 0x%x\n", mapped_block);
+		if (update_bmt(mapped_block << chip->phys_erase_shift, UPDATE_UNMAPPED_BLOCK, NULL, NULL)) {
+			MSG(INIT, "Update BMT success\n");
+			ret = 0;
+		} else {
+			MSG(INIT, "Update BMT fail\n");
+			ret = 1;
+		}
+	}
+#endif
+
+	if (getchip)
+		nand_release_device(mtd);
+
+	return ret;
+}
+#endif
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+char gacBuf[4096 + 288];
+
+static int
+mtk_nand_verify_buf(struct mtd_info *mtd, const uint8_t * buf, int len)
+{
+	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	struct NAND_CMD *pkCMD = &g_kCMD;
+	u32 u4PageSize = mtd->writesize;
+	u32 *pSrc, *pDst;
+	int i;
+
+	mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, gacBuf, gacBuf + u4PageSize);
+
+	pSrc = (u32 *) buf;
+	pDst = (u32 *) gacBuf;
+	len = len / sizeof(u32);
+	for (i = 0; i < len; ++i) {
+		if (*pSrc != *pDst) {
+			MSG(VERIFY, "mtk_nand_verify_buf page fail at page %d\n", pkCMD->u4RowAddr);
+			return -1;
+		}
+		pSrc++;
+		pDst++;
+	}
+
+	pSrc = (u32 *) chip->oob_poi;
+	pDst = (u32 *) (gacBuf + u4PageSize);
+
+	if ((pSrc[0] != pDst[0]) || (pSrc[1] != pDst[1]) || (pSrc[2] != pDst[2]) || (pSrc[3] != pDst[3]) || (pSrc[4] != pDst[4]) || (pSrc[5] != pDst[5])) {
+	// TODO: Ask Designer Why?
+	//(pSrc[6] != pDst[6]) || (pSrc[7] != pDst[7])) 
+		MSG(VERIFY, "mtk_nand_verify_buf oob fail at page %d\n", pkCMD->u4RowAddr);
+		MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pSrc[0], pSrc[1], pSrc[2], pSrc[3], pSrc[4], pSrc[5], pSrc[6], pSrc[7]);
+		MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pDst[0], pDst[1], pDst[2], pDst[3], pDst[4], pDst[5], pDst[6], pDst[7]);
+		return -1;
+	}
+	return 0;
+}
+#endif
+
+static void mtk_nand_pin_setup( void )
+{
+	u32 data;
+	data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60);
+	data &= ~((0x3<<18)|(0x3<<16));
+	data |= ((0x2<<18) |(0x2<<16));
+	DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data);
+}
+
+static void mtk_nand_clk_setup( struct mtk_nand_host_hw *hw )
+{
+	/* Set default NFI access timing control */
+	DRV_WriteReg32(NFI_ACCCON_REG32, hw->nfi_access_timing);
+	DRV_WriteReg16(NFI_CNFG_REG16, 0);
+	DRV_WriteReg16(NFI_PAGEFMT_REG16, 0);
+
+	/* Set burst for read/write to 4, data bus set to pull down */
+	NFI_SET_REG16(NFI_IOCON_REG16, 0x47);
+}
+
+static void
+mtk_nand_ecc_init(struct mtk_nand_host *host) {
+	struct mtk_nand_host_hw *hw = host->hw;
+	struct mtd_info *mtd   = host->mtd;
+	u32 spare_per_sector = mtd->oobsize / (mtd->writesize / 512);
+
+	u32 ecc_bit = 4;
+	u32 spare_bit = PAGEFMT_SPARE_16;
+
+	MSG(INIT, "%s: mtd->oobsize %d mtd->writesize %d\n",__func__,mtd->oobsize, mtd->writesize);
+
+	g_kCMD.u4OOBRowAddr = (u32) - 1;   /*KEN: hmm and this is done why ? */
+
+	/* Set the ECC engine */
+	if (hw->nand_ecc_mode == NAND_ECC_HW) {
+		MSG(INIT, "%s : Use HW ECC\n", MODULE_NAME);
+
+		if (g_bHwEcc)/* KEN: we already have a way to see if hwecc is used why use g_bHwEcc also ?*/
+			NFI_SET_REG32(NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+
+		if (spare_per_sector >= 28) {
+			spare_bit = PAGEFMT_SPARE_28;
+			ecc_bit = 12;
+			spare_per_sector = 28;
+		} else if (spare_per_sector >= 27) {
+			spare_bit = PAGEFMT_SPARE_27;
+			ecc_bit = 8;
+			spare_per_sector = 27;
+		} else if (spare_per_sector >= 26) {
+			spare_bit = PAGEFMT_SPARE_26;
+			ecc_bit = 8;
+			spare_per_sector = 26;
+		} else if (spare_per_sector >= 16) {
+			spare_bit = PAGEFMT_SPARE_16;
+			ecc_bit = 4;
+			spare_per_sector = 16;
+		} else {
+			MSG(INIT, "[NAND]: NFI not support oobsize: %x\n", spare_per_sector);
+			ASSERT(0);
+		}
+
+		MSG(INIT, "[NAND]select ecc bit:%d, sparesize :%d spare_per_sector=%d\n",ecc_bit,mtd->oobsize,spare_per_sector);
+
+		/* Setup PageFormat */
+		if (4096 == mtd->writesize) {
+			NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_4K);
+		} else if (2048 == mtd->writesize) {
+			NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_2K);
+		}
+
+		ECC_Config(hw, ecc_bit);
+		mtk_nand_configure_fdm(8);   /*ken: ok where is the 8 comming from ??? */
+		mtk_nand_configure_lock();
+	}
+}
+
+static int mtk_nand_dev_ready(struct mtd_info *mtd)
+{
+	return !(DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY);
+}
+
+#define FACT_BBT_BLOCK_NUM  32 // use the latest 32 BLOCK for factory bbt table
+#define FACT_BBT_OOB_SIGNATURE  1
+#define FACT_BBT_SIGNATURE_LEN  7
+const u8 oob_signature[] = "mtknand";
+static u8 *fact_bbt = 0;
+static u32 bbt_size = 0;
+
+int
+read_fact_bbt(struct mtd_info *mtd, unsigned int page)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	// read oob
+	if (mtk_nand_read_oob_hw(mtd, chip, page)==0)
+	{
+		if (chip->oob_poi[nand_badblock_offset] != 0xFF)
+		{
+			printk("Bad Block on Page %x\n", page);
+			return -1;
+		}
+		if (memcmp(&chip->oob_poi[FACT_BBT_OOB_SIGNATURE], oob_signature, FACT_BBT_SIGNATURE_LEN) != 0)
+		{
+			printk("compare signature failed %x\n", page);
+			return -1;
+		}
+		if (mtk_nand_exec_read_page(mtd, page, mtd->writesize, chip->buffers->databuf, chip->oob_poi))
+		{
+			printk("Signature matched and data read!\n");
+			memcpy(fact_bbt, chip->buffers->databuf, (bbt_size <= mtd->writesize)? bbt_size:mtd->writesize);
+			return 0;
+		}
+
+	}
+	printk("failed at page %x\n", page);
+	return -1;
+}
+
+int
+load_fact_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	int i;
+	u32 total_block;
+
+	total_block = 1 << (chip->chip_shift - chip->phys_erase_shift);
+
+	bbt_size = total_block >> 2;
+
+	printk("total blocks =%d bbt_size = %d \n",total_block , bbt_size);
+
+	if ((!fact_bbt) && (bbt_size))
+		fact_bbt = (u8 *)kmalloc(bbt_size, GFP_KERNEL);
+	if (!fact_bbt)
+		return -1;
+
+	for (i = total_block - 1; i >= (total_block - FACT_BBT_BLOCK_NUM); i--)
+	{
+		if (read_fact_bbt(mtd, i << (chip->phys_erase_shift - chip->page_shift)) == 0)
+		{
+			printk("load_fact_bbt success %d\n", i);
+			return 0;
+		}
+
+	}
+	printk("load_fact_bbt failed\n");
+	return -1;
+}
+
+int mtk_nand_probe(void)
+{
+#ifndef __UBOOT__
+	struct mtd_part_parser_data ppdata;
+#endif
+	struct mtk_nand_host_hw *hw;
+	struct mtd_info *mtd;
+	struct nand_chip *nand_chip;
+	int err = 0;
+	int rest,rows;
+
+	/* Allocate memory for the device structure (and zero it) */
+	host = kzalloc(sizeof(struct mtk_nand_host), GFP_KERNEL);
+	if (!host) {
+		MSG(INIT, "mtk_nand: failed to allocate device structure.\n");
+		return -ENOMEM;
+	}
+
+	/* Allocate memory for 16 byte aligned buffer */
+	local_buffer_16_align = local_buffer + 16 - ((u32) local_buffer % 16);
+
+	hw = &mt7621_nand_hw;
+	host->hw = hw;
+
+	/* setup soc for using nand */
+	mtk_nand_pin_setup();
+	mtk_nand_clk_setup(hw);
+	mtk_nand_reset();
+
+	/* init pointer aliases */
+	nand_chip = &host->nand_chip;
+	nand_chip->priv = host;     /* link the private data structures */
+	host->mtd = nand_to_mtd(nand_chip);
+	mtd = host->mtd;
+
+	/* setup core mtd fucntions for identification of chip to work */
+
+	mtd->priv = nand_chip;
+	mtd->owner = THIS_MODULE;
+	mtd->name  = "MT7621-NAND";
+
+	nand_chip->select_chip = mtk_nand_select_chip;
+	nand_chip->cmdfunc = mtk_nand_command_bp;
+	nand_chip->read_byte = mtk_nand_read_byte;
+
+	if (nand_scan_ident(mtd, 1, NULL)) {
+		MSG(INIT, "nand_scan_ident: failed \r\n");
+		err = -ENXIO;
+		goto out;
+	}
+
+	/* addr cycle depends on size, there is two column cycles */
+	/* row cycles is dependent on how many bits is needed to address all pages */
+	rest = (unsigned long)nand_chip->chipsize/mtd->writesize;
+	rows = 0;
+	while(rest > 1){
+		rest = rest>>8;
+		rows++;
+	}
+	devinfo.addr_cycle = 2 + rows;
+
+	/* ecc stuff */
+
+	hw->nand_ecc_mode = NAND_ECC_HW;
+
+	nand_chip->ecc.mode = hw->nand_ecc_mode;    /* enable ECC */
+	nand_chip->ecc.strength = 1; // KEN ??????? why ? should be 8 or 4 or ??
+
+	nand_chip->ecc.read_page = mtk_nand_read_page_hwecc;
+	nand_chip->ecc.write_page = mtk_nand_write_page_hwecc;
+
+	nand_chip->ecc.read_oob = mtk_nand_read_oob;
+	nand_chip->ecc.write_oob = mtk_nand_write_oob;
+
+	nand_chip->ecc.layout = &nand_oob_64;
+	nand_chip->ecc.size = hw->nand_ecc_size;    //2048
+	nand_chip->ecc.bytes = hw->nand_ecc_bytes;  //32
+
+	mtk_nand_ecc_init(host);
+
+
+	nand_chip->read_buf = mtk_nand_read_buf;
+ //	nand_chip->write_buf = mtk_nand_write_buf;
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+	nand_chip->verify_buf = mtk_nand_verify_buf;
+#endif
+	nand_chip->dev_ready = mtk_nand_dev_ready;
+	// For BMT, we need to revise driver architecture
+	nand_chip->write_page = mtk_nand_write_page;
+	nand_chip->block_markbad = mtk_nand_block_markbad;   // need to add nand_get_device()/nand_release_device().
+	//nand_chip->erase = mtk_nand_erase;
+	//nand_chip->read_page = mtk_nand_read_page;
+
+	if (nand_scan_tail(mtd)) {
+		err = -ENXIO;
+		goto out;
+	}
+
+	err = nand_register(0, mtd);
+	return err;
+
+out:
+	MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err);
+
+	kfree(host);
+	return err;
+}
+
+#ifndef __UBOOT__
+static int
+mtk_nand_remove(struct platform_device *pdev)
+{
+	struct mtk_nand_host *host = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = &host->mtd;
+
+//	nand_release(mtd);
+	kfree(host);
+	return 0;
+}
+
+
+static const struct of_device_id mt7621_nand_match[] = {
+	{ .compatible = "mtk,mt7621-nand" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mt7621_nand_match);
+
+static struct platform_driver mtk_nand_driver = {
+	.probe = mtk_nand_probe,
+	.remove = mtk_nand_remove,
+	.driver = {
+		.name = "MT7621-NAND",
+		.owner = THIS_MODULE,
+		.of_match_table = mt7621_nand_match,
+	},
+};
+
+static int __init
+mtk_nand_init(void)
+{
+	printk("MediaTek Nand driver init, version %s\n", VERSION);
+
+	return platform_driver_register(&mtk_nand_driver);
+}
+
+static void __exit
+mtk_nand_exit(void)
+{
+	platform_driver_unregister(&mtk_nand_driver);
+}
+
+module_init(mtk_nand_init);
+module_exit(mtk_nand_exit);
+MODULE_LICENSE("GPL");
+#endif
+/*
+ * Main initialization routine
+ */
+
+
+//int board_nand_init(struct nand_chip *chip)
+void  board_nand_init( void )
+{
+//	mtk_nand_probe(struct nand_chip *chip);
+	mtk_nand_probe();
+
+}
diff --git a/drivers/mtd/nand/mtk_nand.h b/drivers/mtd/nand/mtk_nand.h
new file mode 100644
index 0000000000000000000000000000000000000000..681054a6f85a0891c5bcf511104413156fded627
--- /dev/null
+++ b/drivers/mtd/nand/mtk_nand.h
@@ -0,0 +1,452 @@
+#ifndef __MTK_NAND_H
+#define __MTK_NAND_H
+
+#define RALINK_NAND_CTRL_BASE         0xBE003000
+#define RALINK_SYSCTL_BASE            0xBE000000
+#define RALINK_NANDECC_CTRL_BASE      0xBE003800
+/*******************************************************************************
+ * NFI Register Definition 
+ *******************************************************************************/
+
+#define NFI_CNFG_REG16  	((volatile P_U16)(NFI_BASE+0x0000))
+#define NFI_PAGEFMT_REG16   ((volatile P_U16)(NFI_BASE+0x0004))
+#define NFI_CON_REG16      	((volatile P_U16)(NFI_BASE+0x0008))
+#define NFI_ACCCON_REG32   	((volatile P_U32)(NFI_BASE+0x000C))
+#define NFI_INTR_EN_REG16   ((volatile P_U16)(NFI_BASE+0x0010))
+#define NFI_INTR_REG16      ((volatile P_U16)(NFI_BASE+0x0014))
+
+#define NFI_CMD_REG16   	((volatile P_U16)(NFI_BASE+0x0020))
+
+#define NFI_ADDRNOB_REG16   ((volatile P_U16)(NFI_BASE+0x0030))
+#define NFI_COLADDR_REG32  	((volatile P_U32)(NFI_BASE+0x0034))
+#define NFI_ROWADDR_REG32  	((volatile P_U32)(NFI_BASE+0x0038))
+
+#define NFI_STRDATA_REG16   ((volatile P_U16)(NFI_BASE+0x0040))
+
+#define NFI_DATAW_REG32    	((volatile P_U32)(NFI_BASE+0x0050))
+#define NFI_DATAR_REG32    	((volatile P_U32)(NFI_BASE+0x0054))
+#define NFI_PIO_DIRDY_REG16 ((volatile P_U16)(NFI_BASE+0x0058))
+
+#define NFI_STA_REG32      	((volatile P_U32)(NFI_BASE+0x0060))
+#define NFI_FIFOSTA_REG16   ((volatile P_U16)(NFI_BASE+0x0064))
+#define NFI_LOCKSTA_REG16   ((volatile P_U16)(NFI_BASE+0x0068))
+
+#define NFI_ADDRCNTR_REG16  ((volatile P_U16)(NFI_BASE+0x0070))
+
+#define NFI_STRADDR_REG32  	((volatile P_U32)(NFI_BASE+0x0080))
+#define NFI_BYTELEN_REG16   ((volatile P_U16)(NFI_BASE+0x0084))
+
+#define NFI_CSEL_REG16      ((volatile P_U16)(NFI_BASE+0x0090))
+#define NFI_IOCON_REG16     ((volatile P_U16)(NFI_BASE+0x0094))
+
+#define NFI_FDM0L_REG32    	((volatile P_U32)(NFI_BASE+0x00A0))
+#define NFI_FDM0M_REG32    	((volatile P_U32)(NFI_BASE+0x00A4))
+
+#define NFI_LOCK_REG16	  	((volatile P_U16)(NFI_BASE+0x0100))
+#define NFI_LOCKCON_REG32  	((volatile P_U32)(NFI_BASE+0x0104))
+#define NFI_LOCKANOB_REG16  ((volatile P_U16)(NFI_BASE+0x0108))
+#define NFI_LOCK00ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0110))
+#define NFI_LOCK00FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0114))
+#define NFI_LOCK01ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0118))
+#define NFI_LOCK01FMT_REG32 ((volatile P_U32)(NFI_BASE+0x011C))
+#define NFI_LOCK02ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0120))
+#define NFI_LOCK02FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0124))
+#define NFI_LOCK03ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0128))
+#define NFI_LOCK03FMT_REG32 ((volatile P_U32)(NFI_BASE+0x012C))
+#define NFI_LOCK04ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0130))
+#define NFI_LOCK04FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0134))
+#define NFI_LOCK05ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0138))
+#define NFI_LOCK05FMT_REG32 ((volatile P_U32)(NFI_BASE+0x013C))
+#define NFI_LOCK06ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0140))
+#define NFI_LOCK06FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0144))
+#define NFI_LOCK07ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0148))
+#define NFI_LOCK07FMT_REG32 ((volatile P_U32)(NFI_BASE+0x014C))
+#define NFI_LOCK08ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0150))
+#define NFI_LOCK08FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0154))
+#define NFI_LOCK09ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0158))
+#define NFI_LOCK09FMT_REG32 ((volatile P_U32)(NFI_BASE+0x015C))
+#define NFI_LOCK10ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0160))
+#define NFI_LOCK10FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0164))
+#define NFI_LOCK11ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0168))
+#define NFI_LOCK11FMT_REG32 ((volatile P_U32)(NFI_BASE+0x016C))
+#define NFI_LOCK12ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0170))
+#define NFI_LOCK12FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0174))
+#define NFI_LOCK13ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0178))
+#define NFI_LOCK13FMT_REG32 ((volatile P_U32)(NFI_BASE+0x017C))
+#define NFI_LOCK14ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0180))
+#define NFI_LOCK14FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0184))
+#define NFI_LOCK15ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0188))
+#define NFI_LOCK15FMT_REG32 ((volatile P_U32)(NFI_BASE+0x018C))
+
+#define NFI_FIFODATA0_REG32 ((volatile P_U32)(NFI_BASE+0x0190))
+#define NFI_FIFODATA1_REG32 ((volatile P_U32)(NFI_BASE+0x0194))
+#define NFI_FIFODATA2_REG32 ((volatile P_U32)(NFI_BASE+0x0198))
+#define NFI_FIFODATA3_REG32 ((volatile P_U32)(NFI_BASE+0x019C))
+#define NFI_MASTERSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0210))
+
+
+/*******************************************************************************
+ * NFI Register Field Definition 
+ *******************************************************************************/
+
+/* NFI_CNFG */
+#define CNFG_AHB             (0x0001)
+#define CNFG_READ_EN         (0x0002)
+#define CNFG_DMA_BURST_EN    (0x0004)
+#define CNFG_BYTE_RW         (0x0040)
+#define CNFG_HW_ECC_EN       (0x0100)
+#define CNFG_AUTO_FMT_EN     (0x0200)
+#define CNFG_OP_IDLE         (0x0000)
+#define CNFG_OP_READ         (0x1000)
+#define CNFG_OP_SRD          (0x2000)
+#define CNFG_OP_PRGM         (0x3000)
+#define CNFG_OP_ERASE        (0x4000)
+#define CNFG_OP_RESET        (0x5000)
+#define CNFG_OP_CUST         (0x6000)
+#define CNFG_OP_MODE_MASK    (0x7000)
+#define CNFG_OP_MODE_SHIFT   (12)
+
+/* NFI_PAGEFMT */
+#define PAGEFMT_512          (0x0000)
+#define PAGEFMT_2K           (0x0001)
+#define PAGEFMT_4K           (0x0002)
+
+#define PAGEFMT_PAGE_MASK    (0x0003)
+
+#define PAGEFMT_DBYTE_EN     (0x0008)
+
+#define PAGEFMT_SPARE_16     (0x0000)
+#define PAGEFMT_SPARE_26     (0x0001)
+#define PAGEFMT_SPARE_27     (0x0002)
+#define PAGEFMT_SPARE_28     (0x0003)
+#define PAGEFMT_SPARE_MASK   (0x0030)
+#define PAGEFMT_SPARE_SHIFT  (4)
+
+#define PAGEFMT_FDM_MASK     (0x0F00)
+#define PAGEFMT_FDM_SHIFT    (8)
+
+#define PAGEFMT_FDM_ECC_MASK  (0xF000)
+#define PAGEFMT_FDM_ECC_SHIFT (12)
+
+/* NFI_CON */
+#define CON_FIFO_FLUSH       (0x0001)
+#define CON_NFI_RST          (0x0002)
+#define CON_NFI_SRD          (0x0010)
+
+#define CON_NFI_NOB_MASK     (0x0060)
+#define CON_NFI_NOB_SHIFT    (5)
+
+#define CON_NFI_BRD          (0x0100)
+#define CON_NFI_BWR          (0x0200)
+
+#define CON_NFI_SEC_MASK     (0xF000)
+#define CON_NFI_SEC_SHIFT    (12)
+
+/* NFI_ACCCON */
+#define ACCCON_SETTING       ()
+
+/* NFI_INTR_EN */
+#define INTR_RD_DONE_EN      (0x0001)
+#define INTR_WR_DONE_EN      (0x0002)
+#define INTR_RST_DONE_EN     (0x0004)
+#define INTR_ERASE_DONE_EN   (0x0008)
+#define INTR_BSY_RTN_EN      (0x0010)
+#define INTR_ACC_LOCK_EN     (0x0020)
+#define INTR_AHB_DONE_EN     (0x0040)
+#define INTR_ALL_INTR_DE     (0x0000)
+#define INTR_ALL_INTR_EN     (0x007F)
+
+/* NFI_INTR */
+#define INTR_RD_DONE         (0x0001)
+#define INTR_WR_DONE         (0x0002)
+#define INTR_RST_DONE        (0x0004)
+#define INTR_ERASE_DONE      (0x0008)
+#define INTR_BSY_RTN         (0x0010)
+#define INTR_ACC_LOCK        (0x0020)
+#define INTR_AHB_DONE        (0x0040)
+
+/* NFI_ADDRNOB */
+#define ADDR_COL_NOB_MASK    (0x0003)
+#define ADDR_COL_NOB_SHIFT   (0)
+#define ADDR_ROW_NOB_MASK    (0x0030)
+#define ADDR_ROW_NOB_SHIFT   (4)
+
+/* NFI_STA */
+#define STA_READ_EMPTY       (0x00001000)
+#define STA_ACC_LOCK         (0x00000010)
+#define STA_CMD_STATE        (0x00000001)
+#define STA_ADDR_STATE       (0x00000002)
+#define STA_DATAR_STATE      (0x00000004)
+#define STA_DATAW_STATE      (0x00000008)
+
+#define STA_NAND_FSM_MASK    (0x1F000000)
+#define STA_NAND_BUSY        (0x00000100)
+#define STA_NAND_BUSY_RETURN (0x00000200)
+#define STA_NFI_FSM_MASK     (0x000F0000)
+#define STA_NFI_OP_MASK      (0x0000000F)
+
+/* NFI_FIFOSTA */
+#define FIFO_RD_EMPTY        (0x0040)
+#define FIFO_RD_FULL         (0x0080)
+#define FIFO_WR_FULL         (0x8000)
+#define FIFO_WR_EMPTY        (0x4000)
+#define FIFO_RD_REMAIN(x)    (0x1F&(x))
+#define FIFO_WR_REMAIN(x)    ((0x1F00&(x))>>8)
+
+/* NFI_ADDRCNTR */
+#define ADDRCNTR_CNTR(x)     ((0xF000&(x))>>12)
+#define ADDRCNTR_OFFSET(x)   (0x03FF&(x))
+
+/* NFI_LOCK */
+#define NFI_LOCK_ON          (0x0001)
+
+/* NFI_LOCKANOB */
+#define PROG_RADD_NOB_MASK   (0x7000)
+#define PROG_RADD_NOB_SHIFT  (12)
+#define PROG_CADD_NOB_MASK   (0x0300)
+#define PROG_CADD_NOB_SHIFT  (8)
+#define ERASE_RADD_NOB_MASK   (0x0070)
+#define ERASE_RADD_NOB_SHIFT  (4)
+#define ERASE_CADD_NOB_MASK   (0x0007)
+#define ERASE_CADD_NOB_SHIFT  (0)
+
+/*******************************************************************************
+ * ECC Register Definition 
+ *******************************************************************************/
+
+#define ECC_ENCCON_REG16	((volatile P_U16)(NFIECC_BASE+0x0000))
+#define ECC_ENCCNFG_REG32  	((volatile P_U32)(NFIECC_BASE+0x0004))
+#define ECC_ENCDIADDR_REG32	((volatile P_U32)(NFIECC_BASE+0x0008))
+#define ECC_ENCIDLE_REG32  	((volatile P_U32)(NFIECC_BASE+0x000C))
+#define ECC_ENCPAR0_REG32   ((volatile P_U32)(NFIECC_BASE+0x0010))
+#define ECC_ENCPAR1_REG32   ((volatile P_U32)(NFIECC_BASE+0x0014))
+#define ECC_ENCPAR2_REG32   ((volatile P_U32)(NFIECC_BASE+0x0018))
+#define ECC_ENCPAR3_REG32   ((volatile P_U32)(NFIECC_BASE+0x001C))
+#define ECC_ENCPAR4_REG32   ((volatile P_U32)(NFIECC_BASE+0x0020))
+#define ECC_ENCSTA_REG32    ((volatile P_U32)(NFIECC_BASE+0x0024))
+#define ECC_ENCIRQEN_REG16  ((volatile P_U16)(NFIECC_BASE+0x0028))
+#define ECC_ENCIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x002C))
+
+#define ECC_DECCON_REG16    ((volatile P_U16)(NFIECC_BASE+0x0100))
+#define ECC_DECCNFG_REG32   ((volatile P_U32)(NFIECC_BASE+0x0104))
+#define ECC_DECDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0108))
+#define ECC_DECIDLE_REG16   ((volatile P_U16)(NFIECC_BASE+0x010C))
+#define ECC_DECFER_REG16    ((volatile P_U16)(NFIECC_BASE+0x0110))
+#define ECC_DECENUM_REG32   ((volatile P_U32)(NFIECC_BASE+0x0114))
+#define ECC_DECDONE_REG16   ((volatile P_U16)(NFIECC_BASE+0x0118))
+#define ECC_DECEL0_REG32    ((volatile P_U32)(NFIECC_BASE+0x011C))
+#define ECC_DECEL1_REG32    ((volatile P_U32)(NFIECC_BASE+0x0120))
+#define ECC_DECEL2_REG32    ((volatile P_U32)(NFIECC_BASE+0x0124))
+#define ECC_DECEL3_REG32    ((volatile P_U32)(NFIECC_BASE+0x0128))
+#define ECC_DECEL4_REG32    ((volatile P_U32)(NFIECC_BASE+0x012C))
+#define ECC_DECEL5_REG32    ((volatile P_U32)(NFIECC_BASE+0x0130))
+#define ECC_DECIRQEN_REG16  ((volatile P_U16)(NFIECC_BASE+0x0134))
+#define ECC_DECIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x0138))
+#define ECC_FDMADDR_REG32   ((volatile P_U32)(NFIECC_BASE+0x013C))
+#define ECC_DECFSM_REG32    ((volatile P_U32)(NFIECC_BASE+0x0140))
+#define ECC_SYNSTA_REG32    ((volatile P_U32)(NFIECC_BASE+0x0144))
+#define ECC_DECNFIDI_REG32  ((volatile P_U32)(NFIECC_BASE+0x0148))
+#define ECC_SYN0_REG32      ((volatile P_U32)(NFIECC_BASE+0x014C))
+
+/*******************************************************************************
+ * ECC register definition
+ *******************************************************************************/
+/* ECC_ENCON */
+#define ENC_EN             		(0x0001)
+#define ENC_DE                 	(0x0000)
+
+/* ECC_ENCCNFG */
+#define ECC_CNFG_ECC4          	(0x0000)
+#define ECC_CNFG_ECC6          	(0x0001)
+#define ECC_CNFG_ECC8          	(0x0002)
+#define ECC_CNFG_ECC10         	(0x0003)
+#define ECC_CNFG_ECC12         	(0x0004)
+#define ECC_CNFG_ECC_MASK      	(0x00000007)
+
+#define ENC_CNFG_NFI           	(0x0010)
+#define ENC_CNFG_MODE_MASK     	(0x0010)
+
+#define ENC_CNFG_META6         	(0x10300000)
+#define ENC_CNFG_META8         	(0x10400000)
+
+#define ENC_CNFG_MSG_MASK  		(0x1FFF0000)
+#define ENC_CNFG_MSG_SHIFT 		(0x10)
+
+/* ECC_ENCIDLE */
+#define ENC_IDLE           		(0x0001)
+
+/* ECC_ENCSTA */
+#define STA_FSM            		(0x001F)
+#define STA_COUNT_PS       		(0xFF10)
+#define STA_COUNT_MS       		(0x3FFF0000)
+
+/* ECC_ENCIRQEN */
+#define ENC_IRQEN          		(0x0001)
+
+/* ECC_ENCIRQSTA */
+#define ENC_IRQSTA         		(0x0001)
+
+/* ECC_DECCON */
+#define DEC_EN             		(0x0001)
+#define DEC_DE             		(0x0000)
+
+/* ECC_ENCCNFG */
+#define DEC_CNFG_ECC4          (0x0000)
+//#define DEC_CNFG_ECC6          (0x0001)
+//#define DEC_CNFG_ECC12         (0x0002)
+#define DEC_CNFG_NFI           (0x0010)
+//#define DEC_CNFG_META6         (0x10300000)
+//#define DEC_CNFG_META8         (0x10400000)
+
+#define DEC_CNFG_FER           (0x01000)
+#define DEC_CNFG_EL            (0x02000)
+#define DEC_CNFG_CORRECT       (0x03000)
+#define DEC_CNFG_TYPE_MASK     (0x03000)
+
+#define DEC_CNFG_EMPTY_EN      (0x80000000)
+
+#define DEC_CNFG_CODE_MASK     (0x1FFF0000)
+#define DEC_CNFG_CODE_SHIFT    (0x10)
+
+/* ECC_DECIDLE */
+#define DEC_IDLE           		(0x0001)
+
+/* ECC_DECFER */
+#define DEC_FER0               (0x0001)
+#define DEC_FER1               (0x0002)
+#define DEC_FER2               (0x0004)
+#define DEC_FER3               (0x0008)
+#define DEC_FER4               (0x0010)
+#define DEC_FER5               (0x0020)
+#define DEC_FER6               (0x0040)
+#define DEC_FER7               (0x0080)
+
+/* ECC_DECENUM */
+#define ERR_NUM0               (0x0000000F)
+#define ERR_NUM1               (0x000000F0)
+#define ERR_NUM2               (0x00000F00)
+#define ERR_NUM3               (0x0000F000)
+#define ERR_NUM4               (0x000F0000)
+#define ERR_NUM5               (0x00F00000)
+#define ERR_NUM6               (0x0F000000)
+#define ERR_NUM7               (0xF0000000)
+
+/* ECC_DECDONE */
+#define DEC_DONE0               (0x0001)
+#define DEC_DONE1               (0x0002)
+#define DEC_DONE2               (0x0004)
+#define DEC_DONE3               (0x0008)
+#define DEC_DONE4               (0x0010)
+#define DEC_DONE5               (0x0020)
+#define DEC_DONE6               (0x0040)
+#define DEC_DONE7               (0x0080)
+
+/* ECC_DECIRQEN */
+#define DEC_IRQEN         		(0x0001)
+
+/* ECC_DECIRQSTA */
+#define DEC_IRQSTA      		(0x0001)
+
+#define CHIPVER_ECO_1           (0x8a00)
+#define CHIPVER_ECO_2           (0x8a01)
+
+//#define NAND_PFM
+
+/*******************************************************************************
+ * Data Structure Definition
+ *******************************************************************************/
+struct mtk_nand_host 
+{
+	struct nand_chip		nand_chip;
+	struct mtd_info			*mtd;
+	struct mtk_nand_host_hw	*hw;
+};
+
+struct NAND_CMD
+{
+	u32	u4ColAddr;
+	u32 u4RowAddr;
+	u32 u4OOBRowAddr;
+	u8	au1OOB[288];
+	u8*	pDataBuf;
+#ifdef NAND_PFM	
+	u32 pureReadOOB;
+	u32 pureReadOOBNum;
+#endif
+};
+
+/*
+ *	ECC layout control structure. Exported to userspace for
+ *  diagnosis and to allow creation of raw images
+struct nand_ecclayout {
+	uint32_t eccbytes;
+	uint32_t eccpos[64];
+	uint32_t oobavail;
+	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
+};
+*/
+//#define __DEBUG_NAND		1			/* Debug information on/off */
+
+/* Debug message event */
+#define DBG_EVT_NONE		0x00000000	/* No event */
+#define DBG_EVT_INIT		0x00000001	/* Initial related event */
+#define DBG_EVT_VERIFY		0x00000002	/* Verify buffer related event */
+#define DBG_EVT_PERFORMANCE	0x00000004	/* Performance related event */
+#define DBG_EVT_READ		0x00000008	/* Read related event */
+#define DBG_EVT_WRITE		0x00000010	/* Write related event */
+#define DBG_EVT_ERASE		0x00000020	/* Erase related event */
+#define DBG_EVT_BADBLOCK	0x00000040	/* Badblock related event */
+#define DBG_EVT_POWERCTL	0x00000080	/* Suspend/Resume related event */
+
+#define DBG_EVT_ALL			0xffffffff
+
+#define DBG_EVT_MASK      	(DBG_EVT_INIT)
+
+#if __DEBUG_NAND
+#define MSG(evt, fmt, args...) \
+do {	\
+	if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \
+		printk(fmt, ##args); \
+	} \
+} while(0)
+
+#define MSG_FUNC_ENTRY(f)	MSG(FUC, "<FUN_ENT>: %s\n", __FUNCTION__)
+#else
+#define MSG(evt, fmt, args...) do{}while(0)
+#define MSG_FUNC_ENTRY(f)	   do{}while(0)
+#endif
+
+#define RAMDOM_READ 1<<0
+#define CACHE_READ  1<<1
+
+typedef struct
+{
+   u16 id;          //deviceid+menuid
+   u32 ext_id; 
+   u8  addr_cycle;
+   u8  iowidth;
+   u16 totalsize;   
+   u16 blocksize;
+   u16 pagesize;
+   u16 sparesize;
+   u32 timmingsetting;
+   char devciename[14];
+   u32 advancedmode;   //
+}flashdev_info,*pflashdev_info;
+
+/* NAND driver */
+#if 0
+struct mtk_nand_host_hw {
+    unsigned int nfi_bus_width;		    /* NFI_BUS_WIDTH */ 
+	unsigned int nfi_access_timing;		/* NFI_ACCESS_TIMING */  
+	unsigned int nfi_cs_num;			/* NFI_CS_NUM */
+	unsigned int nand_sec_size;			/* NAND_SECTOR_SIZE */
+	unsigned int nand_sec_shift;		/* NAND_SECTOR_SHIFT */
+	unsigned int nand_ecc_size;
+	unsigned int nand_ecc_bytes;
+	unsigned int nand_ecc_mode;
+};
+extern struct mtk_nand_host_hw mt7621_nand_hw;
+extern u32	CFG_BLOCKSIZE;
+#endif
+#endif
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index d1287bc3be9f880d4776683d8f4d267e3f34d643..48be03c094bf7d4b0648ad7eb4fb91f1854fc9d8 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -90,7 +90,7 @@ static struct nand_ecclayout nand_oob_128 = {
 		 .length = 78} }
 };
 
-static int nand_get_device(struct mtd_info *mtd, int new_state);
+int nand_get_device(struct mtd_info *mtd, int new_state);
 
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops);
@@ -128,7 +128,7 @@ static int check_offs_len(struct mtd_info *mtd,
  *
  * Release chip lock and wake up anyone waiting on the device.
  */
-static void nand_release_device(struct mtd_info *mtd)
+void nand_release_device(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
@@ -822,7 +822,7 @@ static void panic_nand_get_device(struct nand_chip *chip,
  *
  * Get the device and lock it for exclusive access
  */
-static int
+int
 nand_get_device(struct mtd_info *mtd, int new_state)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 74c4c9a3c802f679955bfb55be367f2803fa6a5b..9abf31b04512d82e14eee3994c5aa584e7726c4c 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1371,3 +1371,23 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
 
 	return ret;
 }
+
+void nand_bbt_set(struct mtd_info *mtd, int page, int flag)
+{
+       struct nand_chip *this = mtd->priv;
+       int block;
+
+       block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1));
+       this->bbt[block >> 3] &= ~(0x03 << (block & 0x6));
+       this->bbt[block >> 3] |= (flag & 0x3) << (block & 0x6);
+}
+
+int nand_bbt_get(struct mtd_info *mtd, int page)
+{
+       struct nand_chip *this = mtd->priv;
+       int block;
+
+       block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1));
+       return (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+}
+
diff --git a/drivers/mtd/nand/nand_def.h b/drivers/mtd/nand/nand_def.h
new file mode 100644
index 0000000000000000000000000000000000000000..82e957d5aa05c616baddea9a10597e606cbbca36
--- /dev/null
+++ b/drivers/mtd/nand/nand_def.h
@@ -0,0 +1,123 @@
+#ifndef __NAND_DEF_H__
+#define __NAND_DEF_H__
+
+#define VERSION  	"v2.1 Fix AHB virt2phys error"
+#define MODULE_NAME	"# MTK NAND #"
+#define PROCNAME    "driver/nand"
+
+#undef TESTTIME
+//#define __UBOOT_NAND__			1
+#define __KERNEL_NAND__		1
+//#define __PRELOADER_NAND__	1
+//#define PMT 1
+//#define _MTK_NAND_DUMMY_DRIVER
+//#define CONFIG_BADBLOCK_CHECK	1
+//#ifdef CONFIG_BADBLOCK_CHECK
+//#define MTK_NAND_BMT	1
+//#endif
+#define ECC_ENABLE		1
+#define MANUAL_CORRECT	1
+//#define __INTERNAL_USE_AHB_MODE__ 	(0)
+#define SKIP_BAD_BLOCK
+#define FACT_BBT
+
+#ifndef NAND_OTP_SUPPORT
+#define NAND_OTP_SUPPORT 0
+#endif
+
+/*******************************************************************************
+ * Macro definition 
+ *******************************************************************************/
+//#define NFI_SET_REG32(reg, value)   (DRV_WriteReg32(reg, DRV_Reg32(reg) | (value))) 
+//#define NFI_SET_REG16(reg, value)   (DRV_WriteReg16(reg, DRV_Reg16(reg) | (value)))
+//#define NFI_CLN_REG32(reg, value)   (DRV_WriteReg32(reg, DRV_Reg32(reg) & (~(value))))
+//#define NFI_CLN_REG16(reg, value)   (DRV_WriteReg16(reg, DRV_Reg16(reg) & (~(value))))
+
+#if defined (__KERNEL_NAND__)
+#define NFI_SET_REG32(reg, value) \
+do {	\
+	g_value = (DRV_Reg32(reg) | (value));\
+	DRV_WriteReg32(reg, g_value); \
+} while(0)
+
+#define NFI_SET_REG16(reg, value) \
+do {	\
+	g_value = (DRV_Reg16(reg) | (value));\
+	DRV_WriteReg16(reg, g_value); \
+} while(0)
+
+#define NFI_CLN_REG32(reg, value) \
+do {	\
+	g_value = (DRV_Reg32(reg) & (~(value)));\
+	DRV_WriteReg32(reg, g_value); \
+} while(0)
+
+#define NFI_CLN_REG16(reg, value) \
+do {	\
+	g_value = (DRV_Reg16(reg) & (~(value)));\
+	DRV_WriteReg16(reg, g_value); \
+} while(0)
+#endif
+
+#define NFI_WAIT_STATE_DONE(state) do{;}while (__raw_readl(NFI_STA_REG32) & state)
+#define NFI_WAIT_TO_READY()  do{;}while (!(__raw_readl(NFI_STA_REG32) & STA_BUSY2READY))
+
+
+#define NAND_SECTOR_SIZE (512)
+#define OOB_PER_SECTOR      (16)
+#define OOB_AVAI_PER_SECTOR (8)
+
+#ifndef PART_SIZE_BMTPOOL
+#define BMT_POOL_SIZE       (80)
+#else
+#define BMT_POOL_SIZE (PART_SIZE_BMTPOOL)
+#endif
+
+#define PMT_POOL_SIZE	(2)
+
+#define TIMEOUT_1   0x1fff
+#define TIMEOUT_2   0x8ff
+#define TIMEOUT_3   0xffff
+#define TIMEOUT_4   0xffff//5000   //PIO
+
+
+/* temporarity definiation */
+#if !defined (__KERNEL_NAND__) 
+#define KERN_INFO
+#define KERN_WARNING
+#define KERN_ERR
+#define PAGE_SIZE	(4096)
+#endif
+#define AddStorageTrace				//AddStorageTrace
+#define STORAGE_LOGGER_MSG_NAND		0
+#define NFI_BASE 					RALINK_NAND_CTRL_BASE
+#define NFIECC_BASE 				RALINK_NANDECC_CTRL_BASE
+
+#ifdef __INTERNAL_USE_AHB_MODE__
+#define MT65xx_POLARITY_LOW   0
+#define MT65XX_PDN_PERI_NFI   0
+#define MT65xx_EDGE_SENSITIVE 0
+#define MT6575_NFI_IRQ_ID                    (58)
+#endif
+
+#if defined (__KERNEL_NAND__)
+#define RALINK_REG(x)		(*((volatile u32 *)(x)))	
+#define __virt_to_phys(x)	virt_to_phys((volatile void*)x)
+#else
+#define CONFIG_MTD_NAND_VERIFY_WRITE	(1)
+#define printk	printf
+#define ra_dbg printf
+#define BUG()							//BUG()
+#define BUG_ON(x)						//BUG_ON()
+#define NUM_PARTITIONS 				1
+#endif
+
+#define NFI_DEFAULT_ACCESS_TIMING        (0x30C77fff)	//(0x44333)
+
+//uboot only support 1 cs
+#define NFI_CS_NUM                  (1)
+#define NFI_DEFAULT_CS              (0)
+
+#include "mt6575_typedefs.h"
+
+#endif /* __NAND_DEF_H__ */
diff --git a/drivers/mtd/nand/nand_device_list.h b/drivers/mtd/nand/nand_device_list.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c36b3a6b2539cb7c907774c91100523c9b351c0
--- /dev/null
+++ b/drivers/mtd/nand/nand_device_list.h
@@ -0,0 +1,55 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __NAND_DEVICE_LIST_H__
+#define __NAND_DEVICE_LIST_H__
+
+static const flashdev_info gen_FlashTable[]={
+	{0x20BC, 0x105554, 5, 16, 512, 128, 2048, 64, 0x1123, "EHD013151MA_5", 0},
+	{0xECBC, 0x005554, 5, 16, 512, 128, 2048, 64, 0x1123, "K524G2GACB_A0", 0},
+	{0x2CBC, 0x905556, 5, 16, 512, 128, 2048, 64, 0x21044333, "MT29C4G96MAZA", 0},
+	{0xADBC, 0x905554, 5, 16, 512, 128, 2048, 64, 0x10801011, "H9DA4GH4JJAMC", 0},
+    {0x01F1, 0x801D01, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "S34ML01G100TF", 0},
+    {0x92F1, 0x8095FF, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81A", 0},
+	{0xECD3, 0x519558, 5, 8, 1024, 128, 2048, 64, 0x44333, "K9K8G8000", 0},
+    {0xC2F1, 0x801DC2, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G08AA", 0},
+    {0x98D3, 0x902676, 5, 8, 1024, 256, 4096, 224, 0x00C25332, "TC58NVG3S0F", 0},
+    {0x01DA, 0x909546, 5, 8, 256, 128, 2048, 128, 0x30C77fff, "S34ML02G200TF", 0},
+    {0x01DC, 0x909556, 5, 8, 512, 128, 2048, 128, 0x30C77fff, "S34ML04G200TF", 0},
+	{0x0000, 0x000000, 0, 0, 0, 0, 0, 0, 0, "xxxxxxxxxx", 0},
+};
+
+
+#endif
diff --git a/drivers/mtd/nand/partition.h b/drivers/mtd/nand/partition.h
new file mode 100644
index 0000000000000000000000000000000000000000..034e1afeb92ee15f575e05c29776d50d2d67ca3d
--- /dev/null
+++ b/drivers/mtd/nand/partition.h
@@ -0,0 +1,115 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein
+ * is confidential and proprietary to MediaTek Inc. and/or its licensors.
+ * Without the prior written permission of MediaTek inc. and/or its licensors,
+ * any reproduction, modification, use or disclosure of MediaTek Software,
+ * and information contained herein, in whole or in part, shall be strictly prohibited.
+ */
+/* MediaTek Inc. (C) 2010. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek Software")
+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's
+ * applicable license agreements with MediaTek Inc.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#define RECONFIG_PARTITION_SIZE 1
+
+#define MTD_BOOT_PART_SIZE  0x80000
+#define MTD_CONFIG_PART_SIZE    0x20000
+#define MTD_FACTORY_PART_SIZE   0x20000
+
+extern unsigned int  CFG_BLOCKSIZE;
+#define LARGE_MTD_BOOT_PART_SIZE       (CFG_BLOCKSIZE<<2)
+#define LARGE_MTD_CONFIG_PART_SIZE     (CFG_BLOCKSIZE<<2)
+#define LARGE_MTD_FACTORY_PART_SIZE    (CFG_BLOCKSIZE<<1)
+
+/*=======================================================================*/
+/* NAND PARTITION Mapping                                                  */
+/*=======================================================================*/
+//#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition g_pasStatic_Partition[] = {
+	{
+                name:           "ALL",
+                size:           MTDPART_SIZ_FULL,
+                offset:         0,
+        },
+        /* Put your own partition definitions here */
+        {
+                name:           "Bootloader",
+                size:           MTD_BOOT_PART_SIZE,
+                offset:         0,
+        }, {
+                name:           "Config",
+                size:           MTD_CONFIG_PART_SIZE,
+                offset:         MTDPART_OFS_APPEND
+        }, {
+                name:           "Factory",
+                size:           MTD_FACTORY_PART_SIZE,
+                offset:         MTDPART_OFS_APPEND
+#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH
+        }, {
+                name:           "Kernel",
+                size:           MTD_KERN_PART_SIZE,
+                offset:         MTDPART_OFS_APPEND,
+        }, {
+                name:           "RootFS",
+                size:           MTD_ROOTFS_PART_SIZE,
+                offset:         MTDPART_OFS_APPEND,
+#ifdef CONFIG_ROOTFS_IN_FLASH_NO_PADDING
+        }, {
+                name:           "Kernel_RootFS",
+                size:           MTD_KERN_PART_SIZE + MTD_ROOTFS_PART_SIZE,
+                offset:         MTD_BOOT_PART_SIZE + MTD_CONFIG_PART_SIZE + MTD_FACTORY_PART_SIZE,
+#endif
+#else //CONFIG_RT2880_ROOTFS_IN_RAM
+        }, {
+                name:           "Kernel",
+                size:           0x10000,
+                offset:         MTDPART_OFS_APPEND,
+#endif
+#ifdef CONFIG_DUAL_IMAGE
+        }, {
+                name:           "Kernel2",
+                size:           MTD_KERN2_PART_SIZE,
+                offset:         MTD_KERN2_PART_OFFSET,
+#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH
+        }, {
+                name:           "RootFS2",
+                size:           MTD_ROOTFS2_PART_SIZE,
+                offset:         MTD_ROOTFS2_PART_OFFSET,
+#endif
+#endif
+        }
+
+};
+
+#define NUM_PARTITIONS ARRAY_SIZE(g_pasStatic_Partition)
+extern int part_num;	// = NUM_PARTITIONS;
+//#endif
+#undef RECONFIG_PARTITION_SIZE
+
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index be3ed73e52219fbc9179c9d7553cf5887b86c407..a29d56217733940d2fea1bdce33b934e7d40ca2b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -197,4 +197,10 @@ config PIC32_ETH
 	  This driver implements 10/100 Mbps Ethernet and MAC layer for
 	  Microchip PIC32 microcontrollers.
 
+config RT2880_ETH
+	bool "RT2880t"
+	select PHYLIB
+	help
+		bla bla bla
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a4485266d45732a66279fbc32bcdee23632e2552..aab0eb4ac80a64df1b1d6ec1850f2deeae9bd92d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -76,3 +76,4 @@ obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/
 obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
 obj-$(CONFIG_VSC9953) += vsc9953.o
 obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
+obj-$(CONFIG_RT2880_ETH) += rt2880_eth.o mii_mgr.o
diff --git a/drivers/net/mii_mgr.c b/drivers/net/mii_mgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b202bb5ae39450dd5d118fff441bacd8a9e4a34
--- /dev/null
+++ b/drivers/net/mii_mgr.c
@@ -0,0 +1,957 @@
+#include <common.h>
+#include <command.h>
+#include <rt_mmap.h>
+//#include <configs/rt2880.h>
+
+#if defined (CONFIG_MIPS16)
+#define outw(address, value)    *((volatile uint32_t *)(address)) = (value)
+#define inw(address)            (*(volatile u32 *)(address))
+#else
+#define outw(address, value)    *((volatile uint32_t *)(address)) = cpu_to_le32(value)
+#define inw(address)            le32_to_cpu(*(volatile u32 *)(address))
+#endif
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+#define PHY_CONTROL_0 		0xC0   
+#define PHY_CONTROL_1 		0xC4   
+#define MDIO_PHY_CONTROL_0	(RALINK_ETH_SW_BASE + PHY_CONTROL_0)
+#define MDIO_PHY_CONTROL_1 	(RALINK_ETH_SW_BASE + PHY_CONTROL_1)
+
+#define GPIO_MDIO_BIT		(1<<7)
+#define GPIO_PURPOSE_SELECT	0x60
+#define GPIO_PRUPOSE		(RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT)
+
+#elif defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \
+      defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD)
+#define PHY_CONTROL_0 		0x7004   
+#define PHY_CONTROL_1 		0x7000   
+#define MDIO_PHY_CONTROL_0	(RALINK_ETH_SW_BASE + PHY_CONTROL_0)
+#define MDIO_PHY_CONTROL_1 	(RALINK_ETH_SW_BASE + PHY_CONTROL_1)
+
+#define GPIO_MDIO_BIT		(1<<7)
+#define GPIO_PURPOSE_SELECT	0x60
+#define GPIO_PRUPOSE		(RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT)
+
+#elif defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD)
+#define PHY_CONTROL_0 		0x7004   
+#define PHY_CONTROL_1 		0x7000   
+#define MDIO_PHY_CONTROL_0	(RALINK_ETH_SW_BASE + PHY_CONTROL_0)
+#define MDIO_PHY_CONTROL_1 	(RALINK_ETH_SW_BASE + PHY_CONTROL_1)
+
+#define GPIO_MDIO_BIT		(2<<7)
+#define GPIO_PURPOSE_SELECT	0x60
+#define GPIO_PRUPOSE		(RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT)
+
+#elif defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD)
+#define PHY_CONTROL_0 		0x0004   
+#define PHY_CONTROL_1 		0x0000   
+#define MDIO_PHY_CONTROL_0	(RALINK_ETH_SW_BASE + PHY_CONTROL_0)
+#define MDIO_PHY_CONTROL_1 	(RALINK_ETH_SW_BASE + PHY_CONTROL_1)
+#define enable_mdio(x)
+#define GPIO_MDIO_BIT		(1<<12)
+#define GPIO_PURPOSE_SELECT	0x60
+#define GPIO_PRUPOSE		(RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT)
+
+#else 
+#define PHY_CONTROL_0       	0x00
+#define PHY_CONTROL_1       	0x04
+#define MDIO_PHY_CONTROL_0	(RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_0)
+#define MDIO_PHY_CONTROL_1	(RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_1)
+#define enable_mdio(x)
+#endif
+
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \
+    defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+void enable_mdio(int enable)
+{
+#if !defined (P5_MAC_TO_PHY_MODE) && !defined (GE_RGMII_AN) && !defined(GE_MII_AN) && !defined(MT7628_FPGA_BOARD) && !defined(MT7628_ASIC_BOARD)
+	u32 data = inw(GPIO_PRUPOSE);
+	if(enable)
+		data &= ~GPIO_MDIO_BIT;
+	else
+		data |= GPIO_MDIO_BIT;
+	outw(GPIO_PRUPOSE, data);
+#endif
+}
+#endif
+
+#if defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD)
+#define enable_mdio(x)
+#endif
+
+#if defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \
+    defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \
+    defined (MT7620_FPGA_BOARD)
+u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
+{
+	u32 volatile  			status	= 0;
+	u32 volatile  			data 	= 0;
+	u32			  			rc		= 0;
+	unsigned long volatile  t_start = get_timer(0);
+
+	/* We enable mdio gpio purpose register, and disable it when exit.	 */
+	enable_mdio(1);
+
+	//printf("\n MDIO Read operation!!\n");
+	// make sure previous read operation is complete
+	while(1)
+	{
+		// 0 : Read/write operation complet
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+		{
+			break;
+		}else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)){
+			enable_mdio(0);
+			printf("\n MDIO Read operation is ongoing !!\n");
+			return rc;
+		}
+	}
+	
+	data  = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25);
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data);
+	//printf("\n Set Command [0x%08X] to PHY 0x%8x!!\n", data, MDIO_PHY_CONTROL_0);
+
+	
+	// make sure read operation is complete
+	t_start = get_timer(0);
+	while(1)
+	{
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
+		{
+			status = inw(MDIO_PHY_CONTROL_0);
+			*read_data = (u32)(status & 0x0000FFFF);
+			//printf("\n MDIO_PHY_CONTROL_0: 0x%8x!!\n", status);
+
+			enable_mdio(0);
+			return 1;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Read operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+
+
+u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
+{
+	unsigned long volatile  t_start=get_timer(0);
+	u32 volatile  data;
+
+	enable_mdio(1);
+
+	// make sure previous write operation is complete
+	while(1)
+	{
+		if (!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+		{
+			break;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Write operation is ongoing !!\n");
+			return 0;
+		}
+	}
+
+	data = (0x01 << 16) | (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data;
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data); //start operation
+	//printf("\n Set Command [0x%08X] to PHY 0x%8x!!\n", data, MDIO_PHY_CONTROL_0);
+
+	t_start = get_timer(0);
+
+	// make sure write operation is complete
+	while(1)
+	{
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) // 0 : Read/write operation complete
+		{
+			enable_mdio(0);
+			return 1;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Write operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+#elif defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD) || defined (MT7620_ASIC_BOARD)
+u32 __mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
+{
+	u32 volatile  			status	= 0;
+	u32 volatile  			data 	= 0;
+	u32			  	rc		= 0;
+	unsigned long volatile  t_start = get_timer(0);
+	
+	//printf("\n MDIO Read operation!!\n");
+	// make sure previous read operation is complete
+	while(1)
+	{
+		// 0 : Read/write operation complet
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+		{
+			break;
+		}else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)){
+			printf("\n MDIO Read operation is ongoing !!\n");
+			return rc;
+		}
+	}
+	
+	data  = (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register << 25);
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data);
+	//printf("\n Set Command [0x%08X] to PHY 0x%8x!!\n", data, MDIO_PHY_CONTROL_0);
+
+	
+	// make sure read operation is complete
+	t_start = get_timer(0);
+	while(1)
+	{
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
+		{
+			status = inw(MDIO_PHY_CONTROL_0);
+			*read_data = (u32)(status & 0x0000FFFF);
+			//printf("\n MDIO_PHY_CONTROL_0: 0x%8x!!\n", status);
+
+			return 1;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			printf("\n MDIO Read operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+
+u32 __mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
+{
+	unsigned long volatile  t_start=get_timer(0);
+	u32 volatile  data;
+
+	// make sure previous write operation is complete
+	while(1)
+	{
+		if (!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+		{
+			break;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			printf("\n MDIO Write operation is ongoing !!\n");
+			return 0;
+		}
+	}
+	udelay(1);//make sequencial write more robust
+
+	data = (0x01 << 16) | (1<<18) | (phy_addr << 20) | (phy_register << 25) | write_data;
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data); //start operation
+	//printf("\n Set Command [0x%08X] to PHY 0x%8x!!\n", data, MDIO_PHY_CONTROL_0);
+
+	t_start = get_timer(0);
+
+	// make sure write operation is complete
+	while(1)
+	{
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) // 0 : Read/write operation complete
+		{
+			return 1;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			printf("\n MDIO Write operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+
+u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
+{
+	u32 low_word;
+	u32 high_word;
+
+	if(phy_addr==31) {
+		//phase1: write page address phase
+		if(__mii_mgr_write(phy_addr, 0x1f, ((phy_register >> 6) & 0x3FF))) {
+			//phase2: write address & read low word phase
+			if(__mii_mgr_read(phy_addr, (phy_register >> 2) & 0xF, &low_word)) {
+				//phase3: write address & read high word phase
+				if(__mii_mgr_read(phy_addr, (0x1 << 4), &high_word)) {
+					*read_data = (high_word << 16) | (low_word & 0xFFFF);
+				//	printf("%s: phy_addr=%x phy_register=%x *read_data=%x\n", __FUNCTION__, phy_addr, phy_register, *read_data);
+					return 1;
+				}
+			}
+		}
+	} else {
+		if(__mii_mgr_read(phy_addr, phy_register, read_data)) {
+//			printf("%s: phy_addr=%x phy_register=%x *read_data=%x\n",__FUNCTION__, phy_addr, phy_register, *read_data);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
+{
+//	printf("%s: phy_addr=%x phy_register=%x write_data=%x\n", __FUNCTION__, phy_addr, phy_register, write_data);
+	if(phy_addr == 31) {
+		//phase1: write page address phase
+		if(__mii_mgr_write(phy_addr, 0x1f, (phy_register >> 6) & 0x3FF)) {
+			//phase2: write address & read low word phase
+			if(__mii_mgr_write(phy_addr, ((phy_register >> 2) & 0xF), write_data & 0xFFFF)) {
+				//phase3: write address & read high word phase
+				if(__mii_mgr_write(phy_addr, (0x1 << 4), write_data >> 16)) {
+					return 1;
+				}
+			}
+		}
+	} else { 
+		if(__mii_mgr_write(phy_addr, phy_register, write_data)) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+#elif defined (RT3883_ASIC_BOARD) && defined (MAC_TO_MT7530_MODE)
+
+
+u32 __mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
+{
+	u32 volatile  			status	= 0;
+	u32 volatile  			data 	= 0;
+	u32			  			rc		= 0;
+	unsigned long volatile  t_start = get_timer(0);
+
+	/* We enable mdio gpio purpose register, and disable it when exit.	 */
+	enable_mdio(1);
+
+	// make sure previous read operation is complete
+	while(1)
+	{
+		// 0 : Read/write operation complet
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+		{
+			break;
+		}else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)){
+			enable_mdio(0);
+			printf("\n MDIO Read operation is ongoing !!\n");
+			return rc;
+		}
+	}
+	data  = (phy_addr << 24) | (phy_register << 16);
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data);
+	//printf("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
+
+	
+	// make sure read operation is complete
+	t_start = get_timer(0);
+	while(1)
+	{
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
+		{
+			status = inw(MDIO_PHY_CONTROL_0);
+			*read_data = (u32)(status & 0x0000FFFF);
+
+			enable_mdio(0);
+			return 1;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Read operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+
+
+u32 __mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
+{
+	unsigned long volatile  t_start=get_timer(0);
+	u32 volatile  data;
+
+	enable_mdio(1);
+
+	// make sure previous write operation is complete
+	while(1)
+	{
+		if (!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+		{
+			break;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Write operation is ongoing !!\n");
+			return 0;
+		}
+	}
+	data = (1<<30) | (phy_addr << 24) | (phy_register << 16) | write_data;
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data); //start operation
+	//printf("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
+
+	t_start = get_timer(0);
+
+	// make sure write operation is complete
+	while(1)
+	{
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) // 0 : Read/write operation complete
+		{
+			enable_mdio(0);
+			return 1;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Write operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+
+
+
+u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
+{
+	u32 low_word;
+	u32 high_word;
+
+	if(phy_addr==31) {
+		//phase1: write page address phase
+		if(__mii_mgr_write(phy_addr, 0x1f, ((phy_register >> 6) & 0x3FF))) {
+			//phase2: write address & read low word phase
+			if(__mii_mgr_read(phy_addr, (phy_register >> 2) & 0xF, &low_word)) {
+				//phase3: write address & read high word phase
+				if(__mii_mgr_read(phy_addr, (0x1 << 4), &high_word)) {
+					*read_data = (high_word << 16) | (low_word & 0xFFFF);
+				//	printf("%s: phy_addr=%x phy_register=%x *read_data=%x\n", __FUNCTION__, phy_addr, phy_register, *read_data);
+					return 1;
+				}
+			}
+		}
+	} else {
+		if(__mii_mgr_read(phy_addr, phy_register, read_data)) {
+//			printf("%s: phy_addr=%x phy_register=%x *read_data=%x\n",__FUNCTION__, phy_addr, phy_register, *read_data);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
+{
+//	printf("%s: phy_addr=%x phy_register=%x write_data=%x\n", __FUNCTION__, phy_addr, phy_register, write_data);
+	if(phy_addr == 31) {
+		//phase1: write page address phase
+		if(__mii_mgr_write(phy_addr, 0x1f, (phy_register >> 6) & 0x3FF)) {
+			//phase2: write address & read low word phase
+			if(__mii_mgr_write(phy_addr, ((phy_register >> 2) & 0xF), write_data & 0xFFFF)) {
+				//phase3: write address & read high word phase
+				if(__mii_mgr_write(phy_addr, (0x1 << 4), write_data >> 16)) {
+					return 1;
+				}
+			}
+		}
+	} else { 
+		if(__mii_mgr_write(phy_addr, phy_register, write_data)) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+
+
+
+
+#else
+
+u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
+{
+	u32 volatile  			status	= 0;
+	u32 volatile  			data 	= 0;
+	u32			  			rc		= 0;
+	unsigned long volatile  t_start = get_timer(0);
+
+	/* We enable mdio gpio purpose register, and disable it when exit.	 */
+	enable_mdio(1);
+
+	// make sure previous read operation is complete
+	while(1)
+	{
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+		// rd_rdy: read operation is complete
+		if(!( inw(MDIO_PHY_CONTROL_1) & (0x1 << 1))) 
+#else
+		// 0 : Read/write operation complet
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+#endif
+		{
+			break;
+		}else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ)){
+			enable_mdio(0);
+			printf("\n MDIO Read operation is ongoing !!\n");
+			return rc;
+		}
+	}
+	
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+	outw(MDIO_PHY_CONTROL_0 , (1<<14) | (phy_register << 8) | (phy_addr));
+#else
+	data  = (phy_addr << 24) | (phy_register << 16);
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data);
+#endif
+	//printf("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
+
+	
+	// make sure read operation is complete
+	t_start = get_timer(0);
+	while(1)
+	{
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+		if( inw(MDIO_PHY_CONTROL_1) & (0x1 << 1))
+		{
+			status = inw(MDIO_PHY_CONTROL_1);
+			*read_data = (u32)(status >>16);
+
+			enable_mdio(0);
+			return 1;
+		}
+#else
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31)))
+		{
+			status = inw(MDIO_PHY_CONTROL_0);
+			*read_data = (u32)(status & 0x0000FFFF);
+
+			enable_mdio(0);
+			return 1;
+		}
+#endif
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Read operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+
+
+u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
+{
+	unsigned long volatile  t_start=get_timer(0);
+	u32 volatile  data;
+
+	enable_mdio(1);
+
+	// make sure previous write operation is complete
+	while(1)
+	{
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \
+    defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+		if(!( inw(MDIO_PHY_CONTROL_1) & (0x1 << 0)))
+#else
+		if (!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
+#endif
+		{
+			break;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Write operation is ongoing !!\n");
+			return 0;
+		}
+	}
+
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+	data = ((write_data & 0xFFFF)<<16);
+	data |=  (phy_register << 8) | (phy_addr);
+	data |=  (1<<13);
+	outw(MDIO_PHY_CONTROL_0, data);
+#else
+	data = (1<<30) | (phy_addr << 24) | (phy_register << 16) | write_data;
+	outw(MDIO_PHY_CONTROL_0, data);
+	data |= (1<<31);
+	outw(MDIO_PHY_CONTROL_0, data); //start operation
+#endif
+	//printf("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
+
+	t_start = get_timer(0);
+
+	// make sure write operation is complete
+	while(1)
+	{
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+		if( inw(MDIO_PHY_CONTROL_1) & (0x1 << 0)) //wt_done ?= 1
+#else
+		if(!( inw(MDIO_PHY_CONTROL_0) & (0x1 << 31))) // 0 : Read/write operation complete
+#endif
+		{
+			enable_mdio(0);
+			return 1;
+		}
+		else if(get_timer(t_start) > (5 * CONFIG_SYS_HZ))
+		{
+			enable_mdio(0);
+			printf("\n MDIO Write operation is ongoing and Time Out!!\n");
+			return 0;
+		}
+	}
+}
+
+
+
+#endif
+
+
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+void dump_phy_reg(int port_no, int from, int to, int is_local)
+{
+	u32 i=0;
+	u32 temp=0;
+
+	if(is_local==0) {
+	    printf("Global Register\n");
+	    printf("===============");
+	    mii_mgr_write(0, 31, 0); //select global register
+	    for(i=from;i<=to;i++) {
+		if(i%8==0) {
+		    printf("\n");
+		}
+		mii_mgr_read(port_no,i, &temp);
+		printf("%02d: %04X ",i, temp);
+	    }
+	} else {
+	    mii_mgr_write(0, 31, 0x8000); //select local register
+		printf("\n\nLocal Register Port %d\n",port_no);
+		printf("===============");
+		for(i=from;i<=to;i++) {
+		    if(i%8==0) {
+			printf("\n");
+		    }
+		    mii_mgr_read(port_no,i, &temp);
+		    printf("%02d: %04X ",i, temp);
+		}
+	}
+	printf("\n");
+}
+#else
+void dump_phy_reg(int port_no, int from, int to, int is_local, int page_no)
+{
+
+	u32 i=0;
+	u32 temp=0;
+	u32 r31=0;
+
+
+	if(is_local==0) {
+
+	    printf("\n\nGlobal Register Page %d\n",page_no);
+	    printf("===============");
+	    r31 = 0 << 15; //global
+	    r31 = page_no&0x7 << 12; //page no
+	    mii_mgr_write(0, 31, r31); //select global page x
+	    for(i=16;i<32;i++) {
+		if(i%8==0) {
+		    printf("\n");
+		}
+		mii_mgr_read(port_no,i, &temp);
+		printf("%02d: %04X ",i, temp);
+	    }
+	}else {
+	    printf("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
+	    printf("===============");
+	    r31 = 1 << 15; //local
+	    r31 = page_no&0x7 << 12; //page no
+	    mii_mgr_write(0, 31, r31); //select local page x
+	    for(i=16;i<32;i++) {
+		if(i%8==0) {
+		    printf("\n");
+		}
+		mii_mgr_read(port_no,i, &temp);
+		printf("%02d: %04X ",i, temp);
+	    }
+	}
+	printf("\n");
+}
+
+#endif
+
+#ifndef ON_BOARD_NAND_FLASH_COMPONENT
+#define MDIO_DBG_CMD
+#endif
+int rt2880_mdio_access(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	u32 addr;
+	u32 phy_addr;
+	u32 value = 0,bit_offset,temp;
+	u32 i=0, j=0;
+
+	if(!memcmp(argv[0],"mdio.anoff",sizeof("mdio.anoff")))
+	{
+#if   defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \
+      defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \
+      defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD) || \
+      defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD)
+		value = inw(MDIO_PHY_CONTROL_1);
+		value &= ~(1 << 31);
+		outw(MDIO_PHY_CONTROL_1,value);
+		puts("\n GMAC1 Force link status enable !! \n");
+
+#else
+		value = inw(MDIO_PHY_CONTROL_1);
+		value |= (1<<15);
+		outw(MDIO_PHY_CONTROL_1,value);
+		puts("\n GMAC1 Force link status enable !! \n");
+#endif	
+	}
+	else if(!memcmp(argv[0],"mdio.anon",sizeof("mdio.anon")))
+	{
+#if   defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) || \
+      defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \
+      defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD) || \
+      defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD)
+
+		value = inw(MDIO_PHY_CONTROL_1);
+		value |= (1<<31);
+		outw(MDIO_PHY_CONTROL_1,value);
+		puts("\n GMAC1 Force link status disable !! \n");
+
+#else
+		value = inw(MDIO_PHY_CONTROL_1);
+		value &= ~(1 << 15);
+		outw(MDIO_PHY_CONTROL_1,value);
+		puts("\n GMAC1 Force link status disable !! \n");
+#endif	
+	}
+	else if(!memcmp(argv[0],"mdio.r",sizeof("mdio.r")))
+	{
+		if (argc != 3) {
+			printf ("Usage:\n%s\n", cmdtp->usage);
+			return 1;
+	    	}
+		phy_addr = simple_strtoul(argv[1], NULL, 10);
+#if defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD) || \
+    defined (P5_RGMII_TO_MAC_MODE) || defined (MAC_TO_MT7530_MODE)
+		if(phy_addr == 31) {
+			addr = simple_strtoul(argv[2], NULL, 16);
+		} else {
+			addr = simple_strtoul(argv[2], NULL, 10);
+		}
+#else
+		addr = simple_strtoul(argv[2], NULL, 10);
+#endif
+		phy_addr &=0x1f;
+
+		if(mii_mgr_read(phy_addr, addr, &value))
+			printf("\n mdio.r addr[0x%08X]=0x%08X\n",addr,value);
+		else {
+			printf("\n Read addr[0x%08X] is Fail!!\n",addr);
+		}
+	}
+	else if(!memcmp(argv[0],"mdio.w",sizeof("mdio.w")))
+	{
+		if (argc != 4) {
+			printf ("Usage:\n%s\n", cmdtp->usage);
+			return 1;
+	    	}
+		phy_addr = simple_strtoul(argv[1], NULL, 10);
+#if defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD) || \
+    defined (P5_RGMII_TO_MAC_MODE) || defined (MAC_TO_MT7530_MODE)
+		if(phy_addr == 31) {
+			addr = simple_strtoul(argv[2], NULL, 16);
+		} else {
+			addr = simple_strtoul(argv[2], NULL, 10);
+		}
+#else
+		addr = simple_strtoul(argv[2], NULL, 10);
+#endif
+		value = simple_strtoul(argv[3], NULL, 16);
+		phy_addr &=0x1f;
+
+		if(mii_mgr_write(phy_addr, addr,value)) {
+			printf("\n mdio.w addr[0x%08X]  value[0x%08X]\n",addr,value);
+		}
+		else {
+			printf("\n Write[0x%08X] is Fail!!\n",addr);
+		}
+	}
+	else if(!memcmp(argv[0],"mdio.wb",sizeof("mdio.wb")))
+	{
+		if (argc != 4) {
+			printf ("Usage:\n%s\n", cmdtp->usage);
+			return 1;
+		}
+		addr = simple_strtoul(argv[1], NULL, 10);
+		bit_offset = simple_strtoul(argv[2], NULL, 10);
+		value = simple_strtoul(argv[3], NULL, 10);
+
+		if(mii_mgr_read(31, addr,&temp)) {
+		    
+		}
+		else {
+			printf("\n Rasd PHY fail while mdio.wb was called\n");
+			return 1;
+		}
+
+		if(value) {
+			printf("\n Set bit[%d] to '1' \n",bit_offset);
+			temp |= (1<<bit_offset);
+		}
+		else {
+			printf("\n Set bit[%d] to '0' \n",bit_offset);
+			temp &= ~(1<<bit_offset);
+		}
+
+		if(mii_mgr_write(31, addr,temp)) {
+			printf("\n mdio.wb addr[0x%08X]  value[0x%08X]\n",addr,temp);
+		}
+		else {
+			printf("\n Write[0x%08X] is Fail!!\n",addr);
+		}
+	}
+	else if(!memcmp(argv[0],"mdio.d",sizeof("mdio.d")))
+	{
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) || \
+    defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) || \
+    defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+		if (argc == 2) {
+		    addr = simple_strtoul(argv[1], NULL, 10);
+		    dump_phy_reg(0, 0, 31, 0); //dump global register
+		    dump_phy_reg(addr, 0, 31, 1); //dump local register
+		}else {
+		    /* Global Register 0~31
+		     * Local Register 0~31
+		     */
+		    dump_phy_reg(0, 0, 31, 0); //dump global register
+		    for(i=0;i<5;i++) { 	
+			dump_phy_reg(i, 0, 31, 1); //dump local register
+		    }
+		}
+#elif defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD) 
+		if (argc == 2) {
+		    addr = simple_strtoul(argv[1], NULL, 10);
+
+		    for(i=0;i<0x100;i+=4) {
+			    if(i%16==0) {
+				    printf("\n%04X: ",0x4000 + addr*0x100 + i);
+			    }
+			    mii_mgr_read(31, 0x4000 + addr*0x100 + i, &temp);
+			    printf("%08X ", temp);
+		    }
+		    printf("\n");
+		} else {
+		    for(i=0;i<7;i++) {
+			    for(j=0;j<0x100;j+=4) {
+				    if(j%16==0) {
+					    printf("\n%04X: ",0x4000 + i*0x100 + j);
+				    }
+				    mii_mgr_read(31, 0x4000 + i*0x100 + j, &temp);
+				    printf("%08X ", temp);
+			    }
+			    printf("\n");
+		    }
+		}
+#else //RT6855A, RT6855, MT7620, MT7621
+		/* SPEC defined Register 0~15
+		 * Global Register 16~31 for each page
+		 * Local Register 16~31 for each page
+		 */
+		printf("SPEC defined Register\n");
+		printf("===============");
+		for(i=0;i<=16;i++) {
+		    if(i%8==0) {
+			printf("\n");
+		    }
+		    mii_mgr_read(0,i, &temp);
+		    printf("%02d: %04X ",i, temp);
+		}
+
+		if (argc == 2) {
+		    addr = simple_strtoul(argv[1], NULL, 10);
+		    dump_phy_reg(addr, 16, 31, 0, i);
+		    dump_phy_reg(addr, 16, 31, 1, 0); //dump local page 0
+		    dump_phy_reg(addr, 16, 31, 1, 1); //dump local page 1
+		    dump_phy_reg(addr, 16, 31, 1, 2); //dump local page 2
+		    dump_phy_reg(addr, 16, 31, 1, 3); //dump local page 3
+		}else {
+
+		    for(i=0;i<4;i++) { //global register  page 0~4
+			dump_phy_reg(0, 16, 31, 0, i);
+		    }
+	
+		    for(i=0;i<5;i++) { //local register port 0-port4
+			dump_phy_reg(i, 16, 31, 1, 0); //dump local page 0
+			dump_phy_reg(i, 16, 31, 1, 1); //dump local page 1
+			dump_phy_reg(i, 16, 31, 1, 2); //dump local page 2
+			dump_phy_reg(i, 16, 31, 1, 3); //dump local page 3
+		    }
+		}
+#endif	
+	}
+	return 0;
+}
+
+U_BOOT_CMD(
+ 	mdio,	4,	1,	rt2880_mdio_access,
+ 	"mdio   - Ralink PHY register R/W command !!\n",
+ 	"mdio.r [phy_addr(dec)] [reg_addr(dec)] \n"
+ 	"mdio.w [phy_addr(dec)] [reg_addr(dec)] [data(HEX)] \n"
+ 	"mdio.anoff GMAC1 Force link status enable !!  \n"
+ 	"mdio.anon GMAC1 Force link status disable !!  \n"
+ 	"mdio.wb [phy register(dec)] [bit offset(Dec)] [Value(0/1)]  \n"
+ 	"mdio.d - dump all Phy registers \n"
+ 	"mdio.d [phy register(dec)] - dump Phy registers \n"
+);
diff --git a/drivers/net/rt2880_eth.c b/drivers/net/rt2880_eth.c
new file mode 100644
index 0000000000000000000000000000000000000000..f1fa74cc1e90821ac4ccde947df0adbd5d73950f
--- /dev/null
+++ b/drivers/net/rt2880_eth.c
@@ -0,0 +1,3646 @@
+#include <common.h>
+#include <command.h>
+
+#if defined(CONFIG_RT2880_ETH)
+
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/addrspace.h>
+#include <rt_mmap.h>
+
+//#undef DEBUG
+
+/* ====================================== */
+//GDMA1 uni-cast frames destination port
+#define GDM_UFRC_P_CPU     ((u32)(~(0x7 << 12)))
+#define GDM_UFRC_P_GDMA1   (1 << 12)
+#define GDM_UFRC_P_GDMA2   (2 << 12)
+#define GDM_UFRC_P_DROP    (7 << 12)
+//GDMA1 broad-cast MAC address frames
+#define GDM_BFRC_P_CPU     ((u32)(~(0x7 << 8)))
+#define GDM_BFRC_P_GDMA1   (1 << 8)
+#define GDM_BFRC_P_GDMA2   (2 << 8)
+#define GDM_BFRC_P_PPE     (6 << 8)
+#define GDM_BFRC_P_DROP    (7 << 8)
+//GDMA1 multi-cast MAC address frames
+#define GDM_MFRC_P_CPU     ((u32)(~(0x7 << 4)))
+#define GDM_MFRC_P_GDMA1   (1 << 4)
+#define GDM_MFRC_P_GDMA2   (2 << 4)
+#define GDM_MFRC_P_PPE     (6 << 4)
+#define GDM_MFRC_P_DROP    (7 << 4)
+//GDMA1 other MAC address frames destination port
+#define GDM_OFRC_P_CPU     ((u32)(~(0x7)))
+#define GDM_OFRC_P_GDMA1   1
+#define GDM_OFRC_P_GDMA2   2
+#define GDM_OFRC_P_PPE     6
+#define GDM_OFRC_P_DROP    7
+
+#define RST_DRX_IDX0      BIT(16)
+#define RST_DTX_IDX0      BIT(0)
+
+#define TX_WB_DDONE       BIT(6)
+#define RX_DMA_BUSY       BIT(3)
+#define TX_DMA_BUSY       BIT(1)
+#define RX_DMA_EN         BIT(2)
+#define TX_DMA_EN         BIT(0)
+
+#define GP1_FRC_EN        BIT(15)
+#define GP1_FC_TX         BIT(11)
+#define GP1_FC_RX         BIT(10)
+#define GP1_LNK_DWN       BIT(9)
+#define GP1_AN_OK         BIT(8)
+
+/*
+ * FE_INT_STATUS
+ */
+#define CNT_PPE_AF       BIT(31)
+#define CNT_GDM1_AF      BIT(29)
+#define PSE_P1_FC        BIT(22)
+#define PSE_P0_FC        BIT(21)
+#define PSE_FQ_EMPTY     BIT(20)
+#define GE1_STA_CHG      BIT(18)
+#define TX_COHERENT      BIT(17)
+#define RX_COHERENT      BIT(16)
+
+#define TX_DONE_INT1     BIT(9)
+#define TX_DONE_INT0     BIT(8)
+#define RX_DONE_INT0     BIT(2)
+#define TX_DLY_INT       BIT(1)
+#define RX_DLY_INT       BIT(0)
+
+/*
+ * Ethernet chip registers.RT2880
+ */
+#if defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+
+#define PDMA_RELATED		0x0800
+/* 1. PDMA */
+#define TX_BASE_PTR0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x000)
+#define TX_MAX_CNT0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x004)
+#define TX_CTX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x008)
+#define TX_DTX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x00C)
+
+#define TX_BASE_PTR1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x010)
+#define TX_MAX_CNT1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x014)
+#define TX_CTX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x018)
+#define TX_DTX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x01C)
+
+#define TX_BASE_PTR2            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x020)
+#define TX_MAX_CNT2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x024)
+#define TX_CTX_IDX2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x028)
+#define TX_DTX_IDX2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x02C)
+
+#define TX_BASE_PTR3            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x030)
+#define TX_MAX_CNT3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x034)
+#define TX_CTX_IDX3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x038)
+#define TX_DTX_IDX3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x03C)
+
+#define RX_BASE_PTR0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x100)
+#define RX_MAX_CNT0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x104)
+#define RX_CALC_IDX0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x108)
+#define RX_DRX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x10C)
+
+#define RX_BASE_PTR1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x110)
+#define RX_MAX_CNT1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x114)
+#define RX_CALC_IDX1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x118)
+#define RX_DRX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x11C)
+
+#define PDMA_INFO               (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x200)
+#define PDMA_GLO_CFG            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x204)
+#define PDMA_RST_IDX            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x208)
+#define PDMA_RST_CFG            (RALINK_FRAME_ENGINE_BASE + PDMA_RST_IDX)
+#define DLY_INT_CFG             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x20C)
+#define FREEQ_THRES             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x210)
+#define INT_STATUS              (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x220)
+#define FE_INT_STATUS           (INT_STATUS)
+#define INT_MASK                (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x228)
+#define FE_INT_ENABLE           (INT_MASK)
+#define PDMA_WRR                (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x280)
+#define PDMA_SCH_CFG            (PDMA_WRR)
+
+#define SDM_RELATED		0x0C00
+#define SDM_CON                 (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x00)  //Switch DMA configuration
+#define SDM_RRING               (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x04)  //Switch DMA Rx Ring
+#define SDM_TRING               (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x08)  //Switch DMA Tx Ring
+#define SDM_MAC_ADRL            (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x0C)  //Switch MAC address LSB
+#define SDM_MAC_ADRH            (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x10)  //Switch MAC Address MSB
+#define SDM_TPCNT               (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x100) //Switch DMA Tx packet count
+#define SDM_TBCNT               (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x104) //Switch DMA Tx byte count
+#define SDM_RPCNT               (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x108) //Switch DMA rx packet count
+#define SDM_RBCNT               (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x10C) //Switch DMA rx byte count
+#define SDM_CS_ERR              (RALINK_FRAME_ENGINE_BASE + SDM_RELATED+0x110) //Switch DMA rx checksum error count
+
+#elif defined (RT6855_ASIC_BOARD) || defined (RT6855_FPGA_BOARD) || \
+      defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) || \
+      defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) || \
+      defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+/* Old FE with New PDMA */
+#define PDMA_RELATED		0x0800
+/* 1. PDMA */
+#define TX_BASE_PTR0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x000)
+#define TX_MAX_CNT0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x004)
+#define TX_CTX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x008)
+#define TX_DTX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x00C)
+
+#define TX_BASE_PTR1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x010)
+#define TX_MAX_CNT1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x014)
+#define TX_CTX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x018)
+#define TX_DTX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x01C)
+
+#define TX_BASE_PTR2            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x020)
+#define TX_MAX_CNT2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x024)
+#define TX_CTX_IDX2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x028)
+#define TX_DTX_IDX2             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x02C)
+
+#define TX_BASE_PTR3            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x030)
+#define TX_MAX_CNT3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x034)
+#define TX_CTX_IDX3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x038)
+#define TX_DTX_IDX3             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x03C)
+
+#define RX_BASE_PTR0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x100)
+#define RX_MAX_CNT0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x104)
+#define RX_CALC_IDX0            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x108)
+#define RX_DRX_IDX0             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x10C)
+
+#define RX_BASE_PTR1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x110)
+#define RX_MAX_CNT1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x114)
+#define RX_CALC_IDX1            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x118)
+#define RX_DRX_IDX1             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x11C)
+
+#define PDMA_INFO               (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x200)
+#define PDMA_GLO_CFG            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x204)
+#define PDMA_RST_IDX            (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x208)
+#define PDMA_RST_CFG            (RALINK_FRAME_ENGINE_BASE + PDMA_RST_IDX)
+#define DLY_INT_CFG             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x20C)
+#define FREEQ_THRES             (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x210)
+#define INT_STATUS              (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x220) /* FIXME */
+#define INT_MASK                (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x228) /* FIXME */
+#define PDMA_WRR                (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED+0x280)
+#define PDMA_SCH_CFG            (PDMA_WRR)
+
+/* TODO: change FE_INT_STATUS->INT_STATUS 
+ * FE_INT_ENABLE->INT_MASK */
+#define MDIO_ACCESS         RALINK_FRAME_ENGINE_BASE + 0x00
+#define MDIO_CFG            RALINK_FRAME_ENGINE_BASE + 0x04
+#define FE_DMA_GLO_CFG      RALINK_FRAME_ENGINE_BASE + 0x08
+#define FE_RST_GLO          RALINK_FRAME_ENGINE_BASE + 0x0C
+#define FE_INT_STATUS       RALINK_FRAME_ENGINE_BASE + 0x10
+#define FE_INT_ENABLE       RALINK_FRAME_ENGINE_BASE + 0x14
+#define FC_DROP_STA         RALINK_FRAME_ENGINE_BASE + 0x18
+#define FOE_TS_T            RALINK_FRAME_ENGINE_BASE + 0x1C
+
+#if defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD)
+#define GDMA1_RELATED       0x0600
+#define GDMA1_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
+#define GDMA1_SHRP_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
+#define GDMA1_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
+#define GDMA1_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
+#elif defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+
+#define PAD_RGMII2_MDIO_CFG            RALINK_SYSCTL_BASE + 0x58
+
+#define GDMA1_RELATED       0x0500
+#define GDMA1_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
+#define GDMA1_SHRP_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
+#define GDMA1_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
+#define GDMA1_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
+#define GDMA2_RELATED       0x1500
+#define GDMA2_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00)
+#define GDMA2_SHRP_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04)
+#define GDMA2_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08)
+#define GDMA2_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C)
+
+#else
+#define GDMA1_RELATED       0x0020
+#define GDMA1_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
+#define GDMA1_SCH_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
+#define GDMA1_SHRP_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
+#define GDMA1_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
+#define GDMA1_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x10)
+#endif
+
+#define PSE_RELATED         0x0040
+#define PSE_FQFC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00)
+#define CDMA_FC_CFG         (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04)
+#define GDMA1_FC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08)
+#define GDMA2_FC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x0C)
+#define CDMA_OQ_STA         (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x10)
+#define GDMA1_OQ_STA        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x14)
+#define GDMA2_OQ_STA        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x18)
+#define PSE_IQ_STA          (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x1C)
+
+#define CDMA_RELATED        0x0080
+#define CDMA_CSG_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
+#define CDMA_SCH_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04)
+
+#else
+
+#define MDIO_ACCESS         RALINK_FRAME_ENGINE_BASE + 0x00
+#ifdef RT3883_USE_GE2
+#define MDIO_CFG            RALINK_FRAME_ENGINE_BASE + 0x18
+#else
+#define MDIO_CFG            RALINK_FRAME_ENGINE_BASE + 0x04
+#endif // RT3883_USE_GE2 //
+#define FE_DMA_GLO_CFG      RALINK_FRAME_ENGINE_BASE + 0x08
+#define FE_RST_GLO          RALINK_FRAME_ENGINE_BASE + 0x0C
+#define FE_INT_STATUS       RALINK_FRAME_ENGINE_BASE + 0x10
+#define FE_INT_ENABLE       RALINK_FRAME_ENGINE_BASE + 0x14
+#define FC_DROP_STA         RALINK_FRAME_ENGINE_BASE + 0x18
+#define FOE_TS_T            RALINK_FRAME_ENGINE_BASE + 0x1C
+
+#define GDMA1_RELATED       0x0020
+#define GDMA1_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x00)
+#define GDMA1_SCH_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x04)
+#define GDMA1_SHRP_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x08)
+#define GDMA1_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x0C)
+#define GDMA1_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA1_RELATED + 0x10)
+
+#define GDMA2_RELATED       0x0060
+#define GDMA2_FWD_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x00)
+#define GDMA2_SCH_CFG       (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x04)
+#define GDMA2_SHRP_CFG      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x08)
+#define GDMA2_MAC_ADRL      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x0C)
+#define GDMA2_MAC_ADRH      (RALINK_FRAME_ENGINE_BASE + GDMA2_RELATED + 0x10)
+
+#define PSE_RELATED         0x0040
+#define PSE_FQFC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x00)
+#define CDMA_FC_CFG         (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x04)
+#define GDMA1_FC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x08)
+#define GDMA2_FC_CFG        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x0C)
+#define CDMA_OQ_STA         (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x10)
+#define GDMA1_OQ_STA        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x14)
+#define GDMA2_OQ_STA        (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x18)
+#define PSE_IQ_STA          (RALINK_FRAME_ENGINE_BASE + PSE_RELATED + 0x1C)
+
+#define CDMA_RELATED        0x0080
+#define CDMA_CSG_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x00)
+#define CDMA_SCH_CFG        (RALINK_FRAME_ENGINE_BASE + CDMA_RELATED + 0x04)
+
+#define PDMA_RELATED        0x0100
+#define PDMA_GLO_CFG        (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x00)
+#define PDMA_RST_IDX        (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x04)
+#define PDMA_SCH_CFG        (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x08)
+#define DELAY_INT_CFG       (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x0C)
+#define TX_BASE_PTR0        (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x10)
+#define TX_MAX_CNT0         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x14)
+#define TX_CTX_IDX0         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x18)
+#define TX_DTX_IDX0         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x1C)
+#define TX_BASE_PTR1        (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x20)
+#define TX_MAX_CNT1         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x24)
+#define TX_CTX_IDX1         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x28)
+#define TX_DTX_IDX1         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x2C)
+#define RX_BASE_PTR0        (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x30)
+#define RX_MAX_CNT0         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x34)
+#define RX_CALC_IDX0        (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x38)
+#define RX_DRX_IDX0         (RALINK_FRAME_ENGINE_BASE + PDMA_RELATED + 0x3C)
+
+
+#endif
+
+#define INTERNAL_LOOPBACK_ENABLE 1
+#define INTERNAL_LOOPBACK_DISABLE 0
+
+//#define CONFIG_UNH_TEST
+
+#define TOUT_LOOP   1000
+#define ENABLE 1
+#define DISABLE 0
+/*KEN: _start */
+#define NUM_RX_DESC 24
+#define NUM_TX_DESC 24
+
+typedef struct _BUFFER_ELEM_    BUFFER_ELEM;
+
+struct _BUFFER_ELEM_
+{
+        int tx_idx;
+    unsigned char *pbuf;
+    BUFFER_ELEM       *next;
+    
+    
+};
+
+
+typedef struct _VALID_BUFFER_STRUCT_    VALID_BUFFER_STRUCT;
+
+struct _VALID_BUFFER_STRUCT_
+{
+    BUFFER_ELEM    *head;
+    BUFFER_ELEM    *tail;       
+};
+
+/* KEN: End*/
+
+VALID_BUFFER_STRUCT  rt2880_free_buf_list;
+VALID_BUFFER_STRUCT  rt2880_busing_buf_list;
+static BUFFER_ELEM   rt2880_free_buf[PKTBUFSRX];
+
+/*=========================================
+      PDMA RX Descriptor Format define
+=========================================*/
+
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO1_  PDMA_RXD_INFO1_T;
+
+struct _PDMA_RXD_INFO1_
+{
+    unsigned int    PDP0;
+};
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO2_    PDMA_RXD_INFO2_T;
+
+struct _PDMA_RXD_INFO2_
+{
+	unsigned int    PLEN1                   : 14;
+	unsigned int    LS1                     : 1;
+	unsigned int    UN_USED                 : 1;
+	unsigned int    PLEN0                   : 14;
+	unsigned int    LS0                     : 1;
+	unsigned int    DDONE_bit               : 1;
+};
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO3_  PDMA_RXD_INFO3_T;
+
+struct _PDMA_RXD_INFO3_
+{
+	unsigned int    PDP1;
+};
+//-------------------------------------------------
+typedef struct _PDMA_RXD_INFO4_    PDMA_RXD_INFO4_T;
+
+struct _PDMA_RXD_INFO4_
+{
+#if defined (PDMA_NEW)
+	unsigned int    FOE_Entry           	: 14;
+	unsigned int    CRSN                	: 5;
+	unsigned int    SP               	: 3;
+	unsigned int    L4F                 	: 1;
+	unsigned int    L4VLD               	: 1;
+	unsigned int    TACK                	: 1;
+	unsigned int    IP4F                	: 1;
+	unsigned int    IP4                 	: 1;
+	unsigned int    IP6                 	: 1;
+	unsigned int    UN_USE1             	: 4;
+#else
+	unsigned int    FOE_Entry               : 14;
+	unsigned int    FVLD                    : 1;
+	unsigned int    UN_USE1                 : 1;
+	unsigned int    AI                      : 8;
+	unsigned int    SP                      : 3;
+	unsigned int    AIS                     : 1;
+	unsigned int    L4F                     : 1;
+	unsigned int    IPF                     : 1;
+	unsigned int    L4FVLD_bit              : 1;
+	unsigned int    IPFVLD_bit              : 1;
+#endif
+};
+
+struct PDMA_rxdesc {
+	PDMA_RXD_INFO1_T rxd_info1;
+	PDMA_RXD_INFO2_T rxd_info2;
+	PDMA_RXD_INFO3_T rxd_info3;
+	PDMA_RXD_INFO4_T rxd_info4;
+};
+/*=========================================
+      PDMA TX Descriptor Format define
+=========================================*/
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO1_  PDMA_TXD_INFO1_T;
+
+struct _PDMA_TXD_INFO1_
+{
+	unsigned int    SDP0;
+};
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO2_    PDMA_TXD_INFO2_T;
+
+struct _PDMA_TXD_INFO2_
+{
+	unsigned int    SDL1                  : 14;
+	unsigned int    LS1_bit               : 1;
+	unsigned int    BURST_bit             : 1;
+	unsigned int    SDL0                  : 14;
+	unsigned int    LS0_bit               : 1;
+	unsigned int    DDONE_bit             : 1;
+};
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO3_  PDMA_TXD_INFO3_T;
+
+struct _PDMA_TXD_INFO3_
+{
+	unsigned int    SDP1;
+};
+//-------------------------------------------------
+typedef struct _PDMA_TXD_INFO4_    PDMA_TXD_INFO4_T;
+
+struct _PDMA_TXD_INFO4_
+{
+#if defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD)
+    unsigned int    VPRI_VIDX           : 8;
+    unsigned int    SIDX                : 4;
+    unsigned int    INSP                : 1;
+    unsigned int    RESV                : 2;
+    unsigned int    UDF                 : 5;
+    unsigned int    FP_BMAP             : 8;
+    unsigned int    TSO                 : 1;
+    unsigned int    TUI_CO              : 3;
+#elif defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+	unsigned int    VLAN_TAG            :16;
+    unsigned int    INS                 : 1;
+    unsigned int    RESV                : 2;
+    unsigned int    UDF                 : 6;
+    unsigned int    FPORT               : 3;
+    unsigned int    TSO                 : 1;
+    unsigned int    TUI_CO              : 3;
+#else
+    unsigned int    VIDX		: 4;
+    unsigned int    VPRI                : 3;
+    unsigned int    INSV                : 1;
+    unsigned int    SIDX                : 4;
+    unsigned int    INSP                : 1;
+    unsigned int    UN_USE3             : 3;
+    unsigned int    QN                  : 3;
+    unsigned int    UN_USE2             : 5;
+    unsigned int    PN                  : 3;
+    unsigned int    UN_USE1             : 2;
+    unsigned int    TUI_CO              : 3;
+#endif
+};
+
+struct PDMA_txdesc {
+	PDMA_TXD_INFO1_T txd_info1;
+	PDMA_TXD_INFO2_T txd_info2;
+	PDMA_TXD_INFO3_T txd_info3;
+	PDMA_TXD_INFO4_T txd_info4;
+};
+
+
+static  struct PDMA_txdesc tx_ring0_cache[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring         */
+static  struct PDMA_rxdesc rx_ring_cache[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring         */
+
+static int rx_dma_owner_idx0;                             /* Point to the next RXD DMA wants to use in RXD Ring#0.  */
+static int rx_wants_alloc_idx0;                           /* Point to the next RXD CPU wants to allocate to RXD Ring #0. */
+static int tx_cpu_owner_idx0;                             /* Point to the next TXD in TXD_Ring0 CPU wants to use */
+static volatile struct PDMA_rxdesc *rx_ring;
+static volatile struct PDMA_txdesc *tx_ring0;
+
+static char rxRingSize;
+static char txRingSize;
+volatile uchar      *PktBuf;
+volatile uchar	Pkt_Buf_Pool[(PKTBUFSRX+2) * PKTSIZE_ALIGN + PKTALIGN];
+
+static int   rt2880_eth_init(struct eth_device* dev, bd_t* bis);
+static int   rt2880_eth_send(struct eth_device* dev, void *packet, int length);
+static int   rt2880_eth_recv(struct eth_device* dev);
+void  rt2880_eth_halt(struct eth_device* dev);
+
+#ifdef RALINK_MDIO_ACCESS_FUN
+#ifdef RALINK_EPHY_INIT
+int   mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data);
+int   mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data);
+#else
+#define mii_mgr_read(x,y,z)	do{}while(0)
+#define mii_mgr_write(x,y,z)    do{}while(0)
+#endif // RALINK_EPHY_INIT //
+#else
+#define mii_mgr_read(x,y,z)	do{}while(0)
+#define mii_mgr_write(x,y,z)    do{}while(0)
+#endif // RALINK_MDIO_ACCESS_FUN //
+
+
+static int   rt2880_eth_setup(struct eth_device* dev);
+static int   rt2880_eth_initd;
+char         console_buffer[CONFIG_SYS_CBSIZE];		/* console I/O buffer	*/
+
+
+#define phys_to_bus(a) (a & 0x1FFFFFFF)
+
+#define PCI_WAIT_INPUT_CHAR(ch) while((ch = getc())== 0)
+
+struct eth_device* 	rt2880_pdev;
+
+volatile uchar	*PKT_HEADER_Buf;// = (uchar *)CFG_EMBEDED_SRAM_SDP0_BUF_START;
+static volatile uchar	PKT_HEADER_Buf_Pool[(PKTBUFSRX * PKTSIZE_ALIGN) + PKTALIGN];
+extern volatile uchar	*PktBuf;
+
+
+#define PIODIR_R  (RALINK_PIO_BASE + 0X24)
+#define PIODATA_R (RALINK_PIO_BASE + 0X20)
+#define PIODIR3924_R  (RALINK_PIO_BASE + 0x4c)
+#define PIODATA3924_R (RALINK_PIO_BASE + 0x48)
+
+
+#define FREEBUF_OFFSET(CURR)  ((int)(((0x0FFFFFFF & (u32)CURR) - (u32) (0x0FFFFFFF & (u32) rt2880_free_buf[0].pbuf)) / 1536))
+
+void START_ETH(struct eth_device *dev ) {
+	s32 omr;
+	omr=RALINK_REG(PDMA_GLO_CFG);
+	udelay(100);
+	omr |= TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN ;
+		
+	RALINK_REG(PDMA_GLO_CFG)=omr;
+	udelay(500);
+}
+
+
+void STOP_ETH(struct eth_device *dev)
+{
+	s32 omr;
+	omr=RALINK_REG(PDMA_GLO_CFG);
+	udelay(100);
+	omr &= ~(TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN) ;
+	RALINK_REG(PDMA_GLO_CFG)=omr;
+	udelay(500);
+}
+
+
+BUFFER_ELEM *rt2880_free_buf_entry_dequeue(VALID_BUFFER_STRUCT *hdr)
+{
+	int     zero = 0;           /* causes most compilers to place this */
+	/* value in a register only once */
+	BUFFER_ELEM  *node;
+
+	/* Make sure we were not passed a null pointer. */
+	if (!hdr) {
+		return (NULL);
+	}
+
+	/* If there is a node in the list we want to remove it. */
+	if (hdr->head) {
+		/* Get the node to be removed */
+		node = hdr->head;
+
+		/* Make the hdr point the second node in the list */
+		hdr->head = node->next;
+
+		/* If this is the last node the headers tail pointer needs to be nulled
+		   We do not need to clear the node's next since it is already null */
+		if (!(hdr->head)) {
+			hdr->tail = (BUFFER_ELEM *)zero;
+		}
+
+		node->next = (BUFFER_ELEM *)zero;
+
+
+
+
+	}
+	else {
+		node = NULL;
+		return (node);
+	}
+
+	/*  Restore the previous interrupt lockout level.  */
+
+	/* Return a pointer to the removed node */
+
+	//shnat_validation_flow_table_entry[node->index].state = SHNAT_FLOW_TABLE_NODE_USED;
+	return (node);
+}
+
+static BUFFER_ELEM *rt2880_free_buf_entry_enqueue(VALID_BUFFER_STRUCT *hdr, BUFFER_ELEM *item)
+{
+	int zero =0;
+
+	if (!hdr) {
+		return (NULL);
+	}
+
+	if (item != NULL)
+	{
+		/* Temporarily lockout interrupts to protect global buffer variables. */
+		// Sys_Interrupt_Disable_Save_Flags(&cpsr_flags);
+
+		/* Set node's next to point at NULL */
+		item->next = (BUFFER_ELEM *)zero;
+
+		/*  If there is currently a node in the linked list, we want to add the
+		    new node to the end. */
+		if (hdr->head) {
+			/* Make the last node's next point to the new node. */
+			hdr->tail->next = item;
+
+			/* Make the roots tail point to the new node */
+			hdr->tail = item;
+		}
+		else {
+			/* If the linked list was empty, we want both the root's head and
+			   tial to point to the new node. */
+			hdr->head = item;
+			hdr->tail = item;
+		}
+
+		/*  Restore the previous interrupt lockout level.  */
+
+	}
+	else
+	{
+		printf("\n shnat_flow_table_free_entry_enqueue is called,item== NULL \n");
+	}
+
+	return(item);
+
+} /* MEM_Buffer_Enqueue */
+
+int rt2880_eth_initialize(bd_t *bis)
+{
+	struct	eth_device* 	dev;
+	int	i;
+	
+	if (!(dev = (struct eth_device *) malloc (sizeof *dev))) {
+		printf("Failed to allocate memory\n");
+		return 0;
+	}
+
+	memset(dev, 0, sizeof(*dev));
+
+	sprintf(dev->name, "eth0-7621-gig");
+
+	dev->iobase = RALINK_FRAME_ENGINE_BASE;
+	dev->init   = rt2880_eth_init;
+	dev->halt   = rt2880_eth_halt;
+	dev->send   = rt2880_eth_send;
+	dev->recv   = rt2880_eth_recv;
+
+	eth_register(dev);
+	rt2880_pdev = dev;
+
+	rt2880_eth_initd =0;
+	PktBuf = Pkt_Buf_Pool;
+	PKT_HEADER_Buf = PKT_HEADER_Buf_Pool;
+	rx_ring = (struct PDMA_rxdesc *)KSEG1ADDR((ulong)&rx_ring_cache[0]);
+	tx_ring0 = (struct PDMA_txdesc *)KSEG1ADDR((ulong)&tx_ring0_cache[0]);
+
+	rt2880_free_buf_list.head = NULL;
+	rt2880_free_buf_list.tail = NULL;
+
+	rt2880_busing_buf_list.head = NULL;
+	rt2880_busing_buf_list.tail = NULL;
+
+	//2880_free_buf
+
+	/*
+	 *	Setup packet buffers, aligned correctly.
+	 */
+	rt2880_free_buf[0].pbuf = (unsigned char *)(&PktBuf[0] + (PKTALIGN - 1));
+	rt2880_free_buf[0].pbuf -= (ulong)rt2880_free_buf[0].pbuf % PKTALIGN;
+	rt2880_free_buf[0].next = NULL;
+
+	rt2880_free_buf_entry_enqueue(&rt2880_free_buf_list,&rt2880_free_buf[0]);
+
+#ifdef DEBUG
+	printf("\n rt2880_free_buf[0].pbuf = %p \n",rt2880_free_buf[0].pbuf);
+#endif
+	for (i = 1; i < PKTBUFSRX; i++) {
+		rt2880_free_buf[i].pbuf = rt2880_free_buf[0].pbuf + (i)*PKTSIZE_ALIGN;
+		rt2880_free_buf[i].next = NULL;
+#ifdef DEBUG
+		printf("\n rt2880_free_buf[%d].pbuf = %p\n",i,rt2880_free_buf[i].pbuf);
+#endif
+		rt2880_free_buf_entry_enqueue(&rt2880_free_buf_list,&rt2880_free_buf[i]);
+	}
+
+	for (i = 0; i < PKTBUFSRX; i++)
+	{
+		rt2880_free_buf[i].tx_idx = NUM_TX_DESC;
+#ifdef DEBUG
+		printf("\n rt2880_free_buf[%d] = %p,rt2880_free_buf[%d].next=%p \n",i,&rt2880_free_buf[i],i,rt2880_free_buf[i].next);
+#endif
+	}
+
+#if 0
+	//set clock resolution
+	extern unsigned long mips_bus_feq;
+	regValue = le32_to_cpu(*(volatile u_long *)(RALINK_FRAME_ENGINE_BASE + 0x0008));
+	regValue |=  ((mips_bus_feq/1000000) << 8);
+	*((volatile u_long *)(RALINK_FRAME_ENGINE_BASE + 0x0008)) = cpu_to_le32(regValue);
+#endif
+	return 1;
+}
+
+
+static int rt2880_eth_init(struct eth_device* dev, bd_t* bis)
+{
+	if(rt2880_eth_initd == 0)
+	{
+		rt2880_eth_setup(dev);
+	}
+	else
+	{
+		START_ETH(dev);
+	}
+
+	rt2880_eth_initd = 1;
+	return (1);
+}
+
+
+#if defined (RT6855A_ASIC_BOARD) || (RT6855A_FPGA_BOARD) ||\
+    defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD)
+void IsSwitchVlanTableBusy(void)
+{
+	int j = 0;
+	unsigned int value = 0;
+
+	for (j = 0; j < 20; j++) {
+            value = RALINK_REG(RALINK_ETH_SW_BASE+0x90); //VTCR
+	    if ((value & 0x80000000) == 0 ){ //table busy
+		break;
+	    }
+	    udelay(1000);
+	}
+	if (j == 20)
+	    printf("set vlan timeout.\n");
+}
+#elif defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+void IsSwitchVlanTableBusy(void)
+{
+	int j = 0;
+	unsigned int value = 0;
+
+	for (j = 0; j < 20; j++) {
+	    mii_mgr_read(31, 0x90, &value);
+	    if ((value & 0x80000000) == 0 ){ //table busy
+		break;
+	    }
+	    udelay(70000);
+	}
+	if (j == 20)
+	    printf("set vlan timeout value=0x%x.\n", value);
+}
+
+#endif
+
+
+
+void LANWANPartition(void)
+{
+#ifdef MAC_TO_100SW_MODE
+	int sw_id = 0;
+	mii_mgr_read(29, 31, &sw_id);
+#ifdef RALINK_DEMO_BOARD_PVLAN
+	if (sw_id == 0x175c) {
+		//disable tagged VLAN
+		mii_mgr_write(29, 23, 0);
+
+		//WLLLL, wan at P0, demo board
+		mii_mgr_write(29, 19, 0x809c);
+		mii_mgr_write(29, 20, 0x9a96);
+		mii_mgr_write(29, 21, 0x8e00);
+		mii_mgr_write(29, 22, 0x8420);
+	}
+	else {
+		mii_mgr_write(20, 13, 0x21);
+		mii_mgr_write(22, 14, 0x2002);
+		mii_mgr_write(22, 15, 0x1001);
+		mii_mgr_write(22, 16, 0x1001);
+		mii_mgr_write(22, 17, 0x1001);
+		mii_mgr_write(22, 18, 0x1001);
+		mii_mgr_write(22, 19, 0x1001);
+		mii_mgr_write(23, 0, 0x3e21);
+		mii_mgr_write(23, 1, 0x3e3e);
+		mii_mgr_write(23, 2, 0x3e3e);
+		mii_mgr_write(23, 16, 0x3f3f);
+		mii_mgr_write(23, 17, 0x3f3f);
+		mii_mgr_write(23, 18, 0x3f3f);
+	}
+#endif
+#ifdef RALINK_EV_BOARD_PVLAN
+	if (sw_id == 0x175c) {
+		//disable tagged VLAN
+		mii_mgr_write(29, 23, 0);
+
+		//LLLLW, wan at P4, ev board
+		mii_mgr_write(29, 19, 0x8e8d);
+		mii_mgr_write(29, 20, 0x8b87);
+		mii_mgr_write(29, 21, 0x8000);
+		mii_mgr_write(29, 22, 0x8420);
+	}
+	else {
+		mii_mgr_write(20, 13, 0x21);
+		mii_mgr_write(22, 14, 0x1001);
+		mii_mgr_write(22, 15, 0x1001);
+		mii_mgr_write(22, 16, 0x1001);
+		mii_mgr_write(22, 17, 0x1001);
+		mii_mgr_write(22, 18, 0x2002);
+		mii_mgr_write(22, 19, 0x1001);
+		mii_mgr_write(23, 0, 0x2f2f);
+		mii_mgr_write(23, 1, 0x2f2f);
+		mii_mgr_write(23, 2, 0x2f30);
+		mii_mgr_write(23, 16, 0x3f3f);
+		mii_mgr_write(23, 17, 0x3f3f);
+		mii_mgr_write(23, 18, 0x3f3f);
+	}
+#endif
+#endif // MAC_TO_100SW_MODE //
+
+#if defined (RT3052_ASIC_BOARD) || defined (RT3052_FPGA_BOARD) || \
+    defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD) || \
+    defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || \
+    defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+#ifdef RALINK_DEMO_BOARD_PVLAN
+	//WLLLL, wan at P0, demo board
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x40)) = 0x1002; //PVID
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x44)) = 0x1001; //PVID
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x48)) = 0x1001; //PVID
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x70)) = 0xffff417e; //VLAN member
+#endif
+#ifdef RALINK_EV_BOARD_PVLAN
+	//LLLLW, wan at P4, ev board
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x40)) = 0x1001; //PVID
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x44)) = 0x1001; //PVID
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x48)) = 0x1002; //PVID
+	*((volatile u32 *)(RALINK_ETH_SW_BASE + 0x70)) = 0xffff506f; //VLAN member
+#endif
+#endif // (RT3052_ASIC_BOARD || RT3052_FPGA_BOARD || RT3352_ASIC_BOARD || RT3352_FPGA_BOARD)
+
+#if defined (RT6855A_ASIC_BOARD) || (RT6855A_FPGA_BOARD) ||\
+    (defined (MT7620_ASIC_BOARD) && !defined(P5_RGMII_TO_MAC_MODE)) || defined (MT7620_FPGA_BOARD)
+
+#ifdef RALINK_DEMO_BOARD_PVLAN
+	//WLLLL, wan at P0, demo board
+	//LAN/WAN ports as security mode
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2004) = 0xff0003; //port0
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2104) = 0xff0003; //port1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2204) = 0xff0003; //port2
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2304) = 0xff0003; //port3
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2404) = 0xff0003; //port4
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2504) = 0xff0003; //port5
+
+	//set PVID
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2014) = 0x10002; //port0
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2114) = 0x10001; //port1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2214) = 0x10001; //port2
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2314) = 0x10001; //port3
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2414) = 0x10001; //port4
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2514) = 0x10001; //port5
+
+	//VLAN member
+	RALINK_REG(RALINK_ETH_SW_BASE+0x94) = 0x40fe0001; //VAWD1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x90) = 0x80001000; //VTCR
+	IsSwitchVlanTableBusy();
+
+	RALINK_REG(RALINK_ETH_SW_BASE+0x94) = 0x40c10001; //VAWD1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x90) = 0x80001001; //VTCR
+	IsSwitchVlanTableBusy();
+#endif
+#ifdef RALINK_EV_BOARD_PVLAN
+	//LLLLW, wan at P4, ev board
+	//LAN/WAN ports as security mode
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2004) = 0xff0003; //port0
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2104) = 0xff0003; //port1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2204) = 0xff0003; //port2
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2304) = 0xff0003; //port3
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2404) = 0xff0003; //port4
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2504) = 0xff0003; //port5
+
+	//set PVID
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2014) = 0x10001; //port0
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2114) = 0x10001; //port1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2214) = 0x10001; //port2
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2314) = 0x10001; //port3
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2414) = 0x10002; //port4
+	RALINK_REG(RALINK_ETH_SW_BASE+0x2514) = 0x10001; //port5
+
+	//VLAN member
+	RALINK_REG(RALINK_ETH_SW_BASE+0x94) = 0x40ef0001; //VAWD1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x90) = 0x80001000; //VTCR
+	IsSwitchVlanTableBusy();
+	
+	RALINK_REG(RALINK_ETH_SW_BASE+0x94) = 0x40d00001; //VAWD1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x90) = 0x80001001; //VTCR
+	IsSwitchVlanTableBusy();
+#endif
+
+#elif defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD) ||\
+      (defined(MT7620_ASIC_BOARD) && defined(P5_RGMII_TO_MAC_MODE))
+/*Set  MT7530 */
+#ifdef RALINK_DEMO_BOARD_PVLAN
+	printf("set LAN/WAN WLLLL\n");
+	//WLLLL, wan at P0, demo board
+	//LAN/WAN ports as security mode
+	mii_mgr_write(31, 0x2004, 0xff0003);//port0
+	mii_mgr_write(31, 0x2104, 0xff0003);//port1
+	mii_mgr_write(31, 0x2204, 0xff0003);//port2
+	mii_mgr_write(31, 0x2304, 0xff0003);//port3
+	mii_mgr_write(31, 0x2404, 0xff0003);//port4
+	//mii_mgr_write(31, 0x2504, 0xff0003);//port5
+	//mii_mgr_write(31, 0x2604, 0xff0003);//port5
+
+	//set PVID
+	mii_mgr_write(31, 0x2014, 0x10002);//port0
+	mii_mgr_write(31, 0x2114, 0x10001);//port1
+	mii_mgr_write(31, 0x2214, 0x10001);//port2
+	mii_mgr_write(31, 0x2314, 0x10001);//port3
+	mii_mgr_write(31, 0x2414, 0x10001);//port4
+	//mii_mgr_write(31, 0x2514, 0x10001);//port5
+	//mii_mgr_write(31, 0x2614, 0x10001);//port6
+	/*port6 */
+	//VLAN member
+	IsSwitchVlanTableBusy();
+	mii_mgr_write(31, 0x94, 0x407e0001);//VAWD1
+	mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
+	IsSwitchVlanTableBusy();
+
+	mii_mgr_write(31, 0x94, 0x40610001);//VAWD1
+	mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
+	IsSwitchVlanTableBusy();
+#endif
+#ifdef RALINK_EV_BOARD_PVLAN
+	printf("set LAN/WAN LLLLW\n");
+	//LLLLW, wan at P4, ev board
+	//LAN/WAN ports as security mode
+	mii_mgr_write(31, 0x2004, 0xff0003);//port0
+	mii_mgr_write(31, 0x2104, 0xff0003);//port1
+	mii_mgr_write(31, 0x2204, 0xff0003);//port2
+	mii_mgr_write(31, 0x2304, 0xff0003);//port3
+	mii_mgr_write(31, 0x2404, 0xff0003);//port4
+	mii_mgr_write(31, 0x2504, 0xff0003);//port5
+	mii_mgr_write(31, 0x2604, 0xff0003);//port6
+
+	//set PVID
+	mii_mgr_write(31, 0x2014, 0x10001);//port0
+	mii_mgr_write(31, 0x2114, 0x10001);//port1
+	mii_mgr_write(31, 0x2214, 0x10001);//port2
+	mii_mgr_write(31, 0x2314, 0x10001);//port3
+	mii_mgr_write(31, 0x2414, 0x10002);//port4
+	mii_mgr_write(31, 0x2514, 0x10001);//port5
+	mii_mgr_write(31, 0x2614, 0x10001);//port6
+
+
+	//VLAN member
+	IsSwitchVlanTableBusy();
+	//mii_mgr_write(31, 0x94, 0x407e0001);//VAWD1
+	mii_mgr_write(31, 0x94, 0x404f0001);//VAWD1
+	mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
+	IsSwitchVlanTableBusy();
+	
+	//mii_mgr_write(31, 0x94, 0x40610001);//VAWD1
+	mii_mgr_write(31, 0x94, 0x40500001);//VAWD1
+	mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
+	IsSwitchVlanTableBusy();
+#endif
+#endif
+}
+
+#if defined (P5_RGMII_TO_MAC_MODE) || (defined (MAC_TO_VITESSE_MODE) && defined (MAC_TO_MT7530_MODE))
+static void ResetSWusingGPIOx(void)
+{
+#ifdef GPIOx_RESET_MODE
+	u32 value;
+
+#if defined (RT2880_FPGA_BOARD) || defined (RT2880_ASIC_BOARD)
+
+	printf("\n GPIO pin 10 reset to switch\n");
+
+	//set spi/gpio share pin to gpio mode
+	value = le32_to_cpu(*(volatile u_long *)RT2880_GPIOMODE_REG);
+	value |= (1 << 1);
+	*(volatile u_long *)(RT2880_GPIOMODE_REG) = cpu_to_le32(value);
+
+	//Set Gpio pin 10 to output
+	value = le32_to_cpu(*(volatile u_long *)PIODIR_R);
+	value |= (1 << 10);
+	*(volatile u_long *)(PIODIR_R) = cpu_to_le32(value);
+
+	//Set Gpio pin 10 to low
+	value = le32_to_cpu(*(volatile u_long *)PIODATA_R);
+	value &= ~(1 << 10);
+	*(volatile u_long *)(PIODATA_R) = cpu_to_le32(value);
+	
+	udelay(50000);
+	//Set Gpio pin 10 to high
+	value = le32_to_cpu(*(volatile u_long *)PIODATA_R);
+	value |= (1 << 10);
+	*(volatile u_long *)(PIODATA_R) = cpu_to_le32(value);
+
+#elif defined (RT2883_FPGA_BOARD) || defined (RT2883_ASIC_BOARD)
+	printf("\n GPIO pin 12 reset to switch\n");
+
+	//Set UARTF_SHARED_MODE to 3'b111 bcs we need gpio 12, and SPI to normal mode
+	value = le32_to_cpu(*(volatile u_long *)RT2880_GPIOMODE_REG);
+	value |= (7 << 2);
+	value &= ~(1 << 1);
+	*(volatile u_long *)(RT2880_GPIOMODE_REG) = cpu_to_le32(value);
+
+	//Set Gpio pin 12 to output, and pin 7(RTS) to input
+	value = le32_to_cpu(*(volatile u_long *)PIODIR_R);
+	value |= (1 << 12);
+	value &= ~(1 << 7);
+	*(volatile u_long *)(PIODIR_R) = cpu_to_le32(value);
+
+	//Set Gpio pin 12 to low
+	value = le32_to_cpu(*(volatile u_long *)PIODATA_R);
+	value &= ~(1 << 12);
+	*(volatile u_long *)(PIODATA_R) = cpu_to_le32(value);
+	
+	udelay(50000);
+	//Set Gpio pin 12 to high
+	value = le32_to_cpu(*(volatile u_long *)PIODATA_R);
+	value |= (1 << 12);
+	*(volatile u_long *)(PIODATA_R) = cpu_to_le32(value);
+
+#elif defined (RT3052_ASIC_BOARD) || defined (RT3052_FPGA_BOARD) 
+	printf("\n GPIO pin 36 reset to switch\n");
+
+	//Set UARTF_SHARED_MODE to 3'b111 bcs we need gpio 36, and SPI to normal mode
+	value = le32_to_cpu(*(volatile u_long *)RT2880_GPIOMODE_REG);
+	value |= (7 << 2);
+	value &= ~(1 << 1);
+	*(volatile u_long *)(RT2880_GPIOMODE_REG) = cpu_to_le32(value);
+
+	//Set Gpio pin 36 to output
+	value = le32_to_cpu(*(volatile u_long *)0xb000064c);
+	value |= (1 << 12);
+	*(volatile u_long *)(0xb000064c) = cpu_to_le32(value);
+
+	//Set Gpio pin 36 to low
+	value = le32_to_cpu(*(volatile u_long *)0xb0000648);
+	value &= ~(1 << 12);
+	*(volatile u_long *)(0xb0000648) = cpu_to_le32(value);
+	
+	udelay(50000);
+	//Set Gpio pin 36 to high
+	value = le32_to_cpu(*(volatile u_long *)0xb0000648);
+	value |= (1 << 12);
+	*(volatile u_long *)(0xb0000648) = cpu_to_le32(value);
+
+#elif defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD) 
+	printf("\n Please FIXME... \n");
+
+#elif defined (RT3883_ASIC_BOARD)
+	printf("\n GPIO pin 24 reset to switch\n");
+	/* MT7530 reset timing at least 2ms*/
+	//Set Gpio pin 24 to output
+	value = le32_to_cpu(*(volatile u_long *)PIODIR3924_R);
+	value |= 1;
+	*(volatile u_long *)(PIODIR3924_R) = cpu_to_le32(value);
+
+	//Set Gpio pin 24 to low
+	value = le32_to_cpu(*(volatile u_long *)PIODATA3924_R);
+	value &= ~1;
+	*(volatile u_long *)(PIODATA3924_R) = cpu_to_le32(value);
+
+	udelay(50000);
+	//Set Gpio pin 24 to high
+	value = le32_to_cpu(*(volatile u_long *)PIODATA3924_R);
+	value |= 1;
+	*(volatile u_long *)(PIODATA3924_R) = cpu_to_le32(value);
+#elif defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD) 
+	/* TODO */
+#elif defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) 
+	printf("\n GPIO pin 10 reset to switch\n");
+	/* MT7530 reset timing at least 2ms*/
+	//set spi/gpio share pin to gpio mode
+	value = le32_to_cpu(*(volatile u_long *)RT2880_GPIOMODE_REG);
+	value |= (1 << 1);
+	*(volatile u_long *)(RT2880_GPIOMODE_REG) = cpu_to_le32(value);
+
+	//Set Gpio pin 10 to output
+	value = le32_to_cpu(*(volatile u_long *)PIODIR_R);
+	value |= (1 << 10);
+	*(volatile u_long *)(PIODIR_R) = cpu_to_le32(value);
+
+	//Set Gpio pin 10 to low
+	value = le32_to_cpu(*(volatile u_long *)PIODATA_R);
+	value &= ~(1 << 10);
+	*(volatile u_long *)(PIODATA_R) = cpu_to_le32(value);
+	
+	udelay(10000);
+	//Set Gpio pin 10 to high
+	value = le32_to_cpu(*(volatile u_long *)PIODATA_R);
+	value |= (1 << 10);
+	*(volatile u_long *)(PIODATA_R) = cpu_to_le32(value);
+
+#elif defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD) 
+	/* TODO: reset MT7530 switch */
+#else
+#error "Unknown Chip"
+#endif
+#endif // GPIOx_RESET_MODE //
+}
+#endif
+
+#if defined (MAC_TO_GIGAPHY_MODE) || defined (P5_MAC_TO_PHY_MODE)|| defined (P4_MAC_TO_PHY_MODE)
+#define EV_ICPLUS_PHY_ID0 0x0243
+#define EV_ICPLUS_PHY_ID1 0x0D90
+static int isICPlusGigaPHY(int ge)
+{
+	u32 phy_id0,phy_id1;
+        u32 phy_addr = 0;
+	
+#if defined (P5_MAC_TO_PHY_MODE) || defined (MAC_TO_GIGAPHY_MODE)
+	if(ge == 1)
+	    phy_addr = MAC_TO_GIGAPHY_MODE_ADDR;
+#endif
+#if defined (P4_MAC_TO_PHY_MODE)	
+	if(ge == 2)
+	    phy_addr = MAC_TO_GIGAPHY_MODE_ADDR2;
+#endif
+	if( ! mii_mgr_read(phy_addr, 2, &phy_id0)){
+		printf("\n Read PhyID 0 is Fail!!\n");
+		phy_id0 =0;
+	}
+
+	if( ! mii_mgr_read(phy_addr, 3, &phy_id1)){
+		printf("\n Read PhyID 1 is Fail!!\n");
+		phy_id1 = 0;
+	}
+
+	if((phy_id0 == EV_ICPLUS_PHY_ID0) && ((phy_id1 & 0xfff0)== EV_ICPLUS_PHY_ID1))
+		return 1;
+
+	return 0;
+}
+#define EV_MARVELL_PHY_ID0 0x0141
+#define EV_MARVELL_PHY_ID1 0x0CC2
+static int isMarvellGigaPHY(int ge)
+{
+	u32 phy_id0,phy_id1;
+        u32 phy_addr = 0;
+
+#if defined (P5_MAC_TO_PHY_MODE) || defined (MAC_TO_GIGAPHY_MODE)	
+	if(ge == 1)
+	    phy_addr = MAC_TO_GIGAPHY_MODE_ADDR;
+#endif
+#if defined (P4_MAC_TO_PHY_MODE)	
+	if(ge == 2)
+	    phy_addr = MAC_TO_GIGAPHY_MODE_ADDR2;
+#endif
+	if( ! mii_mgr_read(phy_addr, 2, &phy_id0)){
+		printf("\n Read PhyID 0 is Fail!!\n");
+		phy_id0 =0;
+	}
+
+	if( ! mii_mgr_read(phy_addr, 3, &phy_id1)){
+		printf("\n Read PhyID 1 is Fail!!\n");
+		phy_id1 = 0;
+	}
+
+	if((phy_id0 == EV_MARVELL_PHY_ID0) && (phy_id1 == EV_MARVELL_PHY_ID1))
+		return 1;
+
+	return 0;
+}
+
+#define EV_VTSS_PHY_ID0 0x0007
+#define EV_VTSS_PHY_ID1 0x0421
+static int isVtssGigaPHY(int ge)
+{
+	u32 phy_id0,phy_id1;
+        u32 phy_addr = 0;
+
+#if defined (P5_MAC_TO_PHY_MODE) || defined (MAC_TO_GIGAPHY_MODE)	
+	if(ge == 1)
+	    phy_addr = MAC_TO_GIGAPHY_MODE_ADDR;
+#endif
+#if defined (P4_MAC_TO_PHY_MODE)	
+	if(ge == 2)
+	    phy_addr = MAC_TO_GIGAPHY_MODE_ADDR2;
+#endif
+	if( ! mii_mgr_read(phy_addr, 2, &phy_id0)){
+		printf("\n Read PhyID 0 is Fail!!\n");
+		phy_id0 =0;
+	}
+
+	if( ! mii_mgr_read(phy_addr, 3, &phy_id1)){
+		printf("\n Read PhyID 1 is Fail!!\n");
+		phy_id1 = 0;
+	}
+
+	if((phy_id0 == EV_VTSS_PHY_ID0) && (phy_id1 == EV_VTSS_PHY_ID1))
+		return 1;
+
+	return 0;
+}
+
+#endif // MAC_TO_GIGAPHY_MODE || P5_MAC_TO_PHY_MODE //
+
+#if defined (MAC_TO_GIGAPHY_MODE) || defined (P5_MAC_TO_PHY_MODE) || defined (MAC_TO_100PHY_MODE) || defined (P4_MAC_TO_PHY_MODE)
+
+#if defined (RT6855_ASIC_BOARD) || defined (RT6855_FPGA_BOARD) || \
+    defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+
+void enable_auto_negotiate(void)
+{
+	u32 regValue;
+	u32 addr = MAC_TO_GIGAPHY_MODE_ADDR;	// define in config.mk
+
+	regValue = le32_to_cpu(*(volatile u_long *)(RALINK_ETH_SW_BASE+0x7000));
+	regValue |= (1<<31);
+	regValue &= ~(0x1f);
+	regValue &= ~(0x1f<<8);
+	regValue |= (addr << 0);// setup PHY address for auto polling (start Addr).
+	regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
+	
+	*(volatile u_long *)(RALINK_ETH_SW_BASE+0x7000) = cpu_to_le32(regValue);
+}
+
+#elif defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) || \
+      defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+
+void enable_auto_negotiate(void)
+{
+	u32 regValue;
+#if defined (P4_MAC_TO_PHY_MODE)
+	u32 addr = MAC_TO_GIGAPHY_MODE_ADDR2;	// define in config.mk
+#else
+	u32 addr = MAC_TO_GIGAPHY_MODE_ADDR;	// define in config.mk
+#endif
+#if defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD)
+	//enable MDIO mode all the time
+	regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
+	regValue &= ~(0x3 << 12);
+        *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
+#endif
+
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+	regValue = le32_to_cpu(*(volatile u_long *)(RALINK_ETH_SW_BASE+0x0000));
+#else
+	regValue = le32_to_cpu(*(volatile u_long *)(RALINK_ETH_SW_BASE+0x7000));
+#endif
+	regValue |= (1<<31);
+	regValue &= ~(0x1f);
+	regValue &= ~(0x1f<<8);
+#if defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD)
+	regValue |= ((addr-1) << 0);// setup PHY address for auto polling (start Addr).
+	regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
+#elif defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+#ifdef	MT7621_USE_GE1
+	regValue |= (addr << 0);// setup PHY address for auto polling (start Addr).
+	regValue |= ((addr+1) << 8);// setup PHY address for auto polling (End Addr).
+#else
+	regValue |= ((addr-1)&0x1f << 0);// setup PHY address for auto polling (start Addr).
+	regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
+#endif
+#else
+	regValue |= (addr << 0);// setup PHY address for auto polling (start Addr).
+	regValue |= (addr << 8);// setup PHY address for auto polling (End Addr).
+#endif
+
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)	
+	*(volatile u_long *)(RALINK_ETH_SW_BASE+0x0000) = cpu_to_le32(regValue);
+#else
+	*(volatile u_long *)(RALINK_ETH_SW_BASE+0x7000) = cpu_to_le32(regValue);
+#endif
+
+#if defined (P4_MAC_TO_PHY_MODE)      
+	*(volatile u_long *)(RALINK_ETH_SW_BASE+0x3400) &= ~(0x1 << 15);
+#endif
+#if defined (P5_MAC_TO_PHY_MODE) 
+	*(volatile u_long*)(RALINK_ETH_SW_BASE+0x3500) &= ~(0x1 << 15);
+#endif
+
+}
+
+#elif defined (RT2880_ASIC_BOARD) || defined (RT2880_FPGA_BOARD) || \
+      defined (RT3883_ASIC_BOARD) || defined (RT3883_FPGA_BOARD) || \
+      defined (RT3052_ASIC_BOARD) || defined (RT3052_FPGA_BOARD) || \
+      defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD)
+void enable_auto_negotiate(void)
+{
+	u32 regValue;
+	u32 addr = MAC_TO_GIGAPHY_MODE_ADDR;	// define in config.mk
+
+#if defined (RT3052_ASIC_BOARD) || defined (RT3052_FPGA_BOARD) || \
+    defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD) 
+	regValue = le32_to_cpu(*(volatile u_long *)(RALINK_ETH_SW_BASE+0x00C8));
+#else
+	regValue = RALINK_REG(MDIO_CFG);
+#endif
+
+	regValue &= 0xe0ff7fff;				// clear auto polling related field:
+							// (MD_PHY1ADDR & GP1_FRC_EN).
+	regValue |= 0x20000000;				// force to enable MDC/MDIO auto polling.
+	regValue |= (addr << 24);			// setup PHY address for auto polling.
+
+#if defined (RT3052_ASIC_BOARD) || defined (RT3052_FPGA_BOARD) || \
+    defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD)
+	*(volatile u_long *)(RALINK_ETH_SW_BASE+0x00C8) = cpu_to_le32(regValue);
+#else
+	RALINK_REG(MDIO_CFG) = cpu_to_le32(regValue);
+#endif
+
+}
+#else
+#error "unknown platform"
+#endif
+#endif // defined (MAC_TO_GIGAPHY_MODE) || defined (P5_MAC_TO_PHY_MODE) || defined (MAC_TO_100PHY_MODE) //
+
+int isDMABusy(struct eth_device* dev)
+{
+	u32 reg;
+
+	reg = RALINK_REG(PDMA_GLO_CFG);
+
+	if((reg & RX_DMA_BUSY)){
+		return 1;
+	}
+
+	if((reg & TX_DMA_BUSY)){
+		printf("\n  TX_DMA_BUSY !!! ");
+		return 1;
+	}
+	return 0;
+}
+
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+void rt6855A_gsw_init(void)
+{
+	u32	i = 0;
+	u32	phy_val=0;
+	u32     rev=0;
+#if defined (RT6855A_FPGA_BOARD)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3000) = 0x5e353;//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3100) = 0x5e353;//(P1, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+	//RALINK_REG(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
+	//RALINK_REG(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3200) = 0x8000;//P2, link down
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3300) = 0x8000;//P3, link down
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3400) = 0x8000;//P4, link down
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//P5, link down
+
+	/* In order to use 10M/Full on FPGA board. We configure phy capable to
+	 * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
+	for (i=6; i<8; i++) {
+		mii_mgr_write(i, 4, 0x07e1);   //Capable of 10M&100M Full/Half Duplex, flow control on/off
+		//mii_mgr_write(i, 4, 0x0461);   //Capable of 10M Full/Half Duplex, flow control on/off
+		mii_mgr_write(i, 0, 0xB100);   //reset all digital logic, except phy_reg
+		mii_mgr_read(i, 9, &phy_val);
+                phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement
+                mii_mgr_write(i, 9, phy_val);
+	}
+#elif defined (RT6855A_ASIC_BOARD)
+
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//CPU exist in port 6
+        RALINK_REG(RALINK_FRAME_ENGINE_BASE+0x1ec) = 0x0fffffff;//Set PSE should pause 4 tx ring as default
+        RALINK_REG(RALINK_FRAME_ENGINE_BASE+0x1f0) = 0x0fffffff;//switch IOT more stable
+	RALINK_REG(RALINK_ETH_SW_BASE+0x30f0) &= ~(3 << 4); ////keep rx/tx port clock ticking, disable internal clock-gating to avoid switch stuck
+	/*
+	 *  Reg 31: Page Control
+	 *  Bit 15     => PortPageSel, 1=local, 0=global
+	 *  Bit 14:12  => PageSel, local:0~3, global:0~4
+	 *  Reg16~30:Local/Global registers
+	 */
+	/*correct  PHY  setting J8.0*/
+	mii_mgr_read(0, 31, &rev);
+        rev &= (0x0f);
+
+	mii_mgr_write(1, 31, 0x4000); //global, page 4
+
+	mii_mgr_write(1, 16, 0xd4cc);
+	mii_mgr_write(1, 17, 0x7444);
+	mii_mgr_write(1, 19, 0x0112);
+	mii_mgr_write(1, 21, 0x7160);
+	mii_mgr_write(1, 22, 0x10cf);
+	mii_mgr_write(1, 26, 0x0777);
+
+	if(rev == 0){
+	        mii_mgr_write(1, 25, 0x0102);
+		mii_mgr_write(1, 29, 0x8641);
+	}
+	else{
+	        mii_mgr_write(1, 25, 0x0212);
+		mii_mgr_write(1, 29, 0x4640);
+        }
+
+	mii_mgr_write(1, 31, 0x2000); //global, page 2
+	mii_mgr_write(1, 21, 0x0655);
+	mii_mgr_write(1, 22, 0x0fd3);
+	mii_mgr_write(1, 23, 0x003d);
+	mii_mgr_write(1, 24, 0x096e);
+	mii_mgr_write(1, 25, 0x0fed);
+	mii_mgr_write(1, 26, 0x0fc4);
+
+	mii_mgr_write(1, 31, 0x1000); //global, page 1  
+	mii_mgr_write(1, 17, 0xe7f8);
+
+	mii_mgr_write(1, 31, 0xa000); //local, page 2
+
+	mii_mgr_write(0, 16, 0x0e0e);
+	mii_mgr_write(1, 16, 0x0c0c);
+	mii_mgr_write(2, 16, 0x0f0f);
+	mii_mgr_write(3, 16, 0x1010);
+	mii_mgr_write(4, 16, 0x0909);
+
+	mii_mgr_write(0, 17, 0x0000);
+	mii_mgr_write(1, 17, 0x0000);
+	mii_mgr_write(2, 17, 0x0000);
+	mii_mgr_write(3, 17, 0x0000);
+	mii_mgr_write(4, 17, 0x0000);
+
+	/*restart AN to make PHY work normal*/
+	for (i=0; i<5; i++) {
+	    mii_mgr_read(i, 0, &phy_val);
+	    phy_val |= 1<<9; //restart AN
+	    mii_mgr_write(i, 0, phy_val);
+	}
+#endif  
+
+#if defined (RT6855A_ASIC_BOARD)
+#if defined (P5_RGMII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b; ////(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c;//disable port0-port4 internal phy, set phy base address to 12
+	RALINK_REG(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
+	RALINK_REG(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
+#elif defined (P5_MII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x5e337; ////(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+#elif defined (P5_MAC_TO_PHY_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x7014) = 0xc;//TX/RX CLOCK Phase select
+	enable_auto_negotiate();
+	if (isICPlusGigaPHY(1)) {
+	    printf("ICPLUS Phy1\n");
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
+	    phy_val |= 1<<10; //enable pause ability
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
+
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
+	    phy_val |= 1<<9; //restart AN
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
+	}
+	if (isMarvellGigaPHY(1)) {
+		printf("MARVELL Phy1\n");
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 20, 0x0ce0);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, 0x9140);
+	}
+	if (isVtssGigaPHY(1)) {
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
+		printf("GE1 Vitesse Phy reg28 %x --> ",phy_val);
+		phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
+		phy_val &= ~(0x3<<14); // RGMII TX skew compensation= 0 ns
+		printf("%x (without reset PHY)\n", phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 0); //main registers
+	}
+#elif defined (P5_RMII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x5e337; ////(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+#else /* Port 5 disabled */
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x8000; ////(P5, Link Down)
+#endif // P5_RGMII_TO_MAC_MODE //
+#endif
+}
+#endif
+
+
+#if defined (RT6855_ASIC_BOARD) || defined (RT6855_FPGA_BOARD) || \
+    defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD)
+void rt_gsw_init(void)
+{
+	u32	i = 0;
+	u32	phy_val = 0;
+	u32     rev = 0;
+	u32	is_BGA = 0;
+#if defined (P5_RGMII_TO_MAC_MODE)
+	u32	regValue;
+#endif
+#if defined (RT6855_FPGA_BOARD) || defined (MT7620_FPGA_BOARD)
+	/*keep dump switch mode */
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3200) = 0x5e333;//(P2, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3300) = 0x5e333;//(P3, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
+#if defined (MT7620_FPGA_BOARD)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+#else
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3400) = 0x5e333;//(P4, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
+#endif
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+	/* In order to use 10M/Full on FPGA board. We configure phy capable to 
+	 * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
+#if defined (MT7620_FPGA_BOARD)
+	for(i=0;i<4;i++){
+#else
+	for(i=0;i<5;i++){
+#endif
+	    mii_mgr_write(i, 4, 0x0461);   //Capable of 10M Full/Half Duplex, flow control on/off
+	    mii_mgr_write(i, 0, 0xB100);   //reset all digital logic, except phy_reg
+	}
+#endif  
+
+#if defined (MT7620_ASIC_BOARD)
+	is_BGA = (RALINK_REG(RALINK_SYSCTL_BASE + 0xc) >> 16) & 0x1;
+	/*
+	 *  Reg 31: Page Control
+	 *  Bit 15     => PortPageSel, 1=local, 0=global
+	 *  Bit 14:12  => PageSel, local:0~3, global:0~4
+	 *  Reg 16~30:Local/Global registers
+	 */
+	/*correct  PHY  setting L3.0 BGA*/
+
+	mii_mgr_write(1, 31, 0x4000); //global, page 4
+	mii_mgr_write(1, 17, 0x7444);
+	if(is_BGA){
+		mii_mgr_write(1, 19, 0x0114);
+	}else{
+		mii_mgr_write(1, 19, 0x0117);
+	}	
+	mii_mgr_write(1, 22, 0x10cf);
+	mii_mgr_write(1, 25, 0x6212);
+	mii_mgr_write(1, 26, 0x0777);
+	mii_mgr_write(1, 29, 0x4000);
+	mii_mgr_write(1, 28, 0xc077);
+	mii_mgr_write(1, 24, 0x0000);
+
+	mii_mgr_write(1, 31, 0x3000); //global, page 3  
+	mii_mgr_write(1, 17, 0x4838);
+
+	mii_mgr_write(1, 31, 0x2000); //global, page 2
+
+	if(is_BGA){
+	    mii_mgr_write(1, 21, 0x0515);
+	    mii_mgr_write(1, 22, 0x0053);
+	    mii_mgr_write(1, 23, 0x00bf);
+	    mii_mgr_write(1, 24, 0x0aaf);
+	    mii_mgr_write(1, 25, 0x0fad);
+	    mii_mgr_write(1, 26, 0x0fc1);
+	}else{
+	    mii_mgr_write(1, 21, 0x0517);
+	    mii_mgr_write(1, 22, 0x0fd2);
+	    mii_mgr_write(1, 23, 0x00bf);
+	    mii_mgr_write(1, 24, 0x0aab);
+	    mii_mgr_write(1, 25, 0x00ae);
+	    mii_mgr_write(1, 26, 0x0fff);
+	}
+	mii_mgr_write(1, 31, 0x1000); //global, page 1  
+	mii_mgr_write(1, 17, 0xe7f8);
+
+	mii_mgr_write(1, 31, 0x8000); //local, page 0
+	mii_mgr_write(0, 30, 0xa000);
+	mii_mgr_write(1, 30, 0xa000);
+	mii_mgr_write(2, 30, 0xa000);
+	mii_mgr_write(3, 30, 0xa000);
+#if defined(P4_MAC_TO_NONE_MODE)	
+	mii_mgr_write(4, 30, 0xa000);
+#endif
+
+	mii_mgr_write(0, 4, 0x05e1);
+        mii_mgr_write(1, 4, 0x05e1);
+	mii_mgr_write(2, 4, 0x05e1);
+	mii_mgr_write(3, 4, 0x05e1);
+#if defined(P4_MAC_TO_NONE_MODE)	
+	mii_mgr_write(4, 4, 0x05e1);
+#endif
+
+	mii_mgr_write(1, 31, 0xa000); //local, page 2
+	mii_mgr_write(0, 16, 0x1111);
+	mii_mgr_write(1, 16, 0x1010);
+	mii_mgr_write(2, 16, 0x1515);
+	mii_mgr_write(3, 16, 0x0f0f);
+#if defined(P4_MAC_TO_NONE_MODE)	
+	mii_mgr_write(4, 16, 0x1313);
+#endif
+
+	/*restart AN to make PHY work normal*/
+#if defined(P4_MAC_TO_NONE_MODE)	
+	for (i=0; i<5; i++) {
+#else
+	for (i=0; i<4; i++) {
+#endif
+	    mii_mgr_read(i, 0, &phy_val);
+	    phy_val |= 1<<9; //restart AN
+	    mii_mgr_write(i, 0, phy_val);
+	}
+#endif 
+
+
+#if defined (PDMA_NEW)
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 8); //PCIE_RC_MODE=1
+#endif
+
+#if defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0010) = 0x7f7f7fe0;//CPU exist in port 6
+#if defined (P5_RGMII_TO_MAC_MODE)
+	*(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
+
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b; ////(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c;//disable port0-port4 internal phy, set phy base address to 12
+	RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3<<12); ////GE1_MODE=RGMii Mode
+	
+	/*HW RESET MT7530*/
+	ResetSWusingGPIOx();
+	udelay(125000);
+
+	for(i=0;i<=4;i++) 
+	{	
+	       //turn off PHY
+	       mii_mgr_read(i, 0x0 ,&regValue);
+	       regValue |= (0x1<<11);
+               mii_mgr_write(i, 0x0, regValue);
+
+	}
+	mii_mgr_write(31, 0x3500, 0x8000);
+	mii_mgr_write(31, 0x3600, 0x8000);//force MAC link down before reset
+
+
+	/*Init MT7530, we use MT7530 as default external switch*/
+	mii_mgr_write(31, 0x7000, 0x3);//reset MT7530
+	//printf("#Reset_MT7530\n");
+	udelay(100);
+	
+	for(i=0;i<=4;i++) 
+	{	
+	       //turn on PHY
+	       mii_mgr_read(i, 0x0 ,&regValue);
+	       regValue &= ~(0x1<<11);
+               mii_mgr_write(i, 0x0, regValue);
+	}
+	mii_mgr_write(31, 0x3600, 0x5e33b);//MT7530 P6 force 1G
+	mii_mgr_write(31, 0x7804, 0x1117ccf);//MT7530 P5 disable
+#elif defined (P5_MII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x5e337; ////(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+	RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 12);
+#elif defined (P5_MAC_TO_PHY_MODE)
+	RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
+	enable_auto_negotiate();
+	if (isICPlusGigaPHY(1)) {
+	    printf("ICPLUS Phy1\n");
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
+	    phy_val |= 1<<10; //enable pause ability
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
+
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
+	    phy_val |= 1<<9; //restart AN
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
+	}
+	if (isMarvellGigaPHY(1)) {
+		printf("MARVELL Phy1\n");
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 20, 0x0ce0);
+#if defined (MT7620_FPGA_BOARD)
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
+		phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
+#endif
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, 0x9140);
+	}
+	if (isVtssGigaPHY(1)) {
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
+		printf("GE1 Vitesse Phy reg28 %x --> ",phy_val);
+		phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
+		phy_val &= ~(0x3<<14); // RGMII TX skew compensation= 0 ns
+		printf("%x (without reset PHY)\n", phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 0); //main registers
+	}
+#elif defined (P5_RMII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x5e337; ////(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+        RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x2 << 12);
+#else /* Port 5 disabled */
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3500) = 0x8000; ////(P5, Link Down)
+#endif // P5_RGMII_TO_MAC_MODE //
+#endif
+
+
+#if defined (P4_RGMII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3400) = 0x5e33b; ////(P4, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
+	RALINK_REG(0xb0000060) &= ~(1 << 10); //set RGMII to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3<<14); ////GE2_MODE=RGMii Mode
+#elif defined (P4_MII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3400) = 0x5e337; ////(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+	RALINK_REG(0xb0000060) &= ~(1 << 10); //set RGMII2 to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 14);
+#elif defined (P4_MAC_TO_PHY_MODE)
+	RALINK_REG(0xb0000060) &= ~(1 << 10); //set RGMII2 to Normal mode
+	RALINK_REG(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3<<14); ////GE2_MODE=RGMii Mode
+#if defined (MT7620_FPGA_BOARD)
+	    mii_mgr_write(4, 4, 0x05e1);   //Capable of 100M Full/Half Duplex, flow control on/off
+	    mii_mgr_write(4, 0, 0xB100);   //reset all digital logic, except phy_reg
+#endif
+	enable_auto_negotiate();
+	if (isICPlusGigaPHY(2)) {
+	    printf("ICPLUS Phy2\n");
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR2, 4, &phy_val);
+	    phy_val |= 1<<10; //enable pause ability
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 4, phy_val);
+
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
+	    phy_val |= 1<<9; //restart AN
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
+	}
+	if (isMarvellGigaPHY(2)) {
+		printf("MARVELL Phy2\n");
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 20, 0x0ce0);
+#if defined (MT7620_FPGA_BOARD)
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR2, 9, &phy_val);
+		phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 9, phy_val);
+#endif
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 0, 0x9140);
+	}
+	if (isVtssGigaPHY(2)) {
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0001); //extended page
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR2, 28, &phy_val);
+		printf("GE1 Vitesse Phy reg28 %x --> ",phy_val);
+		phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
+		phy_val &= ~(0x3<<14); // RGMII TX skew compensation= 0 ns
+		printf("%x (without reset PHY)\n", phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 28, phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0); //main registers
+	}
+#elif defined (P4_RMII_TO_MAC_MODE)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x3400) = 0x5e337; ////(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+        RALINK_REG(0xb0000060) &= ~(1 << 10); //set RGMII2 to Normal mode
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x2 << 14);
+#else /* Port 4 disabled */
+
+#endif // P4_RGMII_TO_MAC_MODE //
+}
+#endif
+
+#if defined (RT6855A_FPGA_BOARD)
+void rt6855A_eth_gpio_reset(void)
+{
+	u8 ether_gpio = 12;
+
+	/* Load the ethernet gpio value to reset Ethernet PHY */
+	ra_or(RALINK_PIO_BASE, 1<<(ether_gpio<<1));
+	ra_or(RALINK_PIO_BASE+0x14, 1<<ether_gpio);
+
+	ra_and(RALINK_PIO_BASE+0x4, ~(1<<ether_gpio));
+	udelay(100000);
+
+	ra_or(RALINK_PIO_BASE+0x4, 1<<ether_gpio);
+	/* must wait for 0.6 seconds after reset*/
+	udelay(600000);
+}
+#endif
+
+#if defined (MT7628_ASIC_BOARD)
+void mt7628_ephy_init(void)
+{
+	int i;
+	u32 phy_val;
+	mii_mgr_write(0, 31, 0x2000);//change G2 page
+	mii_mgr_write(0, 26, 0x0000);
+
+	for(i=0; i<5; i++){
+		mii_mgr_write(i, 31, 0x8000);//change L0 page
+		mii_mgr_write(i,  0, 0x3100);
+#if 0
+		mii_mgr_read(i, 26, &phy_val);// EEE setting
+		phy_val |= (1 << 5);
+		mii_mgr_write(i, 26, phy_val);
+#endif
+		mii_mgr_write(i, 30, 0xa000);
+		mii_mgr_write(i, 31, 0xa000);// change L2 page
+		mii_mgr_write(i, 16, 0x0606);
+		mii_mgr_write(i, 23, 0x0f0e);
+		mii_mgr_write(i, 24, 0x1610);
+		mii_mgr_write(i, 30, 0x1f15);
+		mii_mgr_write(i, 28, 0x6111);
+#if 0
+		mii_mgr_read(i, 4, &phy_val);
+		phy_val |= (1 << 10);
+		mii_mgr_write(i, 4, phy_val);
+		mii_mgr_write(i, 31, 0x2000);// change G2 page
+		mii_mgr_write(i, 26, 0x0000);
+#endif
+
+	}
+
+        //100Base AOI setting
+	mii_mgr_write(0, 31, 0x5000);//change G5 page
+	mii_mgr_write(0, 19, 0x004a);
+	mii_mgr_write(0, 20, 0x015a);
+	mii_mgr_write(0, 21, 0x00ee);
+	mii_mgr_write(0, 22, 0x0033);
+	mii_mgr_write(0, 23, 0x020a);
+	mii_mgr_write(0, 24, 0x0000);
+	mii_mgr_write(0, 25, 0x024a);
+	mii_mgr_write(0, 26, 0x035a);
+	mii_mgr_write(0, 27, 0x02ee);
+	mii_mgr_write(0, 28, 0x0233);
+	mii_mgr_write(0, 29, 0x000a);
+	mii_mgr_write(0, 30, 0x0000);
+	/* Fix EPHY idle state abnormal behavior */
+	mii_mgr_write(0, 31, 0x4000); //change G4 page
+	mii_mgr_write(0, 29, 0x000d);
+	mii_mgr_write(0, 30, 0x0500);
+
+}
+
+#endif
+
+#if defined (RT3052_ASIC_BOARD) || defined (RT3052_FPGA_BOARD) || \
+    defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD) || \
+    defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || \
+    defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+void rt305x_esw_init(void)
+{
+	u32	i;
+	u32	phy_val=0, phy_val2=0;
+
+	/*                                                                               
+	 * FC_RLS_TH=200, FC_SET_TH=160
+	 * DROP_RLS=120, DROP_SET_TH=80
+	 */
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0008) = 0xC8A07850;       
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00E4) = 0x00000000;
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0014) = 0x00405555;
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0090) = 0x00007f7f;
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0098) = 0x00007f7f; //disable VLAN
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00CC) = 0x0002500c;
+#ifndef CONFIG_UNH_TEST
+	RALINK_REG(RALINK_ETH_SW_BASE+0x009C) = 0x0008a301; //hashing algorithm=XOR48, aging interval=300sec
+#else
+	/*
+	 * bit[30]:1	Backoff Algorithm Option: The latest one to pass UNH test
+	 * bit[29]:1	Length of Received Frame Check Enable
+	 * bit[8]:0	Enable collision 16 packet abort and late collision abort
+	 * bit[7:6]:01	Maximum Packet Length: 1518
+	 */
+	RALINK_REG(RALINK_ETH_SW_BASE+0x009C) = 0x6008a241;
+#endif
+	RALINK_REG(RALINK_ETH_SW_BASE+0x008C) = 0x02404040; 
+
+#if defined (RT3052_ASIC_BOARD) || defined (RT3352_ASIC_BOARD) || defined (RT5350_ASIC_BOARD) || defined (MT7628_ASIC_BOARD)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) = 0x3f502b28; //Ext PHY Addr=0x1F 
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0084) = 0x00000000;
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0110) = 0x7d000000; //1us cycle number=125 (FE's clock=125Mhz)
+#elif defined (RT3052_FPGA_BOARD) || defined (RT3352_FPGA_BOARD) || defined (RT5350_FPGA_BOARD) || defined (MT7628_FPGA_BOARD)
+
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) = 0x00f03ff9; //polling Ext PHY Addr=0x0, force port5 as 100F/D (disable auto-polling)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0084) = 0xffdf1f00;
+	RALINK_REG(RALINK_ETH_SW_BASE+0x0110) = 0x0d000000; //1us cycle number=13 (FE's clock=12.5Mhz)
+
+	/* In order to use 10M/Full on FPGA board. We configure phy capable to 
+	 * 10M Full/Half duplex, so we can use auto-negotiation on PC side */
+	for(i=0;i<5;i++){
+	    mii_mgr_write(i, 4, 0x0461);   //Capable of 10M Full/Half Duplex, flow control on/off
+	    mii_mgr_write(i, 0, 0xB100);   //reset all digital logic, except phy_reg
+	}
+#ifdef MT7628_FPGA_V6
+	    mii_mgr_write(30, 4, 0x0461);   //Capable of 10M Full/Half Duplex, flow control on/off
+	    
+	    mii_mgr_read(30, 9, &phy_val);
+	    phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement
+	    mii_mgr_write(30, 9, phy_val);
+	    
+	    
+	    mii_mgr_write(30, 0, 0xB100);   //reset all digital logic, except phy_reg
+		printf("MARVELL Phy1\n");
+		mii_mgr_write(30, 20, 0x0ce0);
+		mii_mgr_write(30, 0, 0x9140);
+#endif
+#endif
+
+#if defined (P5_RGMII_TO_MAC_MODE)
+	RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) |= 0x3fff; //force 1000M full duplex
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(0xf<<20); //rxclk_skew, txclk_skew = 0
+#elif defined (P5_MII_TO_MAC_MODE)
+	RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
+#if defined (RT3352_ASIC_BOARD)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 12);
+#endif
+#elif defined (P5_MAC_TO_PHY_MODE)
+	RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(0xb0000060) &= ~(1 << 7); //set MDIO to Normal mode
+#if defined (RT3052_ASIC_BOARD) || defined(RT3352_ASIC_BOARD)
+	enable_auto_negotiate();
+#endif
+	if (isICPlusGigaPHY(1)) {
+	    printf("\n ICPLUS Phy\n");
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
+	    phy_val |= 1<<10; //enable pause ability
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
+
+	    mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
+	    phy_val |= 1<<9; //restart AN
+	    mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
+	}
+	if (isMarvellGigaPHY(1)) {
+		printf("\n MARVELL Phy\n");
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 20, 0x0ce0);
+#if defined (RT3052_FPGA_BOARD) || defined(RT3352_FPGA_BOARD)
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
+		phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
+#endif
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, 0x9140);
+	}
+	if (isVtssGigaPHY(1)) {
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
+		printf("GE1 Vitesse Phy reg28 %x --> ",phy_val);
+		phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
+		phy_val &= ~(0x3<<14); // RGMII TX skew compensation= 0 ns
+		printf("%x (without reset PHY)\n", phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 0); //main registers
+	}
+#elif defined (P5_RMII_TO_MAC_MODE)
+	/* Reserved */
+	RALINK_REG(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
+	RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
+#if defined (RT3352_ASIC_BOARD)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x2 << 12);
+#endif
+#else /* Port 5 disabled */
+
+#if defined (RT3052_ASIC_BOARD)
+        RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
+        RALINK_REG(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
+        RALINK_REG(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO41-GPIO50)
+        RALINK_REG(0xb0000674) = 0xFFF; //GPIO41-GPIO50 output mode
+        RALINK_REG(0xb000067C) = 0x0; //GPIO41-GPIO50 output low
+#elif defined (RT3352_ASIC_BOARD)
+        RALINK_REG(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
+        RALINK_REG(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
+        RALINK_REG(0xb0000624) = 0xC0000000; //GPIO22-GPIO23 output mode
+        RALINK_REG(0xb000062C) = 0xC0000000; //GPIO22-GPIO23 output high
+
+        RALINK_REG(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO24-GPIO35)
+        RALINK_REG(0xb000064C) = 0xFFF; //GPIO24-GPIO35 output mode
+        RALINK_REG(0xb0000654) = 0xFFF; //GPIO24-GPIO35 output high
+#endif
+
+#endif // P5_RGMII_TO_MAC_MODE //
+
+#define RSTCTRL_EPHY_RST	(1<<24)
+#define MT7628_EPHY_EN	        (0x1f<<16)
+#define MT7628_P0_EPHY_AIO_EN   (1<<16)	
+	/* We shall prevent modifying PHY registers if it is FPGA mode */
+#if defined (RT3052_ASIC_BOARD) || defined (RT3352_ASIC_BOARD) || defined (RT5350_ASIC_BOARD) || defined (MT7628_ASIC_BOARD)
+#if defined (RT3052_ASIC_BOARD)
+
+	rw_rf_reg(0, 0, &phy_val);
+	phy_val = phy_val >> 4;
+
+	if(phy_val > 0x5) {
+	    
+	    rw_rf_reg(0, 26, &phy_val);
+	    phy_val2 = (phy_val | (0x3 << 5));
+	    rw_rf_reg(1, 26, &phy_val2);
+
+	    // reset phy
+	    i = RALINK_REG(RT2880_RSTCTRL_REG);
+	    i = i | RSTCTRL_EPHY_RST;
+	    RALINK_REG(RT2880_RSTCTRL_REG)= i;
+	    i = i & ~(RSTCTRL_EPHY_RST);
+	    RALINK_REG(RT2880_RSTCTRL_REG)= i;
+
+	    rw_rf_reg(1, 26, &phy_val);
+
+	    //select local register
+	    mii_mgr_write(0, 31, 0x8000);
+	    for(i=0;i<5;i++){
+		mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
+		mii_mgr_write(i, 29, 0x7058);   //TX100/TX10 AD/DA current bias
+		mii_mgr_write(i, 30, 0x0018);   //TX100 slew rate control
+	    }
+
+	    //select global register
+	    mii_mgr_write(0, 31, 0x0);
+	    mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
+	    mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
+	    mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
+//#define ENABLE_LDPS
+#if defined (ENABLE_LDPS)
+            mii_mgr_write(0, 12, 0x7eaa);
+            mii_mgr_write(0, 22, 0x252f); //tune TP_IDL tail and head waveform, enable power down slew rate control
+#else
+            mii_mgr_write(0, 12, 0x0);
+            mii_mgr_write(0, 22, 0x052f);
+#endif
+	    mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
+	    mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
+	    mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
+	    mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
+	    mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
+	    mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
+	    mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
+	    mii_mgr_write(0, 31, 0x8000); //select local register
+
+
+	    for(i=0;i<5;i++){
+		//LSB=1 enable PHY
+		mii_mgr_read(i, 26, &phy_val);
+		phy_val |= 0x0001;
+		mii_mgr_write(i, 26, phy_val);
+	    }
+
+	} else {
+	    //select local register
+	    mii_mgr_write(0, 31, 0x8000);
+	    for(i=0;i<5;i++){
+		mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
+		mii_mgr_write(i, 29, 0x7058);   //TX100/TX10 AD/DA current bias
+		mii_mgr_write(i, 30, 0x0018);   //TX100 slew rate control
+	    }
+	    
+	    //select global register
+	    mii_mgr_write(0, 31, 0x0);
+	    mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
+	    mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
+	    mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
+	    mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
+	    mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
+	    mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
+	    mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
+	    mii_mgr_write(0, 22, 0x052f); //tune TP_IDL tail and head waveform
+	    mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
+	    mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
+	    mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
+	    mii_mgr_write(0, 31, 0x8000); //select local register
+
+	    for(i=0;i<5;i++){
+		//LSB=1 enable PHY
+		mii_mgr_read(i, 26, &phy_val);
+		phy_val |= 0x0001;
+		mii_mgr_write(i, 26, phy_val);
+	    }
+	}
+
+#elif defined (RT3352_ASIC_BOARD)
+    //PHY IOT
+    // reset phy
+    i = RALINK_REG(RT2880_RSTCTRL_REG);
+    i = i | RSTCTRL_EPHY_RST;
+    RALINK_REG(RT2880_RSTCTRL_REG) = i;
+    i = i & ~(RSTCTRL_EPHY_RST);
+    RALINK_REG(RT2880_RSTCTRL_REG) = i;
+
+	//select local register
+	mii_mgr_write(0, 31, 0x8000);
+	for(i=0;i<5;i++){
+	    mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
+	    mii_mgr_write(i, 29, 0x7016);   //TX100/TX10 AD/DA current bias
+	    mii_mgr_write(i, 30, 0x0038);   //TX100 slew rate control
+	}
+
+	//select global register
+	mii_mgr_write(0, 31, 0x0);
+	mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
+	mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
+	mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
+	mii_mgr_write(0, 12, 0x7eaa);
+	mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
+	mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
+	mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
+	mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
+	mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
+	mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
+	mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
+	mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
+	mii_mgr_write(0, 31, 0x8000); //select local register
+
+	for(i=0;i<5;i++){
+	    //LSB=1 enable PHY
+	    mii_mgr_read(i, 26, &phy_val);
+	    phy_val |= 0x0001;
+	    mii_mgr_write(i, 26, phy_val);
+	}
+#elif defined (RT5350_ASIC_BOARD)
+    //PHY IOT
+    // reset phy
+    i = RALINK_REG(RT2880_RSTCTRL_REG);
+    i = i | RSTCTRL_EPHY_RST;
+    RALINK_REG(RT2880_RSTCTRL_REG) = i;
+    i = i & ~(RSTCTRL_EPHY_RST);
+    RALINK_REG(RT2880_RSTCTRL_REG) = i;
+
+	//select local register
+	mii_mgr_write(0, 31, 0x8000);
+	for(i=0;i<5;i++){
+	    mii_mgr_write(i, 26, 0x1600);   //TX10 waveform coefficient //LSB=0 disable PHY
+	    mii_mgr_write(i, 29, 0x7015);   //TX100/TX10 AD/DA current bias
+	    mii_mgr_write(i, 30, 0x0038);   //TX100 slew rate control
+	}
+
+	//select global register
+	mii_mgr_write(0, 31, 0x0);
+	mii_mgr_write(0,  1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
+	mii_mgr_write(0,  2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
+	mii_mgr_write(0,  3, 0xa17f); //enlarge agcsel threshold 6
+	mii_mgr_write(0, 12, 0x7eaa);
+	mii_mgr_write(0, 14, 0x65);   //longer TP_IDL tail length
+	mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
+	mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
+	mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
+	mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
+	mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
+	mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
+	mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
+	mii_mgr_write(0, 31, 0x8000); //select local register
+
+	for(i=0;i<5;i++){
+	    //LSB=1 enable PHY
+	    mii_mgr_read(i, 26, &phy_val);
+	    phy_val |= 0x0001;
+	    mii_mgr_write(i, 26, phy_val);
+	}
+#elif defined (MT7628_ASIC_BOARD)
+/*TODO: Init MT7628 ASIC PHY HERE*/
+	i = RALINK_REG(RT2880_AGPIOCFG_REG);
+#if defined (ETH_ONE_PORT_ONLY)
+	i |= MT7628_EPHY_EN;
+	i = i & ~(MT7628_P0_EPHY_AIO_EN);
+#else
+	i = i & ~(MT7628_EPHY_EN);
+#endif
+	RALINK_REG(RT2880_AGPIOCFG_REG) = i;
+
+	printf("RESET MT7628 PHY!!!!!!");
+	// reset phy
+	i = RALINK_REG(RT2880_RSTCTRL_REG);
+	i = i | RSTCTRL_EPHY_RST;
+	RALINK_REG(RT2880_RSTCTRL_REG) = i;
+	i = i & ~(RSTCTRL_EPHY_RST);
+	RALINK_REG(RT2880_RSTCTRL_REG) = i;
+
+	i = RALINK_REG(RALINK_SYSCTL_BASE + 0x64);
+#if defined (ETH_ONE_PORT_ONLY)
+	i &= 0xf003f003;
+	i |= 0x05540554;
+	RALINK_REG(RALINK_SYSCTL_BASE + 0x64) = i; // set P0 EPHY LED mode
+#else	
+	i &= 0xf003f003;
+	RALINK_REG(RALINK_SYSCTL_BASE + 0x64) = i;
+#endif
+
+	udelay(5000);
+	mt7628_ephy_init();
+
+#else
+#error "Chip is not supported"
+#endif // RT3052_ASIC_BOARD //
+#endif // RT3052_ASIC_BOARD || RT3352_ASIC_BOARD //
+
+}
+#endif
+
+
+#if defined (RT3883_ASIC_BOARD) && defined (MAC_TO_MT7530_MODE)
+void rt3883_gsw_init(void)
+{
+	printf("\n MT7530 Giga Switch support \n");
+	//RALINK_REG(MDIO_CFG)=cpu_to_le32((u32)(0x1F01DC41)); /*GE1 Force 1G/FC ON/MDIO 2Mhz*/
+	RALINK_REG(MDIO_CFG)=cpu_to_le32((u32)(0x1F01DC01)); /*GE1 Force 1G/FC ON/MDIO 4Mhz*/
+	//enable_auto_negotiate();
+	ResetSWusingGPIOx();
+	udelay(125000);
+
+	mii_mgr_write(31, 0x3500, 0x5e33b);//MT7530 P5 force 1G
+	mii_mgr_write(31, 0x7804, 0x1017d8f);//MT7530 HW TRAP,  P6 disable, P5 RGMII GMAC5
+}
+#endif
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)	
+void setup_internal_gsw(void)
+{
+	u32	i;
+	u32	regValue;
+
+	// reset phy
+	regValue = RALINK_REG(RT2880_RSTCTRL_REG);
+	regValue = regValue | (1<<2);
+	RALINK_REG(RT2880_RSTCTRL_REG) = regValue;
+	udelay(1000);
+	regValue = regValue & ~(1<<2);
+	RALINK_REG(RT2880_RSTCTRL_REG) = regValue;
+	udelay(10000);
+
+
+	/* reduce MDIO PAD driving strength */
+	regValue = RALINK_REG(PAD_RGMII2_MDIO_CFG);
+	regValue &= ~(0x3<<4);	// reduce Tx driving strength to 2mA (WDT_E4_E2)
+	RALINK_REG(PAD_RGMII2_MDIO_CFG) = regValue;
+  
+
+	for(i=0;i<=4;i++) 
+	{	
+	       //turn off PHY
+	       mii_mgr_read(i, 0x0 ,&regValue);
+	       regValue |= (0x1<<11);
+               mii_mgr_write(i, 0x0, regValue);
+
+	}
+	mii_mgr_write(31, 0x3500, 0x8000);
+	mii_mgr_write(31, 0x3600, 0x8000);//force MAC link down before reset
+
+	mii_mgr_write(31, 0x7000, 0x3);//reset MT7530
+	//printf("#Reset_MT7530\n");
+	udelay(5);
+	
+
+#ifdef MT7621_USE_GE1
+#if defined (MT7621_ASIC_BOARD)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x100) = 0x2005e33b;//(GE1, Force 1000M/FD, FC ON)
+	mii_mgr_write(31, 0x3600, 0x5e30b);//PDMA is not ready,disable FC, Prevent HOL
+	mii_mgr_write(31, 0x3500, 0x8000);
+
+
+#elif defined (MT7621_FPGA_BOARD)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x100) = 0x2005e337;//(GE1, Force 100M/FD, FC ON)
+	mii_mgr_write(31, 0x3600, 0x5e337);
+#endif
+	RALINK_REG(RALINK_ETH_SW_BASE+0x200) = 0x00008000;// GE2, down
+	
+	RALINK_REG(GDMA1_FWD_CFG) = 0x20710000;
+	RALINK_REG(GDMA2_FWD_CFG) = 0x20717777;
+
+	/* Enable MT7530 Port 6 */
+	regValue = 0x117ccf; //Enable Port 6 only
+	mii_mgr_write(31, 0x7804 ,regValue);
+
+
+#elif defined MT7621_USE_GE2
+	RALINK_REG(RALINK_ETH_SW_BASE+0x100) = 0x000008000;//(GE1, Force LinkDown)
+	mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN
+	RALINK_REG(RALINK_ETH_SW_BASE+0x200) = 0x20056300;// GE2, auto-polling
+	
+
+	/* Set MT7530 Port 0/4 to PHY mode */
+	mii_mgr_read(31, 0x7804 ,&regValue);
+#if defined GE_RGMII_INTERNAL_P0_AN 
+	regValue &= ~((1<<13)|(1<<6));
+	regValue |= ((1<<7)|(1<<16)|(1<<20));
+#elif defined GE_RGMII_INTERNAL_P4_AN 
+	regValue &= ~((1<<13)|(1<<6)|(1<20));
+	regValue |= ((1<<7)|(1<<16));
+#endif
+	mii_mgr_write(31, 0x7804 ,regValue);
+
+	enable_auto_negotiate();
+
+	RALINK_REG(GDMA1_FWD_CFG) = 0x20717777;
+	RALINK_REG(GDMA2_FWD_CFG) = 0x20710000;
+#endif
+
+	regValue = RALINK_REG(RALINK_SYSCTL_BASE + 0x10);
+	regValue = (regValue >> 6) & 0x7;
+	if(regValue >= 6) { //25 Mhz Xtal
+		/* do nothing */
+	} else if(regValue >= 3) { //40Mhz Xtal
+	    mii_mgr_write(0, 13, 0x1f);  // disable MT7530 core clock
+	    mii_mgr_write(0, 14, 0x410);
+	    mii_mgr_write(0, 13, 0x401f);
+	    mii_mgr_write(0, 14, 0x0);
+
+	    mii_mgr_write(0, 13, 0x1f);  // disable MT7530 PLL
+	    mii_mgr_write(0, 14, 0x40d);
+	    mii_mgr_write(0, 13, 0x401f);
+	    mii_mgr_write(0, 14, 0x2020);
+
+	    mii_mgr_write(0, 13, 0x1f);  // for MT7530 core clock = 500Mhz
+	    mii_mgr_write(0, 14, 0x40e);
+	    mii_mgr_write(0, 13, 0x401f);
+	    mii_mgr_write(0, 14, 0x119);
+
+	    mii_mgr_write(0, 13, 0x1f);  // enable MT7530 PLL
+	    mii_mgr_write(0, 14, 0x40d);
+	    mii_mgr_write(0, 13, 0x401f);
+	    mii_mgr_write(0, 14, 0x2820);
+
+	    udelay(20); //suggest by CD
+
+	    mii_mgr_write(0, 13, 0x1f);  // enable MT7530 core clock
+	    mii_mgr_write(0, 14, 0x410);
+	    mii_mgr_write(0, 13, 0x401f);
+	    mii_mgr_write(0, 14, 0x1);
+	} else { //20 Mhz Xtal
+
+		/* TODO */
+
+	}
+/*Tx Driving*/
+	mii_mgr_write(31, 0x7a54, 0x44);  //lower driving
+	mii_mgr_write(31, 0x7a5c, 0x44);  //lower driving
+	mii_mgr_write(31, 0x7a64, 0x44);  //lower driving
+	mii_mgr_write(31, 0x7a6c, 0x44);  //lower driving
+	mii_mgr_write(31, 0x7a74, 0x44);  //lower driving
+	mii_mgr_write(31, 0x7a7c, 0x44);  //lower driving
+
+	for(i=0;i<=4;i++) 
+	{	
+	       //turn on PHY
+	       mii_mgr_read(i, 0x0 ,&regValue);
+	       regValue &= ~(0x1<<11);
+               mii_mgr_write(i, 0x0, regValue);
+	}
+
+
+
+#ifdef MT7621_USE_GE2
+#if 1
+	mii_mgr_write(31, 0x7b00, 0x102);  //delay detting for 10/1000M
+	mii_mgr_write(31, 0x7b04, 0x14);  //delay setting for 10/1000M
+#else
+	mii_mgr_write(31, 0x7b00, 8);  // for 100M
+	mii_mgr_write(31, 0x7b04, 0x14);  // for 100M
+#endif
+#endif
+
+
+
+/*GE2 delay setting only for 1G/10M => turn off 100M for USE_GE2*/
+#ifdef MT7621_USE_GE2
+	for(i=0;i<=4;i++) {	
+	       mii_mgr_read(i, 4, &regValue);
+	       regValue &= ~(3<<7); //turn off 100Base-T Advertisement
+               mii_mgr_write(i, 4, regValue);
+
+		//mii_mgr_read(i, 9, &regValue);
+                //regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
+                //mii_mgr_write(i, 9, regValue);
+
+		//restart AN
+		mii_mgr_read(i, 0, &regValue);
+		regValue |= (1 << 9);
+		mii_mgr_write(i, 0, regValue);
+	}
+#endif
+	mii_mgr_read(31, 0x7808 ,&regValue);
+	regValue |= (3<<16); //Enable INTR
+	mii_mgr_write(31, 0x7808 ,regValue);
+}
+#endif
+
+
+
+
+static int rt2880_eth_setup(struct eth_device* dev)
+{
+	u32	i;
+	u32	regValue;
+	u16	wTmp;
+
+
+	printf("\n Waitting for RX_DMA_BUSY status Start... ");
+	while(1)
+		if(!isDMABusy(dev))
+			break;
+	printf("done\n\n");
+
+
+	// Case1: RT288x/RT3883/MT7621 GE + GigaPhy
+#if defined (MAC_TO_GIGAPHY_MODE) 
+	enable_auto_negotiate();
+	if (isMarvellGigaPHY(1)) {
+#if defined (RT3883_FPGA_BOARD)
+		printf("\n Reset MARVELL phy\n");
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
+		regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
+
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 20, &regValue);
+		regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 20, regValue);
+
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
+		regValue |= 1<<15; //PHY Software Reset
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
+#elif defined (MT7621_FPGA_BOARD)
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
+		regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
+	    
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
+		regValue |= 1<<9; //restart AN
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
+#endif
+	}
+	if (isVtssGigaPHY(1)) {
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 1);
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 28, &regValue);
+		printf("GE1 Vitesse Phy reg28 %x --> ",regValue);
+		regValue |= (0x3<<12);
+		regValue &= ~(0x3<<14);
+		printf("%x (without reset PHY)\n", regValue);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 28, regValue);
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 31, 0);
+
+		/*
+		mii_mgr_read(MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
+		regValue |= 1<<15; //PHY Software Reset
+		mii_mgr_write(MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
+		*/
+	}
+#if defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD)
+#ifdef MT7621_USE_GE1
+	RALINK_REG(RALINK_ETH_SW_BASE+0x100) = 0x20056300;//(P0, Auto mode)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x200) = 0x00008000;//(P1, Down)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=RGMII Mode
+	RALINK_REG(0xbe000060) &= ~(1 << 14); //set RGMII1 to Normal mode
+#else
+	RALINK_REG(RALINK_ETH_SW_BASE+0x200) = 0x20056300;//(P1, Auto mode)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x100) = 0x00008000;//(P0, Down)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 14); //GE2_MODE=RGMII Mode
+	RALINK_REG(0xbe000060) &= ~(1 << 15); //set RGMII2 to Normal mode
+
+#endif
+#endif
+	// Case2. RT305x/RT335x/RT6856/MT7620 + EmbeddedSW
+#elif defined (RT3052_ASIC_BOARD) || defined (RT3052_FPGA_BOARD) || \
+      defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD) || \
+      defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || \
+      defined (RT6855_ASIC_BOARD) || defined (RT6855_FPGA_BOARD) || \
+      defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD) || \
+      defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) || \
+      defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+
+#ifdef P5_RGMII_TO_MAC_MODE
+#if 0 // we don't have such demo board at this moment
+	printf("\n Vitesse giga Mac support \n");
+	ResetSWusingGPIOx();
+	udelay(125000);
+	vtss_init();
+#endif
+#endif
+
+	// Case3: MT7621 + MT7530 GSW
+#elif defined (MAC_TO_MT7530_MODE)
+#if defined (MT7621_FPGA_BOARD) || defined (NT7621_ASIC_BOARD)
+	//enable MDIO
+	RALINK_REG(0xbe000060) &= ~(1 << 12); //set MDIO to Normal mode
+	RALINK_REG(0xbe000060) &= ~(1 << 14); //set RGMII1 to Normal mode
+	RALINK_REG(0xbe000060) &= ~(1 << 15); //set RGMII2 to Normal mode
+#endif
+	// Case4: RT288x/RT388x + Vitesse GigaSW
+#elif defined (MAC_TO_VITESSE_MODE)
+	printf("\n Vitesse giga Mac support \n");
+	RALINK_REG(MDIO_CFG)=cpu_to_le32((u32)(0x1F01DC01));
+	ResetSWusingGPIOx();
+	udelay(125000);
+	vtss_init();
+
+	// Case5. RT288x/RT388x/MT7621 + (10/100 Switch or 100PHY)
+#elif defined (MAC_TO_100SW_MODE) ||  defined (MAC_TO_100PHY_MODE)
+
+#if defined (RT3883_FPGA_BOARD) || defined (RT3883_ASIC_BOARD)
+
+	regValue = RALINK_REG(RT2880_SYSCFG1_REG);
+	regValue &= ~(0xF << 12);
+
+	/* 0=RGMII, 1=MII, 2=RvMii */
+#if defined (RT3883_USE_GE2)
+#if defined (GE_MII_FORCE_100) || defined (GE_MII_AN)
+	regValue |= (0x1 << 14); // GE2 MII Mode
+#elif defined (GE_RVMII_FORCE_100)
+	regValue |= (0x2 << 14); // GE2 RvMII Mode
+#endif
+
+#else //GE1
+#if defined (GE_MII_FORCE_100) || defined (GE_MII_AN)
+	regValue |= (0x1 << 12); // GE1 MII Mode
+#elif defined (GE_RVMII_FORCE_100)
+	regValue |= (0x2 << 12); // GE1 RvMII Mode
+#endif
+
+#endif // RT3883_USE_GE2 //
+
+	RALINK_REG(RT2880_SYSCFG1_REG)=regValue;
+
+#elif defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD)
+#ifdef MT7621_USE_GE1
+#if defined (GE_MII_FORCE_100) || defined (GE_RVMII_FORCE_100)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x100) = 0x2005e337;//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 12);
+#elif defined (GE_MII_AN)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x100) = 0x20056300;//(P0, Auto mode)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 12);
+	enable_auto_negotiate();
+#endif
+#else //MT7621_USE_GE2
+#if defined (GE_MII_FORCE_100) || defined (GE_RVMII_FORCE_100)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x200) = 0x2005e337;//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 14);
+#elif defined (GE_MII_AN)
+	RALINK_REG(RALINK_ETH_SW_BASE+0x200) = 0x20056300;//(P0, Auto mode)
+	RALINK_REG(RT2880_SYSCFG1_REG) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
+	RALINK_REG(RT2880_SYSCFG1_REG) |= (0x1 << 14);
+	enable_auto_negotiate();
+#endif
+#endif
+
+#else // RT288x
+	// due to the flaws of RT2880 GMAC implementation (or IC+ SW ?) we use the
+	// fixed capability instead of auto-polling.
+	RALINK_REG(MDIO_CFG)=cpu_to_le32((u32)(0x1F01BC01));
+
+	//force cpu port is 100F
+	mii_mgr_write(29, 22, 0x8420);
+#endif
+#endif // MAC_TO_GIGAPHY_MODE //
+	
+
+#if defined (RT3883_USE_GE2) || defined (MT7621_USE_GE2)
+	wTmp = (u16)dev->enetaddr[0];
+	regValue = (wTmp << 8) | dev->enetaddr[1];
+	RALINK_REG(GDMA2_MAC_ADRH)=regValue;
+
+	wTmp = (u16)dev->enetaddr[2];
+	regValue = (wTmp << 8) | dev->enetaddr[3];
+	regValue = regValue << 16;
+	wTmp = (u16)dev->enetaddr[4];
+	regValue |= (wTmp<<8) | dev->enetaddr[5];
+	RALINK_REG(GDMA2_MAC_ADRL)=regValue;
+
+	regValue = RALINK_REG(GDMA2_FWD_CFG);
+
+	regValue = regValue & GDM_UFRC_P_CPU;
+	//Broad-cast MAC address frames forward to CPU
+	regValue = regValue & GDM_BFRC_P_CPU;
+	//Multi-cast MAC address frames forward to CPU
+	regValue = regValue & GDM_MFRC_P_CPU;
+	//Other MAC address frames forward to CPU
+	regValue = regValue & GDM_OFRC_P_CPU;
+
+	RALINK_REG(GDMA2_FWD_CFG)=regValue;
+	udelay(500);
+	regValue = RALINK_REG(GDMA2_FWD_CFG);
+#else // non RT3883_USE_GE2 //
+	/* Set MAC address. */
+	wTmp = (u16)dev->enetaddr[0];
+	regValue = (wTmp << 8) | dev->enetaddr[1];
+
+#if defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+	RALINK_REG(SDM_MAC_ADRH)=regValue;
+	// printf("\n dev->iobase=%08X,SDM_MAC_ADRH=%08X\n",dev->iobase,regValue);
+#else
+	RALINK_REG(GDMA1_MAC_ADRH)=regValue;
+	// printf("\n dev->iobase=%08X,GDMA1_MAC_ADRH=%08X\n ",dev->iobase, regValue);
+#endif
+
+	wTmp = (u16)dev->enetaddr[2];
+	regValue = (wTmp << 8) | dev->enetaddr[3];
+	regValue = regValue << 16;
+	wTmp = (u16)dev->enetaddr[4];
+	regValue |= (wTmp<<8) | dev->enetaddr[5];
+#if defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+	RALINK_REG(SDM_MAC_ADRL)=regValue;
+	// printf("\n dev->iobase=%08X,SDM_MAC_ADRL=%08X\n",dev->iobase,regValue);
+#else
+	RALINK_REG(GDMA1_MAC_ADRL)=regValue;
+	// printf("\n dev->iobase=%08X,GDMA1_MAC_ADRL=%08X\n ",dev->iobase, regValue);
+#endif
+
+	//printf("\n rt2880_eth_init,set MAC reg to [%02X:%02X:%02X:%02X:%02X:%02X]\n",
+	//	dev->enetaddr[0],dev->enetaddr[1],dev->enetaddr[2],
+	//	dev->enetaddr[3],dev->enetaddr[4],dev->enetaddr[5]);
+
+#if ! defined (RT5350_ASIC_BOARD) && ! defined (RT5350_FPGA_BOARD) && !defined (MT7628_ASIC_BOARD) && !defined (MT7628_FPGA_BOARD)
+	regValue = RALINK_REG(GDMA1_FWD_CFG);
+	//printf("\n old,GDMA1_FWD_CFG = %08X \n",regValue);
+
+#if (defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD))
+	//frames destination port = port 0 CPU
+	regValue = regValue & ~(0x7);
+#else
+	//Uni-cast frames forward to CPU
+	regValue = regValue & GDM_UFRC_P_CPU;
+	//Broad-cast MAC address frames forward to CPU
+	regValue = regValue & GDM_BFRC_P_CPU;
+	//Multi-cast MAC address frames forward to CPU
+	regValue = regValue & GDM_MFRC_P_CPU;
+	//Other MAC address frames forward to CPU
+	regValue = regValue & GDM_OFRC_P_CPU;
+#endif
+
+	RALINK_REG(GDMA1_FWD_CFG)=regValue;
+	udelay(500);
+	regValue = RALINK_REG(GDMA1_FWD_CFG);
+	//printf("\n new,GDMA1_FWD_CFG = %08X \n",regValue);
+
+	regValue = 0x80504000;
+	RALINK_REG(PSE_FQFC_CFG)=regValue;
+#endif // RT3883_USE_GE2 //
+
+#endif
+
+	for (i = 0; i < NUM_RX_DESC; i++) {
+		memset((void *)&rx_ring[i],0,16);
+		rx_ring[i].rxd_info2.DDONE_bit = 0;
+
+		{
+			BUFFER_ELEM *buf;
+			buf = rt2880_free_buf_entry_dequeue(&rt2880_free_buf_list);
+			net_rx_packets[i] = buf->pbuf;
+#if defined (RX_SCATTER_GATTER_DMA)
+			rx_ring[i].rxd_info2.LS0= 0;
+			rx_ring[i].rxd_info2.PLEN0= PKTSIZE_ALIGN;
+#else
+			rx_ring[i].rxd_info2.LS0= 1;
+#endif
+			rx_ring[i].rxd_info1.PDP0 = cpu_to_le32(phys_to_bus((u32) net_rx_packets[i]));
+		}
+	}
+
+	for (i=0; i < NUM_TX_DESC; i++) {
+		memset((void *)&tx_ring0[i],0,16);
+		tx_ring0[i].txd_info2.LS0_bit = 1;
+		tx_ring0[i].txd_info2.DDONE_bit = 1;
+		/* PN:
+		 *  0:CPU
+		 *  1:GE1
+		 *  2:GE2 (for RT2883)
+		 *  6:PPE
+		 *  7:Discard
+		 */
+#if defined (RT3883_USE_GE2)
+		tx_ring0[i].txd_info4.PN = 2;
+#elif defined (MT7621_USE_GE2)
+		tx_ring0[i].txd_info4.FPORT=2;
+#elif defined (MT7621_USE_GE1)
+		tx_ring0[i].txd_info4.FPORT=1;
+#elif defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD)
+		tx_ring0[i].txd_info4.FP_BMAP=0x0;
+#else
+		tx_ring0[i].txd_info4.PN = 1;
+#endif
+
+	}
+	rxRingSize = NUM_RX_DESC;
+	txRingSize = NUM_TX_DESC;
+
+	rx_dma_owner_idx0 = 0;
+	rx_wants_alloc_idx0 = (NUM_RX_DESC - 1);
+	tx_cpu_owner_idx0 = 0;
+
+	regValue=RALINK_REG(PDMA_GLO_CFG);
+	udelay(100);
+
+	{
+		regValue &= 0x0000FFFF;
+
+		RALINK_REG(PDMA_GLO_CFG)=regValue;
+		udelay(500);
+		regValue=RALINK_REG(PDMA_GLO_CFG);
+	}
+
+	/* Tell the adapter where the TX/RX rings are located. */
+	RALINK_REG(RX_BASE_PTR0)=phys_to_bus((u32) &rx_ring[0]);
+
+	//printf("\n rx_ring=%08X ,RX_BASE_PTR0 = %08X \n",&rx_ring[0],RALINK_REG(RX_BASE_PTR0));
+	RALINK_REG(TX_BASE_PTR0)=phys_to_bus((u32) &tx_ring0[0]);
+
+	//printf("\n tx_ring0=%08X, TX_BASE_PTR0 = %08X \n",&tx_ring0[0],RALINK_REG(TX_BASE_PTR0));
+
+	RALINK_REG(RX_MAX_CNT0)=cpu_to_le32((u32) NUM_RX_DESC);
+	RALINK_REG(TX_MAX_CNT0)=cpu_to_le32((u32) NUM_TX_DESC);
+
+	RALINK_REG(TX_CTX_IDX0)=cpu_to_le32((u32) tx_cpu_owner_idx0);
+	RALINK_REG(PDMA_RST_IDX)=cpu_to_le32((u32)RST_DTX_IDX0);
+
+	RALINK_REG(RX_CALC_IDX0)=cpu_to_le32((u32) (NUM_RX_DESC - 1));
+	RALINK_REG(PDMA_RST_IDX)=cpu_to_le32((u32)RST_DRX_IDX0);
+	
+	udelay(500);
+	START_ETH(dev);
+	
+	return 1;
+}
+
+
+static int rt2880_eth_send(struct eth_device* dev, void *packet, int length)
+{
+	int		status = -1;
+	int		i;
+	int		retry_count = 0, temp;
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD) || \
+    defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || \
+    defined (RT3883_ASIC_BOARD) || defined (RT3883_FPGA_BOARD) || \
+    defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+	char *p=(char *)packet;
+#endif
+
+Retry:
+	if (retry_count > 10) {
+		return (status);
+	}
+
+	if (length <= 0) {
+		printf("%s: bad packet size: %d\n", dev->name, length);
+		return (status);
+	}
+
+#if defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD) || \
+    defined (RT3352_ASIC_BOARD) || defined (RT3352_FPGA_BOARD) || \
+    defined (RT5350_ASIC_BOARD) || defined (RT5350_FPGA_BOARD) || \
+    defined (RT3883_ASIC_BOARD) || defined (RT3883_FPGA_BOARD) || \
+    defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+#define PADDING_LENGTH 60
+	if (length < PADDING_LENGTH) {
+		//	print_packet(packet,length);
+		for(i=0;i<PADDING_LENGTH-length;i++) {
+			p[length+i]=0;
+		}
+		length = PADDING_LENGTH;
+	}
+#endif //RT3052
+
+				for(i = 0; tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit == 0 ; i++)
+
+				{
+					if (i >= TOUT_LOOP) {
+						//printf("%s: TX DMA is Busy !! TX desc is Empty!\n", dev->name);
+						goto Done;
+					}
+				}
+	//dump_reg();
+
+	temp = RALINK_REG(TX_DTX_IDX0);
+
+	if(temp == (tx_cpu_owner_idx0+1) % NUM_TX_DESC) {
+		puts(" @ ");
+		goto Done;
+	}
+
+	{ /*KEN: we copy data from cached dram to non cached, same underlying physical dram address. */
+		void *data = (void *)KSEG1ADDR(packet);
+		memcpy(data, packet, length);
+		tx_ring0[tx_cpu_owner_idx0].txd_info1.SDP0 = cpu_to_le32(phys_to_bus((u32) data));
+	}
+
+	tx_ring0[tx_cpu_owner_idx0].txd_info2.SDL0 = length;
+
+	tx_ring0[tx_cpu_owner_idx0].txd_info2.DDONE_bit = 0;
+#if 0
+	printf("==========TX==========(CTX=%d)\n",tx_cpu_owner_idx0);
+	printf("tx_ring0[tx_cpu_owner_idx0].txd_info1 =%x\n",tx_ring0[tx_cpu_owner_idx0].txd_info1);
+	printf("tx_ring0[tx_cpu_owner_idx0].txd_info2 =%x %p\n",tx_ring0[tx_cpu_owner_idx0].txd_info2,&tx_ring0[tx_cpu_owner_idx0].txd_info2);
+	printf("tx_ring0[tx_cpu_owner_idx0].txd_info3 =%x\n",tx_ring0[tx_cpu_owner_idx0].txd_info3);
+	printf("tx_ring0[tx_cpu_owner_idx0].txd_info4 =%x\n",tx_ring0[tx_cpu_owner_idx0].txd_info4);
+#endif
+
+	status = length;
+
+	tx_cpu_owner_idx0 = (tx_cpu_owner_idx0+1) % NUM_TX_DESC;
+	RALINK_REG(TX_CTX_IDX0)=cpu_to_le32((u32) tx_cpu_owner_idx0);
+
+	return status;
+Done:
+	udelay(500);
+	retry_count++;
+	goto Retry;
+}
+
+
+static int rt2880_eth_recv(struct eth_device* dev)
+{
+	int length = 0;
+	int inter_loopback_cnt =0;
+	u32 *rxd_info;
+
+	for (; ; ) {
+		rxd_info = (u32 *)KSEG1ADDR(&rx_ring[rx_dma_owner_idx0].rxd_info2);
+
+		if ( (*rxd_info & BIT(31)) == 0 )
+		{
+			/*hdr_len =0;*/
+			break;
+		}
+
+		udelay(1);
+			length = rx_ring[rx_dma_owner_idx0].rxd_info2.PLEN0;
+
+		if(length == 0)
+		{
+			printf("\n Warring!! Packet Length has error !!,In normal mode !\n");
+		}
+
+#if defined (PDMA_NEW)
+		if(rx_ring[rx_dma_owner_idx0].rxd_info4.SP == 6)
+#else
+		if(rx_ring[rx_dma_owner_idx0].rxd_info4.SP == 0)
+#endif
+		{// Packet received from CPU port
+			printf("\n Normal Mode,Packet received from CPU port,plen=%d \n",length);
+			//print_packet((void *)KSEG1ADDR(NetRxPackets[rx_dma_owner_idx0]),length);
+			inter_loopback_cnt++;
+			length = inter_loopback_cnt;//for return
+		}
+		else {
+			// KEN: 
+			//NetReceive((void *)KSEG1ADDR(NetRxPackets[rx_dma_owner_idx0]), length );
+			net_process_received_packet( (void *)KSEG1ADDR(net_rx_packets[rx_dma_owner_idx0]), length );
+		}
+
+#if  defined (RX_SCATTER_GATTER_DMA)
+		rx_ring[rx_dma_owner_idx0].rxd_info2.DDONE_bit = 0;
+		rx_ring[rx_dma_owner_idx0].rxd_info2.LS0= 0;
+		rx_ring[rx_dma_owner_idx0].rxd_info2.PLEN0= PKTSIZE_ALIGN;
+#else
+		rxd_info = (u32 *)&rx_ring[rx_dma_owner_idx0].rxd_info4;
+		*rxd_info = 0;
+
+		rxd_info = (u32 *)&rx_ring[rx_dma_owner_idx0].rxd_info2;
+		*rxd_info = 0;
+		rx_ring[rx_dma_owner_idx0].rxd_info2.LS0= 1;
+#endif
+
+#if 0
+		printf("=====RX=======(CALC=%d LEN=%d)\n",rx_dma_owner_idx0, length);
+		printf("rx_ring[rx_dma_owner_idx0].rxd_info1 =%x\n",rx_ring[rx_dma_owner_idx0].rxd_info1);
+		printf("rx_ring[rx_dma_owner_idx0].rxd_info2 =%x\n",rx_ring[rx_dma_owner_idx0].rxd_info2);
+		printf("rx_ring[rx_dma_owner_idx0].rxd_info3 =%x\n",rx_ring[rx_dma_owner_idx0].rxd_info3);
+		printf("rx_ring[rx_dma_owner_idx0].rxd_info4 =%x\n",rx_ring[rx_dma_owner_idx0].rxd_info4);
+#endif
+		/* Tell the adapter where the TX/RX rings are located. */
+		RALINK_REG(RX_BASE_PTR0)=phys_to_bus((u32) &rx_ring[0]);
+
+		//udelay(10000);
+		/*  Move point to next RXD which wants to alloc*/
+		RALINK_REG(RX_CALC_IDX0)=cpu_to_le32((u32) rx_dma_owner_idx0);
+
+		/* Update to Next packet point that was received.
+		 */
+		rx_dma_owner_idx0 = (rx_dma_owner_idx0 + 1) % NUM_RX_DESC;
+
+		//printf("\n ************************************************* \n");
+		//printf("\n RX_CALC_IDX0=%d \n", RALINK_REG(RX_CALC_IDX0));
+		//printf("\n RX_DRX_IDX0 = %d \n",RALINK_REG(RX_DRX_IDX0));
+		//printf("\n ************************************************* \n");
+	}
+	return length;
+}
+
+void rt2880_eth_halt(struct eth_device* dev)
+{
+	 STOP_ETH(dev);
+	//gmac_phy_switch_gear(DISABLE);
+	//printf(" STOP_ETH \n");
+	//dump_reg();
+}
+
+#if 0
+static void print_packet( u8 * buf, int length )
+{
+
+	int i;
+	int remainder;
+	int lines;
+
+
+	printf("Packet of length %d \n", length );
+
+
+	lines = length / 16;
+	remainder = length % 16;
+
+	for ( i = 0; i < lines ; i ++ ) {
+		int cur;
+
+		for ( cur = 0; cur < 8; cur ++ ) {
+			u8 a, b;
+
+			a = *(buf ++ );
+			b = *(buf ++ );
+			printf("%02X %02X ", a, b );
+		}
+		printf("\n");
+	}
+	for ( i = 0; i < remainder/2 ; i++ ) {
+		u8 a, b;
+
+		a = *(buf ++ );
+		b = *(buf ++ );
+		printf("%02X %02X ", a, b );
+	}
+	printf("\n");
+
+}
+#endif
+
+#ifdef RT2880_U_BOOT_CMD_OPEN 
+#if defined (RT3883_FPGA_BOARD) || defined (RT3883_ASIC_BOARD)
+void rt3883_init_gdma(int mode)
+{
+	u32 reg;
+	u16 tmp;
+	//mode 0: all pkts to cpu,
+	if (mode == 0) {
+		reg = RALINK_REG(GDMA1_FWD_CFG);
+		reg &= (GDM_UFRC_P_CPU & GDM_BFRC_P_CPU & GDM_MFRC_P_CPU & GDM_OFRC_P_CPU);
+		RALINK_REG(GDMA1_FWD_CFG)=cpu_to_le32((u32)reg);
+
+		reg = RALINK_REG(GDMA2_FWD_CFG);
+		reg &= (GDM_UFRC_P_CPU & GDM_BFRC_P_CPU & GDM_MFRC_P_CPU & GDM_OFRC_P_CPU);
+		RALINK_REG(GDMA2_FWD_CFG)=cpu_to_le32((u32)reg);
+	}
+	//mode 1: ge1->ge2, ge2->ge1
+	else if (mode == 1) {
+		reg = RALINK_REG(GDMA1_FWD_CFG);
+		reg &= (GDM_UFRC_P_CPU & GDM_BFRC_P_CPU & GDM_MFRC_P_CPU & GDM_OFRC_P_CPU);
+		reg |= (GDM_UFRC_P_GDMA2 | GDM_BFRC_P_GDMA2 | GDM_MFRC_P_GDMA2 | GDM_OFRC_P_GDMA2);
+		RALINK_REG(GDMA1_FWD_CFG)=cpu_to_le32((u32)reg);
+
+		reg = RALINK_REG(GDMA2_FWD_CFG);
+		reg &= (GDM_UFRC_P_CPU & GDM_BFRC_P_CPU & GDM_MFRC_P_CPU & GDM_OFRC_P_CPU);
+		reg |= (GDM_UFRC_P_GDMA1 | GDM_BFRC_P_GDMA1 | GDM_MFRC_P_GDMA1 | GDM_OFRC_P_GDMA1);
+		RALINK_REG(GDMA2_FWD_CFG)=cpu_to_le32((u32)reg);
+	}
+
+	//also set GDMA my MAC
+	tmp = (u16)rt2880_pdev->enetaddr[0];
+	reg = (tmp << 8) | rt2880_pdev->enetaddr[1];
+	RALINK_REG(GDMA1_MAC_ADRH)=reg;
+
+	tmp = (u16)rt2880_pdev->enetaddr[2];
+	reg = (tmp << 8) | rt2880_pdev->enetaddr[3];
+	reg = reg << 16;
+	tmp = (u16)rt2880_pdev->enetaddr[4];
+	//reg |= (tmp<<8) | rt2880_pdev->enetaddr[5];
+	reg |= (tmp<<8) | 1;
+	RALINK_REG(GDMA1_MAC_ADRL)=reg;
+
+	tmp = (u16)rt2880_pdev->enetaddr[0];
+	reg = (tmp << 8) | rt2880_pdev->enetaddr[1];
+	RALINK_REG(GDMA2_MAC_ADRH)=reg;
+
+	tmp = (u16)rt2880_pdev->enetaddr[2];
+	reg = (tmp << 8) | rt2880_pdev->enetaddr[3];
+	reg = reg << 16;
+	tmp = (u16)rt2880_pdev->enetaddr[4];
+	//reg |= (tmp<<8) | rt2880_pdev->enetaddr[5];
+	reg |= (tmp<<8) | 2;
+	RALINK_REG(GDMA2_MAC_ADRL)=reg;
+
+	//enable auto polling for both GE1 and GE2
+	reg = RALINK_REG(MDIO_CFG); 
+	reg |= 0x20000000;
+	RALINK_REG(MDIO_CFG)=reg;
+
+#define MDIO_CFG2           RALINK_FRAME_ENGINE_BASE + 0x18
+	reg = RALINK_REG(MDIO_CFG2);
+	reg |= 0x20000000;
+	RALINK_REG(MDIO_CFG2)=reg;
+}
+
+void rt3883_reset_phy(void)
+{
+	//Marvell phy: adj skew and reset both phy connected to ge1 and ge2
+	mii_mgr_write(31, 20, 0x0ce0);
+#ifdef RT3883_FPGA_BOARD
+	mii_mgr_write(31, 9, 0);
+#endif
+	mii_mgr_write(31, 0, 0x9140);
+	mii_mgr_write(30, 20, 0x0ce0);
+#ifdef RT3883_FPGA_BOARD
+	mii_mgr_write(30, 9, 0);
+#endif
+	mii_mgr_write(30, 0, 0x9140);
+}
+
+int do_rt3883_pseloopback(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	printf("RT3883 PSE loopback mode!\n");
+	rt3883_init_gdma(1);
+	rt3883_reset_phy();
+	return 0;
+}
+
+U_BOOT_CMD(
+	pseloop,	1,	1,	do_rt3883_pseloopback,
+	"pseloop   - RT3883 PSE loopback test\n",
+	"pseloop   - RT3883 PSE loopback test\n"
+);
+#endif
+
+#endif
+
+static char erase_seq[] = "\b \b";              /* erase sequence       */
+static char   tab_seq[] = "        ";           /* used to expand TABs  */
+
+static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
+{
+	char *s;
+
+	if (*np == 0) {
+		return (p);
+	}
+
+	if (*(--p) == '\t') {			/* will retype the whole line	*/
+		while (*colp > plen) {
+			puts (erase_seq);
+			(*colp)--;
+		}
+		for (s=buffer; s<p; ++s) {
+			if (*s == '\t') {
+				puts (tab_seq+((*colp) & 07));
+				*colp += 8 - ((*colp) & 07);
+			} else {
+				++(*colp);
+				putc (*s);
+			}
+		}
+	} else {
+		puts (erase_seq);
+		(*colp)--;
+	}
+	(*np)--;
+	return (p);
+}
+
+/*
+ * Prompt for input and read a line.
+ * If  CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
+ * time out when time goes past endtime (timebase time in ticks).
+ * Return:	number of read characters
+ *		-1 if break
+ *		-2 if timed out
+ */
+int readline (const char *const prompt, int show_buf)
+{
+	char   *p = console_buffer;
+	int	n = 0;				/* buffer index		*/
+	int	plen = 0;			/* prompt length	*/
+	int	col;				/* output column cnt	*/
+	char	c;
+
+	/* print prompt */
+	if (prompt) {
+		plen = strlen (prompt);
+		puts (prompt);
+	}
+	if (show_buf) {
+		puts (p);
+		n = strlen(p);
+		col = plen + strlen(p);
+		p += strlen(p);
+	}
+	else
+		col = plen;
+
+	for (;;) {
+#ifdef CONFIG_BOOT_RETRY_TIME
+		while (!tstc()) {	/* while no incoming data */
+			if (retry_time >= 0 && get_ticks() > endtime)
+				return (-2);	/* timed out */
+		}
+#endif
+//		WATCHDOG_RESET();		/* Trigger watchdog, if needed */
+
+#ifdef CONFIG_SHOW_ACTIVITY
+		while (!tstc()) {
+			extern void show_activity(int arg);
+			show_activity(0);
+		}
+#endif
+		c = getc();
+
+		/*
+		 * Special character handling
+		 */
+		switch (c) {
+		case '\r':				/* Enter		*/
+		case '\n':
+			*p = '\0';
+			puts ("\r\n");
+#ifdef CONFIG_CMD_HISTORY
+			if (history_counter < HISTORY_SIZE) history_counter++;
+			history_last_idx++;
+			history_last_idx %= HISTORY_SIZE;
+			history_cur_idx = history_last_idx;
+			strcpy(&console_history[history_last_idx][0], console_buffer);
+#endif
+			return (p - console_buffer);
+
+		case '\0':				/* nul			*/
+			continue;
+
+		case 0x03:				/* ^C - break		*/
+			console_buffer[0] = '\0';	/* discard input */
+			return (-1);
+
+		case 0x15:				/* ^U - erase line	*/
+			while (col > plen) {
+				puts (erase_seq);
+				--col;
+			}
+			p = console_buffer;
+			n = 0;
+			continue;
+
+		case 0x17:				/* ^W - erase word 	*/
+			p=delete_char(console_buffer, p, &col, &n, plen);
+			while ((n > 0) && (*p != ' ')) {
+				p=delete_char(console_buffer, p, &col, &n, plen);
+			}
+			continue;
+
+		case 0x08:				/* ^H  - backspace	*/
+		case 0x7F:				/* DEL - backspace	*/
+			p=delete_char(console_buffer, p, &col, &n, plen);
+			continue;
+
+#ifdef CONFIG_CMD_HISTORY
+		case 0x1B:	// ESC : ^[
+			history_enable = 1;
+			break;
+		case 0x5B: // [
+			if (history_enable == 0)
+				goto normal_cond;
+			break;
+		case 0x41:  // up [0x1b 0x41]
+		case 0x42:	// down [0x1b 0x41]
+			if (history_enable == 0)
+				goto normal_cond;
+
+			if (history_last_idx == -1)
+				break;
+
+			if (c == 0x41) {
+				if (history_cur_idx > 0) 
+					history_cur_idx--;
+				else
+					history_cur_idx = history_counter-1;									
+			} else {
+				if (history_cur_idx < history_counter-1) 
+					history_cur_idx++;
+				else
+					history_cur_idx = 0;													
+			}											
+
+			while (col > plen) {
+				puts (erase_seq);
+				--col;
+			}			
+			strcpy(console_buffer, &console_history[history_cur_idx][0]);
+			puts(console_buffer);
+			n = strlen(console_buffer);
+			p = console_buffer+n; 
+			col = n+plen;	
+			history_enable = 0;
+			break;
+normal_cond:
+#endif
+		default:
+			/*
+			 * Must be a normal character then
+			 */
+#ifdef CONFIG_CMD_HISTORY
+			history_enable = 0;
+#endif
+			if (n < CONFIG_SYS_CBSIZE-2) {
+				if (c == '\t') {	/* expand TABs		*/
+#ifdef CONFIG_AUTO_COMPLETE
+					/* if auto completion triggered just continue */
+					*p = '\0';
+					if (cmd_auto_complete(prompt, console_buffer, &n, &col)) {
+						p = console_buffer + n;	/* reset */
+						continue;
+					}
+#endif
+					puts (tab_seq+(col&07));
+					col += 8 - (col&07);
+				} else {
+					++col;		/* echo input		*/
+					putc (c);					
+				}
+				*p++ = c;
+				++n;
+			} else {			/* Buffer full		*/
+				putc ('\a');
+			}
+		}
+	}
+}
+
+void input_value(u8 *str)
+{
+	if (str)
+		strcpy(console_buffer, (const char*)str);
+	else
+		console_buffer[0] = '\0';
+	while(1)
+	{
+		if (readline ("==:", 1) > 0)
+		{
+			strcpy ((char*)str, console_buffer);
+			break;
+		}
+		else
+			break;
+	}
+}
+
+#ifdef RALINK_SWITCH_DEBUG_FUN
+#define RALINK_VLAN_ID_BASE	(RALINK_ETH_SW_BASE + 0x50)
+#define RALINK_VLAN_MEMB_BASE	(RALINK_ETH_SW_BASE + 0x70)
+
+#define RALINK_TABLE_SEARCH	(RALINK_ETH_SW_BASE + 0x24)
+#define RALINK_TABLE_STATUS0	(RALINK_ETH_SW_BASE + 0x28)
+#define RALINK_TABLE_STATUS1	(RALINK_ETH_SW_BASE + 0x2c)
+#define RALINK_TABLE_STATUS2	(RALINK_ETH_SW_BASE + 0x30)
+#define RALINK_WT_MAC_AD0	(RALINK_ETH_SW_BASE + 0x34)
+#define RALINK_WT_MAC_AD1	(RALINK_ETH_SW_BASE + 0x38)
+#define RALINK_WT_MAC_AD2	(RALINK_ETH_SW_BASE + 0x3C)
+#define RALINK_WT_MAC_AD2	(RALINK_ETH_SW_BASE + 0x3C)
+
+void table_dump(void)
+{
+	int i, j, value, mac;
+	int vid[16];
+
+	for (i = 0; i < 8; i++) {
+		value = RALINK_REG(RALINK_VLAN_ID_BASE + 4*i);
+		vid[2 * i] = value & 0xfff;
+		vid[2 * i + 1] = (value & 0xfff000) >> 12;
+	}
+
+	RALINK_REG(RALINK_TABLE_SEARCH) = 0x1;
+	printf("hash  port(0:6)  vidx  vid  age   mac-address  filt\n");
+	for (i = 0; i < 0x400; i++) {
+		while(1) {
+			value = RALINK_REG(RALINK_TABLE_STATUS0);
+			if (value & 0x1) { //search_rdy
+				if ((value & 0x70) == 0) {
+					printf("found an unused entry (age = 3'b000), please check!\n");
+					return;
+				}
+				printf("%03x:   ", (value >> 22) & 0x3ff); //hash_addr_lu
+				j = (value >> 12) & 0x7f; //r_port_map
+				printf("%c", (j & 0x01)? '1':'-');
+				printf("%c", (j & 0x02)? '1':'-');
+				printf("%c", (j & 0x04)? '1':'-');
+				printf("%c", (j & 0x08)? '1':'-');
+				printf("%c ", (j & 0x10)? '1':'-');
+				printf("%c", (j & 0x20)? '1':'-');
+				printf("%c", (j & 0x40)? '1':'-');
+				printf("   %2d", (value >> 7) & 0xf); //r_vid
+				printf("  %4d", vid[(value >> 7) & 0xf]);
+				printf("    %1d", (value >> 4) & 0x7); //r_age_field
+				mac = RALINK_REG(RALINK_TABLE_STATUS2);
+				printf("  %08x", mac);
+				mac = RALINK_REG(RALINK_TABLE_STATUS1);
+				printf("%04x", (mac & 0xffff));
+				printf("     %c\n", (value & 0x8)? 'y':'-');
+				if (value & 0x2) {
+					printf("end of table %d\n", i);
+					return;
+				}
+				break;
+			}
+			else if (value & 0x2) { //at_table_end
+				printf("found the last entry %d (not ready)\n", i);
+				return;
+			}
+			udelay(5000);
+		}
+		RALINK_REG(RALINK_TABLE_SEARCH) = 0x2; //search for next address
+	}
+}
+
+void table_add(int argc, char *argv[])
+{
+	int i, j, value, is_filter;
+	char tmpstr[9];
+
+	is_filter = (argv[1][0] == 'f')? 1 : 0;
+	if (!argv[2] || strlen(argv[2]) != 12) {
+		printf("MAC address format error, should be of length 12\n");
+		return;
+	}
+	strncpy(tmpstr, argv[2], 8);
+	tmpstr[8] = '\0';
+	value = simple_strtoul(tmpstr, NULL, 16);
+	RALINK_REG(RALINK_WT_MAC_AD2) = value;
+
+	strncpy(tmpstr, argv[2]+8, 4);
+	tmpstr[4] = '\0';
+	value = simple_strtoul(tmpstr, NULL, 16);
+	RALINK_REG(RALINK_WT_MAC_AD1) = value;
+
+	if (!argv[3] || strlen(argv[3]) != 7) {
+		if (is_filter)
+			argv[3] = "1111111";
+		else {
+			printf("portmap format error, should be of length 7\n");
+			return;
+		}
+	}
+	j = 0;
+	for (i = 0; i < 7; i++) {
+		if (argv[3][i] != '0' && argv[3][i] != '1') {
+			printf("portmap format error, should be of combination of 0 or 1\n");
+			return;
+		}
+		j += (argv[3][i] - '0') * (1 << i);
+	}
+	value = j << 12; //w_port_map
+
+	if (argc > 4) {
+		j = simple_strtoul(argv[4], NULL, 0);
+		if (j < 0 || 15 < j) {
+			printf("wrong member index range, should be within 0~15\n");
+			return;
+		}
+		value += (j << 7); //w_index
+	}
+
+	if (argc > 5) {
+		j = simple_strtoul(argv[5], NULL, 0);
+		if (j < 1 || 7 < j) {
+			printf("wrong age range, should be within 1~7\n");
+			return;
+		}
+		value += (j << 4); //w_age_field
+	}
+	else
+		value += (7 << 4); //w_age_field
+
+	if (is_filter)
+		value |= (1 << 3); //sa_filter
+
+	value += 1; //w_mac_cmd
+	RALINK_REG(RALINK_WT_MAC_AD0) = value;
+
+	for (i = 0; i < 20; i++) {
+		value = RALINK_REG(RALINK_WT_MAC_AD0);
+		if (value & 0x2) { //w_mac_done
+			printf("done.\n");
+			return;
+		}
+		udelay(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void table_del(int argc, char *argv[])
+{
+	int i, j, value;
+	char tmpstr[9];
+
+	if (!argv[2] || strlen(argv[2]) != 12) {
+		printf("MAC address format error, should be of length 12\n");
+		return;
+	}
+	strncpy(tmpstr, argv[2], 8);
+	tmpstr[8] = '\0';
+	value = simple_strtoul(tmpstr, NULL, 16);
+	RALINK_REG(RALINK_WT_MAC_AD2) = value;
+
+	strncpy(tmpstr, argv[2]+8, 4);
+	tmpstr[4] = '\0';
+	value = simple_strtoul(tmpstr, NULL, 16);
+	RALINK_REG(RALINK_WT_MAC_AD1) = value;
+
+	value = 0;
+	if (argc > 3) {
+		j = simple_strtoul(argv[3], NULL, 0);
+		if (j < 0 || 15 < j) {
+			printf("wrong member index range, should be within 0~15\n");
+			return;
+		}
+		value += (j << 7); //w_index
+	}
+
+	value += 1; //w_mac_cmd
+	RALINK_REG(RALINK_WT_MAC_AD0) = value;
+
+	for (i = 0; i < 20; i++) {
+		value = RALINK_REG(RALINK_WT_MAC_AD0);
+		if (value & 0x2) { //w_mac_done
+			if (argv[1] != NULL)
+				printf("done.\n");
+			return;
+		}
+		udelay(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void table_clear(void)
+{
+	int i, value, mac;
+	char v[2][13];
+	char *argv[4];
+
+	memset(argv, 0, sizeof(v));
+	memset(argv, 0, sizeof(argv));
+
+	RALINK_REG(RALINK_TABLE_SEARCH) = 0x1;
+	for (i = 0; i < 0x400; i++) {
+		while(1) {
+			value = RALINK_REG(RALINK_TABLE_STATUS0);
+			if (value & 0x1) { //search_rdy
+				if ((value & 0x70) == 0) {
+					return;
+				}
+				sprintf(v[1], "%d", (value >> 7) & 0xf);
+				mac = RALINK_REG(RALINK_TABLE_STATUS2);
+				sprintf(v[0], "%08x", mac);
+				mac = RALINK_REG(RALINK_TABLE_STATUS1);
+				sprintf(v[0]+8, "%04x", (mac & 0xffff));
+				argv[2] = v[0];
+				argv[3] = v[1];
+				table_del(4, argv);
+				if (value & 0x2) {
+					return;
+				}
+				break;
+			}
+			else if (value & 0x2) { //at_table_end
+				return;
+			}
+			udelay(5000);
+		}
+		RALINK_REG(RALINK_TABLE_SEARCH) = 0x2; //search for next address
+	}
+}
+
+void vlan_dump(void)
+{
+	int i, vid, value;
+
+	printf("idx   vid  portmap\n");
+	for (i = 0; i < 8; i++) {
+		vid = RALINK_REG(RALINK_VLAN_ID_BASE + 4*i);
+		value = RALINK_REG(RALINK_VLAN_MEMB_BASE + 4*(i/2));
+		printf(" %2d  %4d  ", 2*i, vid & 0xfff);
+		if (i%2 == 0) {
+			printf("%c", (value & 0x00000001)? '1':'-');
+			printf("%c", (value & 0x00000002)? '1':'-');
+			printf("%c", (value & 0x00000004)? '1':'-');
+			printf("%c", (value & 0x00000008)? '1':'-');
+			printf("%c", (value & 0x00000010)? '1':'-');
+			printf("%c", (value & 0x00000020)? '1':'-');
+			printf("%c\n", (value & 0x00000040)? '1':'-');
+		}
+		else {
+			printf("%c", (value & 0x00010000)? '1':'-');
+			printf("%c", (value & 0x00020000)? '1':'-');
+			printf("%c", (value & 0x00040000)? '1':'-');
+			printf("%c", (value & 0x00080000)? '1':'-');
+			printf("%c", (value & 0x00100000)? '1':'-');
+			printf("%c", (value & 0x00200000)? '1':'-');
+			printf("%c\n", (value & 0x00400000)? '1':'-');
+		}
+		printf(" %2d  %4d  ", 2*i+1, ((vid & 0xfff000) >> 12));
+		if (i%2 == 0) {
+			printf("%c", (value & 0x00000100)? '1':'-');
+			printf("%c", (value & 0x00000200)? '1':'-');
+			printf("%c", (value & 0x00000400)? '1':'-');
+			printf("%c", (value & 0x00000800)? '1':'-');
+			printf("%c", (value & 0x00001000)? '1':'-');
+			printf("%c", (value & 0x00002000)? '1':'-');
+			printf("%c\n", (value & 0x00004000)? '1':'-');
+		}
+		else {
+			printf("%c", (value & 0x01000000)? '1':'-');
+			printf("%c", (value & 0x02000000)? '1':'-');
+			printf("%c", (value & 0x04000000)? '1':'-');
+			printf("%c", (value & 0x08000000)? '1':'-');
+			printf("%c", (value & 0x10000000)? '1':'-');
+			printf("%c", (value & 0x20000000)? '1':'-');
+			printf("%c\n", (value & 0x40000000)? '1':'-');
+		}
+	}
+}
+
+void vlan_set(int argc, char *argv[])
+{
+	int i, j, value;
+	int idx, vid;
+
+	if (argc != 6) {
+		printf("insufficient arguments!\n");
+		return;
+	}
+	idx = simple_strtoul(argv[3], NULL, 0);
+	if (idx < 0 || 15 < idx) {
+		printf("wrong member index range, should be within 0~15\n");
+		return;
+	}
+	vid = simple_strtoul(argv[4], NULL, 0);
+	if (vid < 0 || 0xfff < vid) {
+		printf("wrong vlan id range, should be within 0~4095\n");
+		return;
+	}
+	if (strlen(argv[5]) != 7) {
+		printf("portmap format error, should be of length 7\n");
+		return;
+	}
+	j = 0;
+	for (i = 0; i < 7; i++) {
+		if (argv[5][i] != '0' && argv[5][i] != '1') {
+			printf("portmap format error, should be of combination of 0 or 1\n");
+			return;
+		}
+		j += (argv[5][i] - '0') * (1 << i);
+	}
+
+	//set vlan identifier
+	value = RALINK_REG(RALINK_VLAN_ID_BASE + 4*(idx/2));
+	if (idx % 2 == 0) {
+		value &= 0xfff000;
+		value |= vid;
+	}
+	else {
+		value &= 0xfff;
+		value |= (vid << 12);
+	}
+	RALINK_REG(RALINK_VLAN_ID_BASE + 4*(idx/2)) = value;
+
+	//set vlan member
+	value = RALINK_REG(RALINK_VLAN_MEMB_BASE + 4*(idx/4));
+	if (idx % 4 == 0) {
+		value &= 0xffffff00;
+		value |= j;
+	}
+	else if (idx % 4 == 1) {
+		value &= 0xffff00ff;
+		value |= (j << 8);
+	}
+	else if (idx % 4 == 2) {
+		value &= 0xff00ffff;
+		value |= (j << 16);
+	}
+	else {
+		value &= 0x00ffffff;
+		value |= (j << 24);
+	}
+	RALINK_REG(RALINK_VLAN_MEMB_BASE + 4*(idx/4)) = value;
+}
+
+int rt3052_switch_command(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	if (argc < 2) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+	if (argc == 2) {
+		if (!strncmp(argv[1], "dump", 5))
+			table_dump();
+		else if (!strncmp(argv[1], "clear", 6)) {
+			table_clear();
+			printf("done.\n");
+		}
+		else {
+			printf ("Usage:\n%s\n", cmdtp->usage);
+			return 1;
+		}
+	}
+	else if (!strncmp(argv[1], "add", 4))
+		table_add(argc, argv);
+	else if (!strncmp(argv[1], "filt", 5))
+		table_add(argc, argv);
+	else if (!strncmp(argv[1], "del", 4))
+		table_del(argc, argv);
+	else if (!strncmp(argv[1], "vlan", 5)) {
+		if (argc < 3)
+			printf ("Usage:\n%s\n", cmdtp->usage);
+		if (!strncmp(argv[2], "dump", 5))
+			vlan_dump();
+		else if (!strncmp(argv[2], "set", 4))
+			vlan_set(argc, argv);
+		else
+			printf ("Usage:\n%s\n", cmdtp->usage);
+	}
+	else {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+	return 0;
+}
+
+U_BOOT_CMD(
+ 	switch,	6,	1,	rt3052_switch_command,
+ 	"switch  - rt3052 embedded switch command\n",
+ 	"switch dump - dump switch table\n"
+	"switch clear - clear switch table\n"
+ 	"switch add [mac] [portmap] - add an entry to switch table\n"
+ 	"switch add [mac] [portmap] [vlan idx] - add an entry to switch table\n"
+ 	"switch add [mac] [portmap] [vlan idx] [age] - add an entry to switch table\n"
+ 	"switch filt [mac] - add an SA filtering entry (with portmap 1111111) to switch table\n"
+ 	"switch filt [mac] [portmap] - add an SA filtering entry to switch table\n"
+ 	"switch filt [mac] [portmap] [vlan idx] - add an SA filtering entry to switch table\n"
+ 	"switch filt [mac] [portmap] [vlan idx] [age] - add an SA filtering entry to switch table\n"
+ 	"switch del [mac] - delete an entry from switch table\n"
+ 	"switch del [mac] [vlan idx] - delete an entry from switch table\n"
+	"switch vlan dump - dump switch table\n"
+	"switch vlan set [vlan idx] [vid] [portmap] - set vlan id and associated member\n"
+);
+#endif // RALINK_SWITCH_DEBUG_FUN //
+
+#endif	/* CONFIG_TULIP */
diff --git a/include/configs/ex300.h b/include/configs/ex300.h
new file mode 100644
index 0000000000000000000000000000000000000000..33e4f0e55b2ca9eb12baa920ba804e4251b31c7f
--- /dev/null
+++ b/include/configs/ex300.h
@@ -0,0 +1,201 @@
+/*
+ *
+ */
+
+#ifndef _MT7621_CONFIG_H
+#define _MT7621_CONFIG_H
+//#define DEBUG
+//#define CONFIG_MTD_DEBUG
+//#define CONFIG_MTD_DEBUG_VERBOSE 1
+
+//#define TRACE32
+
+/********************************************************************************/
+/* hmmm  crap  from old uboot/include/configs/rt2888.h */
+
+#define RALINK_REG(x)          (*((volatile u32 *)(x)))
+
+#define RT2880_REGS_BASE                        0xA0000000
+#define RT2880_SYS_CNTL_BASE                    (RALINK_SYSCTL_BASE)
+#define RT2880_RSTCTRL_REG                      (RT2880_SYS_CNTL_BASE+0x34)
+
+/********************************************************************************/
+
+/*
+ * System configuration
+ */
+#define CONFIG_MT7621
+
+/* net stuff */
+//#define CONFIG_RT2880_ETH
+//#define CONFIG_DM_ETH
+#define MT7621_USE_GE1
+#define MT7621_ASIC_BOARD
+#define MAC_TO_MT7530_MODE
+#define PDMA_NEW
+#define RALINK_MDIO_ACCESS_FUN
+#define RALINK_EPHY_INIT
+#define RX_SCATTER_GATTER_DMA
+#define CONFIG_SYS_RX_ETH_BUFFER 60 /* code assumes 24+24 plus some extra I guess. */
+
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_R
+
+#define CONFIG_DISPLAY_BOARDINFO
+
+#define CONFIG_MEMSIZE_IN_BYTES
+#define CONFIG_LZMA
+
+#define CONFIG_SYS_ISA_IO_BASE_ADDRESS	0
+
+/*
+ * CPU Configuration
+ */
+#define CONFIG_SYS_MHZ			880/2
+#define CONFIG_SYS_MIPS_TIMER_FREQ	(CONFIG_SYS_MHZ * 1000000)
+
+/*
+ * Memory map
+ */
+//#define CONFIG_SYS_TEXT_BASE		0xbfc00000 /* Rom version */
+#define CONFIG_SYS_TEXT_BASE		0xA0200000 /* DRAM version */
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_SDRAM_BASE		0x80000000 /* Cached addr */
+//#define CONFIG_SYS_MEM_SIZE		(256 * 1024 * 1024)
+#define CONFIG_SYS_MEM_SIZE		(128 * 1024 * 1024)
+
+#define CONFIG_SYS_INIT_SP_OFFSET	0x400000
+
+#define CONFIG_SYS_LOAD_ADDR		0x81000000
+#define CONFIG_SYS_MEMTEST_START	0x80100000
+#define CONFIG_SYS_MEMTEST_END		0x80800000
+
+#define CONFIG_SYS_MALLOC_LEN		(1024 * 1024)
+#define CONFIG_SYS_BOOTPARAMS_LEN	(128 * 1024)
+#define CONFIG_SYS_BOOTM_LEN		(64 * 1024 * 1024)
+
+#define CONFIG_SYS_CBSIZE		256
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					 sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS		16
+
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+
+
+/*
+ * Serial driver
+ */
+#define CONFIG_BAUDRATE			57600
+#define SERIAL_CLOCK_DIVISOR 16
+
+
+//#include "../rt_mmap.h"
+// KEN:BUG  can not be included here but we need the addresses... what to do ???
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE	-4			/* little endian 32 bit registers, clearly we need to have -4 in reg size */
+#define CONFIG_SYS_NS16550_CLK		(50 * 1000 * 1000)	/* we have a 50 MHz base clock into the UART hardware */
+#define CONFIG_SYS_NS16550_COM1		(0xBE000000 + 0xc00)
+#define CONFIG_SYS_NS16550_COM2		(0xBE000000 + 0xd00)
+#define CONFIG_SYS_NS16550_COM3		(0xBE000000 + 0xe00)
+#define CONFIG_CONS_INDEX		1
+
+/*
+ * Flash configuration
+ */
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_MTK_MTD_NAND
+#define CONFIG_CMD_NAND
+
+
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_SYS_MAX_NAND_DEVICE      1
+#define CONFIG_SYS_NAND_SELF_INIT
+
+/* memory layout
+
+   u-boot	0  -> 1M
+   UBI		1M -> reest of memory
+*/
+
+//#include "../rt_mmap.h"
+// KEN:BUG  can not be included here but we need the addresses... what to do ???
+#define RALINK_NAND_CTRL_BASE            0xBE003000
+#define CONFIG_SYS_NAND_BASE RALINK_NAND_CTRL_BASE
+
+/*
+ * Environment in UBI
+ */
+#define CONFIG_MTD_UBI_BEB_LIMIT 30 /* this is 30 blocks per 1024 -> 3%, its also a runtime value do it's not stored on disk need to do same change in kernel */
+#define CONFIG_MTD_UBI_FASTMAP
+
+#define CONFIG_ENV_IS_IN_UBI
+#define CONFIG_ENV_UBI_PART "ubi"
+#define CONFIG_ENV_UBI_VOLUME "env1"
+#define CONFIG_ENV_UBI_VOLUME_REDUND "env2"
+#define CONFIG_ENV_SIZE 126976 /* we have a full UBI LEB and that is 126976 bytes */
+
+#else
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE			(1024*10) /*can actually be 128kB */
+#endif
+
+//#define CONFIG_BOOTDELAY      3       /* autoboot after 3 seconds     */
+#define CONFIG_CMD_UBI
+#define CONFIG_RBTREE
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE
+
+#define NANDID                  "MT7621-NAND"
+#define MTDIDS_DEFAULT          "nand0=" NANDID ""
+#define MTDPARTS_DEFAULT        "mtdparts=" NANDID ":1M(uboot),-(ubi)"
+
+#define CONFIG_CMD_UBIFS
+#define CONFIG_LZO
+#define CONFIG_BOOTCOMMAND "run boot_ubi"
+
+#define CONFIG_EXTRA_ENV_SETTINGS               \
+        "ethaddr=00:AA:BB:CC:DD:10\0"           \
+        "ipaddr=192.168.1.1\0"                  \
+        "serverip=192.168.1.2\0"                \
+        "mtdparts=" MTDPARTS_DEFAULT "\0"       \
+        "loadaddr=0x85000000\0"                 \
+        "fdtaddr=0x84000000\0" \
+        "root_vol=rootfs_0\0"   \
+        "update_uboot=" \
+                "if tftpboot ${loadaddr} uboot.img; then " \
+                        "nand erase.part uboot ;" \
+                        "nand write ${loadaddr} uboot $filesize;" \
+                "fi;\0" \
+        "update_root0=" \
+                "if tftpboot ${loadaddr} root.ubifs; then " \
+                        "ubi write ${loadaddr} rootfs_0 $filesize;" \
+                        "setenv root_vol rootfs_0;" \
+                "fi;\0" \
+        "boot_ram="\
+                "run bootargs_ram;" \
+                "tftpboot ${loadaddr} initramfs-kernel.bin;"\
+                "tftpboot ${fdtaddr}  dtb;"        \
+                "bootm ${loadaddr} - ${fdtaddr}\0" \
+        "boot_ubi="\
+                "run bootargs_ubi;" \
+                "ubifsmount ubi0:${root_vol};"\
+                "ubifsload ${loadaddr} /boot/uImage;"\
+                "ubifsload ${fdtaddr} /boot/dtb;"\
+                "bootm ${loadaddr} - ${fdtaddr}\0" \
+        "bootargs_ubi=setenv bootargs " \
+                "${extra} console=ttyS0,${baudrate} root=ubi0:${root_vol} ubi.mtd=ubi rootfstype=ubifs ${mtdparts}\0" \
+        "bootargs_ram=setenv bootargs " \
+                "${extra} console=ttyS0,${baudrate} ${mtdparts}\0"
+
+
+/*
+ * Commands
+ */
+
+#define CONFIG_SYS_LONGHELP		/* verbose help, undef to save memory */
+
+#endif /* */
diff --git a/include/launch.h b/include/launch.h
new file mode 100644
index 0000000000000000000000000000000000000000..af491e424cac03e249edc9898c47b2691aa6b48f
--- /dev/null
+++ b/include/launch.h
@@ -0,0 +1,71 @@
+
+/************************************************************************
+ *
+ *  loader_api.h
+ *
+ *  API file for load image module
+ *
+ * ######################################################################
+ *
+ * mips_start_of_header
+ * 
+ *  $Id: launch.h,v 1.6 2008-06-26 22:16:44 chris Exp $
+ * 
+ * Copyright (c) [Year(s)] MIPS Technologies, Inc. All rights reserved.
+ *
+ * Unpublished rights reserved under U.S. copyright law.
+ *
+ * PROPRIETARY/SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES,
+ * INC. FOR INTERNAL USE ONLY.
+ *
+ * Under no circumstances (contract or otherwise) may this information be
+ * disclosed to, or copied, modified or used by anyone other than employees
+ * or contractors of MIPS Technologies having a need to know.
+ *
+ * 
+ * mips_end_of_header
+ *
+ ************************************************************************/
+
+
+#ifndef LAUNCH_H
+#define LAUNCH_H
+
+#ifndef _ASSEMBLER_
+
+typedef struct {
+    unsigned long	pc;
+    unsigned long	gp;
+    unsigned long	sp;
+    unsigned long	a0;
+    unsigned long	_pad[3]; /* pad to cache line size to avoid thrashing */
+    unsigned long	flags;
+} cpulaunch_t;
+
+#else
+
+#define LOG2CPULAUNCH	5
+#define	LAUNCH_PC	0
+#define	LAUNCH_GP	4
+#define	LAUNCH_SP	8
+#define	LAUNCH_A0	12
+#define	LAUNCH_FLAGS	28
+
+#endif
+
+#define LAUNCH_FREADY	1
+#define LAUNCH_FGO	2
+#define LAUNCH_FGONE	4
+
+#define SCRLAUNCH	0x00000e00
+#define CPULAUNCH	0x00000f00
+#define NCPULAUNCH	8
+
+/* Polling period in count cycles for secondary CPU's */
+#define LAUNCHPERIOD	10000	
+
+#ifndef __ASSEMBLER__
+int cpu_present (int);
+#endif
+
+#endif /* LAUNCH_H */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 7236b8d0c302b7c42bb4128d3ea75de27ae822fe..cd62e5dacefe0db1ec475a16d7108e3e5c6fcd30 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -41,6 +41,7 @@ extern struct p_current *current;
 
 #define GFP_ATOMIC ((gfp_t) 0)
 #define GFP_KERNEL ((gfp_t) 0)
+#define GFP_DMA ((gfp_t) 0)
 #define GFP_NOFS ((gfp_t) 0)
 #define GFP_USER ((gfp_t) 0)
 #define __GFP_NOWARN ((gfp_t) 0)
diff --git a/include/mipsmtregs.h b/include/mipsmtregs.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bc5b497383f3d025989c32f6928a90d3888460c
--- /dev/null
+++ b/include/mipsmtregs.h
@@ -0,0 +1,395 @@
+/*
+ * MT regs definitions, follows on from mipsregs.h
+ * Copyright (C) 2004 - 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Elizabeth Clarke et. al.
+ *
+ */
+#ifndef _ASM_MIPSMTREGS_H
+#define _ASM_MIPSMTREGS_H
+
+#include <asm/mipsregs.h>
+/* #include <asm/war.h> */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * C macros
+ */
+
+#define read_c0_mvpcontrol()		__read_32bit_c0_register($0, 1)
+#define write_c0_mvpcontrol(val)	__write_32bit_c0_register($0, 1, val)
+
+#define read_c0_mvpconf0()		__read_32bit_c0_register($0, 2)
+#define read_c0_mvpconf1()		__read_32bit_c0_register($0, 3)
+
+#define read_c0_vpecontrol()		__read_32bit_c0_register($1, 1)
+#define write_c0_vpecontrol(val)	__write_32bit_c0_register($1, 1, val)
+
+#define read_c0_vpeconf0()		__read_32bit_c0_register($1, 2)
+#define write_c0_vpeconf0(val)		__write_32bit_c0_register($1, 2, val)
+
+#define read_c0_tcstatus()		__read_32bit_c0_register($2, 1)
+#define write_c0_tcstatus(val)		__write_32bit_c0_register($2, 1, val)
+
+#define read_c0_tcbind()		__read_32bit_c0_register($2, 2)
+
+#define read_c0_tccontext()		__read_32bit_c0_register($2, 5)
+#define write_c0_tccontext(val)		__write_32bit_c0_register($2, 5, val)
+
+#else /* Assembly */
+/*
+ * Macros for use in assembly language code
+ */
+
+#define CP0_MVPCONTROL		$0, 1
+#define CP0_MVPCONF0		$0, 2
+#define CP0_MVPCONF1		$0, 3
+#define CP0_VPECONTROL		$1, 1
+#define CP0_VPECONF0		$1, 2
+#define CP0_VPECONF1		$1, 3
+#define CP0_YQMASK		$1, 4
+#define CP0_VPESCHEDULE	$1, 5
+#define CP0_VPESCHEFBK		$1, 6
+#define CP0_TCSTATUS		$2, 1
+#define CP0_TCBIND		$2, 2
+#define CP0_TCRESTART		$2, 3
+#define CP0_TCHALT		$2, 4
+#define CP0_TCCONTEXT		$2, 5
+#define CP0_TCSCHEDULE		$2, 6
+#define CP0_TCSCHEFBK		$2, 7
+#define CP0_SRSCONF0		$6, 1
+#define CP0_SRSCONF1		$6, 2
+#define CP0_SRSCONF2		$6, 3
+#define CP0_SRSCONF3		$6, 4
+#define CP0_SRSCONF4		$6, 5
+
+#endif
+
+/* MVPControl fields */
+#define MVPCONTROL_EVP		(_ULCAST_(1))
+
+#define MVPCONTROL_VPC_SHIFT	1
+#define MVPCONTROL_VPC		(_ULCAST_(1) << MVPCONTROL_VPC_SHIFT)
+
+#define MVPCONTROL_STLB_SHIFT	2
+#define MVPCONTROL_STLB		(_ULCAST_(1) << MVPCONTROL_STLB_SHIFT)
+
+
+/* MVPConf0 fields */
+#define MVPCONF0_PTC_SHIFT	0
+#define MVPCONF0_PTC		( _ULCAST_(0xff))
+#define MVPCONF0_PVPE_SHIFT	10
+#define MVPCONF0_PVPE		( _ULCAST_(0xf) << MVPCONF0_PVPE_SHIFT)
+#define MVPCONF0_TCA_SHIFT	15
+#define MVPCONF0_TCA		( _ULCAST_(1) << MVPCONF0_TCA_SHIFT)
+#define MVPCONF0_PTLBE_SHIFT	16
+#define MVPCONF0_PTLBE		(_ULCAST_(0x3ff) << MVPCONF0_PTLBE_SHIFT)
+#define MVPCONF0_TLBS_SHIFT	29
+#define MVPCONF0_TLBS		(_ULCAST_(1) << MVPCONF0_TLBS_SHIFT)
+#define MVPCONF0_M_SHIFT	31
+#define MVPCONF0_M		(_ULCAST_(0x1) << MVPCONF0_M_SHIFT)
+
+
+/* config3 fields */
+#define CONFIG3_MT_SHIFT	2
+#define CONFIG3_MT		(_ULCAST_(1) << CONFIG3_MT_SHIFT)
+
+
+/* VPEControl fields (per VPE) */
+#define VPECONTROL_TARGTC	(_ULCAST_(0xff))
+
+#define VPECONTROL_TE_SHIFT	15
+#define VPECONTROL_TE		(_ULCAST_(1) << VPECONTROL_TE_SHIFT)
+#define VPECONTROL_EXCPT_SHIFT	16
+#define VPECONTROL_EXCPT	(_ULCAST_(0x7) << VPECONTROL_EXCPT_SHIFT)
+
+/* Thread Exception Codes for EXCPT field */
+#define THREX_TU		0
+#define THREX_TO		1
+#define THREX_IYQ		2
+#define THREX_GSX		3
+#define THREX_YSCH		4
+#define THREX_GSSCH		5
+
+#define VPECONTROL_GSI_SHIFT	20
+#define VPECONTROL_GSI		(_ULCAST_(1) << VPECONTROL_GSI_SHIFT)
+#define VPECONTROL_YSI_SHIFT	21
+#define VPECONTROL_YSI		(_ULCAST_(1) << VPECONTROL_YSI_SHIFT)
+
+/* VPEConf0 fields (per VPE) */
+#define VPECONF0_VPA_SHIFT	0
+#define VPECONF0_VPA		(_ULCAST_(1) << VPECONF0_VPA_SHIFT)
+#define VPECONF0_MVP_SHIFT	1
+#define VPECONF0_MVP		(_ULCAST_(1) << VPECONF0_MVP_SHIFT)
+#define VPECONF0_XTC_SHIFT	21
+#define VPECONF0_XTC		(_ULCAST_(0xff) << VPECONF0_XTC_SHIFT)
+
+/* TCStatus fields (per TC) */
+#define TCSTATUS_TASID		(_ULCAST_(0xff))
+#define TCSTATUS_IXMT_SHIFT	10
+#define TCSTATUS_IXMT		(_ULCAST_(1) << TCSTATUS_IXMT_SHIFT)
+#define TCSTATUS_TKSU_SHIFT	11
+#define TCSTATUS_TKSU		(_ULCAST_(3) << TCSTATUS_TKSU_SHIFT)
+#define TCSTATUS_A_SHIFT	13
+#define TCSTATUS_A		(_ULCAST_(1) << TCSTATUS_A_SHIFT)
+#define TCSTATUS_DA_SHIFT	15
+#define TCSTATUS_DA		(_ULCAST_(1) << TCSTATUS_DA_SHIFT)
+#define TCSTATUS_DT_SHIFT	20
+#define TCSTATUS_DT		(_ULCAST_(1) << TCSTATUS_DT_SHIFT)
+#define TCSTATUS_TDS_SHIFT	21
+#define TCSTATUS_TDS		(_ULCAST_(1) << TCSTATUS_TDS_SHIFT)
+#define TCSTATUS_TSST_SHIFT	22
+#define TCSTATUS_TSST		(_ULCAST_(1) << TCSTATUS_TSST_SHIFT)
+#define TCSTATUS_RNST_SHIFT	23
+#define TCSTATUS_RNST		(_ULCAST_(3) << TCSTATUS_RNST_SHIFT)
+/* Codes for RNST */
+#define TC_RUNNING		0
+#define TC_WAITING		1
+#define TC_YIELDING		2
+#define TC_GATED		3
+
+#define TCSTATUS_TMX_SHIFT	27
+#define TCSTATUS_TMX		(_ULCAST_(1) << TCSTATUS_TMX_SHIFT)
+/* TCStatus TCU bits can use same definitions/offsets as CU bits in Status */
+
+/* TCBind */
+#define TCBIND_CURVPE_SHIFT	0
+#define TCBIND_CURVPE		(_ULCAST_(0xf))
+
+#define TCBIND_CURTC_SHIFT	21
+
+#define TCBIND_CURTC		(_ULCAST_(0xff) << TCBIND_CURTC_SHIFT)
+
+/* TCHalt */
+#define TCHALT_H		(_ULCAST_(1))
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned int dvpe(void)
+{
+	int res = 0;
+
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	noreorder					\n"
+	"	.set	noat						\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41610001		# dvpe $1		\n"
+	"	move	%0, $1						\n"
+	"	ehb							\n"
+	"	.set	pop						\n"
+	: "=r" (res));
+
+	instruction_hazard();
+
+	return res;
+}
+
+static inline void __raw_evpe(void)
+{
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	noreorder					\n"
+	"	.set	noat						\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41600021		# evpe			\n"
+	"	ehb							\n"
+	"	.set	pop						\n");
+}
+
+/* Enable virtual processor execution if previous suggested it should be.
+   EVPE_ENABLE to force */
+
+#define EVPE_ENABLE MVPCONTROL_EVP
+
+static inline void evpe(int previous)
+{
+	if ((previous & MVPCONTROL_EVP))
+		__raw_evpe();
+}
+
+static inline unsigned int dmt(void)
+{
+	int res;
+
+	__asm__ __volatile__(
+	"	.set	push						\n"
+	"	.set	mips32r2					\n"
+	"	.set	noat						\n"
+	"	.word	0x41610BC1			# dmt $1	\n"
+	"	ehb							\n"
+	"	move	%0, $1						\n"
+	"	.set	pop						\n"
+	: "=r" (res));
+
+	instruction_hazard();
+
+	return res;
+}
+
+static inline void __raw_emt(void)
+{
+	__asm__ __volatile__(
+	"	.set	noreorder					\n"
+	"	.set	mips32r2					\n"
+	"	.word	0x41600be1			# emt		\n"
+	"	ehb							\n"
+	"	.set	mips0						\n"
+	"	.set	reorder");
+}
+
+/* enable multi-threaded execution if previous suggested it should be.
+   EMT_ENABLE to force */
+
+#define EMT_ENABLE VPECONTROL_TE
+
+static inline void emt(int previous)
+{
+	if ((previous & EMT_ENABLE))
+		__raw_emt();
+}
+
+static inline void ehb(void)
+{
+	__asm__ __volatile__(
+	"	.set	mips32r2				\n"
+	"	ehb						\n"
+	"	.set	mips0					\n");
+}
+
+#define mftc0(rt,sel)							\
+({									\
+	 unsigned long  __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	# mftc0	$1, $" #rt ", " #sel "			\n"	\
+	"	.word	0x41000800 | (" #rt " << 16) | " #sel "	\n"	\
+	"	move	%0, $1					\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mftgpr(rt)							\
+({									\
+	unsigned long __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noat					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	# mftgpr $1," #rt "				\n"	\
+	"	.word	0x41000820 | (" #rt " << 16)		\n"	\
+	"	move	%0, $1					\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mftr(rt, u, sel)							\
+({									\
+	unsigned long __res;						\
+									\
+	__asm__ __volatile__(						\
+	"	mftr	%0, " #rt ", " #u ", " #sel "		\n"	\
+	: "=r" (__res));						\
+									\
+	__res;								\
+})
+
+#define mttgpr(rd,v)							\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttgpr $1, " #rd "				\n"	\
+	"	.word	0x41810020 | (" #rd " << 11)		\n"	\
+	"	.set	pop					\n"	\
+	: : "r" (v));							\
+} while (0)
+
+#define mttc0(rd, sel, v)							\
+({									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	mips32r2				\n"	\
+	"	.set	noat					\n"	\
+	"	move	$1, %0					\n"	\
+	"	# mttc0 %0," #rd ", " #sel "			\n"	\
+	"	.word	0x41810000 | (" #rd " << 11) | " #sel "	\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "r" (v));							\
+})
+
+
+#define mttr(rd, u, sel, v)						\
+({									\
+	__asm__ __volatile__(						\
+	"mttr	%0," #rd ", " #u ", " #sel				\
+	: : "r" (v));							\
+})
+
+
+#define settc(tc)							\
+do {									\
+	write_c0_vpecontrol((read_c0_vpecontrol()&~VPECONTROL_TARGTC) | (tc)); \
+	ehb();								\
+} while (0)
+
+
+/* you *must* set the target tc (settc) before trying to use these */
+#define read_vpe_c0_vpecontrol()	mftc0(1, 1)
+#define write_vpe_c0_vpecontrol(val)	mttc0(1, 1, val)
+#define read_vpe_c0_vpeconf0()		mftc0(1, 2)
+#define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val)
+#define read_vpe_c0_count()		mftc0(9, 0)
+#define write_vpe_c0_count(val)		mttc0(9, 0, val)
+#define read_vpe_c0_status()		mftc0(12, 0)
+#define write_vpe_c0_status(val)	mttc0(12, 0, val)
+#define read_vpe_c0_cause()		mftc0(13, 0)
+#define write_vpe_c0_cause(val)		mttc0(13, 0, val)
+#define read_vpe_c0_config()		mftc0(16, 0)
+#define write_vpe_c0_config(val)	mttc0(16, 0, val)
+#define read_vpe_c0_config1()		mftc0(16, 1)
+#define write_vpe_c0_config1(val)	mttc0(16, 1, val)
+#define read_vpe_c0_config7()		mftc0(16, 7)
+#define write_vpe_c0_config7(val)	mttc0(16, 7, val)
+#define read_vpe_c0_ebase()		mftc0(15, 1)
+#define write_vpe_c0_ebase(val)		mttc0(15, 1, val)
+#define write_vpe_c0_compare(val)	mttc0(11, 0, val)
+#define read_vpe_c0_badvaddr()		mftc0(8, 0)
+#define read_vpe_c0_epc()		mftc0(14, 0)
+#define write_vpe_c0_epc(val)		mttc0(14, 0, val)
+
+
+/* TC */
+#define read_tc_c0_tcstatus()		mftc0(2, 1)
+#define write_tc_c0_tcstatus(val)	mttc0(2, 1, val)
+#define read_tc_c0_tcbind()		mftc0(2, 2)
+#define write_tc_c0_tcbind(val)		mttc0(2, 2, val)
+#define read_tc_c0_tcrestart()		mftc0(2, 3)
+#define write_tc_c0_tcrestart(val)	mttc0(2, 3, val)
+#define read_tc_c0_tchalt()		mftc0(2, 4)
+#define write_tc_c0_tchalt(val)		mttc0(2, 4, val)
+#define read_tc_c0_tccontext()		mftc0(2, 5)
+#define write_tc_c0_tccontext(val)	mttc0(2, 5, val)
+
+/* GPR */
+#define read_tc_gpr_sp()		mftgpr(29)
+#define write_tc_gpr_sp(val)		mttgpr(29, val)
+#define read_tc_gpr_gp()		mftgpr(28)
+#define write_tc_gpr_gp(val)		mttgpr(28, val)
+
+__BUILD_SET_C0(mvpcontrol)
+
+#endif /* Not __ASSEMBLY__ */
+
+#endif
diff --git a/include/rt_mmap.h b/include/rt_mmap.h
new file mode 100644
index 0000000000000000000000000000000000000000..8cbcc730cf4b9d2616f3745ee9456b0f10f4c755
--- /dev/null
+++ b/include/rt_mmap.h
@@ -0,0 +1,844 @@
+/**************************************************************************
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *     register definition for Ralink RT-series SoC
+ *
+ *  Copyright 2007 Ralink 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 __RALINK_MMAP__
+#define __RALINK_MMAP__
+
+#if defined (RT2880_FPGA_BOARD) || defined (RT2880_ASIC_BOARD)
+
+#ifdef RT2880_SHUTTLE
+
+#define RALINK_SYSCTL_BASE 		0xA0300000
+#define RALINK_TIMER_BASE		0xA0300100
+#define RALINK_INTCL_BASE		0xA0300200
+#define RALINK_MEMCTRL_BASE		0xA0300300
+#define RALINK_UART_BASE		0xA0300500
+#define RALINK_PIO_BASE			0xA0300600
+#define RALINK_I2C_BASE			0xA0300900
+#define RALINK_SPI_BASE			0xA0300B00
+#define RALINK_UART_LITE_BASE		0xA0300C00
+#define RALINK_FRAME_ENGINE_BASE	0xA0310000
+#define RALINK_EMBEDD_ROM_BASE		0xA0400000
+#define RALINK_PCI_BASE			0xA0500000
+#define RALINK_11N_MAC_BASE		0xA0600000
+
+#else // RT2880_MP
+
+#define RALINK_SYSCTL_BASE 		0xA0300000
+#define RALINK_TIMER_BASE		0xA0300100
+#define RALINK_INTCL_BASE		0xA0300200
+#define RALINK_MEMCTRL_BASE		0xA0300300
+#define RALINK_UART_BASE		0xA0300500
+#define RALINK_PIO_BASE			0xA0300600
+#define RALINK_I2C_BASE			0xA0300900
+#define RALINK_SPI_BASE			0xA0300B00
+#define RALINK_UART_LITE_BASE		0x00300C00
+#define RALINK_FRAME_ENGINE_BASE	0xA0400000
+#define RALINK_EMBEDD_ROM_BASE		0xA0410000
+#define RALINK_PCI_BASE			0xA0440000
+#define RALINK_11N_MAC_BASE		0xA0480000
+
+//Interrupt Controller
+#define RALINK_INTCTL_TIMER0		(1<<0)
+#define RALINK_INTCTL_WDTIMER		(1<<1)
+#define RALINK_INTCTL_UART		(1<<2)
+#define RALINK_INTCTL_PIO		(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UARTLITE		(1<<8)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<23)
+
+//Reset Control Register
+#define RALINK_TIMER_RST		(1<<1)
+#define RALINK_INTC_RST			(1<<2)
+#define RALINK_MC_RST			(1<<3)
+#define RALINK_CPU_RST			(1<<4)
+#define RALINK_UART_RST			(1<<5)
+#define RALINK_PIO_RST			(1<<6)
+#define RALINK_I2C_RST			(1<<9)
+#define RALINK_SPI_RST			(1<<11)
+#define RALINK_UART2_RST		(1<<12)
+#define RALINK_PCI_RST			(1<<16)
+#define RALINK_2860_RST			(1<<17)
+#define RALINK_FE_RST			(1<<18)
+#define RALINK_PCM_RST			(1<<19)
+
+#endif
+
+#elif defined (RT3052_FPGA_BOARD) || defined (RT3052_ASIC_BOARD)
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_PCM_BASE			0xB0000400
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_GDMA_BASE		0xB0000700
+#define RALINK_NAND_CTRL_BASE		0xB0000800
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_NAND		(1<<8)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_OTG		(1<<18)
+#define RALINK_INTCTL_OTG_IRQN		18
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_CPU_RST			(1<<1)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_RT2872_RST		(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_OTG_RST			(1<<22)
+#define RALINK_SW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+
+#elif defined (RT3352_FPGA_BOARD) || defined (RT3352_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN		(1<<20)
+#define RALINK_UPHY0_CLK_EN		(1<<18)
+#define RALINK_GE1_CLK_EN		(1<<16)
+
+
+#elif defined (RT6855_FPGA_BOARD) || defined (RT6855_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_NAND_CTRL_BASE		0xB0000810
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_PCIE_BASE		0xB0140000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UHST0_RST		(1<<25)
+#define RALINK_UDEV_RST			(1<<25)
+#define RALINK_PCIE0_RST		(1<<26)
+#define RALINK_PCIE1_RST		(1<<27)
+
+//Clock Conf Register
+#define RALINK_UPHY0_CLK_EN		(1<<25)
+
+#elif defined (MT7620_FPGA_BOARD) || defined (MT7620_ASIC_BOARD)
+#define RALINK_SYSCTL_BASE              0xB0000000
+#define RALINK_TIMER_BASE               0xB0000100
+#define RALINK_INTCL_BASE               0xB0000200
+#define RALINK_MEMCTRL_BASE             0xB0000300
+#define RALINK_RBUS_MATRIXCTL_BASE      0xB0000400
+#define RALINK_UART_BASE                0x10000500
+#define RALINK_PIO_BASE                 0xB0000600
+#define RALINK_NAND_CTRL_BASE           0xB0000810
+#define RALINK_I2C_BASE                 0xB0000900
+#define RALINK_I2S_BASE                 0xB0000A00
+#define RALINK_SPI_BASE                 0xB0000B00
+#define RALINK_UART_LITE_BASE           0x10000C00
+#define RALINK_MIPS_CNT_BASE            0x10000D00
+#define RALINK_PCM_BASE                 0xB0002000
+#define RALINK_GDMA_BASE                0xB0002800
+#define RALINK_CRYPTO_ENGING_BASE       0xB0004000
+#define RALINK_FRAME_ENGINE_BASE        0xB0100000
+#define RALINK_ETH_SW_BASE              0xB0110000
+#define RALINK_USB_DEV_BASE             0x10120000
+#define RALINK_MSDC_BASE                0xB0130000
+#define RALINK_PCI_BASE                 0xB0140000
+#define RALINK_11N_MAC_BASE             0xB0180000
+#define RALINK_USB_HOST_BASE            0x101C0000
+
+#define RALINK_MCNT_CFG                 0xB0000D00
+#define RALINK_COMPARE                  0xB0000D04
+#define RALINK_COUNT                    0xB0000D08
+
+#define RALINK_CPLLCFG0_REG		(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG		(RALINK_SYSCTL_BASE+0x58)
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL            (1<<0)
+#define RALINK_INTCTL_TIMER0            (1<<1)
+#define RALINK_INTCTL_WDTIMER           (1<<2)
+#define RALINK_INTCTL_ILL_ACCESS        (1<<3)
+#define RALINK_INTCTL_PCM               (1<<4)
+#define RALINK_INTCTL_UART              (1<<5)
+#define RALINK_INTCTL_PIO               (1<<6)
+#define RALINK_INTCTL_DMA               (1<<7)
+#define RALINK_INTCTL_PC                (1<<9)
+#define RALINK_INTCTL_I2S               (1<<10)
+#define RALINK_INTCTL_SPI               (1<<11)
+#define RALINK_INTCTL_UARTLITE          (1<<12)
+#define RALINK_INTCTL_CRYPTO            (1<<13)
+#define RALINK_INTCTL_ESW               (1<<17)
+#define RALINK_INTCTL_UHST              (1<<18)
+#define RALINK_INTCTL_UDEV              (1<<19)
+#define RALINK_INTCTL_GLOBAL            (1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST                  (1<<0)
+#define RALINK_TIMER_RST                (1<<8)
+#define RALINK_INTC_RST                 (1<<9)
+#define RALINK_MC_RST                   (1<<10)
+#define RALINK_PCM_RST                  (1<<11)
+#define RALINK_UART_RST                 (1<<12)
+#define RALINK_PIO_RST                  (1<<13)
+#define RALINK_DMA_RST                  (1<<14)
+#define RALINK_I2C_RST                  (1<<16)
+#define RALINK_I2S_RST                  (1<<17)
+#define RALINK_SPI_RST                  (1<<18)
+#define RALINK_UARTL_RST                (1<<19)
+#define RALINK_FE_RST                   (1<<21)
+#define RALINK_UHST_RST                 (1<<22)
+#define RALINK_ESW_RST                  (1<<23)
+#define RALINK_EPHY_RST                 (1<<24)
+#define RALINK_UDEV_RST                 (1<<25)
+#define RALINK_PCIE0_RST                (1<<26)
+#define RALINK_PCIE1_RST                (1<<27)
+#define RALINK_MIPS_CNT_RST             (1<<28)
+#define RALINK_CRYPTO_RST               (1<<29)
+
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN     (1<<22)
+#define RALINK_UPHY0_CLK_EN     (1<<25)
+
+#elif defined (MT7628_FPGA_BOARD) || defined (MT7628_ASIC_BOARD)
+
+#define RALINK_SYSCTL_BASE              0xB0000000
+#define RALINK_TIMER_BASE               0xB0000100
+#define RALINK_INTCL_BASE               0xB0000200
+#define RALINK_MEMCTRL_BASE             0xB0000300
+#define RALINK_RBUS_MATRIXCTL_BASE      0xB0000400
+#define RALINK_MIPS_CNT_BASE            0x10000500
+#define RALINK_PIO_BASE                 0xB0000600
+#define RALINK_I2C_BASE                 0xB0000900
+#define RALINK_I2S_BASE                 0xB0000A00
+#define RALINK_SPI_BASE                 0xB0000B00
+#define RALINK_UART_LITE_BASE           0x10000C00
+#define RALINK_UART_LITE2_BASE          0x10000D00
+#define RALINK_UART_LITE3_BASE          0x10000E00
+#define RALINK_PCM_BASE                 0xB0002000
+#define RALINK_GDMA_BASE                0xB0002800
+#define RALINK_AES_ENGING_BASE          0xB0004000
+#define RALINK_CRYPTO_ENGING_BASE       RALINK_AES_ENGING_BASE
+#define RALINK_RGCTRL_BASE				0xB0001000
+#define RALINK_FRAME_ENGINE_BASE        0xB0100000
+#define RALINK_ETH_SW_BASE              0xB0110000
+#define RALINK_USB_DEV_BASE             0x10120000
+#define RALINK_MSDC_BASE                0xB0130000
+#define RALINK_PCI_BASE                 0xB0140000
+#define RALINK_11N_MAC_BASE             0xB0180000
+#define RALINK_USB_HOST_BASE            0x101C0000
+
+#define RALINK_MCNT_CFG                 0xB0000D00
+#define RALINK_COMPARE                  0xB0000D04
+#define RALINK_COUNT                    0xB0000D08
+
+#define RALINK_CPLLCFG0_REG		(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG		(RALINK_SYSCTL_BASE+0x58)
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL            (1<<0)
+#define RALINK_INTCTL_TIMER0            (1<<1)
+#define RALINK_INTCTL_WDTIMER           (1<<2)
+#define RALINK_INTCTL_ILL_ACCESS        (1<<3)
+#define RALINK_INTCTL_PCM               (1<<4)
+#define RALINK_INTCTL_UART              (1<<5)
+#define RALINK_INTCTL_PIO               (1<<6)
+#define RALINK_INTCTL_DMA               (1<<7)
+#define RALINK_INTCTL_PC                (1<<9)
+#define RALINK_INTCTL_I2S               (1<<10)
+#define RALINK_INTCTL_SPI               (1<<11)
+#define RALINK_INTCTL_UARTLITE          (1<<12)
+#define RALINK_INTCTL_CRYPTO            (1<<13)
+#define RALINK_INTCTL_ESW               (1<<17)
+#define RALINK_INTCTL_UHST              (1<<18)
+#define RALINK_INTCTL_UDEV              (1<<19)
+#define RALINK_INTCTL_GLOBAL            (1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST                  (1<<0)
+#define RALINK_TIMER_RST                (1<<8)
+#define RALINK_INTC_RST                 (1<<9)
+#define RALINK_MC_RST                   (1<<10)
+#define RALINK_PCM_RST                  (1<<11)
+#define RALINK_UART_RST                 (1<<12)
+#define RALINK_PIO_RST                  (1<<13)
+#define RALINK_DMA_RST                  (1<<14)
+#define RALINK_I2C_RST                  (1<<16)
+#define RALINK_I2S_RST                  (1<<17)
+#define RALINK_SPI_RST                  (1<<18)
+#define RALINK_UARTL_RST                (1<<19)
+#define RALINK_FE_RST                   (1<<21)
+#define RALINK_UHST_RST                 (1<<22)
+#define RALINK_ESW_RST                  (1<<23)
+#define RALINK_EPHY_RST                 (1<<24)
+#define RALINK_UDEV_RST                 (1<<25)
+#define RALINK_PCIE0_RST                (1<<26)
+#define RALINK_PCIE1_RST                (1<<27)
+#define RALINK_MIPS_CNT_RST             (1<<28)
+#define RALINK_CRYPTO_RST               (1<<29)
+
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN     (1<<22)
+#define RALINK_UPHY0_CLK_EN     (1<<25)
+#define RALINK_PCIE_CLK_EN    	(1<<26)
+
+#elif defined (MT7621_FPGA_BOARD) || defined (MT7621_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE              0xBE000000
+#define RALINK_TIMER_BASE               0xBE000100
+#define RALINK_INTCL_BASE               0xBE000200
+#define RALINK_RBUS_MATRIXCTL_BASE      0xBE000400
+#define RALINK_MIPS_CNT_BASE            0x1E000500
+#define RALINK_PIO_BASE                 0xBE000600
+#define RALINK_SPDIF_BASE               0xBE000700
+#define RALINK_DMA_ARB_BASE             0xBE000800
+#define RALINK_I2C_BASE                 0xBE000900
+#define RALINK_I2S_BASE                 0xBE000A00
+#define RALINK_SPI_BASE                 0xBE000B00
+#define RALINK_UART_LITE_BASE           0xBE000C00
+#define RALINK_UART_LITE2_BASE          0xBE000D00
+#define RALINK_UART_LITE3_BASE          0xBE000E00
+#define RALINK_PCM_BASE                 0xBE002000
+#define RALINK_GDMA_BASE                0xBE002800
+#define RALINK_NAND_CTRL_BASE           0xBE003000
+#define RALINK_NANDECC_CTRL_BASE	0xBE003800
+#define RALINK_CRYPTO_ENGINE_BASE       0xBE004000
+#define RALINK_MEMCTRL_BASE             0xBE005000
+#define RALINK_FRAME_ENGINE_BASE        0xBE100000
+#define RALINK_ETH_GMAC_BASE            0xBE110000
+#define RALINK_ETH_SW_BASE		0xBE110000
+#define RALINK_ROM_BASE                 0xBE118000
+#define RALINK_MSDC_BASE                0xBE130000
+#define RALINK_PCI_BASE                 0xBE140000
+#define RALINK_USB_HOST_BASE            0x1E1C0000
+
+
+#define RALINK_CPLLCFG0_REG		(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG		(RALINK_SYSCTL_BASE+0x58)
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL            (1<<0)
+#define RALINK_INTCTL_TIMER0            (1<<1)
+#define RALINK_INTCTL_WDTIMER           (1<<2)
+#define RALINK_INTCTL_ILL_ACCESS        (1<<3)
+#define RALINK_INTCTL_PCM               (1<<4)
+#define RALINK_INTCTL_UART              (1<<5)
+#define RALINK_INTCTL_PIO               (1<<6)
+#define RALINK_INTCTL_DMA               (1<<7)
+#define RALINK_INTCTL_PC                (1<<9)
+#define RALINK_INTCTL_I2S               (1<<10)
+#define RALINK_INTCTL_SPI               (1<<11)
+#define RALINK_INTCTL_UARTLITE          (1<<12)
+#define RALINK_INTCTL_CRYPTO            (1<<13)
+#define RALINK_INTCTL_ESW               (1<<17)
+#define RALINK_INTCTL_UHST              (1<<18)
+#define RALINK_INTCTL_UDEV              (1<<19)
+#define RALINK_INTCTL_GLOBAL            (1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST                  (1<<0)
+#define RALINK_TIMER_RST                (1<<8)
+#define RALINK_INTC_RST                 (1<<9)
+#define RALINK_MC_RST                   (1<<10)
+#define RALINK_PCM_RST                  (1<<11)
+#define RALINK_UART_RST                 (1<<12)
+#define RALINK_PIO_RST                  (1<<13)
+#define RALINK_DMA_RST                  (1<<14)
+#define RALINK_I2C_RST                  (1<<16)
+#define RALINK_I2S_RST                  (1<<17)
+#define RALINK_SPI_RST                  (1<<18)
+#define RALINK_UARTL_RST                (1<<19)
+#define RALINK_FE_RST                   (1<<21)
+#define RALINK_UHST_RST                 (1<<22)
+#define RALINK_ESW_RST                  (1<<23)
+#define RALINK_EPHY_RST                 (1<<24)
+#define RALINK_UDEV_RST                 (1<<25)
+#define RALINK_PCIE0_RST                (1<<26)
+#define RALINK_PCIE1_RST                (1<<27)
+#define RALINK_MIPS_CNT_RST             (1<<28)
+#define RALINK_CRYPTO_RST               (1<<29)
+
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN     (1<<22)
+#define RALINK_UPHY0_CLK_EN     (1<<25)
+
+#elif defined (RT2883_FPGA_BOARD) || defined (RT2883_ASIC_BOARD)
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_PCM_BASE			0xB0000400
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_GDMA_BASE		0xB0000700
+#define RALINK_NAND_CTRL_BASE		0xB0000800
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_PCI_BASE			0xB0140000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_OTG_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_NAND		(1<<8)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_OTG		(1<<18)
+#define RALINK_INTCTL_OTG_IRQN		18
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_CPU_RST			(1<<1)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_OTG_RST			(1<<22)
+#define RALINK_PCIE_RST			(1<<23)
+
+
+#elif defined (RT3883_FPGA_BOARD) || defined (RT3883_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_NOR_CTRL_BASE		0xB0000700
+#define RALINK_NAND_CTRL_BASE		0xB0000810
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_CODEC1_BASE		0xB0003000
+#define RALINK_CODEC2_BASE		0xB0003800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_PCI_BASE			0xB0140000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_HOST_BASE		0xB01C0000
+#define RALINK_PCIE_BASE		0xB0200000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_NAND		(1<<8)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_NAND_RST			(1<<15)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_PCIE_RST			(1<<23)
+#define RALINK_PCI_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+#define RALINK_FLASH_RST		(1<<26)
+
+//Clock Conf Register
+#define RALINK_UPHY1_CLK_EN		(1<<20)
+#define RALINK_UPHY0_CLK_EN		(1<<18)
+#define RALINK_GE1_CLK_EN		(1<<16)
+
+
+#elif defined (RT5350_FPGA_BOARD) || defined (RT5350_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xB0000000
+#define RALINK_TIMER_BASE		0xB0000100
+#define RALINK_INTCL_BASE		0xB0000200
+#define RALINK_MEMCTRL_BASE		0xB0000300
+#define RALINK_UART_BASE		0xB0000500
+#define RALINK_PIO_BASE			0xB0000600
+#define RALINK_I2C_BASE			0xB0000900
+#define RALINK_I2S_BASE			0xB0000A00
+#define RALINK_SPI_BASE			0xB0000B00
+#define RALINK_UART_LITE_BASE		0xB0000C00
+#define RALINK_PCM_BASE			0xB0002000
+#define RALINK_GDMA_BASE		0xB0002800
+#define RALINK_FRAME_ENGINE_BASE	0xB0100000
+#define RALINK_ETH_SW_BASE		0xB0110000
+#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_11N_MAC_BASE		0xB0180000
+#define RALINK_USB_HOST_BASE		0xB01C0000
+
+//Interrupt Controller
+#define RALINK_INTCTL_SYSCTL		(1<<0)
+#define RALINK_INTCTL_TIMER0		(1<<1)
+#define RALINK_INTCTL_WDTIMER		(1<<2)
+#define RALINK_INTCTL_ILL_ACCESS	(1<<3)
+#define RALINK_INTCTL_PCM		(1<<4)
+#define RALINK_INTCTL_UART		(1<<5)
+#define RALINK_INTCTL_PIO		(1<<6)
+#define RALINK_INTCTL_DMA		(1<<7)
+#define RALINK_INTCTL_PC		(1<<9)
+#define RALINK_INTCTL_I2S		(1<<10)
+#define RALINK_INTCTL_UARTLITE		(1<<12)
+#define RALINK_INTCTL_ESW		(1<<17)
+#define RALINK_INTCTL_UHST		(1<<18)
+#define RALINK_INTCTL_UDEV		(1<<19)
+#define RALINK_INTCTL_GLOBAL		(1<<31)
+
+//Reset Control Register
+#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+#define RALINK_MIPS_RST			(1<<26)
+
+//Clock Conf Register
+#define RALINK_UPHY0_CLK_EN		(1<<18)
+#define RALINK_GE1_CLK_EN		(1<<16)
+
+#elif defined (RT6855A_FPGA_BOARD) || defined (RT6855A_ASIC_BOARD) 
+
+#define RALINK_SYSCTL_BASE		0xBFB00000
+#define RALINK_TIMER_BASE		0xBFBF0100
+#define RALINK_INTCL_BASE		0xBFB40000
+#define RALINK_MEMCTRL_BASE		0xBFB20000
+#define RALINK_PIO_BASE			0xBFBF0200
+#define RALINK_NAND_CTRL_BASE		0xBFBE0010
+#define RALINK_I2C_BASE			0xBFBF8000
+#define RALINK_I2S_BASE			0xBFBF8100
+#define RALINK_SPI_BASE			0xBFBC0B00
+#define RALINK_UART_LITE_BASE		0xBFBF0000
+#define RALINK_UART_LITE2_BASE		0xBFBF0300
+#define RALINK_PCM_BASE			0xBFBD0000
+#define RALINK_GDMA_BASE		0xBFB30000
+#define RALINK_FRAME_ENGINE_BASE	0xBFB50000
+#define RALINK_ETH_SW_BASE		0xBFB58000
+//#define RALINK_USB_DEV_BASE		0xB0120000
+#define RALINK_PCI_BASE			0xBFB80000
+//#define RALINK_USB_HOST_BASE		0xB01C0000
+#define RALINK_PCIE_BASE		0xBFB81000
+
+//Interrupt Controller
+#define RALINK_INTCTL_UARTLITE		(1<<0)
+#define RALINK_INTCTL_PIO		(1<<10)
+#define RALINK_INTCTL_PCM		(1<<11)
+#define RALINK_INTCTL_DMA		(1<<14)
+#define RALINK_INTCTL_GMAC2		(1<<15)
+#define RALINK_INTCTL_PCI		(1<<17)
+#define RALINK_INTCTL_UHST2		(1<<20)
+#define RALINK_INTCTL_GMAC1		(1<<21)
+#define RALINK_INTCTL_UHST1		(1<<23)
+#define RALINK_INTCTL_PCIE		(1<<24)
+#define RALINK_INTCTL_NAND		(1<<25)
+#define RALINK_INTCTL_SPI		(1<<27)
+
+//Reset Control Register
+//#define RALINK_SYS_RST			(1<<0)
+#define RALINK_TIMER_RST		(1<<8)
+#define RALINK_INTC_RST			(1<<9)
+#define RALINK_MC_RST			(1<<10)
+#define RALINK_PCM_RST			(1<<11)
+#define RALINK_UART_RST			(1<<12)
+#define RALINK_PIO_RST			(1<<13)
+#define RALINK_DMA_RST			(1<<14)
+#define RALINK_I2C_RST			(1<<16)
+#define RALINK_I2S_RST			(1<<17)
+#define RALINK_SPI_RST			(1<<18)
+#define RALINK_UARTL_RST		(1<<19)
+#define RALINK_WLAN_RST			(1<<20)
+#define RALINK_FE_RST			(1<<21)
+#define RALINK_UHST_RST			(1<<22)
+#define RALINK_ESW_RST			(1<<23)
+#define RALINK_EPHY_RST			(1<<24)
+#define RALINK_UDEV_RST			(1<<25)
+//#define RALINK_MIPS_RST			(1<<26)
+
+#endif
+
+
+/*kurtis:define DDR parameter here for better performance*/
+#ifdef ON_BOARD_DDR2
+/*define ddr module here to choose proper setting or use default setting*/
+//#define W9751G6IB_25
+
+#define DDR_CFG0_REG	RALINK_MEMCTRL_BASE+0x40
+#define RAS_OFFSET	23
+#define TRFC_OFFSET	13
+#define TRFI_OFFSET	0
+#ifdef  ON_BOARD_32BIT_DRAM_BUS
+#define BL_VALUE	2//BL=4
+#else
+#define BL_VALUE	3 //BL=8
+#endif
+
+#define CAS_OFFSET	4
+#define BL_OFFSET	0
+#define AdditiveLatency_OFFSET 3
+
+#if defined (W9751G6IB_25)
+#define RAS_VALUE	7
+#define TRFC_VALUE	9
+#define TRFI_VALUE	650
+#define CAS_VALUE	3
+#define AdditiveLatency_VALUE  0
+#endif //W9751G6IB_25
+
+#endif //DDR
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+#define RALINK_SDRAM_CFG0_REG 	(RALINK_MEMCTRL_BASE)
+#define RALINK_SDRAM_CFG1_REG 	(RALINK_MEMCTRL_BASE+0x4)
+#define RALINK_DDR_CFG0		(RALINK_MEMCTRL_BASE+0x40)
+#define RALINK_DDR_CFG1		(RALINK_MEMCTRL_BASE+0x44)
+#define RALINK_DDR_CFG2		(RALINK_MEMCTRL_BASE+0x48)
+#define RALINK_DDR_CFG3		(RALINK_MEMCTRL_BASE+0x4c)
+#define RALINK_DDR_CFG4		(RALINK_MEMCTRL_BASE+0x50)
+#define RALINK_DDR_CFG9		(RALINK_MEMCTRL_BASE+0x64)
+#endif
+
+#if defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) || defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+/* CPLL related */
+#define RALINK_CPLLCFG0_REG	(RALINK_SYSCTL_BASE+0x54)
+#define RALINK_CPLLCFG1_REG	(RALINK_SYSCTL_BASE+0x58)
+#define CPLL_SW_CONFIG                  (0x1UL << 31)
+#define CPLL_MULT_RATIO_SHIFT           16
+#define CPLL_MULT_RATIO                 (0x7UL << CPLL_MULT_RATIO_SHIFT)
+#define CPLL_DIV_RATIO_SHIFT            10
+#define CPLL_DIV_RATIO                  (0x3UL << CPLL_DIV_RATIO_SHIFT)
+#define BASE_CLOCK                      40      /* Mhz */
+#endif
+
+/* Timer related */
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+#define RALINK_TIMER_CTL	(RALINK_TIMER_BASE + 0x00)
+#define RALINK_TIMER5_LDV	(RALINK_TIMER_BASE + 0x2C)
+#endif
+
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+#define RALINK_HIR_REG	(RALINK_SYSCTL_BASE+0x64)
+#endif
+
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+#define RALINK_PIO_BASE			0xBE000600
+#define RALINK_CLKCFG0_REG		0xBE00002C
+#define RALINK_GPIOMODE_REG		0xBE000060
+#define RALINK_CUR_CLK_STS_REG		0xBE000044
+#define RALINK_DYN_CFG0_REG		0xBE000410
+#endif
+
+#if defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+#define RALINK_CLKCFG0_REG      0xB000002C
+#define RALINK_DYN_CFG0_REG		0xB0000440
+#endif
+
+#endif // __RALINK_MMAP__
diff --git a/include/sysdefs.h b/include/sysdefs.h
new file mode 100644
index 0000000000000000000000000000000000000000..083b431f059a4f8f103072d0b65fd1e06f828f16
--- /dev/null
+++ b/include/sysdefs.h
@@ -0,0 +1,467 @@
+
+/************************************************************************
+ *
+ *  sysdefs.h
+ *
+ *  System definitions
+ *
+ * ######################################################################
+ *
+ * mips_start_of_header
+ * 
+ *  $Id: sysdefs.h,v 1.65 2010-03-12 19:44:16 douglas Exp $
+ * 
+ * Copyright (c) [Year(s)] MIPS Technologies, Inc. All rights reserved.
+ *
+ * Unpublished rights reserved under U.S. copyright law.
+ *
+ * PROPRIETARY/SECRET CONFIDENTIAL INFORMATION OF MIPS TECHNOLOGIES,
+ * INC. FOR INTERNAL USE ONLY.
+ *
+ * Under no circumstances (contract or otherwise) may this information be
+ * disclosed to, or copied, modified or used by anyone other than employees
+ * or contractors of MIPS Technologies having a need to know.
+ *
+ * 
+ * mips_end_of_header
+ *
+ ************************************************************************/
+
+
+#ifndef SYSDEFS_H
+#define SYSDEFS_H
+
+
+/************************************************************************
+ *  Include files
+ ************************************************************************/
+
+/************************************************************************
+ *  Definitions
+*************************************************************************/
+#ifdef __ASSEMBLER__
+#define _ASSEMBLER_
+#endif
+
+#ifdef __ghs__
+#define _GHS_
+#endif
+
+#ifdef _ASSEMBLER_
+
+/******** ASSEMBLER SPECIFIC DEFINITIONS ********/
+
+#ifdef  __ghs__
+#define ALIGN(x) .##align (1 << (x))
+#else
+#define ALIGN(x) .##align (x)
+#endif
+
+#ifdef __ghs__
+#define SET_MIPS3()
+#define SET_MIPS0()
+#define SET_PUSH()
+#define SET_POP()
+#else
+#define SET_MIPS3() .##set mips3
+#define SET_MIPS0() .##set mips0
+#define SET_PUSH()  .##set push
+#define SET_POP()   .##set pop
+#endif
+
+/*  Different assemblers have different requirements for how to
+ *  indicate that the next section is bss : 
+ *
+ *  Some use :   .bss
+ *  Others use : .section bss
+ *
+ *  We select which to use based on _BSS_OLD_, which may be defined 
+ *  in makefile.
+ */
+#ifdef _BSS_OLD_
+#define BSS	.##section bss
+#else
+#define BSS	.##bss
+#endif
+
+#define SWAPEND32( src, tmp0, tmp1 )\
+		and	tmp0, src, 0xff;\
+		srl	src,  8;\
+		sll	tmp0, 8;\
+		and	tmp1, src, 0xff;\
+		or	tmp0, tmp1;\
+		srl	src,  8;\
+		sll	tmp0, 8;\
+		and	tmp1, src, 0xff;\
+		or	tmp0, tmp1;\
+		srl	src,  8;\
+		sll	tmp0, 8;\
+		or	src,  tmp0
+
+#define LEAF(name)\
+  		.##text;\
+  		.##globl	name;\
+  		.##ent	name;\
+name:
+
+
+#define SLEAF(name)\
+  		.##text;\
+  		.##ent	name;\
+name:
+
+
+#ifdef __ghs__
+#define END(name)\
+  		.##end	name
+#else
+#define END(name)\
+  		.##size name,.-name;\
+  		.##end	name
+#endif
+
+
+#define EXTERN(name)
+
+# else /* not assembler */
+
+/******** C specific definitions ********/
+
+#define SWAPEND32(d)    ((BYTE(d,0) << 24) |\
+		         (BYTE(d,1) << 16) |\
+		         (BYTE(d,2) << 8)  |\
+		         (BYTE(d,3) << 0))
+
+#define SWAPEND64(d)    ((BYTE(d,0) << 56) |\
+		         (BYTE(d,1) << 48) |\
+		         (BYTE(d,2) << 40)  |\
+		         (BYTE(d,3) << 32)  |\
+			 (BYTE(d,4) << 24) |\
+		         (BYTE(d,5) << 16) |\
+		         (BYTE(d,6) << 8)  |\
+		         (BYTE(d,7) << 0))
+
+typedef unsigned char		UINT8;
+typedef signed char		INT8;
+typedef unsigned short		UINT16;
+typedef signed short		INT16;
+typedef unsigned int		UINT32;
+typedef signed int		INT32;
+typedef unsigned long long	UINT64;
+typedef signed long long	INT64;
+typedef UINT8			bool;
+
+#ifndef _SIZE_T
+#define _SIZE_T
+#ifdef __ghs__
+   typedef unsigned int size_t;
+#else
+   typedef unsigned long size_t;
+#endif
+#endif
+
+#endif /* #ifdef _ASSEMBLER_ */
+
+
+
+/******** DEFINITIONS FOR BOTH ASSEMBLER AND C ********/
+
+
+#define FALSE		          0
+#define TRUE			  (!FALSE)
+
+#define NULL		          ((void *)0)
+#define MIN(x,y)		  ((x) < (y) ? (x) : (y))
+#define MAX(x,y)      		  ((x) > (y) ? (x) : (y))
+ 
+#define INCWRAP( ptr, size )      (ptr) = ((ptr)+1) % (size)
+#define DECWRAP( ptr, size )      (ptr) = (((ptr) == 0) ? ((size) - 1) : ((ptr) - 1))
+
+#define MAXUINT(w)	(\
+		((w) == sizeof(UINT8))  ? 0xFFU :\
+		((w) == sizeof(UINT16)) ? 0xFFFFU :\
+		((w) == sizeof(UINT32)) ? 0xFFFFFFFFU : 0\
+		        )
+
+#define MAXINT(w)	(\
+		((w) == sizeof(INT8))  ? 0x7F :\
+		((w) == sizeof(INT16)) ? 0x7FFF :\
+		((w) == sizeof(INT32)) ? 0x7FFFFFFF : 0\
+		        )
+
+#define MSK(n)			  ((1 << (n)) - 1)
+
+#define KUSEG_MSK		  0x80000000
+#define KSEG_MSK		  0xE0000000
+#define KUSEGBASE		  0x00000000
+#define KSEG0BASE		  0x80000000
+#define KSEG1BASE		  0xA0000000
+#define KSSEGBASE		  0xC0000000
+#define KSEG3BASE		  0xE0000000
+
+/*  Below macros perform the following functions :
+ *
+ *  KSEG0    : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG0.
+ *  KSEG1    : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG1.
+ *  PHYS     : Converts KSEG0/1 or physical addr (below 0.5GB) to physical address.
+ *  KSSEG    : Not relevant for converting, but used for determining range.
+ *  KSEG3    : Not relevant for converting, but used for determining range.
+ *  KUSEG    : Not relevant for converting, but used for determining range.
+ *  KSEG0A   : Same as KSEG0 but operates on register rather than constant.
+ *  KSEG1A   : Same as KSEG1 but operates on register rather than constant.
+ *  PHYSA    : Same as PHYS  but operates on register rather than constant.
+ *  CACHED   : Alias for KSEG0 macro .
+ *	       (Note that KSEG0 cache attribute is determined by K0
+ *	       field of Config register, but this is typically cached).
+ *  UNCACHED : Alias for KSEG1 macro .
+ */
+#ifdef _ASSEMBLER_
+#define KSEG0(addr)     (((addr) & ~KSEG_MSK)  | KSEG0BASE)
+#define KSEG1(addr)     (((addr) & ~KSEG_MSK)  | KSEG1BASE)
+#define KSSEG(addr)     (((addr) & ~KSEG_MSK)  | KSSEGBASE)
+#define KSEG3(addr)     (((addr) & ~KSEG_MSK)  | KSEG3BASE)
+#define KUSEG(addr)     (((addr) & ~KUSEG_MSK) | KUSEGBASE)
+#define PHYS(addr)      ( (addr) & ~KSEG_MSK)
+#define KSEG0A(reg) 	and reg, ~KSEG_MSK; or reg, KSEG0BASE
+#define KSEG1A(reg) 	and reg, ~KSEG_MSK; or reg, KSEG1BASE
+#define PHYSA(reg)	and reg, ~KSEG_MSK
+#define KSEG0A2(d,s)	and d, s, ~KSEG_MSK; or d, KSEG0BASE
+#define KSEG1A2(d,s)	and d, s, ~KSEG_MSK; or d, KSEG1BASE
+#define PHYSA2(d,s)	and d, s, ~KSEG_MSK
+#else
+#define KSEG0(addr)     (((UINT32)(addr) & ~KSEG_MSK)  | KSEG0BASE)
+#define KSEG1(addr)     (((UINT32)(addr) & ~KSEG_MSK)  | KSEG1BASE)
+#define KSSEG(addr)	(((UINT32)(addr) & ~KSEG_MSK)  | KSSEGBASE)
+#define KSEG3(addr)	(((UINT32)(addr) & ~KSEG_MSK)  | KSEG3BASE)
+#define KUSEG(addr)	(((UINT32)(addr) & ~KUSEG_MSK) | KUSEGBASE)
+#define PHYS(addr) 	((UINT32)(addr)  & ~KSEG_MSK)
+#endif
+
+#define CACHED(addr)	KSEG0(addr)
+#define UNCACHED(addr)	KSEG1(addr)
+
+
+#ifdef _ASSEMBLER_
+/* Macroes to access variables at constant addresses 
+ * Compensates for signed 16 bit displacement
+ * Typical use:	li	a0, HIKSEG1(ATLAS_ASCIIWORD)
+ *		sw	v1, LO_OFFS(ATLAS_ASCIIWORD)(a0)
+ */
+#define HIKSEG0(addr)	((KSEG0(addr) + 0x8000) & 0xffff0000)
+#define HIKSEG1(addr)	((KSEG1(addr) + 0x8000) & 0xffff0000)
+#define HI_PART(addr)	(((addr) + 0x8000) & 0xffff0000)
+#define LO_OFFS(addr)	((addr) & 0xffff)
+#endif
+
+
+/* Most/Least significant 32 bit from 64 bit double word */
+#define HI32(data64)		  ((UINT32)(data64 >> 32))
+#define LO32(data64)		  ((UINT32)(data64 & 0xFFFFFFFF))
+
+#define REG8( addr )		  (*(volatile UINT8 *) (addr))
+#define REG16( addr )		  (*(volatile UINT16 *)(addr))
+#define REG32( addr )		  (*(volatile UINT32 *)(addr))
+#define REG64( addr )		  (*(volatile UINT64 *)(addr))
+
+
+/* Register field mapping */
+#define REGFIELD(reg, rfld)	  (((reg) & rfld##_MSK) >> rfld##_SHF)
+
+/* absolute register address, access 					*/
+#define	REGA(addr)		  REG32(addr)
+
+/* physical register address, access: base address + offsett		*/
+#define	REGP(base,phys)	REG32( (UINT32)(base) + (phys) )
+
+/* relative register address, access: base address + offsett		*/
+#define REG(base,offs)  REG32( (UINT32)(base) + offs##_##OFS )
+
+/**************************************
+ * Macroes not used by YAMON any more
+ * (kept for backwards compatibility)
+ */
+/* register read field							*/
+#define	REGARD(addr,fld)	((REGA(addr) & addr##_##fld##_##MSK) 	\
+			 >> addr##_##fld##_##SHF)
+
+/* register write numeric field value					*/
+#define	REGAWRI(addr,fld,intval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
+				 | ((intval) << addr##_##fld##_##SHF))
+
+/* register write enumerated field value				*/
+#define	REGAWRE(addr,fld,enumval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
+			| ((addr##_##fld##_##enumval) << addr##_##fld##_##SHF))
+
+
+/* Examples:
+ * 
+ *	exccode = REGARD(CPU_CAUSE,EXC);
+ *
+ *	REGA(SDR_CONTROL) = REGAWRI(OSG_CONTROL,TMO,17)
+ *			 | REGAWRE(OSG_CONTROL,DTYPE,PC1);
+ */
+
+
+/* register read field							*/
+#define	REGRD(base,offs,fld) ((REG(base,offs) & offs##_##fld##_##MSK) 	\
+			 >> offs##_##fld##_##SHF)
+
+/* register write numeric field value					*/
+#define	REGWRI(base,offs,fld,intval)((REG(base,offs)& ~(offs##_##fld##_##MSK))\
+                                 | (((intval) << offs##_##fld##_##SHF) & offs##_##fld##_##MSK))
+
+/* register write enumerated field value				*/
+#define	REGWRE(base,offs,fld,enumval)((REG(base,offs) & ~(offs##_##fld##_##MSK))\
+				| ((offs##_##fld##_##enumval) << offs##_##fld##_##SHF))
+
+
+/* physical register read field							*/
+#define	REGPRD(base,phys,fld) ((REGP(base,phys) & phys##_##fld##_##MSK) 	\
+			 >> phys##_##fld##_##SHF)
+
+/* physical register write numeric field value					*/
+#define	REGPWRI(base,phys,fld,intval)((REGP(base,phys)& ~(phys##_##fld##_##MSK))\
+				 | ((intval) << phys##_##fld##_##SHF))
+
+/* physical register write enumerated field value				*/
+#define	REGPWRE(base,phys,fld,enumval)((REGP(base,phys) & ~(phys##_##fld##_##MSK))\
+				| ((phys##_##fld##_##enumval) << phys##_##fld##_##SHF))
+/*
+ * End of macroes not used by YAMON any more
+ *********************************************/
+
+/* Endian related macros */
+
+#define SWAP_BYTEADDR32( addr )   ( (addr) ^ 0x3 )
+#define SWAP_UINT16ADDR32( addr ) ( (addr) ^ 0x2 )
+
+#define BYTE(d,n)		  (((d) >> ((n) << 3)) & 0xFF)
+
+/* Set byte address to little endian format */
+#ifdef EL
+#define SWAP_BYTEADDR_EL(addr) 	  addr
+#else
+#define SWAP_BYTEADDR_EL(addr)    SWAP_BYTEADDR32( addr )
+#endif
+
+/* Set byte address to big endian format */
+#ifdef EB
+#define SWAP_BYTEADDR_EB(addr) 	  addr
+#else
+#define SWAP_BYTEADDR_EB(addr)    SWAP_BYTEADDR32( addr )
+#endif
+
+/* Set UINT16 address to little endian format */
+#ifdef EL
+#define SWAP_UINT16ADDR_EL(addr)  addr
+#else
+#define SWAP_UINT16ADDR_EL(addr)  SWAP_UINT16ADDR32( addr )
+#endif
+
+/* Set UINT16 address to big endian format */
+#ifdef EB
+#define SWAP_UINT16ADDR_EB(addr)  addr
+#else
+#define SWAP_UINT16ADDR_EB(addr)  SWAP_UINT16ADDR32( addr )
+#endif
+
+#ifdef EL
+#define REGW32LE(addr, data)      REG32(addr) = (data)
+#define REGR32LE(addr, data)      (data)      = REG32(addr)
+#else
+#define REGW32LE(addr, data)      REG32(addr) = SWAPEND32(data)
+#define REGR32LE(addr, data)      (data)      = REG32(addr), (data) = SWAPEND32(data)
+#endif
+
+/* Set of 'LE'-macros, convert by BE: */
+#ifdef EL
+#define CPU_TO_LE32( value ) (value)
+#define LE32_TO_CPU( value ) (value)
+
+#define CPU_TO_LE16( value ) (value)
+#define LE16_TO_CPU( value ) (value)
+#else
+#define CPU_TO_LE32( value ) ( (                ((UINT32)value)  << 24) |   \
+                               ((0x0000FF00UL & ((UINT32)value)) <<  8) |   \
+                               ((0x00FF0000UL & ((UINT32)value)) >>  8) |   \
+                               (                ((UINT32)value)  >> 24)   )
+#define LE32_TO_CPU( value ) CPU_TO_LE32( value )
+
+#define CPU_TO_LE16( value ) ( ((UINT16)(((UINT16)value)  << 8)) |   \
+                               ((UINT16)(((UINT16)value)  >> 8))   )
+#define LE16_TO_CPU( value ) CPU_TO_LE16( value )
+#endif
+
+/* Set of 'BE'-macros, convert by LE: */
+#ifdef EB
+#define CPU_TO_BE32( value ) (value)
+#define BE32_TO_CPU( value ) (value)
+
+#define CPU_TO_BE16( value ) (value)
+#define BE16_TO_CPU( value ) (value)
+#else
+#define CPU_TO_BE32( value ) ( (                ((UINT32)value)  << 24) |   \
+                               ((0x0000FF00UL & ((UINT32)value)) <<  8) |   \
+                               ((0x00FF0000UL & ((UINT32)value)) >>  8) |   \
+                               (                ((UINT32)value)  >> 24)   )
+#define BE32_TO_CPU( value ) CPU_TO_BE32( value )
+
+#define CPU_TO_BE16( value ) ( ((UINT16)(((UINT16)value)  << 8)) |   \
+                               ((UINT16)(((UINT16)value)  >> 8))   )
+#define BE16_TO_CPU( value ) CPU_TO_BE16( value )
+#endif
+
+#ifdef _ASSEMBLER_
+EXTERN(default_port)
+EXTERN(debug_port)
+EXTERN(default_gdb_port)
+#else
+extern UINT8 default_port;
+extern UINT8 debug_port;
+extern UINT8 default_gdb_port;
+#endif
+
+/* Standard ports */
+#define PORT_TTY0	 0
+#define PORT_TTY1	 1
+#define PORT_NET	 2
+#define DEFAULT_PORT	 default_port
+#define DEBUG_PORT	 degug_port
+#define DEFAULT_GDB_PORT default_gdb_port
+
+/* Pick either TTY1 or TTY0 as the default port */
+#define DEFAULT_TTY_PORT       PORT_TTY0
+
+/* Env. variable for default serial port used for load */
+#define DEFAULT_BOOTPORT_ENV   "tty0"
+
+/* Control characters */
+#define CTRL_A          ('A'-0x40)
+#define CTRL_B          ('B'-0x40)
+#define CTRL_C          ('C'-0x40)
+#define CTRL_D          ('D'-0x40)
+#define CTRL_E          ('E'-0x40)
+#define CTRL_F          ('F'-0x40)
+#define CTRL_H          ('H'-0x40)
+#define CTRL_K          ('K'-0x40)
+#define CTRL_N          ('N'-0x40)
+#define CTRL_P          ('P'-0x40)
+#define CTRL_U          ('U'-0x40)
+#define DEL             0x7F
+#define TAB             0x09
+#define CR              0x0D
+#define LF              0x0A
+#define ESC             0x1B
+#define SP              0x20
+#define CSI             0x9B
+#define EOF_SREC        -2
+#define UART_ERROR      -1
+
+
+/* DEF2STR(x) converts #define symbol to string */
+#define DEF2STR1(x) #x
+#define DEF2STR(x)  DEF2STR1(x)
+
+
+#endif /* #ifndef SYSDEFS_H */
+
diff --git a/mt7621_ddr.sh b/mt7621_ddr.sh
new file mode 100755
index 0000000000000000000000000000000000000000..bbb3fe856adbd96c659ccc96eef0e61b41705ab6
--- /dev/null
+++ b/mt7621_ddr.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+VAR=$4
+DDR3=$(echo ${VAR##*DDR3})
+
+if [ "$DDR3" == "$4" ]; then
+ddr_param_offset=200
+else
+ddr_param_offset=96
+fi
+ 
+LINE_NUM=$(cat ./$3|sed -n "/$4/=")
+LINE_NUM=$(echo $LINE_NUM + "1"|bc)
+
+if [ "$5" == "IN_NAND" ]; then
+offset=$ddr_param_offset
+sed -n "${LINE_NUM}p" ./$3|xxd -r -c 32|dd bs=1 count=32 seek=$offset of=$2 conv=notrunc
+offset=$(echo $offset + "32"|bc)
+LINE_NUM=$(echo $LINE_NUM + "1"|bc)
+sed -n "${LINE_NUM}p" ./$3|xxd -r -c 32|dd bs=1 count=32 seek=$offset of=$2 conv=notrunc
+offset=$(echo $offset + "32"|bc)
+LINE_NUM=$(echo $LINE_NUM + "1"|bc)
+sed -n "${LINE_NUM}p" ./$3|xxd -r -c 32|dd bs=1 count=32 seek=$offset of=$2 conv=notrunc
+else
+offset=$(echo "(($(stat -c %s uboot.bin)+$ddr_param_offset))" |bc)
+sed -n "${LINE_NUM}p" ./$3|xxd -r -c 32|dd bs=1 count=32 seek=$offset of=$2 conv=notrunc
+LINE_NUM=$(echo $LINE_NUM + "1"|bc)
+offset=$(echo $offset + "32"|bc)
+sed -n "${LINE_NUM}p" ./$3|xxd -r -c 32|dd bs=1 count=32 seek=$offset of=$2 conv=notrunc
+LINE_NUM=$(echo $LINE_NUM + "1"|bc)
+offset=$(echo $offset + "32"|bc)
+sed -n "${LINE_NUM}p" ./$3|xxd -r -c 32|dd bs=1 count=32 seek=$offset of=$2 conv=notrunc
+fi
+
diff --git a/mt7621_ddr_param.txt b/mt7621_ddr_param.txt
new file mode 100755
index 0000000000000000000000000000000000000000..00db55dd4ee406cc62edf912db0257e20ff7c6ed
--- /dev/null
+++ b/mt7621_ddr_param.txt
@@ -0,0 +1,32 @@
+[DEFAULT_DDR2_512M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x22174441 0x00000000 0xF0748661 0x40001273 0x9F0A0481	
+0x0304692F 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000000 0x07100000
+0x00001B63 0x00002000 0x00004000 0x00006000 0x00000000 0x00000000 0x00000000 0x00000000
+[W9751G6KB_A02_DDR2_1066_512M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x33484584 0x00000000 0xF07486A1 0x50001273 0x9F010481
+0x0304693F 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000010 0x07100000
+0x00001F73 0x00002000 0x00004000 0x00006000 0x00000000 0x00000000 0x00000000 0x00000000
+[DEFAULT_DDR2_1024M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x22174441 0x01000000 0xF0748661 0x40001273 0x9F0F0481	
+0x0304692F 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000000 0x07100000
+0x00001B63 0x00002000 0x00004000 0x00006000 0x00000000 0x00000000 0x00000000 0x00000000
+[W971GG6KB25_DDR2_800_1024M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x22174430 0x01000000 0xF0748661 0x40001273 0x9F0F0481	
+0x0304692F 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000000 0x07100000
+0x00001B63 0x00002000 0x00004000 0x00006000 0x00000000 0x00000000 0x00000000 0x00000000
+[W971GG6KB18_DDR2_1066_1024M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x33484584 0x01000000 0xF07486A1 0x50001273 0x9F070481
+0x0304693F 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000010 0x07100000
+0x00001F73 0x00002000 0x00004000 0x00006000 0x00000000 0x00000000 0x00000000 0x00000000
+[DEFAULT_DDR3_1024M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x44694683 0x01000000 0xF07486A1 0xC287221D 0x9F060481	
+0x03046948 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000210 0x07100000
+0x00001B61 0x00002040 0x00004010 0x00006000 0x0A000000 0x07070000 0x00000000 0x00000000
+[DEFAULT_DDR3_2048M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x44694673 0x01000000 0xF07486A1 0xC287221D 0x9F050481	
+0x03046948 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000220 0x07100000
+0x00001B61 0x00002040 0x00004010 0x00006000 0x0A000000 0x07070000 0x00000000 0x00000000
+[DEFAULT_DDR3_4096M]
+0xAA00AA00 0xAA00AA00 0x00000007 0x44694683 0x01000000 0xF07486A1 0xC287221D 0x9F0F0481	
+0x03046948 0x15602842 0x00008888 0x88888888 0x00000000 0x00000000 0x00000240 0x07100000
+0x00001B61 0x00002040 0x00004010 0x00006000 0x0A000000 0x07070000 0x00000000 0x00000000
diff --git a/mt7621_stage_L2.bin b/mt7621_stage_L2.bin
new file mode 100755
index 0000000000000000000000000000000000000000..f436add8cbf7e13371eba948dfd5858d5d664042
Binary files /dev/null and b/mt7621_stage_L2.bin differ
diff --git a/mt7621_stage_sram.bin b/mt7621_stage_sram.bin
new file mode 100755
index 0000000000000000000000000000000000000000..4cbff0a4e10c18e47b8f49764ab09a70d9ea73c5
Binary files /dev/null and b/mt7621_stage_sram.bin differ
diff --git a/tools/.gitignore b/tools/.gitignore
index cb1e722d4575ec0d329fcdea86ec6b681cbfc53f..f8307fce352ad8e36439805ab90bd106b7fcb6cf 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -23,6 +23,6 @@
 /easylogo/easylogo
 /gdb/gdbcont
 /gdb/gdbsend
-
+mkimage_mediatek
 /lib/
 /common/
diff --git a/tools/Makefile b/tools/Makefile
index 421414bc154b0a596cb5833148f2c19c614d5fa9..e30a541be77b5db5aa673768da09953c48387873 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -48,6 +48,9 @@ HOSTCFLAGS_img2srec.o := -pedantic
 hostprogs-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes
 HOSTCFLAGS_xway-swap-bytes.o := -pedantic
 
+hostprogs-y += mkimage_mediatek
+mkimage_mediatek-objs := mkimage_mediatek.o crc.o lib/crc32.o
+
 hostprogs-y += mkenvimage
 mkenvimage-objs := mkenvimage.o os_support.o lib/crc32.o
 
diff --git a/tools/crc.c b/tools/crc.c
new file mode 100755
index 0000000000000000000000000000000000000000..1454121cb2e6b1f3678a5fdff9573da27dc316e4
--- /dev/null
+++ b/tools/crc.c
@@ -0,0 +1,150 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)crc.c	8.1 (Berkeley) 6/17/93";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+
+#include <stdint.h>
+#include <unistd.h>
+
+
+static const uint32_t crctab[] = {
+	0x0,
+	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
+	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
+	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
+	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
+	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
+	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
+	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
+	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
+	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
+	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
+	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
+	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
+	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
+	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
+	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
+	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
+	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
+	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
+	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
+	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
+	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
+	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
+	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
+	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
+	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
+	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
+	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
+	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
+	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
+	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+/*
+ * Compute a POSIX 1003.2 checksum.  This routine has been broken out so that
+ * other programs can use it.  It takes a file descriptor to read from and
+ * locations to store the crc and the number of bytes read.  It returns 0 on
+ * success and 1 on failure.  Errno is set on failure.
+ */
+uint32_t crc_total = ~0;		/* The crc over a number of files. */
+
+int
+crc(u_char* psrc, uint32_t *cval, int clen)
+{
+	uint32_t lcrc;
+	int nr;
+	off_t len;
+	u_char *pbuf;
+	int total_len = clen;
+#define	COMPUTE(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
+
+	lcrc = len = 0;
+	crc_total = ~crc_total;	
+
+	pbuf = psrc;
+	while (total_len>0)
+	{	
+		if (total_len >= 64)
+			nr = 64;
+		else
+			nr = total_len;
+		total_len-=nr;
+		for (len += nr; nr--; ++pbuf) {
+			COMPUTE(lcrc, *pbuf);
+			COMPUTE(crc_total, *pbuf);
+		}
+	}	
+
+	
+	/* Include the length of the file. */
+	for (; len != 0; len >>= 8) {
+		COMPUTE(lcrc, len & 0xff);
+		COMPUTE(crc_total, len & 0xff);
+	}
+
+	*cval = ~lcrc;
+	crc_total = ~crc_total;
+	return (0);
+}
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index d27f57e251f654d4b204e1a7f3cfc8f9e875e7f7..531aebcffda4aa9642683375a267eadd88d0be2b 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -25,6 +25,7 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <dirent.h>
 
 #ifdef MTD_OLD
 # include <stdint.h>
@@ -34,6 +35,8 @@
 # include <mtd/mtd-user.h>
 #endif
 
+#include <mtd/ubi-user.h>
+
 #include "fw_env.h"
 
 struct env_opts default_opts = {
@@ -57,6 +60,7 @@ struct envdev_s {
 	ulong erase_size;		/* device erase size */
 	ulong env_sectors;		/* number of environment sectors */
 	uint8_t mtd_type;		/* type of the MTD device */
+	int is_ubi;			/* set if we use UBI volume */
 };
 
 static struct envdev_s envdevices[2] =
@@ -75,6 +79,7 @@ static int dev_current;
 #define DEVESIZE(i)   envdevices[(i)].erase_size
 #define ENVSECTORS(i) envdevices[(i)].env_sectors
 #define DEVTYPE(i)    envdevices[(i)].mtd_type
+#define IS_UBI(i)     envdevices[(i)].is_ubi
 
 #define CUR_ENVSIZE ENVSIZE(dev_current)
 
@@ -121,6 +126,229 @@ static unsigned char obsolete_flag = 0;
 #define DEFAULT_ENV_INSTANCE_STATIC
 #include <env_default.h>
 
+#define UBI_DEV_START "/dev/ubi"
+#define UBI_SYSFS "/sys/class/ubi"
+#define UBI_VOL_NAME_PATT "ubi%d_%d"
+
+static int is_ubi_devname(const char *devname)
+{
+	return !strncmp(devname, UBI_DEV_START, sizeof(UBI_DEV_START) - 1);
+}
+
+static int ubi_check_volume_sysfs_name(const char *volume_sysfs_name,
+				const char *volname)
+{
+	char path[256];
+	FILE *file;
+	char *name;
+	int ret;
+
+	strcpy(path, UBI_SYSFS "/");
+	strcat(path, volume_sysfs_name);
+	strcat(path, "/name");
+
+	file = fopen(path, "r");
+	if (!file)
+		return -1;
+
+	ret = fscanf(file, "%ms", &name);
+	fclose(file);
+	if (ret <= 0 || !name) {
+		fprintf(stderr,
+			"Failed to read from file %s, ret = %d, name = %s\n",
+			path, ret, name);
+		return -1;
+	}
+
+	if (!strcmp(name, volname)) {
+		free(name);
+		return 0;
+	}
+	free(name);
+
+	return -1;
+}
+
+static int ubi_get_volnum_by_name(int devnum, const char *volname)
+{
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	int ret;
+	int tmp_devnum;
+	int volnum;
+
+	sysfs_ubi = opendir(UBI_SYSFS);
+	if (!sysfs_ubi)
+		return -1;
+
+#ifdef DEBUG
+	fprintf(stderr, "Looking for volume name \"%s\"\n", volname);
+#endif
+
+	while (1) {
+		dirent = readdir(sysfs_ubi);
+		if (!dirent)
+			return -1;
+
+		ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT,
+				&tmp_devnum, &volnum);
+		if (ret == 2 && devnum == tmp_devnum) {
+			if (ubi_check_volume_sysfs_name(dirent->d_name,
+								volname) == 0)
+				return volnum;
+		}
+	}
+
+	return -1;
+}
+
+static int ubi_get_devnum_by_devname(const char *devname)
+{
+	int devnum;
+	int ret;
+
+	ret = sscanf(devname + sizeof(UBI_DEV_START) - 1, "%d", &devnum);
+	if (ret != 1)
+		return -1;
+
+	return devnum;
+}
+
+static const char *ubi_get_volume_devname(const char *devname,
+					const char *volname)
+{
+	char *volume_devname;
+	int volnum;
+	int devnum;
+	int ret;
+
+	devnum = ubi_get_devnum_by_devname(devname);
+	if (devnum < 0)
+		return NULL;
+
+	volnum = ubi_get_volnum_by_name(devnum, volname);
+	if (volnum < 0)
+		return NULL;
+
+	ret = asprintf(&volume_devname, "%s_%d", devname, volnum);
+	if (ret < 0)
+		return NULL;
+
+#ifdef DEBUG
+	fprintf(stderr, "Found ubi volume \"%s:%s\" -> %s\n",
+		devname, volname, volume_devname);
+#endif
+
+	return volume_devname;
+}
+
+static void ubi_check_dev(unsigned int dev_id)
+{
+	char *devname = (char *) DEVNAME(dev_id);
+	char *pname;
+	const char *volname = NULL;
+	const char *volume_devname;
+
+	if (!is_ubi_devname(DEVNAME(dev_id)))
+		return;
+
+	IS_UBI(dev_id) = 1;
+
+	for (pname = devname; *pname != '\0'; pname++) {
+		if (*pname == ':') {
+			*pname = '\0';
+			volname = pname + 1;
+			break;
+		}
+	}
+
+	if (volname) {
+		/* Let's find real volume device name */
+		volume_devname = ubi_get_volume_devname(devname,
+							volname);
+		if (!volume_devname) {
+			fprintf(stderr, "Didn't found ubi volume \"%s\"\n",
+				volname);
+			return;
+		}
+
+		free(devname);
+		DEVNAME(dev_id) = volume_devname;
+	}
+}
+
+static int ubi_update_start(int fd, int64_t bytes)
+{
+	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
+		return -1;
+	return 0;
+}
+
+static int ubi_read(int fd, void *buf, size_t count)
+{
+	ssize_t ret;
+
+	while (count > 0) {
+		ret = read(fd, buf, count);
+		if (ret > 0) {
+			count -= ret;
+			buf += ret;
+
+			continue;
+		}
+
+		if (ret == 0) {
+			/*
+			 * Happens in case of too short volume data size. If we
+			 * return error status we will fail it will be treated
+			 * as UBI device error.
+			 *
+			 * Leave catching this error to CRC check.
+			 */
+			fprintf(stderr, "Warning: end of data on ubi volume\n");
+			return 0;
+		} else if (errno == EBADF) {
+			/*
+			 * Happens in case of corrupted volume. The same as
+			 * above, we cannot return error now, as we will still
+			 * be able to successfully write environment later.
+			 */
+			fprintf(stderr, "Warning: corrupted volume?\n");
+			return 0;
+		} else if (errno == EINTR) {
+			continue;
+		}
+
+		fprintf(stderr, "Cannot read %u bytes from ubi volume, %s\n",
+			(unsigned int) count, strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+static int ubi_write(int fd, const void *buf, size_t count)
+{
+	ssize_t ret;
+
+	while (count > 0) {
+		ret = write(fd, buf, count);
+		if (ret <= 0) {
+			if (ret < 0 && errno == EINTR)
+				continue;
+
+			fprintf(stderr, "Cannot write %u bytes to ubi volume\n",
+				(unsigned int) count);
+			return -1;
+		}
+
+		count -= ret;
+		buf += ret;
+	}
+
+	return 0;
+}
+
 static int flash_io (int mode);
 static int parse_config(struct env_opts *opts);
 
@@ -1009,6 +1237,12 @@ static int flash_write (int fd_current, int fd_target, int dev_target)
 		DEVOFFSET (dev_target), DEVNAME (dev_target));
 #endif
 
+	if (IS_UBI(dev_target)) {
+		if (ubi_update_start(fd_target, CUR_ENVSIZE) < 0)
+			return 0;
+		return ubi_write(fd_target, environment.image, CUR_ENVSIZE);
+	}
+
 	rc = flash_write_buf(dev_target, fd_target, environment.image,
 			      CUR_ENVSIZE, DEVOFFSET(dev_target),
 			      DEVTYPE(dev_target));
@@ -1034,6 +1268,12 @@ static int flash_read (int fd)
 {
 	int rc;
 
+	if (IS_UBI(dev_current)) {
+		DEVTYPE(dev_current) = MTD_ABSENT;
+
+		return ubi_read(fd, environment.image, CUR_ENVSIZE);
+	}
+
 	rc = flash_read_buf(dev_current, fd, environment.image, CUR_ENVSIZE,
 			    DEVOFFSET(dev_current), DEVTYPE(dev_current));
 	if (rc != CUR_ENVSIZE)
@@ -1202,7 +1442,8 @@ int fw_env_open(struct env_opts *opts)
 			   DEVTYPE(!dev_current) == MTD_UBIVOLUME) {
 			environment.flag_scheme = FLAG_INCREMENTAL;
 		} else if (DEVTYPE(dev_current) == MTD_ABSENT &&
-			   DEVTYPE(!dev_current) == MTD_ABSENT) {
+			   DEVTYPE(!dev_current) == MTD_ABSENT &&
+			   IS_UBI(dev_current) == IS_UBI(!dev_current)) {
 			environment.flag_scheme = FLAG_INCREMENTAL;
 		} else {
 			fprintf (stderr, "Incompatible flash types!\n");
@@ -1413,9 +1654,12 @@ static int parse_config(struct env_opts *opts)
 	HaveRedundEnv = 1;
 #endif
 #endif
-	rc = check_device_config(0);
-	if (rc < 0)
-		return rc;
+
+	/* Fills in IS_UBI(), converts DEVNAME() with ubi volume name */
+	ubi_check_dev(0);
+	if (HaveRedundEnv)
+		ubi_check_dev(1);
+
 
 	if (HaveRedundEnv) {
 		rc = check_device_config(1);
diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
index 7916ebdb1f6d1836c49d9374cf4ebfac2bcf0009..e8316051b1bc188af86012f428665fa7ee056a43 100644
--- a/tools/env/fw_env.config
+++ b/tools/env/fw_env.config
@@ -28,3 +28,11 @@
 
 # VFAT example
 #/boot/uboot.env	0x0000          0x4000
+
+# UBI volume
+#/dev/ubi0_0		0x0		0x20000
+#/dev/ubi0_1		0x0		0x20000
+
+# UBI volume by name
+#/dev/ubi0:env		0x0		0x20000
+#/dev/ubi0:env-redund	0x0		0x20000
diff --git a/tools/mediatek.h b/tools/mediatek.h
new file mode 100644
index 0000000000000000000000000000000000000000..de9a85a4392ef0760081eaeac9ef1c8494f3649e
--- /dev/null
+++ b/tools/mediatek.h
@@ -0,0 +1,65 @@
+/*
+ * Automatically generated by make menuconfig: don't edit
+ */
+#define AUTOCONF_INCLUDED
+#define CONFIG_CROSS_COMPILER_PATH "/opt/mips-2012.03/bin/"
+#define ASIC_BOARD 1
+#undef  RT2880_ASIC_BOARD
+#undef  RT3350_ASIC_BOARD
+#undef  RT3052_ASIC_BOARD
+#undef  RT3352_ASIC_BOARD
+#undef  RT3883_ASIC_BOARD
+#undef  RT5350_ASIC_BOARD
+#undef  RT6855A_ASIC_BOARD
+#undef  MT7620_ASIC_BOARD
+#define MT7621_ASIC_BOARD 1
+#undef  MT7628_ASIC_BOARD
+#define MT7621_MP 1
+#define MT7621_USE_GE1 1
+#undef  MT7621_USE_GE2
+#undef  GE_MII_FORCE_100
+#undef  GE_RVMII_FORCE_100
+#undef  GE_MII_AN
+#define GE_RGMII_FORCE_1000 1
+#undef  GE_RGMII_AN
+#define MAC_TO_MT7530_MODE 1
+#define GPIOx_RESET_MODE 1
+#define ON_BOARD_NAND_FLASH_COMPONENT 1
+#undef  ON_BOARD_SPI_FLASH_COMPONENT
+#define ON_BOARD_NAND_BOOTSTRAP 1
+#define ON_BOARD_DDR3 1
+#define ON_BOARD_DDR_WIDTH_16 1
+#define ON_BOARD_16BIT_DRAM_BUS 1
+#undef  ON_BOARD_512M_DRAM_COMPONENT
+#undef  ON_BOARD_1024M_DRAM_COMPONENT
+#define ON_BOARD_2048M_DRAM_COMPONENT 1
+#undef  ON_BOARD_4096M_DRAM_COMPONENT
+#define MT7621_DDR_1200MHZ 1
+#undef  MT7621_DDR_1066MHZ
+#undef  MT7621_DDR_800MHZ
+#undef  MT7621_DDR_400MHZ
+#define MT7621_DDR_SPEED 0x11
+#define MT7621_CPU_880MHZ 1
+#undef  MT7621_CPU_875MHZ
+#undef  MT7621_CPU_800MHZ
+#undef  MT7621_CPU_500MHZ
+#undef  MT7621_CPU_50MHZ
+#define MT7621_CPU_FREQUENCY 0x370
+#define PDMA_NEW 1
+#define RX_SCATTER_GATTER_DMA 1
+#define UBOOT_RAM 1
+#undef  DUAL_IMAGE_SUPPORT
+#define RALINK_DUAL_CORE_FUN 1
+#define RALINK_DUAL_VPE_FUN 1
+#undef  LAN_WAN_PARTITION
+#define DDR_ACT_SETTING 1
+#undef  DEFAULT_DDR3_1024M
+#define DEFAULT_DDR3_2048M 1
+#undef  DEFAULT_DDR3_4096M
+#undef  DEFAULT_DDR2_512M
+#undef  W9751G6KB_A02_DDR2_1066_512M
+#undef  DEFAULT_DDR2_1024M
+#undef  W971GG6KB25_DDR2_800_1024M
+#undef  W971GG6KB18_DDR2_1066_1024M
+#define DDR_CHIP "DEFAULT_DDR3_2048M"
+#define TEXT_BASE 0xA0200000
diff --git a/tools/mediatek_image.h b/tools/mediatek_image.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1eb60f6af086f8b852de87347bf2accdb086ce1
--- /dev/null
+++ b/tools/mediatek_image.h
@@ -0,0 +1,269 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __IMAGE_H__
+#define __IMAGE_H__
+
+#include "mediatek.h"
+
+/*
+ * Operating System Codes
+ */
+#define IH_OS_INVALID		0	/* Invalid OS	*/
+#define IH_OS_OPENBSD		1	/* OpenBSD	*/
+#define IH_OS_NETBSD		2	/* NetBSD	*/
+#define IH_OS_FREEBSD		3	/* FreeBSD	*/
+#define IH_OS_4_4BSD		4	/* 4.4BSD	*/
+#define IH_OS_LINUX		5	/* Linux	*/
+#define IH_OS_SVR4		6	/* SVR4		*/
+#define IH_OS_ESIX		7	/* Esix		*/
+#define IH_OS_SOLARIS		8	/* Solaris	*/
+#define IH_OS_IRIX		9	/* Irix		*/
+#define IH_OS_SCO		10	/* SCO		*/
+#define IH_OS_DELL		11	/* Dell		*/
+#define IH_OS_NCR		12	/* NCR		*/
+#define IH_OS_LYNXOS		13	/* LynxOS	*/
+#define IH_OS_VXWORKS		14	/* VxWorks	*/
+#define IH_OS_PSOS		15	/* pSOS		*/
+#define IH_OS_QNX		16	/* QNX		*/
+#define IH_OS_U_BOOT		17	/* Firmware	*/
+#define IH_OS_RTEMS		18	/* RTEMS	*/
+#define IH_OS_ARTOS		19	/* ARTOS	*/
+#define IH_OS_UNITY		20	/* Unity OS	*/
+
+/*
+ * CPU Architecture Codes (supported by Linux)
+ */
+#define IH_CPU_INVALID		0	/* Invalid CPU	*/
+#define IH_CPU_ALPHA		1	/* Alpha	*/
+#define IH_CPU_ARM		2	/* ARM		*/
+#define IH_CPU_I386		3	/* Intel x86	*/
+#define IH_CPU_IA64		4	/* IA64		*/
+#define IH_CPU_MIPS		5	/* MIPS		*/
+#define IH_CPU_MIPS64		6	/* MIPS	 64 Bit */
+#define IH_CPU_PPC		7	/* PowerPC	*/
+#define IH_CPU_S390		8	/* IBM S390	*/
+#define IH_CPU_SH		9	/* SuperH	*/
+#define IH_CPU_SPARC		10	/* Sparc	*/
+#define IH_CPU_SPARC64		11	/* Sparc 64 Bit */
+#define IH_CPU_M68K		12	/* M68K		*/
+#define IH_CPU_NIOS		13	/* Nios-32	*/
+#define IH_CPU_MICROBLAZE	14	/* MicroBlaze   */
+#define IH_CPU_NIOS2		15	/* Nios-II	*/
+
+/*
+ * Image Types
+ *
+ * "Standalone Programs" are directly runnable in the environment
+ *	provided by U-Boot; it is expected that (if they behave
+ *	well) you can continue to work in U-Boot after return from
+ *	the Standalone Program.
+ * "OS Kernel Images" are usually images of some Embedded OS which
+ *	will take over control completely. Usually these programs
+ *	will install their own set of exception handlers, device
+ *	drivers, set up the MMU, etc. - this means, that you cannot
+ *	expect to re-enter U-Boot except by resetting the CPU.
+ * "RAMDisk Images" are more or less just data blocks, and their
+ *	parameters (address, size) are passed to an OS kernel that is
+ *	being started.
+ * "Multi-File Images" contain several images, typically an OS
+ *	(Linux) kernel image and one or more data images like
+ *	RAMDisks. This construct is useful for instance when you want
+ *	to boot over the network using BOOTP etc., where the boot
+ *	server provides just a single image file, but you want to get
+ *	for instance an OS kernel and a RAMDisk image.
+ *
+ *	"Multi-File Images" start with a list of image sizes, each
+ *	image size (in bytes) specified by an "uint32_t" in network
+ *	byte order. This list is terminated by an "(uint32_t)0".
+ *	Immediately after the terminating 0 follow the images, one by
+ *	one, all aligned on "uint32_t" boundaries (size rounded up to
+ *	a multiple of 4 bytes - except for the last file).
+ *
+ * "Firmware Images" are binary images containing firmware (like
+ *	U-Boot or FPGA images) which usually will be programmed to
+ *	flash memory.
+ *
+ * "Script files" are command sequences that will be executed by
+ *	U-Boot's command interpreter; this feature is especially
+ *	useful when you configure U-Boot to use a real shell (hush)
+ *	as command interpreter (=> Shell Scripts).
+ */
+
+#define IH_TYPE_INVALID		0	/* Invalid Image		*/
+#define IH_TYPE_STANDALONE	1	/* Standalone Program		*/
+#define IH_TYPE_KERNEL		2	/* OS Kernel Image		*/
+#define IH_TYPE_RAMDISK		3	/* RAMDisk Image		*/
+#define IH_TYPE_MULTI		4	/* Multi-File Image		*/
+#define IH_TYPE_FIRMWARE	5	/* Firmware Image		*/
+#define IH_TYPE_SCRIPT		6	/* Script file			*/
+#define IH_TYPE_FILESYSTEM	7	/* Filesystem Image (any type)	*/
+
+/*
+ * Compression Types
+ */
+#define IH_COMP_NONE		0	/*  No	 Compression Used	*/
+#define IH_COMP_GZIP		1	/* gzip	 Compression Used	*/
+#define IH_COMP_BZIP2		2	/* bzip2 Compression Used	*/
+#define IH_COMP_LZMA		3	/* lzma  Compression Used	*/
+#define IH_COMP_XZ		5	/* xz    Compression Used	*/
+
+#define IH_MAGIC	0x27051956	/* Image Magic Number		*/
+
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+#if defined (ON_BOARD_NAND_FLASH_COMPONENT)
+#define IH_NMLEN		(16-4)
+#else
+#define IH_NMLEN        (16)
+#endif
+#elif defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) || defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+#define IH_NMLEN		(16-4*2)	/* Image Name Length		*/
+#elif defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+#define IH_NMLEN		(16-4*4)
+#else
+#define IH_NMLEN		16	/* Image Name Length		*/
+#endif
+/*
+ * all data in network byte order (aka natural aka bigendian)
+ */
+
+
+typedef struct dram_header {
+#if defined(MT7620_ASIC_BOARD) || defined(MT7620_FPGA_BOARD) || defined(MT7628_ASIC_BOARD) || defined(MT7628_FPGA_BOARD)
+	uint16_t	ddr_self_refresh;
+	uint16_t	ddr_cfg11;
+	uint32_t	ddr_cfg10;
+#endif
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+	uint32_t	dram_pad_setting;
+	uint32_t	ddr_cfg2;
+	uint32_t	ddr_cfg3;
+	uint32_t	ddr_cfg4;
+#endif
+	uint8_t		dram_parm;	/* DRAM setting */
+	union{
+	uint8_t		dram_magic;	/* Magic number of DRAM setting (0x5a) */
+	struct {
+		uint8_t	cpu_pll_magic_l:4;	
+		uint8_t	dram_magic_h:4;
+		}u;
+	};
+	uint16_t	cpu_pll_cfg;
+#if defined(RT3052_ASIC_BOARD) || defined(RT3052_FPGA_BOARD) ||\
+	defined(RT3352_ASIC_BOARD) || defined(RT3352_FPGA_BOARD) ||\
+	defined(RT5350_ASIC_BOARD) || defined(RT5350_FPGA_BOARD) ||\
+	defined(RT3883_ASIC_BOARD) || defined(RT3883_FPGA_BOARD)
+	uint16_t	magic_lh;       /* low half word of magic number 0x5244 */
+	uint16_t	magic_hh;       /* high half word of magic number 0x4D41 */
+	union {
+	    struct {
+		uint8_t syscfg1;
+		uint8_t ddr_cfg3;
+		uint16_t resv1;
+		uint32_t resv2;
+	    }ddr;
+	    
+	    struct {
+		uint32_t sdram_cfg0;
+		uint32_t sdram_cfg1;
+	    }sdr;
+	};
+#else
+	uint8_t		magic;       /* magic number 0x68 */
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+	uint8_t		rsvd0[3];
+#else
+	uint8_t		reservd;
+	uint16_t	syscfg1_ddrcfg3_odt;
+#endif	
+	union {
+		struct {
+		uint32_t ddr_cfg0;
+		uint32_t ddr_cfg1;
+		}ddr;		
+		struct {
+		uint32_t sdram_cfg0;
+		uint32_t sdram_cfg1;
+		}sdr;
+	};
+#endif
+} dram_header_t __attribute__ ((packed));
+
+typedef struct  nand_badblock_info1_type {
+	uint32_t	ecc_bits	:	3;
+	uint32_t	rsvd		:	5;
+	uint32_t	ecc_offset	:	8;
+	uint32_t	bad_block_offser	:	8;
+	uint32_t	checksum	:	8;
+} nand_badblock_info1_t __attribute__ ((packed));
+
+typedef struct  nand_info_1_type {	
+	uint32_t	pagesize 	: 2;
+	uint32_t	rsvd0		: 2;	
+	uint32_t	addr_cycle 	: 2;
+	uint32_t	rsvd1		: 2;	
+	uint32_t	spare_size	: 2;
+	uint32_t	rsvd2		: 2;	
+	uint32_t	total_size	: 3;
+	uint32_t	rsvd3		: 1;
+	uint32_t	block_size	: 2;
+	uint32_t	rsvd4		: 2;	
+	uint32_t	magic_id	: 12;	
+} nand_info_1_t __attribute__ ((packed));
+
+	
+typedef struct nand_header {
+	uint32_t			nand_ac_timing;
+	uint32_t				ih_stage_offset;			/* stage1 offset */
+	uint32_t				ih_bootloader_offset;		/* bootloader offset */
+	union 
+	{
+	nand_info_1_t			nand_info_1;
+		uint32_t				nand_info_1_data;
+	};
+	//nand_badblock_info1_t	nand_badblock_info1;
+	uint32_t				crc;
+} nand_header_t __attribute__ ((packed));
+
+typedef struct image_header {
+	uint32_t	ih_magic;	/* Image Header Magic Number	*/
+	uint32_t	ih_hcrc;	/* Image Header CRC Checksum	*/
+	uint32_t	ih_time;	/* Image Creation Timestamp	*/
+	uint32_t	ih_size;	/* Image Data Size		*/
+	uint32_t	ih_load;	/* Data	 Load  Address		*/
+	uint32_t	ih_ep;		/* Entry Point Address		*/
+	uint32_t	ih_dcrc;	/* Image Data CRC Checksum	*/
+	uint8_t		ih_os;		/* Operating System		*/
+	uint8_t		ih_arch;	/* CPU architecture		*/
+	uint8_t		ih_type;	/* Image Type			*/
+	uint8_t		ih_comp;	/* Compression Type		*/
+	uint8_t		ih_name[IH_NMLEN];	/* Image Name		*/
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+	nand_header_t	ih_nand;
+#else
+	dram_header_t   ih_dram;
+#endif	
+} image_header_t __attribute__((packed));
+
+
+#endif	/* __IMAGE_H__ */
diff --git a/tools/mkimage_mediatek.c b/tools/mkimage_mediatek.c
new file mode 100644
index 0000000000000000000000000000000000000000..b61de02f551988e94fb8339e857518223d0e9f6b
--- /dev/null
+++ b/tools/mkimage_mediatek.c
@@ -0,0 +1,1017 @@
+/*
+ * (C) Copyright 2000-2004
+ * DENX Software Engineering
+ * Wolfgang Denk, wd@denx.de
+ * All rights reserved.
+ *
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef __WIN32__
+#include <netinet/in.h>		/* for host / network byte order conversions	*/
+#endif
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__)
+#include <inttypes.h>
+#endif
+
+#ifdef __WIN32__
+typedef unsigned int __u32;
+
+#define SWAP_LONG(x) \
+	((__u32)( \
+		(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
+		(((__u32)(x) & (__u32)0x0000ff00UL) <<  8) | \
+		(((__u32)(x) & (__u32)0x00ff0000UL) >>  8) | \
+		(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
+typedef		unsigned char	uint8_t;
+typedef		unsigned short	uint16_t;
+typedef		unsigned int	uint32_t;
+
+#define     ntohl(a)	SWAP_LONG(a)
+#define     htonl(a)	SWAP_LONG(a)
+#endif	/* __WIN32__ */
+
+#ifndef	O_BINARY		/* should be define'd on __WIN32__ */
+#define O_BINARY	0
+#endif
+
+#include "mediatek_image.h"
+#include "mediatek.h"
+
+extern int errno;
+
+#ifndef MAP_FAILED
+#define MAP_FAILED (-1)
+#endif
+
+char *cmdname;
+
+extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len);
+
+typedef struct table_entry {
+	int	val;		/* as defined in image.h	*/
+	char	*sname;		/* short (input) name		*/
+	char	*lname;		/* long (output) name		*/
+} table_entry_t;
+
+table_entry_t arch_name[] = {
+    {	IH_CPU_INVALID,		NULL,		"Invalid CPU",	},
+    {	IH_CPU_ALPHA,		"alpha",	"Alpha",	},
+    {	IH_CPU_ARM,		"arm",		"ARM",		},
+    {	IH_CPU_I386,		"x86",		"Intel x86",	},
+    {	IH_CPU_IA64,		"ia64",		"IA64",		},
+    {	IH_CPU_M68K,		"m68k",		"MC68000",	},
+    {	IH_CPU_MICROBLAZE,	"microblaze",	"MicroBlaze",	},
+    {	IH_CPU_MIPS,		"mips",		"MIPS",		},
+    {	IH_CPU_MIPS64,		"mips64",	"MIPS 64 Bit",	},
+    {	IH_CPU_PPC,		"ppc",		"PowerPC",	},
+    {	IH_CPU_S390,		"s390",		"IBM S390",	},
+    {	IH_CPU_SH,		"sh",		"SuperH",	},
+    {	IH_CPU_SPARC,		"sparc",	"SPARC",	},
+    {	IH_CPU_SPARC64,		"sparc64",	"SPARC 64 Bit",	},
+    {	-1,			"",		"",		},
+};
+
+table_entry_t os_name[] = {
+    {	IH_OS_INVALID,	NULL,		"Invalid OS",		},
+    {	IH_OS_4_4BSD,	"4_4bsd",	"4_4BSD",		},
+    {	IH_OS_ARTOS,	"artos",	"ARTOS",		},
+    {	IH_OS_DELL,	"dell",		"Dell",			},
+    {	IH_OS_ESIX,	"esix",		"Esix",			},
+    {	IH_OS_FREEBSD,	"freebsd",	"FreeBSD",		},
+    {	IH_OS_IRIX,	"irix",		"Irix",			},
+    {	IH_OS_LINUX,	"linux",	"Linux",		},
+    {	IH_OS_LYNXOS,	"lynxos",	"LynxOS",		},
+    {	IH_OS_NCR,	"ncr",		"NCR",			},
+    {	IH_OS_NETBSD,	"netbsd",	"NetBSD",		},
+    {	IH_OS_OPENBSD,	"openbsd",	"OpenBSD",		},
+    {	IH_OS_PSOS,	"psos",		"pSOS",			},
+    {	IH_OS_QNX,	"qnx",		"QNX",			},
+    {	IH_OS_RTEMS,	"rtems",	"RTEMS",		},
+    {	IH_OS_SCO,	"sco",		"SCO",			},
+    {	IH_OS_SOLARIS,	"solaris",	"Solaris",		},
+    {	IH_OS_SVR4,	"svr4",		"SVR4",			},
+    {	IH_OS_U_BOOT,	"u-boot",	"U-Boot",		},
+    {	IH_OS_VXWORKS,	"vxworks",	"VxWorks",		},
+    {	-1,		"",		"",			},
+};
+
+table_entry_t type_name[] = {
+    {	IH_TYPE_INVALID,    NULL,	  "Invalid Image",	},
+    {	IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image",	},
+    {	IH_TYPE_FIRMWARE,   "firmware",	  "Firmware",		},
+    {	IH_TYPE_KERNEL,	    "kernel",	  "Kernel Image",	},
+    {	IH_TYPE_MULTI,	    "multi",	  "Multi-File Image",	},
+    {	IH_TYPE_RAMDISK,    "ramdisk",	  "RAMDisk Image",	},
+    {	IH_TYPE_SCRIPT,     "script",	  "Script",		},
+    {	IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
+    {	-1,		    "",		  "",			},
+};
+
+table_entry_t comp_name[] = {
+    {	IH_COMP_NONE,	"none",		"uncompressed",		},
+    {	IH_COMP_BZIP2,	"bzip2",	"bzip2 compressed",	},
+    {	IH_COMP_GZIP,	"gzip",		"gzip compressed",	},
+    {	IH_COMP_LZMA,	"lzma",		"lzma compressed",	},
+    {	IH_COMP_XZ,	"xz",		"xz compressed",	},
+    {	-1,		"",		"",			},
+};
+
+static	void	copy_file (int, const char *, int);
+static	void	usage	(void);
+static	void	print_header (image_header_t *);
+static	void	print_type (image_header_t *);
+static	char	*put_table_entry (table_entry_t *, char *, int);
+static	char	*put_arch (int);
+static	char	*put_type (int);
+static	char	*put_os   (int);
+static	char	*put_comp (int);
+static	int	get_table_entry (table_entry_t *, char *, char *);
+static	int	get_arch(char *);
+static	int	get_comp(char *);
+static	int	get_os  (char *);
+static	int	get_type(char *);
+
+
+char	*datafile;
+char	*imagefile;
+
+int dflag    = 0;
+int eflag    = 0;
+int lflag    = 0;
+int vflag    = 0;
+int xflag    = 0;
+int opt_os   = IH_OS_LINUX;
+int opt_arch = IH_CPU_PPC;
+int opt_type = IH_TYPE_KERNEL;
+int opt_comp = IH_COMP_GZIP;
+
+image_header_t header;
+image_header_t *hdr = &header;
+
+int
+main (int argc, char **argv)
+{
+	int ifd;
+	uint32_t checksum;
+	uint32_t addr;
+	uint32_t ep;
+	struct stat sbuf;
+	unsigned char *ptr;
+	char *name = "";
+	char *dram_name = "";
+	uint32_t dram_type;
+	uint32_t dram_total_width;
+	uint32_t dram_size;
+	uint32_t dram_width;
+	uint32_t dram_cfg0;
+	uint32_t dram_cfg1;
+	uint16_t cpu_pll;
+	uint32_t stage1_start, bootloader_start;
+	cmdname = *argv;
+
+	addr = ep = 0;
+
+	while (--argc > 0 && **++argv == '-') {
+		while (*++*argv) {
+			switch (**argv) {
+			case 'l':
+				lflag = 1;
+				break;
+			case 'A':
+				if ((--argc <= 0) ||
+				    (opt_arch = get_arch(*++argv)) < 0)
+					usage ();
+				goto NXTARG;
+			case 'C':
+				if ((--argc <= 0) ||
+				    (opt_comp = get_comp(*++argv)) < 0)
+					usage ();
+				goto NXTARG;
+			case 'O':
+				if ((--argc <= 0) ||
+				    (opt_os = get_os(*++argv)) < 0)
+					usage ();
+				goto NXTARG;
+			case 'T':
+				if ((--argc <= 0) ||
+				    (opt_type = get_type(*++argv)) < 0)
+					usage ();
+				goto NXTARG;
+
+			case 'a':
+				if (--argc <= 0)
+					usage ();
+				addr = strtoul (*++argv, (char **)&ptr, 16);
+				if (*ptr) {
+					fprintf (stderr,
+						"%s: invalid load address %s\n",
+						cmdname, *argv);
+					exit (EXIT_FAILURE);
+				}
+				goto NXTARG;
+			case 'd':
+				if (--argc <= 0)
+					usage ();
+				datafile = *++argv;
+				dflag = 1;
+				goto NXTARG;
+			case 'e':
+				if (--argc <= 0)
+					usage ();
+				ep = strtoul (*++argv, (char **)&ptr, 16);
+				if (*ptr) {
+					fprintf (stderr,
+						"%s: invalid entry point %s\n",
+						cmdname, *argv);
+					exit (EXIT_FAILURE);
+				}
+				eflag = 1;
+				goto NXTARG;
+			case 'r':
+				if (--argc <= 0)
+					usage ();
+				dram_name=*++argv;
+				if(strncasecmp(dram_name,"sdr",3)==0) {
+				    dram_type=0;
+				}else if(strncasecmp(dram_name,"ddr",3)==0) {
+				    dram_type=1;
+				}else {
+				    if (*ptr) {
+					fprintf (stderr,
+						"%s: invalid dram type %s\n",
+						cmdname, *argv);
+					exit (EXIT_FAILURE);
+				    }
+				}
+				goto NXTARG;
+			case 's':
+				if (--argc <= 0)
+					usage ();
+				dram_total_width = strtoul (*++argv, (char **)&ptr, 10);
+				switch(dram_total_width) {
+				case 16:
+				    dram_total_width=0;
+				    break;
+				case 32:
+				    dram_total_width=1;
+				    break;
+				default:
+				    if (*ptr) {
+					fprintf (stderr,
+						"%s: invalid dram total width %s\n",
+						cmdname, *argv);
+					exit (EXIT_FAILURE);
+				    }
+				}
+				goto NXTARG;
+			case 't':
+				if (--argc <= 0)
+					usage ();
+				dram_size = strtoul (*++argv, (char **)&ptr, 10);
+				switch(dram_size) {
+				case 2:
+				    dram_size=0;
+				    break;
+				case 8:
+				    dram_size=1;
+				    break;
+				case 16:
+				    dram_size=2;
+				    break;
+				case 32:
+				    dram_size=3;
+				    break;
+				case 64:
+				    dram_size=4;
+				    break;
+				case 128:
+				    dram_size=5;
+				    break;
+				case 256:
+				    dram_size=6;
+				    break;
+				default:
+				    if (*ptr) {
+					fprintf (stderr,
+						"%s: invalid dram size%s\n",
+						cmdname, *argv);
+					exit (EXIT_FAILURE);
+				    }
+				}
+				goto NXTARG;
+			case 'u':
+				if (--argc <= 0)
+					usage ();
+				dram_width = strtoul (*++argv, (char **)&ptr, 10);
+				switch(dram_width) {
+				case 16:
+				    dram_width=0;
+				    break;
+				case 32:
+				    dram_width=1;
+				    break;
+				default:
+				    if (*ptr) {
+					fprintf (stderr,
+						"%s: invalid dram width %s\n",
+						cmdname, *argv);
+					exit (EXIT_FAILURE);
+				    }
+				}
+				goto NXTARG;
+			case 'n':
+				if (--argc <= 0)
+					usage ();
+				name = *++argv;
+				goto NXTARG;
+			case 'v':
+				vflag++;
+				break;
+			case 'x':
+				xflag++;
+				break;
+			case 'y':
+				if (--argc <= 0)
+					usage ();
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+				stage1_start = strtoul (*++argv, (char **)&ptr, 16);
+#else					
+				dram_cfg0 = strtoul (*++argv, (char **)&ptr, 16);
+				if (*ptr) {
+				    fprintf (stderr,
+					    "%s: invalid dram parameter 0 %s\n",
+					    cmdname, *argv);
+				    exit (EXIT_FAILURE);
+				}
+#endif
+				goto NXTARG;
+			case 'z':
+				if (--argc <= 0)
+					usage ();
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+				bootloader_start = strtoul (*++argv, (char **)&ptr, 16);
+#else				
+				dram_cfg1 = strtoul (*++argv, (char **)&ptr, 16);
+				if (*ptr) {
+				    fprintf (stderr,
+					    "%s: invalid dram parameter 1 %s\n",
+					    cmdname, *argv);
+				    exit (EXIT_FAILURE);
+				}
+#endif
+				goto NXTARG;
+			case 'w':
+				if (--argc <= 0)
+					usage ();
+				cpu_pll = strtoul (*++argv, (char **)&ptr, 16);
+				goto NXTARG;
+			default:
+				usage ();
+			}
+		}
+NXTARG:		;
+	}
+
+	if ((argc != 1) || ((lflag ^ dflag) == 0))
+		usage();
+
+	if (!eflag) {
+		ep = addr;
+		/* If XIP, entry point must be after the U-Boot header */
+		if (xflag)
+			ep += sizeof(image_header_t);
+	}
+
+	/*
+	 * If XIP, ensure the entry point is equal to the load address plus
+	 * the size of the U-Boot header.
+	 */
+	if (xflag) {
+		if (ep != addr + sizeof(image_header_t)) {
+			fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %lu\n",
+				cmdname,
+				(unsigned long)sizeof(image_header_t));
+			exit (EXIT_FAILURE);
+		}
+	}
+
+	imagefile = *argv;
+
+	if (lflag) {
+		ifd = open(imagefile, O_RDONLY|O_BINARY);
+	} else {
+		ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
+	}
+
+	if (ifd < 0) {
+		fprintf (stderr, "%s: Can't open %s: %s\n",
+			cmdname, imagefile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	if (lflag) {
+		int len;
+		char *data;
+		/*
+		 * list header information of existing image
+		 */
+		if (fstat(ifd, &sbuf) < 0) {
+			fprintf (stderr, "%s: Can't stat %s: %s\n",
+				cmdname, imagefile, strerror(errno));
+			exit (EXIT_FAILURE);
+		}
+
+		if ((unsigned)sbuf.st_size < sizeof(image_header_t)) {
+			fprintf (stderr,
+				"%s: Bad size: \"%s\" is no valid image\n",
+				cmdname, imagefile);
+			exit (EXIT_FAILURE);
+		}
+
+		ptr = (unsigned char *)mmap(0, sbuf.st_size,
+					    PROT_READ, MAP_SHARED, ifd, 0);
+		if ((caddr_t)ptr == (caddr_t)-1) {
+			fprintf (stderr, "%s: Can't read %s: %s\n",
+				cmdname, imagefile, strerror(errno));
+			exit (EXIT_FAILURE);
+		}
+
+		/*
+		 * create copy of header so that we can blank out the
+		 * checksum field for checking - this can't be done
+		 * on the PROT_READ mapped data.
+		 */
+		memcpy (hdr, ptr, sizeof(image_header_t));
+
+		if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+			fprintf (stderr,
+				"%s: Bad Magic Number: \"%s\" is no valid image\n",
+				cmdname, imagefile);
+			exit (EXIT_FAILURE);
+		}
+
+		data = (char *)hdr;
+		len  = sizeof(image_header_t);
+
+		checksum = ntohl(hdr->ih_hcrc);
+		hdr->ih_hcrc = htonl(0);	/* clear for re-calculation */
+
+		if (crc32 (0, data, len) != checksum) {
+			fprintf (stderr,
+				"*** Warning: \"%s\" has bad header checksum!\n",
+				imagefile);
+		}
+
+		data = (char *)(ptr + sizeof(image_header_t));
+		len  = sbuf.st_size - sizeof(image_header_t) ;
+
+		if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) {
+			fprintf (stderr,
+				"*** Warning: \"%s\" has corrupted data!\n",
+				imagefile);
+		}
+
+		/* for multi-file images we need the data part, too */
+		print_header ((image_header_t *)ptr);
+
+		(void) munmap((void *)ptr, sbuf.st_size);
+		(void) close (ifd);
+
+		exit (EXIT_SUCCESS);
+	}
+
+	/*
+	 * Must be -w then:
+	 *
+	 * write dummy header, to be fixed later
+	 */
+	memset (hdr, 0, sizeof(image_header_t));
+
+	if (write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) {
+		fprintf (stderr, "%s: Write error on %s: %s\n",
+			cmdname, imagefile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	if (opt_type == IH_TYPE_MULTI || opt_type == IH_TYPE_SCRIPT) {
+		char *file = datafile;
+		unsigned long size;
+
+		for (;;) {
+			char *sep = NULL;
+
+			if (file) {
+				if ((sep = strchr(file, ':')) != NULL) {
+					*sep = '\0';
+				}
+
+				if (stat (file, &sbuf) < 0) {
+					fprintf (stderr, "%s: Can't stat %s: %s\n",
+						cmdname, file, strerror(errno));
+					exit (EXIT_FAILURE);
+				}
+				size = htonl(sbuf.st_size);
+			} else {
+				size = 0;
+			}
+
+			if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
+				fprintf (stderr, "%s: Write error on %s: %s\n",
+					cmdname, imagefile, strerror(errno));
+				exit (EXIT_FAILURE);
+			}
+
+			if (!file) {
+				break;
+			}
+
+			if (sep) {
+				*sep = ':';
+				file = sep + 1;
+			} else {
+				file = NULL;
+			}
+		}
+
+		file = datafile;
+
+		for (;;) {
+			char *sep = strchr(file, ':');
+			if (sep) {
+				*sep = '\0';
+				copy_file (ifd, file, 1);
+				*sep++ = ':';
+				file = sep;
+			} else {
+				copy_file (ifd, file, 0);
+				break;
+			}
+		}
+	} else {
+		copy_file (ifd, datafile, 0);
+	}
+
+	/* We're a bit of paranoid */
+#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
+	(void) fdatasync (ifd);
+#else
+	(void) fsync (ifd);
+#endif
+
+	if (fstat(ifd, &sbuf) < 0) {
+		fprintf (stderr, "%s: Can't stat %s: %s\n",
+			cmdname, imagefile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	ptr = (unsigned char *)mmap(0, sbuf.st_size,
+				    PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
+	if (ptr == (unsigned char *)MAP_FAILED) {
+		fprintf (stderr, "%s: Can't map %s: %s\n",
+			cmdname, imagefile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	hdr = (image_header_t *)ptr;
+
+	checksum = crc32 (0,
+			  (const char *)(ptr + sizeof(image_header_t)),
+			  sbuf.st_size - sizeof(image_header_t)
+			 );
+
+	/* Build new header */
+	hdr->ih_magic = htonl(IH_MAGIC);
+	hdr->ih_time  = htonl(sbuf.st_mtime);
+	hdr->ih_size  = htonl(sbuf.st_size - sizeof(image_header_t));
+	hdr->ih_load  = htonl(addr);
+	hdr->ih_ep    = htonl(ep);
+	hdr->ih_dcrc  = htonl(checksum);
+	hdr->ih_os    = opt_os;
+	hdr->ih_arch  = opt_arch;
+	hdr->ih_type  = opt_type;
+	hdr->ih_comp  = opt_comp;
+
+	strncpy((char *)hdr->ih_name, name, IH_NMLEN);
+
+	
+#if defined (MT7621_ASIC_BOARD) || defined(MT7621_FPGA_BOARD)
+#if defined (ON_BOARD_NAND_FLASH_COMPONENT)
+	//memset(&(hdr->ih_nand), 0, sizeof(nand_header_t));	
+	printf("DDRCal Code Offset 	: 0x%08X\n",stage1_start);
+	printf("Uboot Offset 		: 0x%08X\n",bootloader_start);
+	hdr->ih_nand.ih_stage_offset = htonl(stage1_start);
+	hdr->ih_nand.ih_bootloader_offset = htonl(bootloader_start);
+#if defined (ON_BOARD_NAND_HEADER)
+	hdr->ih_nand.nand_info_1.pagesize = NAND_PAGESIZE_INDEX;
+	hdr->ih_nand.nand_info_1.addr_cycle = NAND_ADDRLEN_INDEX;
+	hdr->ih_nand.nand_info_1.spare_size = NAND_SPARESIZE_INDEX;
+	hdr->ih_nand.nand_info_1.total_size = NAND_TOTALSIZE_INDEX;
+	hdr->ih_nand.nand_info_1.block_size = NAND_BLOCKSIZE_INDEX;
+	hdr->ih_nand.nand_info_1.magic_id = 0xDA0;
+	hdr->ih_nand.nand_info_1_data = htonl((unsigned int)(hdr->ih_nand.nand_info_1_data));	
+	hdr->ih_nand.nand_ac_timing = htonl(NAND_ACCTIME);	
+#endif
+#endif	
+#else
+	//if dram_size=2M, that means dram parameters is invalid
+	if(dram_size==0) { 
+	    hdr->ih_dram.dram_magic=0;
+	} else {
+#if defined (RT3352_ASIC_BOARD) || defined(RT3352_FPGA_BOARD) ||\
+		defined (RT3883_ASIC_BOARD) || defined(RT3883_FPGA_BOARD)
+		hdr->ih_dram.dram_magic=0x5A;
+#else
+		hdr->ih_dram.u.dram_magic_h=0x5;
+#endif
+	}
+
+	hdr->ih_dram.dram_parm = (dram_type<<5 | dram_total_width<<4 | dram_size<<1 | dram_width);
+
+	if(dram_cfg0!=0xFF && dram_cfg1!=0xFF) {
+
+#if defined (RT3052_ASIC_BOARD) || defined(RT3052_FPGA_BOARD) ||\
+	defined (RT3352_ASIC_BOARD) || defined(RT3352_FPGA_BOARD) ||\
+	defined (RT5350_ASIC_BOARD) || defined(RT5350_FPGA_BOARD) ||\
+	defined (RT3883_ASIC_BOARD) || defined(RT3883_FPGA_BOARD)
+	    hdr->ih_dram.magic_lh=0x5244;
+	    hdr->ih_dram.magic_hh=0x4D41;
+#else
+		hdr->ih_dram.magic = 0x68;
+#endif		
+	} else {
+#if defined(RT3052_ASIC_BOARD) || defined(RT3052_FPGA_BOARD) ||\
+	defined(RT3352_ASIC_BOARD) || defined(RT3352_FPGA_BOARD) ||\
+	defined(RT5350_ASIC_BOARD) || defined(RT5350_FPGA_BOARD) ||\
+	defined(RT3883_ASIC_BOARD) || defined(RT3883_FPGA_BOARD)
+	    hdr->ih_dram.magic_lh=0;
+	    hdr->ih_dram.magic_hh=0;
+#else
+		hdr->ih_dram.magic = 0x0;
+#endif		
+	    dram_cfg0=0;
+	    dram_cfg1=0;
+	}
+
+#if defined (CPU_PLL_PARAMETERS)
+#if defined (RT6855A_ASIC_BOARD) || defined(RT6855A_FPGA_BOARD)
+#endif
+#if defined (MT7620_ASIC_BOARD) || defined(MT7620_FPGA_BOARD) || defined (MT7628_ASIC_BOARD) || defined(MT7628_FPGA_BOARD)
+#if defined (CPLL_FROM_480MHZ)
+	cpu_pll = ntohs(1<<11);
+#elif defined (CPLL_FROM_XTAL)
+	cpu_pll = ntohs(1<<12);
+#else
+	cpu_pll = ntohs((CPLL_MULTI_RATIO_CFG<<8)|(CPLL_DIV_RATIO_CFG<<6)|(CPLL_SSC_CFG<<0));
+#endif
+#endif
+	if(cpu_pll==0) {
+		hdr->ih_dram.u.cpu_pll_magic_l=0;
+		hdr->ih_dram.cpu_pll_cfg = 0;
+	}else{
+		hdr->ih_dram.u.cpu_pll_magic_l=0xa;
+		hdr->ih_dram.cpu_pll_cfg = cpu_pll;
+	}
+#endif
+
+#if defined (DRAM_PARAMETERS)
+#if defined (RT3052_ASIC_BOARD) || defined(RT3052_FPGA_BOARD) ||\
+	defined (RT3352_ASIC_BOARD) || defined(RT3352_FPGA_BOARD) ||\
+	defined (RT5350_ASIC_BOARD) || defined(RT5350_FPGA_BOARD) ||\
+	defined (RT3883_ASIC_BOARD) || defined(RT3883_FPGA_BOARD)	
+	if(dram_type==0) {//SDR
+	    hdr->ih_dram.sdr.sdram_cfg0 = dram_cfg0;
+	    hdr->ih_dram.sdr.sdram_cfg1 = dram_cfg1;
+	}else { //DDR
+	    hdr->ih_dram.ddr.syscfg1= (dram_cfg0 & 0x3F);
+	    hdr->ih_dram.ddr.ddr_cfg3= (dram_cfg1 & 0x3);
+	}
+#elif defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD) ||\
+	defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) ||\
+        defined (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+	if(dram_type==0) {//SDR
+	    hdr->ih_dram.sdr.sdram_cfg0 = ntohl(dram_cfg0);
+	    hdr->ih_dram.sdr.sdram_cfg1 = ntohl(dram_cfg1);
+	}else { //DDR
+#if defined (RT6855A_ASIC_BOARD) || defined (RT6855A_FPGA_BOARD)
+			hdr->ih_dram.ddr_cfg2 = ntohl(DDR_CFG2_SETTING);
+			hdr->ih_dram.ddr_cfg3 = ntohl(DDR_CFG3_SETTING);
+			hdr->ih_dram.ddr_cfg4 = ntohl(DDR_CFG4_SETTING);
+			hdr->ih_dram.dram_pad_setting = ntohl(DRAM_PAD_SETTING);
+#endif
+			hdr->ih_dram.ddr.ddr_cfg0 = ntohl(dram_cfg0);
+			hdr->ih_dram.ddr.ddr_cfg1 = ntohl(dram_cfg1);
+#if defined (MT7620_ASIC_BOARD) || defined (MT7620_FPGA_BOARD) || (MT7628_ASIC_BOARD) || defined (MT7628_FPGA_BOARD)
+			hdr->ih_dram.ddr_self_refresh = ntohs((((DDR_ODT_SRC&0x0F)<<8)|(DDR_ODT_OFF_DLY&0x0F)<<4)|\
+											(DDR_ODT_ON_DLY&0x0F)); 
+			hdr->ih_dram.syscfg1_ddrcfg3_odt = ntohs((SYSCFG1_ODT&0x0FFFC)|(DDRCFG3_ODT&0x03));   
+			hdr->ih_dram.ddr_cfg11 = ntohs(((DDR_CFG2_CAS&0x7)<<13)|(DDR_CFG11_FFD_EN<<12)|(DDR_CFG11_FCD_EN<<11)|\
+								((DDR_CFG11_FFD&0x0F)<<7)|(DDR_CFG11_FCD&0x7F));
+			hdr->ih_dram.ddr_cfg10 = ntohl(((DDR_CFG3_DS&0x1)<<31)|DDR_CFG10_SETTING&(~((1<<31)|(1<<23)|(1<<15)|(1<<7))));
+#endif
+	}
+#else
+#error "DRAM config in imageheader is not supported"	
+#endif	
+#endif
+#endif /* ! MT7621_ASIC_BOARD or MT7621_FPGA_BOARD */
+
+#if (defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD))
+	//crc((const char *)hdr, &(hdr->ih_nand.crc), sizeof(image_header_t));	
+    crc((const char *)hdr, &checksum, sizeof(image_header_t));
+    hdr->ih_nand.crc = htonl(checksum);
+#endif	
+	checksum = crc32(0,(const char *)hdr,sizeof(image_header_t));
+
+	hdr->ih_hcrc = htonl(checksum);
+
+	print_header (hdr);
+
+	(void) munmap((void *)ptr, sbuf.st_size);
+
+	/* We're a bit of paranoid */
+#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
+	(void) fdatasync (ifd);
+#else
+	(void) fsync (ifd);
+#endif
+
+	if (close(ifd)) {
+		fprintf (stderr, "%s: Write error on %s: %s\n",
+			cmdname, imagefile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	exit (EXIT_SUCCESS);
+}
+
+static void
+copy_file (int ifd, const char *datafile, int pad)
+{
+	int dfd;
+	struct stat sbuf;
+	unsigned char *ptr;
+	int tail;
+	int zero = 0;
+	int offset = 0;
+	int size;
+
+	if (vflag) {
+		fprintf (stderr, "Adding Image %s\n", datafile);
+	}
+
+	if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
+		fprintf (stderr, "%s: Can't open %s: %s\n",
+			cmdname, datafile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	if (fstat(dfd, &sbuf) < 0) {
+		fprintf (stderr, "%s: Can't stat %s: %s\n",
+			cmdname, datafile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	ptr = (unsigned char *)mmap(0, sbuf.st_size,
+				    PROT_READ, MAP_SHARED, dfd, 0);
+	if (ptr == (unsigned char *)MAP_FAILED) {
+		fprintf (stderr, "%s: Can't read %s: %s\n",
+			cmdname, datafile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	if (xflag) {
+		unsigned char *p = NULL;
+		/*
+		 * XIP: do not append the image_header_t at the
+		 * beginning of the file, but consume the space
+		 * reserved for it.
+		 */
+
+		if ((unsigned)sbuf.st_size < sizeof(image_header_t)) {
+			fprintf (stderr,
+				"%s: Bad size: \"%s\" is too small for XIP\n",
+				cmdname, datafile);
+			exit (EXIT_FAILURE);
+		}
+
+		for (p=ptr; p < ptr+sizeof(image_header_t); p++) {
+			if ( *p != 0xff ) {
+				fprintf (stderr,
+					"%s: Bad file: \"%s\" has invalid buffer for XIP\n",
+					cmdname, datafile);
+				exit (EXIT_FAILURE);
+			}
+		}
+
+		offset = sizeof(image_header_t);
+	}
+
+	size = sbuf.st_size - offset;
+	if (write(ifd, ptr + offset, size) != size) {
+		fprintf (stderr, "%s: Write error on %s: %s\n",
+			cmdname, imagefile, strerror(errno));
+		exit (EXIT_FAILURE);
+	}
+
+	if (pad && ((tail = size % 4) != 0)) {
+
+		if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
+			fprintf (stderr, "%s: Write error on %s: %s\n",
+				cmdname, imagefile, strerror(errno));
+			exit (EXIT_FAILURE);
+		}
+	}
+
+	(void) munmap((void *)ptr, sbuf.st_size);
+	(void) close (dfd);
+}
+
+void
+usage ()
+{
+	fprintf (stderr, "Usage: %s -l image\n"
+			 "          -l ==> list image header information\n"
+			 "       %s [-x] -A arch -O os -T type -C comp "
+			 "-a addr -e ep -n name -d data_file[:data_file...] image\n",
+		cmdname, cmdname);
+	fprintf (stderr, "          -A ==> set architecture to 'arch'\n"
+			 "          -O ==> set operating system to 'os'\n"
+			 "          -T ==> set image type to 'type'\n"
+			 "          -C ==> set compression type 'comp'\n"
+			 "          -a ==> set load address to 'addr' (hex)\n"
+			 "          -e ==> set entry point to 'ep' (hex)\n"
+			 "          -n ==> set image name to 'name'\n"
+			 "          -r ==> set dram type (sdr/ddr)\n"
+			 "          -s ==> set dram total width (16/32)\n"
+			 "          -t ==> set dram size (2/8/16/32/64/128/256MB)\n"
+			 "          -u ==> set dram width (16/32)\n"
+			 "          -d ==> use image data from 'datafile'\n"
+			 "          -x ==> set XIP (execute in place)\n"
+			 "          -y ==> set dram parameter 0\n"
+			 "          -z ==> set dram parameter 1\n"
+		);
+	exit (EXIT_FAILURE);
+}
+
+static void
+print_header (image_header_t *hdr)
+{
+	time_t timestamp;
+	uint32_t size;
+
+	timestamp = (time_t)ntohl(hdr->ih_time);
+	size = ntohl(hdr->ih_size);
+
+	printf ("Image Name:   %.*s\n", IH_NMLEN, hdr->ih_name);
+	printf ("Created:      %s", ctime(&timestamp));
+	printf ("Image Type:   "); print_type(hdr);
+	printf ("Data Size:    %d Bytes = %.2f kB = %.2f MB\n",
+		size, (double)size / 1.024e3, (double)size / 1.048576e6 );
+	printf ("Load Address: 0x%08X\n", ntohl(hdr->ih_load));
+	printf ("Entry Point:  0x%08X\n", ntohl(hdr->ih_ep));
+#if defined (MT7621_ASIC_BOARD) || defined (MT7621_FPGA_BOARD)
+#else	
+	printf ("DRAM Parameter: %x (Parm0=%x Parm1=%x)\n", hdr->ih_dram.dram_parm, hdr->ih_dram.sdr.sdram_cfg0, hdr->ih_dram.sdr.sdram_cfg1);
+#endif
+	if (hdr->ih_type == IH_TYPE_MULTI || hdr->ih_type == IH_TYPE_SCRIPT) {
+		int i, ptrs;
+		uint32_t pos;
+		unsigned long *len_ptr = (unsigned long *) (
+					(unsigned long)hdr + sizeof(image_header_t)
+				);
+
+		/* determine number of images first (to calculate image offsets) */
+		for (i=0; len_ptr[i]; ++i)	/* null pointer terminates list */
+			;
+		ptrs = i;		/* null pointer terminates list */
+
+		pos = sizeof(image_header_t) + ptrs * sizeof(long);
+		printf ("Contents:\n");
+		for (i=0; len_ptr[i]; ++i) {
+			size = ntohl(len_ptr[i]);
+
+			printf ("   Image %d: %8d Bytes = %4d kB = %d MB\n",
+				i, size, size>>10, size>>20);
+			if (hdr->ih_type == IH_TYPE_SCRIPT && i > 0) {
+				/*
+				 * the user may need to know offsets
+				 * if planning to do something with
+				 * multiple files
+				 */
+				printf ("    Offset = %08X\n", pos);
+			}
+			/* copy_file() will pad the first files to even word align */
+			size += 3;
+			size &= ~3;
+			pos += size;
+		}
+	}
+}
+
+
+static void
+print_type (image_header_t *hdr)
+{
+	printf ("%s %s %s (%s)\n",
+		put_arch (hdr->ih_arch),
+		put_os   (hdr->ih_os  ),
+		put_type (hdr->ih_type),
+		put_comp (hdr->ih_comp)
+	);
+}
+
+static char *put_arch (int arch)
+{
+	return (put_table_entry(arch_name, "Unknown Architecture", arch));
+}
+
+static char *put_os (int os)
+{
+	return (put_table_entry(os_name, "Unknown OS", os));
+}
+
+static char *put_type (int type)
+{
+	return (put_table_entry(type_name, "Unknown Image", type));
+}
+
+static char *put_comp (int comp)
+{
+	return (put_table_entry(comp_name, "Unknown Compression", comp));
+}
+
+static char *put_table_entry (table_entry_t *table, char *msg, int type)
+{
+	for (; table->val>=0; ++table) {
+		if (table->val == type)
+			return (table->lname);
+	}
+	return (msg);
+}
+
+static int get_arch(char *name)
+{
+	return (get_table_entry(arch_name, "CPU", name));
+}
+
+
+static int get_comp(char *name)
+{
+	return (get_table_entry(comp_name, "Compression", name));
+}
+
+
+static int get_os (char *name)
+{
+	return (get_table_entry(os_name, "OS", name));
+}
+
+
+static int get_type(char *name)
+{
+	return (get_table_entry(type_name, "Image", name));
+}
+
+static int get_table_entry (table_entry_t *table, char *msg, char *name)
+{
+	table_entry_t *t;
+	int first = 1;
+
+	for (t=table; t->val>=0; ++t) {
+		if (t->sname && strcasecmp(t->sname, name)==0)
+			return (t->val);
+	}
+	fprintf (stderr, "\nInvalid %s Type - valid names are", msg);
+	for (t=table; t->val>=0; ++t) {
+		if (t->sname == NULL)
+			continue;
+		fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname);
+		first = 0;
+	}
+	fprintf (stderr, "\n");
+	return (-1);
+}