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); +}