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 ,®Value);
+ 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 ,®Value);
+ 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 ,®Value);
+ 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 ,®Value);
+#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 ,®Value);
+ 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, ®Value);
+ regValue &= ~(3<<7); //turn off 100Base-T Advertisement
+ mii_mgr_write(i, 4, regValue);
+
+ //mii_mgr_read(i, 9, ®Value);
+ //regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
+ //mii_mgr_write(i, 9, regValue);
+
+ //restart AN
+ mii_mgr_read(i, 0, ®Value);
+ regValue |= (1 << 9);
+ mii_mgr_write(i, 0, regValue);
+ }
+#endif
+ mii_mgr_read(31, 0x7808 ,®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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(×tamp));
+ 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);
+}