public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/5] [MIPS] add jz4740 base file and Ben NanoNote
@ 2010-11-11  3:37 Xiangfu Liu
  2010-11-11  3:37 ` [U-Boot] [PATCH 1/5] those files are jz4740 base files Xiangfu Liu
  0 siblings, 1 reply; 11+ messages in thread
From: Xiangfu Liu @ 2010-11-11  3:37 UTC (permalink / raw)
  To: u-boot

Hi Shinya 

very thanks for your feed pack, and I am really sorry for so later 
reply.

the "[PATCH 1/5] those files are jz4740 base files" is patch v2 of 
    "[PATCH] [MIPS] those files are jz4740 base files"

I have try to fix all your comments. only one thing, I am not very 
understand the "flash cache" stuff, so I maybe still keep the 
flash ICache DCache like before.

please give me some feedback. now I have more time working on U-Boot :)

thanks very much.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/5] those files are jz4740 base files
  2010-11-11  3:37 [U-Boot] [PATCH 0/5] [MIPS] add jz4740 base file and Ben NanoNote Xiangfu Liu
@ 2010-11-11  3:37 ` Xiangfu Liu
       [not found]   ` <1289446657-12499-3-git-send-email-xiangfu@openmobilefree.net>
                     ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Xiangfu Liu @ 2010-11-11  3:37 UTC (permalink / raw)
  To: u-boot

From: Xiangfu Liu <xiangfu@sharism.cc>

Signed-off-by: Xiangfu Liu <xiangfu@openmobilefree.net>
---
 arch/mips/cpu/xburst/Makefile     |   50 +++
 arch/mips/cpu/xburst/config.mk    |   33 ++
 arch/mips/cpu/xburst/cpu.c        |  158 +++++++
 arch/mips/cpu/xburst/interrupts.c |   33 ++
 arch/mips/cpu/xburst/jz4740.c     |  257 +++++++++++
 arch/mips/cpu/xburst/jz_serial.c  |  139 ++++++
 arch/mips/cpu/xburst/start.S      |  165 +++++++
 arch/mips/cpu/xburst/start_spl.S  |   63 +++
 arch/mips/cpu/xburst/timer.c      |  174 ++++++++
 arch/mips/cpu/xburst/usbboot.S    |  880 +++++++++++++++++++++++++++++++++++++
 10 files changed, 1952 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/cpu/xburst/Makefile
 create mode 100644 arch/mips/cpu/xburst/config.mk
 create mode 100644 arch/mips/cpu/xburst/cpu.c
 create mode 100644 arch/mips/cpu/xburst/interrupts.c
 create mode 100644 arch/mips/cpu/xburst/jz4740.c
 create mode 100644 arch/mips/cpu/xburst/jz_serial.c
 create mode 100644 arch/mips/cpu/xburst/start.S
 create mode 100644 arch/mips/cpu/xburst/start_spl.S
 create mode 100644 arch/mips/cpu/xburst/timer.c
 create mode 100644 arch/mips/cpu/xburst/usbboot.S

diff --git a/arch/mips/cpu/xburst/Makefile b/arch/mips/cpu/xburst/Makefile
new file mode 100644
index 0000000..2e29851
--- /dev/null
+++ b/arch/mips/cpu/xburst/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(CPU).a
+
+START	= start.o
+SOBJS-y	= 
+COBJS-y = cpu.o interrupts.o timer.o jz_serial.o 
+
+COBJS-$(CONFIG_JZ4740) += jz4740.o
+
+SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+START	:= $(addprefix $(obj),$(START))
+
+all:	$(obj).depend $(START) $(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/mips/cpu/xburst/config.mk b/arch/mips/cpu/xburst/config.mk
new file mode 100644
index 0000000..f43f53b
--- /dev/null
+++ b/arch/mips/cpu/xburst/config.mk
@@ -0,0 +1,33 @@
+#
+# (C) Copyright 2003
+# 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
+#
+v=$(shell $(AS) --version | grep 'GNU assembler' | egrep -o '2\.[0-9\.]+' | cut -d. -f2)
+MIPSFLAGS:=$(shell \
+if [ "$v" -lt "14" ]; then \
+	echo "-mcpu=4kc"; \
+else \
+	echo "-march=4kc -mtune=4kc"; \
+fi)
+
+MIPSFLAGS += $(ENDIANNESS) -mabicalls -mips32
+
+PLATFORM_CPPFLAGS += $(MIPSFLAGS)
diff --git a/arch/mips/cpu/xburst/cpu.c b/arch/mips/cpu/xburst/cpu.c
new file mode 100644
index 0000000..682debf
--- /dev/null
+++ b/arch/mips/cpu/xburst/cpu.c
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2003
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <netdev.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheops.h>
+#include <asm/reboot.h>
+#include <asm/jz4740.h>
+
+#define cache_op(op,addr)						\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	noreorder				\n"	\
+	"	.set	mips3\n\t				\n"	\
+	"	cache	%0, %1					\n"	\
+	"	.set	pop					\n"	\
+	:								\
+	: "i" (op), "R" (*(unsigned char *)(addr)))
+
+#if !defined (CONFIG_NAND_SPL) && !defined (CONFIG_MSC_SPL) 
+
+void __attribute__((weak)) _machine_restart(void)
+{
+	__wdt_select_extalclk();
+	__wdt_select_clk_div64();
+	__wdt_set_data(100);
+	__wdt_set_count(0);
+	__tcu_start_wdt_clock();
+	__wdt_start();
+	while(1);
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char const *argv[])
+{
+	_machine_restart();
+
+	fprintf(stderr, "*** reset failed ***\n");
+	return 0;
+}
+
+void flush_cache(ulong start_addr, ulong size)
+{
+	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
+	unsigned long addr = start_addr & ~(lsize - 1);
+	unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
+
+	while (1) {
+		cache_op(Hit_Writeback_Inv_D, addr);
+		cache_op(Hit_Invalidate_I, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+}
+
+void flush_dcache_range(ulong start_addr, ulong stop)
+{
+	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
+	unsigned long addr = start_addr & ~(lsize - 1);
+	unsigned long aend = (stop - 1) & ~(lsize - 1);
+
+	while (1) {
+		cache_op(Hit_Writeback_Inv_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+}
+
+void invalidate_dcache_range(ulong start_addr, ulong stop)
+{
+	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
+	unsigned long addr = start_addr & ~(lsize - 1);
+	unsigned long aend = (stop - 1) & ~(lsize - 1);
+
+	while (1) {
+		cache_op(Hit_Invalidate_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+}
+
+void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
+{
+	write_c0_entrylo0(low0);
+	write_c0_pagemask(pagemask);
+	write_c0_entrylo1(low1);
+	write_c0_entryhi(hi);
+	write_c0_index(index);
+	tlb_write_indexed();
+}
+
+#endif /* !CONFIG_NAND_SPL  !CONFIG_MSC_SPL */
+
+void flush_icache_all(void)
+{
+	u32 addr, t = 0;
+
+	asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
+	asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
+
+	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE;
+	     addr += CONFIG_SYS_CACHELINE_SIZE) {
+		cache_op(Index_Store_Tag_I, addr);
+	}
+
+	/* invalidate btb */
+	asm volatile (
+		".set mips32\n\t"
+		"mfc0 %0, $16, 7\n\t"
+		"nop\n\t"
+		"ori %0,2\n\t"
+		"mtc0 %0, $16, 7\n\t"
+		".set mips2\n\t"
+		:
+		: "r" (t));
+}
+
+void flush_dcache_all(void)
+{
+	u32 addr;
+
+	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; 
+	     addr += CONFIG_SYS_CACHELINE_SIZE) {
+		cache_op(Index_Writeback_Inv_D, addr);
+	}
+
+	asm volatile ("sync");
+}
+
+void flush_cache_all(void)
+{
+	flush_dcache_all();
+	flush_icache_all();
+}
diff --git a/arch/mips/cpu/xburst/interrupts.c b/arch/mips/cpu/xburst/interrupts.c
new file mode 100644
index 0000000..87f7a9f
--- /dev/null
+++ b/arch/mips/cpu/xburst/interrupts.c
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2003
+ * 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
+ */
+
+#include <common.h>
+
+void enable_interrupts(void)
+{
+}
+
+int disable_interrupts(void)
+{
+	return 0;
+}
diff --git a/arch/mips/cpu/xburst/jz4740.c b/arch/mips/cpu/xburst/jz4740.c
new file mode 100644
index 0000000..b8e9a15
--- /dev/null
+++ b/arch/mips/cpu/xburst/jz4740.c
@@ -0,0 +1,257 @@
+/*
+ * Jz4740 common routines
+ *
+ *  Copyright (c) 2006
+ *  Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * 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 <config.h>
+#include <common.h>
+
+#include <asm/jz4740.h>
+
+/* PLL output clock = EXTAL * NF / (NR * NO)
+ *
+ * NF = FD + 2, NR = RD + 2
+ * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
+ */
+void pll_init(void)
+{
+	register unsigned int cfcr, plcr1;
+	int n2FR[33] = {
+		0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
+		7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
+		9
+	};
+	int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
+	int nf, pllout2;
+
+	cfcr = CPM_CPCCR_CLKOEN |
+		CPM_CPCCR_PCS |
+		(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
+		(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
+		(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
+		(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
+		(n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
+
+	pllout2 = (cfcr & CPM_CPCCR_PCS) ? CONFIG_SYS_CPU_SPEED : (CONFIG_SYS_CPU_SPEED / 2);
+
+	/* Init USB Host clock, pllout2 must be n*48MHz */
+	REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
+
+	nf = CONFIG_SYS_CPU_SPEED * 2 / CONFIG_SYS_EXTAL;
+	plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
+		(0 << CPM_CPPCR_PLLN_BIT) |	/* RD=0, NR=2 */
+		(0 << CPM_CPPCR_PLLOD_BIT) |    /* OD=0, NO=1 */
+		(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
+		CPM_CPPCR_PLLEN;                /* enable PLL */
+
+	/* init PLL */
+	REG_CPM_CPCCR = cfcr;
+	REG_CPM_CPPCR = plcr1;
+}
+
+void sdram_init(void)
+{
+	register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
+
+	unsigned int cas_latency_sdmr[2] = {
+		EMC_SDMR_CAS_2,
+		EMC_SDMR_CAS_3,
+	};
+
+	unsigned int cas_latency_dmcr[2] = {
+		1 << EMC_DMCR_TCL_BIT,	/* CAS latency is 2 */
+		2 << EMC_DMCR_TCL_BIT	/* CAS latency is 3 */
+	};
+
+	int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+	cpu_clk = CONFIG_SYS_CPU_SPEED;
+	mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
+
+	REG_EMC_BCR = 0;	/* Disable bus release */
+	REG_EMC_RTCSR = 0;	/* Disable clock for counting */
+
+	/* Fault DMCR value for mode register setting*/
+#define SDRAM_ROW0    11
+#define SDRAM_COL0     8
+#define SDRAM_BANK40   0
+
+	dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
+		((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
+		(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
+		(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
+		EMC_DMCR_EPIN |
+		cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+	/* Basic DMCR value */
+	dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
+		((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
+		(SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
+		(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
+		EMC_DMCR_EPIN |
+		cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+	/* SDRAM timimg */
+	ns = 1000000000 / mem_clk;
+	tmp = SDRAM_TRAS/ns;
+	if (tmp < 4) tmp = 4;
+	if (tmp > 11) tmp = 11;
+	dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
+	tmp = SDRAM_RCD/ns;
+	if (tmp > 3) tmp = 3;
+	dmcr |= (tmp << EMC_DMCR_RCD_BIT);
+	tmp = SDRAM_TPC/ns;
+	if (tmp > 7) tmp = 7;
+	dmcr |= (tmp << EMC_DMCR_TPC_BIT);
+	tmp = SDRAM_TRWL/ns;
+	if (tmp > 3) tmp = 3;
+	dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
+	tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
+	if (tmp > 14) tmp = 14;
+	dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
+
+	/* SDRAM mode value */
+	sdmode = EMC_SDMR_BT_SEQ | 
+		 EMC_SDMR_OM_NORMAL |
+		 EMC_SDMR_BL_4 | 
+		 cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
+
+	/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
+	REG_EMC_DMCR = dmcr;
+	REG8(EMC_SDMR0|sdmode) = 0;
+
+	/* Wait for precharge, > 200us */
+	tmp = (cpu_clk / 1000000) * 1000;
+	while (tmp--);
+
+	/* Stage 2. Enable auto-refresh */
+	REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
+
+	tmp = SDRAM_TREF/ns;
+	tmp = tmp/64 + 1;
+	if (tmp > 0xff) tmp = 0xff;
+	REG_EMC_RTCOR = tmp;
+	REG_EMC_RTCNT = 0;
+	REG_EMC_RTCSR = EMC_RTCSR_CKS_64;	/* Divisor is 64, CKO/64 */
+
+	/* Wait for number of auto-refresh cycles */
+	tmp = (cpu_clk / 1000000) * 1000;
+	while (tmp--);
+
+ 	/* Stage 3. Mode Register Set */
+	REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
+	REG8(EMC_SDMR0|sdmode) = 0;
+
+        /* Set back to basic DMCR value */
+	REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
+
+	/* everything is ok now */
+}
+
+#ifndef CONFIG_NAND_SPL
+
+static void calc_clocks(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	unsigned int pllout;
+	unsigned int div[10] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+
+	pllout = __cpm_get_pllout();
+
+	gd->cpu_clk = pllout / div[__cpm_get_cdiv()];
+	gd->sys_clk = pllout / div[__cpm_get_hdiv()];
+	gd->per_clk = pllout / div[__cpm_get_pdiv()];
+	gd->mem_clk = pllout / div[__cpm_get_mdiv()];
+	gd->dev_clk = CONFIG_SYS_EXTAL;
+}
+
+static void rtc_init(void)
+{
+	while ( !__rtc_write_ready()) ;
+	__rtc_enable_alarm();	/* enable alarm */
+
+	while ( !__rtc_write_ready())
+		;
+	REG_RTC_RGR   = 0x00007fff; /* type value */
+
+	while ( !__rtc_write_ready())
+		;
+	REG_RTC_HWFCR = 0x0000ffe0; /* Power on delay 2s */
+
+	while ( !__rtc_write_ready())
+		;
+	REG_RTC_HRCR  = 0x00000fe0; /* reset delay 125ms */
+#if 0
+	unsigned long rtcsta;
+
+	while ( !__rtc_write_ready())
+		;
+	rtcsta = REG_RTC_HWRSR;
+	while ( !__rtc_write_ready())
+		;
+	if (rtcsta & 0x33) {
+		if (rtcsta & 0x10) {
+			while ( !__rtc_write_ready())
+				;
+			REG_RTC_RSR = 0x0;
+		}
+		while ( !__rtc_write_ready())
+			;
+		REG_RTC_HWRSR = 0x0;
+	}
+#endif
+}
+
+/* U-Boot common routines */
+phys_size_t initdram(int board_type)
+{
+	u32 dmcr;
+	u32 rows, cols, dw, banks;
+	ulong size;
+
+	dmcr = REG_EMC_DMCR;
+	rows = 11 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT);
+	cols = 8 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT);
+	dw = (dmcr & EMC_DMCR_BW) ? 2 : 4;
+	banks = (dmcr & EMC_DMCR_BA) ? 4 : 2;
+
+	size = (1 << (rows + cols)) * dw * banks;
+
+	return size;
+}
+
+/*
+ * jz4740 board init routine
+ */
+extern void board_early_init(void);
+int jz_board_init(void)
+{
+	board_early_init();  /* init gpio, pll etc. */
+#ifndef CONFIG_NAND_U_BOOT
+	pll_init();          /* init PLL */
+	sdram_init();        /* init sdram memory */
+#endif
+	calc_clocks();       /* calc the clocks */
+	rtc_init();		/* init rtc on any reset: */
+	return 0;
+}
+
+#endif /* CONFIG_NAND_SPL */
diff --git a/arch/mips/cpu/xburst/jz_serial.c b/arch/mips/cpu/xburst/jz_serial.c
new file mode 100644
index 0000000..c5cc28e
--- /dev/null
+++ b/arch/mips/cpu/xburst/jz_serial.c
@@ -0,0 +1,139 @@
+/*
+ * Jz47xx UART support
+ *
+ * Hardcoded to UART 0 for now
+ * Options also hardcoded to 8N1
+ *
+ *  Copyright (c) 2005
+ *  Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * 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 <config.h>
+#include <common.h>
+
+#if defined(CONFIG_JZ4740)
+#include <asm/jz4740.h>
+#endif
+ 
+#undef UART_BASE
+#ifndef CONFIG_SYS_UART_BASE
+#define UART_BASE  UART0_BASE
+#else
+#define UART_BASE  CONFIG_SYS_UART_BASE
+#endif
+
+/******************************************************************************
+*
+* serial_init - initialize a channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
+	volatile u8 *uart_fcr = (volatile u8 *)(UART_BASE + OFF_FCR);
+	volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
+	volatile u8 *uart_ier = (volatile u8 *)(UART_BASE + OFF_IER);
+	volatile u8 *uart_sircr = (volatile u8 *)(UART_BASE + OFF_SIRCR);
+
+	/* Disable port interrupts while changing hardware */
+	*uart_ier = 0;
+
+	/* Disable UART unit function */
+	*uart_fcr = ~UART_FCR_UUE;
+
+	/* Set both receiver and transmitter in UART mode (not SIR) */
+	*uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
+
+	/* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
+	*uart_lcr = UART_LCR_WLEN_8 | UART_LCR_STOP_1;
+
+	/* Set baud rate */
+	serial_setbrg();
+
+	/* Enable UART unit, enable and clear FIFO */
+	*uart_fcr = UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS;
+#endif
+	return 0;
+}
+
+void serial_setbrg (void)
+{
+	volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
+	volatile u8 *uart_dlhr = (volatile u8 *)(UART_BASE + OFF_DLHR);
+	volatile u8 *uart_dllr = (volatile u8 *)(UART_BASE + OFF_DLLR);
+	u32 baud_div, tmp;
+
+	baud_div = CONFIG_SYS_EXTAL / 16 / CONFIG_BAUDRATE;
+
+	tmp = *uart_lcr;
+	tmp |= UART_LCR_DLAB;
+	*uart_lcr = tmp;
+
+	*uart_dlhr = (baud_div >> 8) & 0xff;
+	*uart_dllr = baud_div & 0xff;
+
+	tmp &= ~UART_LCR_DLAB;
+	*uart_lcr = tmp;
+}
+
+void serial_putc (const char c)
+{
+	volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
+	volatile u8 *uart_tdr = (volatile u8 *)(UART_BASE + OFF_TDR);
+
+	if (c == '\n') serial_putc ('\r');
+
+	/* Wait for fifo to shift out some bytes */
+	while ( !((*uart_lsr & (UART_LSR_TDRQ | UART_LSR_TEMT)) == 0x60) );
+
+	*uart_tdr = (u8)c;
+}
+
+void serial_puts (const char *s)
+{
+	while (*s) {
+		serial_putc (*s++);
+	}
+}
+
+int serial_getc (void)
+{
+	volatile u8 *uart_rdr = (volatile u8 *)(UART_BASE + OFF_RDR);
+
+	while (!serial_tstc());
+
+	return *uart_rdr;
+}
+
+int serial_tstc (void)
+{
+	volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
+
+	if (*uart_lsr & UART_LSR_DR) {
+		/* Data in rfifo */
+		return (1);
+	}
+	return 0;
+}
+
diff --git a/arch/mips/cpu/xburst/start.S b/arch/mips/cpu/xburst/start.S
new file mode 100644
index 0000000..b05cc67
--- /dev/null
+++ b/arch/mips/cpu/xburst/start.S
@@ -0,0 +1,165 @@
+/*
+ *  Startup Code for MIPS32 XBURST CPU-core
+ *
+ *  Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+
+#include <asm/jz4740.h>
+
+	.set noreorder
+
+	.globl _start
+	.text
+_start:
+	/* Initialize GOT pointer.
+	*/
+	bal     1f
+	nop
+	.word   _GLOBAL_OFFSET_TABLE_
+1:
+	lw      gp, 0(ra) 
+	li      sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET 
+
+	la	t9, board_init_f
+	jr	t9
+	nop
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * a0 = addr_sp
+ * a1 = gd
+ * a2 = destination address
+ */
+	.globl	relocate_code
+	.ent	relocate_code
+relocate_code:
+	move	sp, a0		/* Set new stack pointer	*/
+
+	li	t0, TEXT_BASE
+	la	t3, in_ram
+	lw	t2, -12(t3)	/* t2 <-- uboot_end_data	*/
+	move	t1, a2
+
+	/*
+	 * Fix GOT pointer:
+	 *
+	 * New GOT-PTR = (old GOT-PTR - TEXT_BASE) + Destination Address
+	 */
+	move	t6, gp
+	sub	gp, TEXT_BASE
+	add	gp, a2			/* gp now adjusted	*/
+	sub	t6, gp, t6		/* t6 <-- relocation offset*/
+
+	/*
+	 * t0 = source address
+	 * t1 = target address
+	 * t2 = source end address
+	 */
+1:
+	lw	t3, 0(t0)
+	sw	t3, 0(t1)
+	addu	t0, 4
+	ble	t0, t2, 1b
+	addu	t1, 4			/* delay slot		*/
+
+	/* If caches were enabled, we would have to flush them here.
+	 * flush d-cache */
+	.set	push
+	li	t0, KSEG0
+	addi	t1, t0, CONFIG_SYS_DCACHE_SIZE
+2:
+	cache	Index_Writeback_Inv_D, 0(t0)
+	bne	t0, t1, 2b
+	addi	t0, CONFIG_SYS_CACHELINE_SIZE
+
+	sync
+
+	/* flush i-cache */
+	li	t0, KSEG0
+	addi	t1, t0, CONFIG_SYS_ICACHE_SIZE
+3:
+	cache	Index_Invalidate_I, 0(t0)
+	bne	t0, t1, 3b
+	addi	t0, CONFIG_SYS_CACHELINE_SIZE
+
+	/* Invalidate BTB */
+	mfc0	t0, CP0_CONFIG, 7
+	nop
+	ori	t0, 2
+	mtc0	t0, CP0_CONFIG, 7
+	nop
+
+	.set	pop
+
+	/* Jump to where we've relocated ourselves.
+	 */
+	addi	t0, a2, in_ram - _start
+	j	t0
+	nop
+
+	.word	uboot_end_data
+	.word	uboot_end
+	.word	num_got_entries
+
+in_ram:
+	/* Now we want to update GOT  */
+	lw	t3, -4(t0)	/* t3 <-- num_got_entries	*/
+	addi	t4, gp, 8	/* Skipping first two entries.	*/
+	li	t2, 2
+1:
+	lw	t1, 0(t4)
+	beqz	t1, 2f
+	add	t1, t6
+	sw	t1, 0(t4)
+2:
+	addi	t2, 1
+	blt	t2, t3, 1b
+	addi	t4, 4		/* delay slot			*/
+
+	/* Clear BSS  */
+	lw	t1, -12(t0)	/* t1 <-- uboot_end_data	*/
+	lw	t2, -8(t0)	/* t2 <-- uboot_end		*/
+	add	t1, t6		/* adjust pointers		*/
+	add	t2, t6
+
+	sub	t1, 4
+1:	addi	t1, 4
+	bltl	t1, t2, 1b
+	sw	zero, 0(t1)	/* delay slot			*/
+
+	move	a0, a1
+	la	t9, board_init_r
+	j	t9
+	move	a1, a2		/* delay slot			*/
+
+	.end	relocate_code
+	
\ No newline at end of file
diff --git a/arch/mips/cpu/xburst/start_spl.S b/arch/mips/cpu/xburst/start_spl.S
new file mode 100644
index 0000000..f775e3a
--- /dev/null
+++ b/arch/mips/cpu/xburst/start_spl.S
@@ -0,0 +1,63 @@
+/*
+ *  Startup Code for MIPS32 XBURST CPU-core
+ *
+ *  Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
+ *
+ * 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 3 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 <config.h>
+#include <version.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+
+#include <asm/jz4740.h>
+
+	.set noreorder
+	
+	.globl _start
+	.text
+_start:
+	.word JZ4740_NANDBOOT_CFG /* fetched during NAND Boot */
+reset:	
+	/* 
+	 * STATUS register
+	 * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
+	 */
+	li	t0, 0x0040FC04
+	mtc0	t0, CP0_STATUS
+	/* CAUSE register
+	 * IV=1, use the specical interrupt vector (0x200) */
+	li	t1, 0x00800000
+	mtc0	t1, CP0_CAUSE
+	
+	bal     1f
+	nop
+	.word   _GLOBAL_OFFSET_TABLE_
+1:
+	move    gp, ra
+	lw      t1, 0(ra)
+	move	gp, t1
+
+	la	sp, 0x80004000
+	la	t9, nand_boot
+	j	t9
+	nop
diff --git a/arch/mips/cpu/xburst/timer.c b/arch/mips/cpu/xburst/timer.c
new file mode 100644
index 0000000..5fef521
--- /dev/null
+++ b/arch/mips/cpu/xburst/timer.c
@@ -0,0 +1,174 @@
+/*
+ *  Copyright (c) 2006
+ *  Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * 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 <config.h>
+#include <common.h>
+
+#include <asm/jz4740.h>
+
+/*
+ * Timer routines 
+ */
+#define TIMER_CHAN  0
+#define TIMER_FDATA 0xffff  /* Timer full data value */
+#define TIMER_HZ    CONFIG_SYS_HZ
+
+#define READ_TIMER  REG_TCU_TCNT(TIMER_CHAN)  /* macro to read the 16 bit timer */
+
+static ulong timestamp;
+static ulong lastdec;
+
+void	reset_timer_masked	(void);
+ulong	get_timer_masked	(void);
+void	udelay_masked		(unsigned long usec);
+
+/*
+ * timer without interrupts
+ */
+
+int timer_init(void)
+{
+	REG_TCU_TCSR(TIMER_CHAN) = TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN;
+	REG_TCU_TCNT(TIMER_CHAN) = 0;
+	REG_TCU_TDHR(TIMER_CHAN) = 0;
+	REG_TCU_TDFR(TIMER_CHAN) = TIMER_FDATA;
+
+	REG_TCU_TMSR = (1 << TIMER_CHAN) | (1 << (TIMER_CHAN + 16)); /* mask irqs */
+	REG_TCU_TSCR = (1 << TIMER_CHAN); /* enable timer clock */
+	REG_TCU_TESR = (1 << TIMER_CHAN); /* start counting up */
+
+	lastdec = 0;
+	timestamp = 0;
+
+	return 0;
+}
+
+void reset_timer(void)
+{
+	reset_timer_masked ();
+}
+
+ulong get_timer(ulong base)
+{
+	return get_timer_masked () - base;
+}
+
+void set_timer(ulong t)
+{
+	timestamp = t;
+}
+
+void __udelay (unsigned long usec)
+{
+	ulong tmo,tmp;
+
+	/* normalize */
+	if (usec >= 1000) {
+		tmo = usec / 1000;
+		tmo *= TIMER_HZ;
+		tmo /= 1000;
+	}
+	else {
+		if (usec >= 1) {
+			tmo = usec * TIMER_HZ;
+			tmo /= (1000*1000);
+		}
+		else
+			tmo = 1;
+	}
+
+	/* check for rollover during this delay */
+	tmp = get_timer (0);
+	if ((tmp + tmo) < tmp )
+		reset_timer_masked();  /* timer would roll over */
+	else
+		tmo += tmp;
+
+	while (get_timer_masked () < tmo);
+}
+
+void reset_timer_masked (void)
+{
+	/* reset time */
+	lastdec = READ_TIMER;
+	timestamp = 0;
+}
+
+ulong get_timer_masked (void)
+{
+	ulong now = READ_TIMER;
+
+	if (lastdec <= now) {
+		/* normal mode */
+		timestamp += (now - lastdec);
+	} else {
+		/* we have an overflow ... */
+		timestamp += TIMER_FDATA + now - lastdec;
+	}
+	lastdec = now;
+
+	return timestamp;
+}
+
+void udelay_masked (unsigned long usec)
+{
+	ulong tmo;
+	ulong endtime;
+	signed long diff;
+
+	/* normalize */
+	if (usec >= 1000) {
+		tmo = usec / 1000;
+		tmo *= TIMER_HZ;
+		tmo /= 1000;
+	} else {
+		if (usec > 1) {
+			tmo = usec * TIMER_HZ;
+			tmo /= (1000*1000);
+		} else {
+			tmo = 1;
+		}
+	}
+
+	endtime = get_timer_masked () + tmo;
+
+	do {
+		ulong now = get_timer_masked ();
+		diff = endtime - now;
+	} while (diff >= 0);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On MIPS it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On MIPS it returns the number of timer ticks per second.
+ */
+ulong get_tbclk (void)
+{
+	return TIMER_HZ;
+}
diff --git a/arch/mips/cpu/xburst/usbboot.S b/arch/mips/cpu/xburst/usbboot.S
new file mode 100644
index 0000000..eb8faa6
--- /dev/null
+++ b/arch/mips/cpu/xburst/usbboot.S
@@ -0,0 +1,880 @@
+/*
+ *  for jz4740 usb boot
+ *
+ *  Copyright (c) 2009 Author: <jlwei@ingenic.cn>
+ *
+ * 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
+ */
+    .set noreorder
+    .globl usb_boot
+    .text
+
+//----------------------------------------------------------------------
+// Both NAND and USB boot load data to D-Cache first, then transfer
+// data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
+// So init caches first and then dispatch to a proper boot routine.
+//----------------------------------------------------------------------
+
+.macro load_addr reg addr
+	li \reg, 0x80000000
+	addiu \reg, \reg, \addr
+	la $2, usbboot_begin
+	subu \reg, \reg, $2
+.endm
+
+usb_boot:
+	//--------------------------------------------------------------
+	// Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
+	//--------------------------------------------------------------
+	la	$9, 0xB0000000		// CPCCR: Clock Control Register
+	la	$8, 0x42041110		// I:S:M:P=1:2:2:2
+	sw	$8, 0($9)
+
+	la	$9, 0xB0000010		// CPPCR: PLL Control Register
+	la	$8, 0x06000120		// M=12 N=0 D=0 CLK=12*(M+2)/(N+2)
+	sw	$8, 0($9)
+
+	mtc0	$0, $26			// CP0_ERRCTL, restore WST reset state
+	nop
+
+	mtc0	$0, $16			// CP0_CONFIG
+	nop
+
+	// Relocate code to beginning of the ram
+
+	la $2, usbboot_begin
+	la $3, usbboot_end
+	li $4, 0x80000000
+
+1:
+	lw $5, 0($2)
+	sw $5, 0($4)
+	addiu $2, $2, 4
+	bne $2, $3, 1b
+	addiu $4, $4, 4
+
+	li $2, 0x80000000
+	ori $3, $2, 0
+	addiu $3, $3, usbboot_end
+	la $4, usbboot_begin
+	subu $3, $3, $4
+
+
+2:
+	cache	0x0, 0($2)		// Index_Invalidate_I
+	cache	0x1, 0($2)		// Index_Writeback_Inv_D
+	addiu	$2, $2, 32
+	subu $4, $3, $2
+	bgtz	$4, 2b
+	nop
+
+	load_addr $3, usb_boot_return
+
+	jr $3
+
+usbboot_begin:
+
+init_caches:
+	li	$2, 3			// cacheable for kseg0 access
+	mtc0	$2, $16			// CP0_CONFIG
+	nop
+
+	li	$2, 0x20000000		// enable idx-store-data cache insn
+	mtc0	$2, $26			// CP0_ERRCTL
+
+	ori	$2, $28, 0		// start address
+	ori	$3, $2, 0x3fe0		// end address, total 16KB
+	mtc0	$0, $28, 0		// CP0_TAGLO
+	mtc0	$0, $28, 1		// CP0_DATALO
+cache_clear_a_line:
+	cache	0x8, 0($2)		// Index_Store_Tag_I
+	cache	0x9, 0($2)		// Index_Store_Tag_D
+	bne	$2, $3, cache_clear_a_line
+	addiu	$2, $2, 32		// increment CACHE_LINE_SIZE
+
+	ori	$2, $28, 0		// start address
+	ori	$3, $2, 0x3fe0		// end address, total 16KB
+	la	$4, 0x1ffff000		// physical address and 4KB page mask
+cache_alloc_a_line:
+	and	$5, $2, $4
+	ori	$5, $5, 1		// V bit of the physical tag
+	mtc0	$5, $28, 0		// CP0_TAGLO
+	cache	0x8, 0($2)		// Index_Store_Tag_I
+	cache	0x9, 0($2)		// Index_Store_Tag_D
+	bne	$2, $3, cache_alloc_a_line
+	addiu	$2, $2, 32		// increment CACHE_LINE_SIZE
+
+	nop
+	nop
+	nop
+	//--------------------------------------------------------------
+	// Transfer data from dcache to icache, then jump to icache.
+	//
+	// Input parameters:
+	//
+	// $19: data length in bytes
+	// $20: jump target address
+	//--------------------------------------------------------------
+xfer_d2i:
+
+	ori	$8, $20, 0
+	addu	$9, $8, $19		// total 16KB
+
+1:
+	cache	0x0, 0($8)		// Index_Invalidate_I
+	cache	0x1, 0($8)		// Index_Writeback_Inv_D
+	bne	$8, $9, 1b
+	addiu	$8, $8, 32
+
+	// flush write-buffer
+	sync
+
+	// Invalidate BTB
+	mfc0	$8, $16, 7		// CP0_CONFIG
+	nop
+	ori	$8, 2
+	mtc0	$8, $16, 7
+	nop
+
+	// Overwrite config to disable ram initalisation
+	li $2, 0xff
+	sb $2, 20($20)
+
+	jalr	$20
+	nop
+
+icache_return:
+	//--------------------------------------------------------------
+	// User code can return to here after executing itself in 
+	// icache, by jumping to $31.
+	//--------------------------------------------------------------
+	b	usb_boot_return
+	nop
+
+
+usb_boot_return:
+	//--------------------------------------------------------------
+	// Enable the USB PHY
+	//--------------------------------------------------------------
+	la	$9, 0xB0000024		// CPM_SCR
+	lw	$8, 0($9)
+	ori	$8, 0x40		// USBPHY_ENABLE
+	sw	$8, 0($9)
+
+	//--------------------------------------------------------------
+	// Initialize USB registers
+	//--------------------------------------------------------------
+	la	$27, 0xb3040000		// USB registers base address
+
+	sb	$0, 0x0b($27)		// INTRUSBE: disable common USB interrupts
+	sh	$0, 0x06($27)		// INTRINE: disable EPIN interrutps
+	sh	$0, 0x08($27)		// INTROUTE: disable EPOUT interrutps
+
+	li	$9, 0x61
+	sb	$9, 0x01($27)		// POWER: HSENAB | SUSPENDM | SOFTCONN
+
+	//--------------------------------------------------------------
+	// Initialize USB states
+	//--------------------------------------------------------------
+	li	$22, 0			// set EP0 to IDLE state
+	li	$23, 1			// no data stage
+
+	//--------------------------------------------------------------
+	// Main loop of polling the usb commands
+	//--------------------------------------------------------------
+usb_command_loop:
+	lbu	$9, 0x0a($27)		// read INTRUSB
+	andi	$9, 0x04		// check USB_INTR_RESET
+	beqz	$9, check_intr_ep0in
+	nop
+
+	//--------------------------------------------------------------
+ 	// 1. Handle USB reset interrupt
+	//--------------------------------------------------------------
+handle_reset_intr:
+	lbu	$9, 0x01($27)		// read POWER
+	andi	$9, 0x10		// test HS_MODE
+	bnez	$9, _usb_set_maxpktsize
+	li	$9, 512			// max packet size of HS mode
+	li	$9, 64			// max packet size of FS mode
+
+_usb_set_maxpktsize:
+	li	$8, 1
+	sb	$8, 0x0e($27)		// set INDEX 1
+
+	sh	$9, 0x10($27)		// INMAXP
+	sb	$0, 0x13($27)		// INCSRH
+	sh	$9, 0x14($27)		// OUTMAXP
+	sb	$0, 0x17($27)		// OUTCSRH
+
+_usb_flush_fifo:
+	li	$8, 0x48		// INCSR_CDT && INCSR_FF
+	sb	$8, 0x12($27)		// INCSR
+	li	$8, 0x90		// OUTCSR_CDT && OUTCSR_FF
+	sb	$8, 0x16($27)		// OUTCSR
+
+	li	$22, 0			// set EP0 to IDLE state
+	li	$23, 1			// no data stage
+
+	//--------------------------------------------------------------
+	// 2. Check and handle EP0 interrupt
+	//--------------------------------------------------------------
+check_intr_ep0in:
+	lhu	$10, 0x02($27)		// read INTRIN
+	andi	$9, $10, 0x1		// check EP0 interrupt
+	beqz	$9, check_intr_ep1in
+	nop
+
+handle_ep0_intr:
+	sb	$0, 0x0e($27)		// set INDEX 0
+	lbu	$11, 0x12($27)		// read CSR0
+
+	andi	$9, $11, 0x04		// check SENTSTALL
+	beqz	$9, _ep0_setupend
+	nop
+
+_ep0_sentstall:
+	andi	$9, $11, 0xdb
+	sb	$9, 0x12($27)		// clear SENDSTALL and SENTSTALL
+	li	$22, 0			// set EP0 to IDLE state
+
+_ep0_setupend:
+	andi	$9, $11, 0x10		// check SETUPEND
+	beqz	$9, ep0_idle_state
+	nop
+
+	ori	$9, $11, 0x80
+	sb	$9, 0x12($27)		// set SVDSETUPEND
+	li	$22, 0			// set EP0 to IDLE state
+
+ep0_idle_state:
+	bnez	$22, ep0_tx_state
+	nop
+
+	//--------------------------------------------------------------
+	// 2.1 Handle EP0 IDLE state interrupt
+	//--------------------------------------------------------------
+	andi	$9, $11, 0x01		// check OUTPKTRDY
+	beqz	$9, check_intr_ep1in
+	nop
+
+	//--------------------------------------------------------------
+	// Read 8-bytes setup packet from the FIFO
+	//--------------------------------------------------------------
+	lw	$25, 0x20($27)		// first word of setup packet
+	lw	$26, 0x20($27)		// second word of setup packet
+
+	andi	$9, $25, 0x60		// bRequestType & USB_TYPE_MASK
+	beqz	$9, _ep0_std_req
+	nop
+
+	//--------------------------------------------------------------
+	// 2.1.1 Vendor-specific setup request
+	//--------------------------------------------------------------
+_ep0_vend_req:
+	li	$22, 0			// set EP0 to IDLE state
+	li	$23, 1			// NoData = 1
+
+	andi	$9, $25, 0xff00		// check bRequest
+	srl	$9, $9, 8
+	beqz	$9, __ep0_get_cpu_info
+	sub	$8, $9, 0x1
+	beqz	$8, __ep0_set_data_address
+	sub	$8, $9, 0x2
+	beqz	$8, __ep0_set_data_length
+	sub	$8, $9, 0x3
+	beqz	$8, __ep0_flush_caches
+	sub	$8, $9, 0x4
+	beqz	$8, __ep0_prog_start1
+	sub	$8, $9, 0x5
+	beqz	$8, __ep0_prog_start2
+	nop
+	b	_ep0_idle_state_fini	// invalid request
+	nop
+
+__ep0_get_cpu_info:
+	load_addr $20, cpu_info_data	// data pointer to transfer
+	li	$21, 8			// bytes left to transfer
+	li	$22, 1			// set EP0 to TX state
+	li	$23, 0			// NoData = 0
+
+	b	_ep0_idle_state_fini
+	nop
+
+__ep0_set_data_address:
+	li	$9, 0xffff0000
+	and	$9, $25, $9
+	andi	$8, $26, 0xffff
+	or	$20, $9, $8		// data address of next transfer
+
+	b	_ep0_idle_state_fini
+	nop
+
+__ep0_set_data_length:
+	li	$9, 0xffff0000
+	and	$9, $25, $9
+	andi	$8, $26, 0xffff
+	or	$21, $9, $8		// data length of next transfer
+
+	li	$9, 0x48		// SVDOUTPKTRDY and DATAEND
+	sb	$9, 0x12($27)		// CSR0
+
+	// We must write packet to FIFO before EP1-IN interrupt here.
+	b	handle_epin1_intr
+	nop
+
+__ep0_flush_caches:
+	// Flush dcache and invalidate icache.
+	li	$8, 0x80000000
+	addi	$9, $8, 0x3fe0		// total 16KB
+
+1:
+	cache	0x0, 0($8)		// Index_Invalidate_I
+	cache	0x1, 0($8)		// Index_Writeback_Inv_D
+	bne	$8, $9, 1b
+	addiu	$8, $8, 32
+
+	// flush write-buffer
+	sync
+
+	// Invalidate BTB
+	mfc0	$8, $16, 7		// CP0_CONFIG
+	nop
+	ori	$8, 2
+	mtc0	$8, $16, 7
+	nop
+
+	b	_ep0_idle_state_fini
+	nop
+
+__ep0_prog_start1:
+	li	$9, 0x48		// SVDOUTPKTRDY and DATAEND
+	sb	$9, 0x12($27)		// CSR0
+
+	li	$9, 0xffff0000
+	and	$9, $25, $9
+	andi	$8, $26, 0xffff
+	or	$20, $9, $8		// target address
+
+	b	xfer_d2i
+	li	$19, 0x2000		// 16KB data length
+
+__ep0_prog_start2:
+	li	$9, 0x48		// SVDOUTPKTRDY and DATAEND
+	sb	$9, 0x12($27)		// CSR0
+
+	li	$9, 0xffff0000
+	and	$9, $25, $9
+	andi	$8, $26, 0xffff
+	or	$20, $9, $8		// target address
+
+	jalr	$20			// jump, and place the return address in $31
+	nop
+
+__ep0_prog_start2_return:
+	// User code can return to here after executing itself, by jumping to $31.
+	b	usb_boot_return
+	nop
+
+	//--------------------------------------------------------------
+	// 2.1.2 Standard setup request
+	//--------------------------------------------------------------
+_ep0_std_req:
+	andi	$12, $25, 0xff00	// check bRequest
+	srl	$12, $12, 8
+	sub	$9, $12, 0x05		// check USB_REQ_SET_ADDRESS
+	bnez	$9, __ep0_req_set_config
+	nop
+
+	//--------------------------------------------------------------
+	// Handle USB_REQ_SET_ADDRESS
+	//--------------------------------------------------------------
+__ep0_req_set_addr:
+	srl	$9, $25, 16		// get wValue
+	sb	$9, 0x0($27)		// set FADDR
+	li	$23, 1			// NoData = 1
+	b	_ep0_idle_state_fini
+	nop
+
+__ep0_req_set_config:
+	sub	$9, $12, 0x09		// check USB_REQ_SET_CONFIGURATION
+	bnez	$9, __ep0_req_get_desc
+	nop
+
+	//--------------------------------------------------------------
+	// Handle USB_REQ_SET_CONFIGURATION
+	//--------------------------------------------------------------
+	li	$23, 1			// NoData = 1
+	b	_ep0_idle_state_fini
+	nop
+
+__ep0_req_get_desc:
+	sub	$9, $12, 0x06		// check USB_REQ_GET_DESCRIPTOR
+	bnez	$9, _ep0_idle_state_fini
+	li	$23, 1			// NoData = 1
+
+	//--------------------------------------------------------------
+	// Handle USB_REQ_GET_DESCRIPTOR
+	//--------------------------------------------------------------
+	li	$23, 0			// NoData = 0
+
+	srl	$9, $25, 24		// wValue >> 8
+	sub	$8, $9, 0x01		// check USB_DT_DEVICE
+	beqz	$8, ___ep0_get_dev_desc
+	srl	$21, $26, 16		// get wLength
+	sub	$8, $9, 0x02		// check USB_DT_CONFIG
+	beqz	$8, ___ep0_get_conf_desc
+	sub	$8, $9, 0x03		// check USB_DT_STRING
+	beqz	$8, ___ep0_get_string_desc
+	sub	$8, $9, 0x06		// check USB_DT_DEVICE_QUALIFIER
+	beqz	$8, ___ep0_get_dev_qualifier
+	nop
+	b	_ep0_idle_state_fini
+	nop
+
+___ep0_get_dev_desc:
+	load_addr	$20, device_desc	// data pointer
+	li	$22, 1			// set EP0 to TX state
+	sub	$8, $21, 18
+	blez	$8, _ep0_idle_state_fini // wLength <= 18
+	nop
+	li	$21, 18			// max length of device_desc
+	b	_ep0_idle_state_fini
+	nop
+
+___ep0_get_dev_qualifier:
+	load_addr	$20, dev_qualifier	// data pointer
+	li	$22, 1			// set EP0 to TX state
+	sub	$8, $21, 10
+	blez	$8, _ep0_idle_state_fini // wLength <= 10
+	nop
+	li	$21, 10			// max length of dev_qualifier
+	b	_ep0_idle_state_fini
+	nop
+
+___ep0_get_conf_desc:
+	load_addr	$20, config_desc_fs	// data pointer of FS mode
+	lbu	$8, 0x01($27)		// read POWER
+	andi	$8, 0x10		// test HS_MODE
+	beqz	$8, ___ep0_get_conf_desc2
+	nop
+	load_addr $20, config_desc_hs	// data pointer of HS mode
+
+___ep0_get_conf_desc2:
+	li	$22, 1			// set EP0 to TX state
+	sub	$8, $21, 32
+	blez	$8, _ep0_idle_state_fini // wLength <= 32
+	nop
+	li	$21, 32			// max length of config_desc
+	b	_ep0_idle_state_fini
+	nop
+
+___ep0_get_string_desc:
+	li	$22, 1			// set EP0 to TX state
+
+	srl	$9, $25, 16		// wValue & 0xff
+	andi	$9, 0xff
+
+	sub	$8, $9, 1
+	beqz	$8, ___ep0_get_string_manufacture
+	sub	$8, $9, 2
+	beqz	$8, ___ep0_get_string_product
+	nop
+
+___ep0_get_string_lang_ids:
+	load_addr	$20, string_lang_ids	// data pointer
+	b	_ep0_idle_state_fini
+	li	$21, 4			// data length
+
+___ep0_get_string_manufacture:
+	load_addr	$20, string_manufacture	// data pointer
+	b	_ep0_idle_state_fini
+	li	$21, 16			// data length
+
+___ep0_get_string_product:
+	load_addr	$20, string_product	// data pointer
+	b	_ep0_idle_state_fini
+	li	$21, 46			// data length
+
+_ep0_idle_state_fini:
+	li	$9, 0x40		// SVDOUTPKTRDY
+	beqz	$23, _ep0_idle_state_fini2
+	nop
+	ori	$9, $9, 0x08		// DATAEND
+_ep0_idle_state_fini2:
+	sb	$9, 0x12($27)		// CSR0
+	beqz	$22, check_intr_ep1in
+	nop
+
+	//--------------------------------------------------------------
+	// 2.2 Handle EP0 TX state interrupt
+	//--------------------------------------------------------------
+ep0_tx_state:
+	sub	$9, $22, 1
+	bnez	$9, check_intr_ep1in
+	nop
+
+	sub	$9, $21, 64		// max packetsize
+	blez	$9, _ep0_tx_state2	// data count <= 64
+	ori	$19, $21, 0
+	li	$19, 64
+
+_ep0_tx_state2:
+	beqz	$19, _ep0_tx_state3	// send ZLP
+	ori	$18, $19, 0		// record bytes to be transferred
+	sub	$21, $21, $19		// decrement data count
+
+_ep0_fifo_write_loop:
+	lbu	$9, 0($20)		// read data
+	sb	$9, 0x20($27)		// load FIFO
+	sub	$19, $19, 1		// decrement counter
+	bnez	$19, _ep0_fifo_write_loop
+	addi	$20, $20, 1		// increment data pointer
+
+	sub	$9, $18, 64		// max packetsize
+	beqz	$9, _ep0_tx_state4
+	nop
+
+_ep0_tx_state3:
+	// transferred bytes < max packetsize
+	li	$9, 0x0a		// set INPKTRDY and DATAEND
+	sb	$9, 0x12($27)		// CSR0
+	li	$22, 0			// set EP0 to IDLE state
+	b	check_intr_ep1in
+	nop
+
+_ep0_tx_state4:
+	// transferred bytes == max packetsize
+	li	$9, 0x02		// set INPKTRDY
+	sb	$9, 0x12($27)		// CSR0
+	b	check_intr_ep1in
+	nop
+
+	//--------------------------------------------------------------
+	// 3. Check and handle EP1 BULK-IN interrupt
+	//--------------------------------------------------------------
+check_intr_ep1in:
+	andi	$9, $10, 0x2		// check EP1 IN interrupt
+	beqz	$9, check_intr_ep1out
+	nop
+
+handle_epin1_intr:
+	li	$9, 1
+	sb	$9, 0x0e($27)		// set INDEX 1
+	lbu	$9, 0x12($27)		// read INCSR
+
+	andi	$8, $9, 0x2		// check INCSR_FFNOTEMPT
+	bnez	$8, _epin1_tx_state4
+	nop
+
+_epin1_write_fifo:
+	lhu	$9, 0x10($27)		// get INMAXP
+	sub	$8, $21, $9
+	blez	$8, _epin1_tx_state1	// bytes left <= INMAXP
+	ori	$19, $21, 0
+	ori	$19, $9, 0
+
+_epin1_tx_state1:
+	beqz	$19, _epin1_tx_state4	// No data
+	nop
+
+	sub	$21, $21, $19		// decrement data count
+
+	srl	$5, $19, 2		// # of word
+	andi	$6, $19, 0x3		// # of byte
+	beqz	$5, _epin1_tx_state2
+	nop
+
+_epin1_fifo_write_word:
+	lw	$9, 0($20)		// read data from source address
+	sw	$9, 0x24($27)		// write FIFO
+	sub	$5, $5, 1		// decrement counter
+	bnez	$5, _epin1_fifo_write_word
+	addiu	$20, $20, 4		// increment dest address
+
+_epin1_tx_state2:
+	beqz	$6, _epin1_tx_state3
+	nop
+
+_epin1_fifo_write_byte:
+	lbu	$9, 0($20)		// read data from source address
+	sb	$9, 0x24($27)		// write FIFO
+	sub	$6, $6, 1		// decrement counter
+	bnez	$6, _epin1_fifo_write_byte
+	addiu	$20, $20, 1		// increment dest address
+
+_epin1_tx_state3:
+	li	$9, 0x1
+	sb	$9, 0x12($27)		// INCSR, set INPKTRDY
+
+_epin1_tx_state4:
+	// nop
+
+	//--------------------------------------------------------------
+	// 4. Check and handle EP1 BULK-OUT interrupt
+	//--------------------------------------------------------------
+check_intr_ep1out:
+	lhu	$9, 0x04($27)		// read INTROUT
+	andi	$9, 0x2
+	beqz	$9, check_status_next
+	nop
+
+handle_epout1_intr:
+	li	$9, 1
+	sb	$9, 0x0e($27)		// set INDEX 1
+
+	lbu	$9, 0x16($27)		// read OUTCSR
+	andi	$9, 0x1			// check OUTPKTRDY
+	beqz	$9, check_status_next
+	nop
+
+_epout1_read_fifo:
+	lhu	$19, 0x18($27)		// read OUTCOUNT
+	srl	$5, $19, 2		// # of word
+	andi	$6, $19, 0x3		// # of byte
+	beqz	$5, _epout1_rx_state1
+	nop
+
+_epout1_fifo_read_word:
+	lw	$9, 0x24($27)		// read FIFO
+	sw	$9, 0($20)		// store to dest address
+	sub	$5, $5, 1		// decrement counter
+	bnez	$5, _epout1_fifo_read_word
+	addiu	$20, $20, 4		// increment dest address
+
+_epout1_rx_state1:
+	beqz	$6, _epout1_rx_state2
+	nop
+
+_epout1_fifo_read_byte:
+	lbu	$9, 0x24($27)		// read FIFO
+	sb	$9, 0($20)		// store to dest address
+	sub	$6, $6, 1		// decrement counter
+	bnez	$6, _epout1_fifo_read_byte
+	addiu	$20, $20, 1		// increment dest address
+
+_epout1_rx_state2:
+	sb	$0, 0x16($27)		// clear OUTPKTRDY
+
+check_status_next:
+	b	usb_command_loop
+	nop
+
+//--------------------------------------------------------------
+// Device/Configuration/Interface/Endpoint/String Descriptors
+//--------------------------------------------------------------
+
+	.align	2
+device_desc:
+	.byte	0x12		// bLength
+	.byte	0x01		// bDescriptorType
+	.byte	0x00		// bcdUSB
+	.byte	0x02		// bcdUSB
+	.byte	0x00		// bDeviceClass
+	.byte	0x00		// bDeviceSubClass
+	.byte	0x00		// bDeviceProtocol
+	.byte	0x40		// bMaxPacketSize0
+	.byte	0x1a		// idVendor
+	.byte	0x60		// idVendor
+	.byte	0x40		// idProduct
+	.byte	0x47		// idProduct
+	.byte	0x00		// bcdDevice
+	.byte	0x01		// bcdDevice
+	.byte	0x01		// iManufacturer
+	.byte	0x02		// iProduct
+	.byte	0x00		// iSerialNumber
+	.byte	0x01		// bNumConfigurations
+
+	.align	2
+dev_qualifier:
+	.byte	0x0a		// bLength
+	.byte	0x06		// bDescriptorType
+	.byte	0x00		// bcdUSB
+	.byte	0x02		// bcdUSB
+	.byte	0x00		// bDeviceClass
+	.byte	0x00		// bDeviceSubClass
+	.byte	0x00		// bDeviceProtocol
+	.byte	0x40		// bMaxPacketSize0
+	.byte	0x01		// bNumConfigurations
+	.byte	0x00		// bRESERVED
+
+	.align	2
+config_desc_hs:
+	.byte	0x09		// bLength
+	.byte	0x02		// bDescriptorType
+	.byte	0x20		// wTotalLength
+	.byte	0x00		// wTotalLength
+	.byte	0x01		// bNumInterfaces
+	.byte	0x01		// bConfigurationValue
+	.byte	0x00		// iConfiguration
+	.byte	0xc0		// bmAttributes
+	.byte	0x01		// MaxPower
+intf_desc_hs:
+	.byte	0x09		// bLength
+	.byte	0x04		// bDescriptorType
+	.byte	0x00		// bInterfaceNumber
+	.byte	0x00		// bAlternateSetting
+	.byte	0x02		// bNumEndpoints
+	.byte	0xff		// bInterfaceClass
+	.byte	0x00		// bInterfaceSubClass
+	.byte	0x50		// bInterfaceProtocol
+	.byte	0x00		// iInterface
+ep1_desc_hs:
+	.byte	0x07		// bLength
+	.byte	0x05		// bDescriptorType
+	.byte	0x01		// bEndpointAddress
+	.byte	0x02		// bmAttributes
+	.byte	0x00		// wMaxPacketSize
+	.byte	0x02		// wMaxPacketSize
+	.byte	0x00		// bInterval
+ep2_desc_hs:
+	.byte	0x07		// bLength
+	.byte	0x05		// bDescriptorType
+	.byte	0x81		// bEndpointAddress
+	.byte	0x02		// bmAttributes
+	.byte	0x00		// wMaxPacketSize
+	.byte	0x02		// wMaxPacketSize
+	.byte	0x00		// bInterval
+
+	.align	2
+config_desc_fs:
+	.byte	0x09		// bLength
+	.byte	0x02		// bDescriptorType
+	.byte	0x20		// wTotalLength
+	.byte	0x00		// wTotalLength
+	.byte	0x01		// bNumInterfaces
+	.byte	0x01		// bConfigurationValue
+	.byte	0x00		// iConfiguration
+	.byte	0xc0		// bmAttributes
+	.byte	0x01		// MaxPower
+intf_desc_fs:
+	.byte	0x09		// bLength
+	.byte	0x04		// bDescriptorType
+	.byte	0x00		// bInterfaceNumber
+	.byte	0x00		// bAlternateSetting
+	.byte	0x02		// bNumEndpoints
+	.byte	0xff		// bInterfaceClass
+	.byte	0x00		// bInterfaceSubClass
+	.byte	0x50		// bInterfaceProtocol
+	.byte	0x00		// iInterface
+ep1_desc_fs:
+	.byte	0x07		// bLength
+	.byte	0x05		// bDescriptorType
+	.byte	0x01		// bEndpointAddress
+	.byte	0x02		// bmAttributes
+	.byte	0x40		// wMaxPacketSize
+	.byte	0x00		// wMaxPacketSize
+	.byte	0x00		// bInterval
+ep2_desc_fs:
+	.byte	0x07		// bLength
+	.byte	0x05		// bDescriptorType
+	.byte	0x81		// bEndpointAddress
+	.byte	0x02		// bmAttributes
+	.byte	0x40		// wMaxPacketSize
+	.byte	0x00		// wMaxPacketSize
+	.byte	0x00		// bInterval
+
+	.align	2
+string_lang_ids:
+	.byte	0x04
+	.byte	0x03
+	.byte	0x09
+	.byte	0x04
+
+	.align	2
+string_manufacture:
+	.byte	0x10
+	.byte	0x03
+	.byte	0x49
+	.byte	0x00
+	.byte	0x6e
+	.byte	0x00
+	.byte	0x67
+	.byte	0x00
+	.byte	0x65
+	.byte	0x00
+	.byte	0x6e
+	.byte	0x00
+	.byte	0x69
+	.byte	0x00
+	.byte	0x63
+	.byte	0x00
+
+	.align	2
+string_product:
+	.byte	0x2e
+	.byte	0x03
+	.byte	0x4a
+	.byte	0x00
+	.byte	0x5a
+	.byte	0x00
+	.byte	0x34
+	.byte	0x00
+	.byte	0x37
+	.byte	0x00
+	.byte	0x34
+	.byte	0x00
+	.byte	0x30
+	.byte	0x00
+	.byte	0x20
+	.byte	0x00
+	.byte	0x55
+	.byte	0x00
+	.byte	0x53
+	.byte	0x00
+	.byte	0x42
+	.byte	0x00
+	.byte	0x20
+	.byte	0x00
+	.byte	0x42
+	.byte	0x00
+	.byte	0x6f
+	.byte	0x00
+	.byte	0x6f
+	.byte	0x00
+	.byte	0x74
+	.byte	0x00
+	.byte	0x20
+	.byte	0x00
+	.byte	0x44
+	.byte	0x00
+	.byte	0x65
+	.byte	0x00
+	.byte	0x76
+	.byte	0x00
+	.byte	0x69
+	.byte	0x00
+	.byte	0x63
+	.byte	0x00
+	.byte	0x65
+	.byte	0x00
+
+	.align	2
+cpu_info_data:
+	.byte	0x4a
+	.byte	0x5a
+	.byte	0x34
+	.byte	0x37
+	.byte	0x34
+	.byte	0x30
+	.byte	0x56
+	.byte	0x31
+usbboot_end:
+
+    .set reorder
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 3/5] jz4740 nand spl files
       [not found]   ` <1289446657-12499-3-git-send-email-xiangfu@openmobilefree.net>
@ 2010-11-11  3:37     ` Xiangfu Liu
  2010-11-11  3:37       ` [U-Boot] [PATCH 4/5] jz4740 nand driver Xiangfu Liu
                         ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Xiangfu Liu @ 2010-11-11  3:37 UTC (permalink / raw)
  To: u-boot

From: Xiangfu Liu <xiangfu@sharism.cc>

Signed-off-by: Xiangfu Liu <xiangfu@openmobilefree.net>
---
 nand_spl/board/xburst/nanonote/Makefile   |   96 +++++++
 nand_spl/board/xburst/nanonote/u-boot.lds |   63 +++++
 nand_spl/nand_boot_jz4740.c               |  395 +++++++++++++++++++++++++++++
 3 files changed, 554 insertions(+), 0 deletions(-)
 create mode 100644 nand_spl/board/xburst/nanonote/Makefile
 create mode 100644 nand_spl/board/xburst/nanonote/u-boot.lds
 create mode 100644 nand_spl/nand_boot_jz4740.c

diff --git a/nand_spl/board/xburst/nanonote/Makefile b/nand_spl/board/xburst/nanonote/Makefile
new file mode 100644
index 0000000..f5d1eb5
--- /dev/null
+++ b/nand_spl/board/xburst/nanonote/Makefile
@@ -0,0 +1,96 @@
+#
+# (C) Copyright 2006
+# Stefan Roese, DENX Software Engineering, sr at 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
+#
+
+include $(TOPDIR)/config.mk
+TEXT_BASE = 0x80000000
+
+LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
+LDFLAGS	= -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE)
+AFLAGS	+= -DCONFIG_NAND_SPL
+CFLAGS	+= -DCONFIG_NAND_SPL -O2
+
+SOBJS	= start.o usbboot.o
+COBJS	= nand_boot_jz4740.o cpu.o jz4740.o jz_serial.o
+
+SRCS	:= $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+__OBJS	:= $(SOBJS) $(COBJS)
+LNDIR	:= $(OBJTREE)/nand_spl/board/$(BOARDDIR)
+
+nandobj	:= $(OBJTREE)/nand_spl/
+
+ALL	= $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
+all:	$(obj).depend $(ALL)
+
+$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl.bin
+	dd bs=1024 count=8 if=/dev/zero of=$(nandobj)junk1
+	cat $< $(nandobj)junk1 > $(nandobj)junk2
+	dd bs=1024 count=8 if=$(nandobj)junk2 of=$(nandobj)junk3
+	cat $(nandobj)junk3 $(nandobj)junk3 > $(nandobj)junk4
+	dd bs=1024 count=256 if=/dev/zero of=$(nandobj)junk5
+	cat $(nandobj)junk4 $(nandobj)junk5 > $(nandobj)junk6
+	dd bs=1024 count=256 if=$(nandobj)junk6 of=$@
+	rm -f $(nandobj)junk*
+
+$(nandobj)u-boot-spl.bin:	$(nandobj)u-boot-spl
+	$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
+
+$(nandobj)u-boot-spl:	$(OBJS)
+	cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
+		-Map $(nandobj)u-boot-spl.map \
+		-o $(nandobj)u-boot-spl
+
+# create symbolic links for common files
+$(obj)start.S:
+	@rm -f $(obj)start.S
+	ln -s $(SRCTREE)/arch/mips/cpu/xburst/start_spl.S $(obj)start.S
+
+$(obj)usbboot.S:
+	@rm -f $(obj)usbboot.S
+	ln -s $(SRCTREE)/arch/mips/cpu/xburst/usbboot.S $(obj)usbboot.S
+
+$(obj)cpu.c:
+	@rm -f $(obj)cpu.c
+	ln -s $(SRCTREE)/arch/mips/cpu/xburst/cpu.c $(obj)cpu.c
+
+$(obj)jz4740.c:
+	@rm -f $(obj)jz4740.c
+	ln -s $(SRCTREE)/arch/mips/cpu/xburst/jz4740.c $(obj)jz4740.c
+
+$(obj)jz_serial.c:
+	@rm -f $(obj)jz_serial.c
+	ln -s $(SRCTREE)/arch/mips/cpu/xburst/jz_serial.c $(obj)jz_serial.c
+
+$(obj)nand_boot_jz4740.c:
+	@rm -f $(obj)nand_boot_jz4740.c
+	ln -s $(SRCTREE)/nand_spl/nand_boot_jz4740.c $(obj)nand_boot_jz4740.c
+
+$(obj)%.o:	$(obj)%.S
+	$(CC) $(AFLAGS) -c -o $@ $<
+
+$(obj)%.o:	$(obj)%.c
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
diff --git a/nand_spl/board/xburst/nanonote/u-boot.lds b/nand_spl/board/xburst/nanonote/u-boot.lds
new file mode 100644
index 0000000..7042388
--- /dev/null
+++ b/nand_spl/board/xburst/nanonote/u-boot.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2005
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text       :
+	{
+	  *(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata  : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data  : { *(.data) }
+
+	. = ALIGN(4);
+	.sdata  : { *(.sdata) }
+
+	_gp = ALIGN(16);
+
+	__got_start = .;
+	.got  : { *(.got) }
+	__got_end = .;
+
+	.sdata  : { *(.sdata) }
+
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	uboot_end_data = .;
+	num_got_entries = (__got_end - __got_start) >> 2;
+
+	. = ALIGN(4);
+	.sbss  : { *(.sbss) }
+	.bss  : { *(.bss) }
+	uboot_end = .;
+}
diff --git a/nand_spl/nand_boot_jz4740.c b/nand_spl/nand_boot_jz4740.c
new file mode 100644
index 0000000..44fe95d
--- /dev/null
+++ b/nand_spl/nand_boot_jz4740.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2007 Ingenic Semiconductor Inc.
+ * Author: Peter <jlwei@ingenic.cn>
+ *
+ * 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 <common.h>
+#include <nand.h>
+
+#include <asm/jz4740.h>
+
+#define KEY_U_OUT       (32 * 2 + 16)
+#define KEY_U_IN        (32 * 3 + 19)
+
+/*
+ * NAND flash definitions
+ */
+#define NAND_DATAPORT	0xb8000000
+#define NAND_ADDRPORT	0xb8010000
+#define NAND_COMMPORT	0xb8008000
+
+#define __nand_enable()		(REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
+#define __nand_disable()	(REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
+#define __nand_ecc_rs_encoding() \
+	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
+#define __nand_ecc_rs_decoding() \
+	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
+#define __nand_ecc_disable()	(REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
+#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
+#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
+#define __nand_cmd(n)		(REG8(NAND_COMMPORT) = (n))
+#define __nand_addr(n)		(REG8(NAND_ADDRPORT) = (n))
+#define __nand_data8()		REG8(NAND_DATAPORT)
+#define __nand_data16()		REG16(NAND_DATAPORT)
+
+#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R3)
+	#define NAND_BUS_WIDTH 8
+	#define NAND_ROW_CYCLE 3
+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R2)
+	#define NAND_BUS_WIDTH 8
+	#define NAND_ROW_CYCLE 2
+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R3)
+	#define NAND_BUS_WIDTH 16
+	#define NAND_ROW_CYCLE 3
+#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R2)
+	#define NAND_BUS_WIDTH 16
+	#define NAND_ROW_CYCLE 2
+#endif
+
+static inline void __nand_dev_ready(void)
+{
+	unsigned int timeout = 10000;
+	while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
+	while (!(REG_GPIO_PXPIN(2) & 0x40000000));
+}
+
+/*
+ * NAND flash parameters
+ */
+static int page_size = 2048;
+static int oob_size = 64;
+static int ecc_count = 4;
+static int page_per_block = 64;
+static int bad_block_pos = 0;
+static int block_size = 131072;
+static unsigned char oob_buf[128] = {0};
+
+/*
+ * External routines
+ */
+extern void flush_cache_all(void);
+extern int serial_init(void);
+extern void serial_puts(const char *s);
+extern void sdram_init(void);
+extern void pll_init(void);
+extern void usb_boot();
+
+/*
+ * NAND flash routines
+ */
+#if NAND_BUS_WIDTH == 16
+static inline void nand_read_buf16(void *buf, int count)
+{
+	int i;
+	u16 *p = (u16 *)buf;
+
+	for (i = 0; i < count; i += 2)
+		*p++ = __nand_data16();
+}
+#define nand_read_buf nand_read_buf16
+
+#elif NAND_BUS_WIDTH == 8
+static inline void nand_read_buf8(void *buf, int count)
+{
+	int i;
+	u8 *p = (u8 *)buf;
+
+	for (i = 0; i < count; i++)
+		*p++ = __nand_data8();
+}
+#define nand_read_buf nand_read_buf8
+
+#endif
+
+/* Correct 1~9-bit errors in 512-bytes data */
+static void rs_correct(unsigned char *dat, int idx, int mask)
+{
+	int i;
+
+	idx--;
+
+	i = idx + (idx >> 3);
+	if (i >= 512)
+		return;
+
+	mask <<= (idx & 0x7);
+
+	dat[i] ^= mask & 0xff;
+	if (i < 511)
+		dat[i+1] ^= (mask >> 8) & 0xff;
+}
+
+static int nand_read_oob(int page_addr, uchar *buf, int size)
+{
+	int col_addr;
+	if (page_size != 512)
+		col_addr = page_size;
+	else {
+		col_addr = 0;
+		__nand_dev_ready();
+	}
+
+	if (page_size != 512)
+		/* Send READ0 command */
+		__nand_cmd(NAND_CMD_READ0);
+	else
+		/* Send READOOB command */
+		__nand_cmd(NAND_CMD_READOOB);
+
+	/* Send column address */
+	__nand_addr(col_addr & 0xff);
+	if (page_size != 512)
+		__nand_addr((col_addr >> 8) & 0xff);
+
+	/* Send page address */
+	__nand_addr(page_addr & 0xff);
+	__nand_addr((page_addr >> 8) & 0xff);
+	#if defined NAND_ROW_CYCLE && NAND_ROW_CYCLE == 3
+		__nand_addr((page_addr >> 16) & 0xff);
+	#endif
+
+	/* Send READSTART command for 2048 or 4096 ps NAND */
+	if (page_size != 512)
+		__nand_cmd(NAND_CMD_READSTART);
+
+	/* Wait for device ready */
+	__nand_dev_ready();
+
+	/* Read oob data */
+	nand_read_buf(buf, size);
+	if (page_size == 512)
+		__nand_dev_ready();
+	return 0;
+}
+
+static int nand_read_page(int page_addr, uchar *dst, uchar *oobbuf)
+{
+	uchar *databuf = dst, *tmpbuf;
+	int i, j;
+
+	/*
+	 * Read oob data
+	 */
+	nand_read_oob(page_addr, oobbuf, oob_size);
+
+	/*
+	 * Read page data
+	 */
+	/* Send READ0 command */
+	__nand_cmd(NAND_CMD_READ0);
+
+	/* Send column address */
+	__nand_addr(0);
+	if (page_size != 512)
+		__nand_addr(0);
+
+	/* Send page address */
+	__nand_addr(page_addr & 0xff);
+	__nand_addr((page_addr >> 8) & 0xff);
+	#if defined NAND_ROW_CYCLE && NAND_ROW_CYCLE == 3
+		__nand_addr((page_addr >> 16) & 0xff);
+	#endif
+
+	/* Send READSTART command for 2048 or 4096 ps NAND */
+	if (page_size != 512)
+		__nand_cmd(NAND_CMD_READSTART);
+
+	/* Wait for device ready */
+	__nand_dev_ready();
+
+	/* Read page data */
+	tmpbuf = databuf;
+
+	for (i = 0; i < ecc_count; i++) {
+		volatile unsigned char *paraddr = (volatile unsigned char *)EMC_NFPAR0;
+		unsigned int stat;
+
+		/* Enable RS decoding */
+		REG_EMC_NFINTS = 0x0;
+		__nand_ecc_rs_decoding();
+
+		/* Read data */
+		nand_read_buf((void *)tmpbuf, CONFIG_SYS_NAND_ECCSIZE);
+
+		/* Set PAR values */
+		for (j = 0; j < CONFIG_SYS_NAND_ECCBYTES; j++)
+			*paraddr++ = oobbuf[CONFIG_SYS_NAND_ECC_POS + i*CONFIG_SYS_NAND_ECCBYTES + j];
+
+		/* Set PRDY */
+		REG_EMC_NFECR |= EMC_NFECR_PRDY;
+
+		/* Wait for completion */
+		__nand_ecc_decode_sync();
+
+		/* Disable decoding */
+		__nand_ecc_disable();
+
+		/* Check result of decoding */
+		stat = REG_EMC_NFINTS;
+		if (stat & EMC_NFINTS_ERR) {
+			/* Error occurred */
+			/* serial_puts("Error occurred\n"); */
+			if (stat & EMC_NFINTS_UNCOR) {
+				/* Uncorrectable error occurred */
+				/* serial_puts("Uncorrectable error occurred\n"); */
+			} else {
+				unsigned int errcnt, index, mask;
+
+				errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
+				switch (errcnt) {
+				case 4:
+					index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+					mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+					rs_correct(tmpbuf, index, mask);
+					/* FALL-THROUGH */
+				case 3:
+					index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+					mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+					rs_correct(tmpbuf, index, mask);
+					/* FALL-THROUGH */
+				case 2:
+					index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+					mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+					rs_correct(tmpbuf, index, mask);
+					/* FALL-THROUGH */
+				case 1:
+					index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
+					mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
+					rs_correct(tmpbuf, index, mask);
+					break;
+				default:
+					break;
+				}
+			}
+		}
+		tmpbuf += CONFIG_SYS_NAND_ECCSIZE;
+	}
+
+	return 0;
+}
+
+#ifndef CONFIG_SYS_NAND_BADBLOCK_PAGE
+#define CONFIG_SYS_NAND_BADBLOCK_PAGE 0 /* NAND bad block was marked at this page in a block, starting from 0 */
+#endif
+
+static void nand_load(int offs, int uboot_size, uchar *dst)
+{
+	int page;
+	int pagecopy_count;
+
+	__nand_enable();
+
+	page = offs / page_size;
+	pagecopy_count = 0;
+	while (pagecopy_count < (uboot_size / page_size)) {
+		if (page % page_per_block == 0) {
+			nand_read_oob(page + CONFIG_SYS_NAND_BADBLOCK_PAGE, oob_buf, oob_size);
+			if (oob_buf[bad_block_pos] != 0xff) {
+				page += page_per_block;
+				/* Skip bad block */
+				continue;
+			}
+		}
+		/* Load this page to dst, do the ECC */
+		nand_read_page(page, dst, oob_buf);
+
+		dst += page_size;
+		page++;
+		pagecopy_count++;
+	}
+
+	__nand_disable();
+}
+
+static void jz_nand_init(void) {
+ 	/* Optimize the timing of nand */
+	REG_EMC_SMCR1 = 0x094c4400;
+}
+
+static void gpio_init(void)
+{
+	/*
+	 * Initialize SDRAM pins
+	 */
+	__gpio_as_sdram_16bit_4720();
+
+	/*
+	 * Initialize UART0 pins
+	 */
+	__gpio_as_uart0();
+	__gpio_jtag_to_uart0();
+}
+
+static int is_usb_boot()
+{
+	__gpio_as_input(KEY_U_IN);
+	__gpio_enable_pull(KEY_U_IN);
+	__gpio_as_output(KEY_U_OUT);
+	__gpio_clear_pin(KEY_U_OUT);
+
+	if (__gpio_get_pin(KEY_U_IN) == 0)
+		return 1;
+
+	return 0;
+}
+
+void nand_boot(void)
+{
+	void (*uboot)(void);
+
+	/*
+	 * Init hardware
+	 */
+	gpio_init();
+	pll_init();
+
+	serial_init();
+	sdram_init();
+	jz_nand_init();
+
+	serial_puts("\nNAND Boot\n");
+
+#if defined(CONFIG_NANONOTE)
+	if(is_usb_boot()) {
+		serial_puts("[U] pressed, goto USBBOOT mode\n");
+		usb_boot();
+	}
+#endif
+	page_size = CONFIG_SYS_NAND_PAGE_SIZE;
+	block_size = CONFIG_SYS_NAND_BLOCK_SIZE;
+	page_per_block = CONFIG_SYS_NAND_BLOCK_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;
+	bad_block_pos = (page_size == 512) ? 5 : 0;
+	oob_size = page_size / 32;
+	ecc_count = page_size / CONFIG_SYS_NAND_ECCSIZE;
+
+	/*
+	 * Load U-Boot image from NAND into RAM
+	 */
+	nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
+		  (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
+
+	uboot = (void (*)(void))CONFIG_SYS_NAND_U_BOOT_START;
+
+	serial_puts("Starting U-Boot ...\n");
+
+	/* Flush caches */
+	flush_cache_all();
+
+	/* Jump to U-Boot image */
+	(*uboot)();
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 4/5] jz4740 nand driver
  2010-11-11  3:37     ` [U-Boot] [PATCH 3/5] jz4740 nand spl files Xiangfu Liu
@ 2010-11-11  3:37       ` Xiangfu Liu
  2010-11-11  3:37         ` [U-Boot] [PATCH 5/5] add Ben NanoNote board Xiangfu Liu
  2010-11-15 23:02         ` [U-Boot] [PATCH 4/5] jz4740 nand driver Scott Wood
  2010-11-11  7:32       ` [U-Boot] [PATCH 3/5] jz4740 nand spl files Wolfgang Denk
  2010-11-15 22:56       ` Scott Wood
  2 siblings, 2 replies; 11+ messages in thread
From: Xiangfu Liu @ 2010-11-11  3:37 UTC (permalink / raw)
  To: u-boot

From: Xiangfu Liu <xiangfu@sharism.cc>

Signed-off-by: Xiangfu Liu <xiangfu@openmobilefree.net>
---
 drivers/mtd/nand/jz4740_nand.c |  250 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 250 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/jz4740_nand.c

diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
new file mode 100644
index 0000000..f661b36
--- /dev/null
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -0,0 +1,250 @@
+/*
+ * Platform independend driver for JZ4740.
+ *
+ * Copyright (c) 2007 Ingenic Semiconductor Inc.
+ * Author: <jlwei@ingenic.cn>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+#include <common.h>
+
+#if defined(CONFIG_CMD_NAND)
+#include <nand.h>
+#include <asm/io.h>
+#include <asm/jz4740.h>
+
+#define __nand_ecc_enable()		(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST )
+#define __nand_ecc_disable()		(REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
+
+#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
+#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
+#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
+
+#define BIT(x) (1 << (x))
+#define JZ_NAND_ECC_CTRL_ENCODING	BIT(3)
+#define JZ_NAND_ECC_CTRL_RS		BIT(2)
+#define JZ_NAND_ECC_CTRL_RESET		BIT(1)
+#define JZ_NAND_ECC_CTRL_ENABLE		BIT(0)
+
+static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
+	.eccbytes = 72,
+	.eccpos = {
+		12, 13, 14, 15, 16, 17, 18, 19,
+		20, 21, 22, 23, 24, 25, 26, 27, 
+		28, 29, 30, 31, 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, 64, 65, 66, 67, 
+		68, 69, 70, 71, 72, 73, 74, 75, 
+		76, 77, 78, 79, 80, 81, 82, 83},
+	.oobfree = {
+ 		{.offset = 2,
+		 .length = 10},
+		{.offset = 84,
+		 .length = 44}}
+};
+
+static int is_reading;
+
+static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		if (ctrl & NAND_ALE)
+			this->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
+		else if (ctrl & NAND_CLE)
+			this->IO_ADDR_W = JZ_NAND_CMD_ADDR;
+		else
+			this->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+		if (ctrl & NAND_NCE)
+			REG_EMC_NFCSR |= EMC_NFCSR_NFCE1; 
+		else
+			REG_EMC_NFCSR &= ~EMC_NFCSR_NFCE1;
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W);
+}
+
+static int jz_nand_device_ready(struct mtd_info *mtd)
+{
+	udelay(20);
+	return (REG_GPIO_PXPIN(2) & 0x40000000) ? 1 : 0;
+}
+
+void board_nand_select_device(struct nand_chip *nand, int chip)
+{
+	/*
+	 * Don't use "chip" to address the NAND device,
+	 * generate the cs from the address where it is encoded.
+	 */
+}
+
+static int jz_nand_rs_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
+				u_char* ecc_code)
+{
+	uint32_t reg, status;
+	int i;
+	volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
+
+	if(is_reading)
+		return 0;
+
+	do {
+		status = REG_EMC_NFINTS;
+	} while(!(status & EMC_NFINTS_ENCF));
+
+	__nand_ecc_disable();
+
+	for(i = 0; i < 9; i++)
+		ecc_code[i] = *(paraddr + i);
+
+	return 0;
+}
+
+static void jz_nand_hwctl(struct mtd_info* mtd, int mode)
+{
+	uint32_t reg;
+	REG_EMC_NFINTS = 0;
+	reg = REG_EMC_NFECR;
+	reg |= JZ_NAND_ECC_CTRL_RESET;
+	reg |= JZ_NAND_ECC_CTRL_ENABLE;
+	reg |= JZ_NAND_ECC_CTRL_RS;
+
+	switch(mode) {
+	case NAND_ECC_READ:
+		reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
+		is_reading = 1;
+		break;
+	case NAND_ECC_WRITE:
+		reg |= JZ_NAND_ECC_CTRL_ENCODING;
+		is_reading = 0;
+		break;
+	default:
+		break;
+	}
+
+	REG_EMC_NFECR = reg;
+}
+
+/* Correct 1~9-bit errors in 512-bytes data */
+static void jz_rs_correct(unsigned char *dat, int idx, int mask)
+{
+	int i;
+
+	idx--;
+
+	i = idx + (idx >> 3);
+	if (i >= 512)
+		return;
+
+	mask <<= (idx & 0x7);
+
+	dat[i] ^= mask & 0xff;
+	if (i < 511)
+		dat[i+1] ^= (mask >> 8) & 0xff;
+}
+
+static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
+				   u_char *read_ecc, u_char *calc_ecc)
+{
+	int k;
+	uint32_t reg, status;
+	volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
+
+	/* Set PAR values */
+	static uint8_t all_ff_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4, 0x8b, 0xff, 0xb7, 0x6f};
+	if (read_ecc[0] == 0xff && 
+	    read_ecc[1] == 0xff &&
+	    read_ecc[2] == 0xff &&
+	    read_ecc[3] == 0xff &&
+	    read_ecc[4] == 0xff &&
+	    read_ecc[5] == 0xff &&
+	    read_ecc[6] == 0xff &&
+	    read_ecc[7] == 0xff &&
+	    read_ecc[8] == 0xff) {
+		for (k = 0; k < 9; k++)
+			*(paraddr + k) = all_ff_ecc[k];
+	} else {
+
+		for (k = 0; k < 9; k++)
+			*(paraddr + k) = read_ecc[k];
+	}
+	/* Set PRDY */
+	REG_EMC_NFECR |= EMC_NFECR_PRDY;
+
+	/* Wait for completion */
+	do {
+		status = REG_EMC_NFINTS;
+	} while (!(status & EMC_NFINTS_DECF));
+
+	__nand_ecc_disable();
+
+	/* Check decoding */
+	if (status & EMC_NFINTS_ERR) {
+		if (status & EMC_NFINTS_UNCOR) {
+			printk("uncorrectable ecc\n");
+			while(1);
+			return -1;
+		}
+
+		uint32_t errcnt = (status & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
+		switch (errcnt) {
+		case 4:
+			jz_rs_correct(dat, 
+				      (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, 
+				      (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+		case 3:
+			jz_rs_correct(dat, 
+				      (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, 
+				      (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+		case 2:
+			jz_rs_correct(dat, 
+				      (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, 
+				      (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+		case 1:
+			jz_rs_correct(dat, 
+				      (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, 
+				      (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
+			return errcnt;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Main initialization routine
+ */
+int board_nand_init(struct nand_chip *nand)
+{
+	/* EMC setup, Set NFE bit */
+	REG_EMC_NFCSR |= EMC_NFCSR_NFE1;
+	REG_EMC_SMCR1 = 0x094c4400;
+	/* REG_EMC_SMCR3 = 0x04444400; */
+
+	nand->IO_ADDR_R		= JZ_NAND_DATA_ADDR;
+	nand->IO_ADDR_W		= JZ_NAND_DATA_ADDR;
+	nand->cmd_ctrl		= jz_nand_cmd_ctrl;
+	nand->dev_ready		= jz_nand_device_ready;
+
+	nand->ecc.hwctl		= jz_nand_hwctl;
+	nand->ecc.correct	= jz_nand_rs_correct_data;
+	nand->ecc.calculate	= jz_nand_rs_calculate_ecc;
+	nand->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
+	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
+	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.layout	= &qi_lb60_ecclayout_2gb;
+	nand->chip_delay	= 50;
+
+	return 0;
+}
+#endif /* (CONFIG_CMD_NAND) */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 5/5] add Ben NanoNote board
  2010-11-11  3:37       ` [U-Boot] [PATCH 4/5] jz4740 nand driver Xiangfu Liu
@ 2010-11-11  3:37         ` Xiangfu Liu
  2010-11-11  8:28           ` Wolfgang Denk
  2010-11-15 23:02         ` [U-Boot] [PATCH 4/5] jz4740 nand driver Scott Wood
  1 sibling, 1 reply; 11+ messages in thread
From: Xiangfu Liu @ 2010-11-11  3:37 UTC (permalink / raw)
  To: u-boot

From: Xiangfu Liu <xiangfu@sharism.cc>

Signed-off-by: Xiangfu Liu <xiangfu@openmobilefree.net>
---
 board/xburst/nanonote/Makefile        |   45 ++++++++
 board/xburst/nanonote/config.mk       |   31 ++++++
 board/xburst/nanonote/nanonote.c      |  124 ++++++++++++++++++++++
 board/xburst/nanonote/u-boot-nand.lds |   63 +++++++++++
 include/configs/nanonote.h            |  188 +++++++++++++++++++++++++++++++++
 include/configs/qi_lb60.h             |   28 +++++
 6 files changed, 479 insertions(+), 0 deletions(-)
 create mode 100644 board/xburst/nanonote/Makefile
 create mode 100644 board/xburst/nanonote/config.mk
 create mode 100644 board/xburst/nanonote/nanonote.c
 create mode 100644 board/xburst/nanonote/u-boot-nand.lds
 create mode 100644 include/configs/nanonote.h
 create mode 100644 include/configs/qi_lb60.h

diff --git a/board/xburst/nanonote/Makefile b/board/xburst/nanonote/Makefile
new file mode 100644
index 0000000..a4f6bd0
--- /dev/null
+++ b/board/xburst/nanonote/Makefile
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2006
+# Ingenic Semiconductor, <jlwei@ingenic.cn>
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).a
+
+COBJS	:= $(BOARD).o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/xburst/nanonote/config.mk b/board/xburst/nanonote/config.mk
new file mode 100644
index 0000000..858e6a2
--- /dev/null
+++ b/board/xburst/nanonote/config.mk
@@ -0,0 +1,31 @@
+#
+# (C) Copyright 2006 Qi Hardware, Inc.
+# Author: Xiangfu Liu <xiangfu.z@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This 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
+#
+
+#
+# Qi Hardware, Inc. Ben NanoNote (QI_LB60)
+#
+
+ifndef TEXT_BASE
+# ROM version
+# TEXT_BASE = 0x88000000
+
+# RAM version
+TEXT_BASE = 0x80100000
+endif
diff --git a/board/xburst/nanonote/nanonote.c b/board/xburst/nanonote/nanonote.c
new file mode 100644
index 0000000..ef9552a
--- /dev/null
+++ b/board/xburst/nanonote/nanonote.c
@@ -0,0 +1,124 @@
+/*
+ * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 3 of the License, or (at your option) any later version.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/jz4740.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void gpio_init(void)
+{
+	/*
+	 * Initialize NAND Flash Pins
+	 */
+	__gpio_as_nand();
+
+	/*
+	 * Initialize SDRAM pins
+	 */
+	__gpio_as_sdram_16bit_4720();
+
+	/*
+	 * Initialize LCD pins
+	 */
+	__gpio_as_lcd_18bit();
+
+	/*
+	 * Initialize MSC pins
+	 */
+	__gpio_as_msc();
+
+	/*
+	 * Initialize Other pins
+	 */
+	unsigned int i;
+	for (i = 0; i < 7; i++){
+		__gpio_as_input(GPIO_KEYIN_BASE + i);
+		__gpio_enable_pull(GPIO_KEYIN_BASE + i);
+	}
+
+	for (i = 0; i < 8; i++) {
+		__gpio_as_output(GPIO_KEYOUT_BASE + i);
+		__gpio_clear_pin(GPIO_KEYOUT_BASE + i);
+	}
+
+	/* enable the TP4, TP5 as UART0 */
+	__gpio_jtag_to_uart0();
+
+	/*
+	 * Initialize UART0 pins, in Ben NanoNote uart0 and keyin8 use the
+	 * same gpio, init the gpio as uart0 cause a keyboard bug. so for
+	 * end user we disable the uart0
+	 */
+	if (__gpio_get_pin(GPIO_KEYIN_BASE + 2) == 0){
+		/* if pressed [S] */
+		printf("[S] pressed, enable UART0\n");
+		gd->boot_option |= BOOT_WITH_ENABLE_UART;
+		__gpio_as_uart0();
+	} else {
+		__gpio_as_input(GPIO_KEYIN_8);
+		__gpio_enable_pull(GPIO_KEYIN_8);
+	}
+
+	__gpio_as_output(GPIO_AUDIO_POP);
+	__gpio_set_pin(GPIO_AUDIO_POP);
+
+	__gpio_as_output(GPIO_LCD_CS);
+	__gpio_clear_pin(GPIO_LCD_CS);
+
+	__gpio_as_output(GPIO_AMP_EN);
+	__gpio_clear_pin(GPIO_AMP_EN);
+
+	__gpio_as_output(GPIO_SDPW_EN);
+	__gpio_disable_pull(GPIO_SDPW_EN);
+	__gpio_clear_pin(GPIO_SDPW_EN);
+
+	__gpio_as_input(GPIO_SD_DETECT);
+	__gpio_disable_pull(GPIO_SD_DETECT);
+
+	__gpio_as_input(GPIO_USB_DETECT);
+	__gpio_enable_pull(GPIO_USB_DETECT);
+
+	if (__gpio_get_pin(GPIO_KEYIN_BASE + 3) == 0) {
+		printf("[M] pressed, boot from sd card\n");
+		gd->boot_option |= BOOT_FROM_SDCARD;
+	}
+}
+
+static void cpm_init(void)
+{
+	__cpm_stop_ipu();
+	__cpm_stop_cim();
+	__cpm_stop_i2c();
+	__cpm_stop_ssi();
+	__cpm_stop_uart1();
+	__cpm_stop_sadc();
+	__cpm_stop_uhc();
+	__cpm_stop_udc();
+	__cpm_stop_aic1();
+/*	__cpm_stop_aic2();*/
+}
+
+void board_early_init(void)
+{
+	gpio_init();
+	cpm_init();
+}
+
+/* U-Boot common routines */
+
+int checkboard (void)
+{
+	printf("Board: Qi LB60 (Ingenic XBurst Jz4740 SoC, Speed %d MHz)\n",
+	       gd->cpu_clk / 1000000);
+
+	return 0; /* success */
+}
diff --git a/board/xburst/nanonote/u-boot-nand.lds b/board/xburst/nanonote/u-boot-nand.lds
new file mode 100644
index 0000000..a15a96e
--- /dev/null
+++ b/board/xburst/nanonote/u-boot-nand.lds
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2006
+ * Ingenic Semiconductor, <jlwei@ingenic.cn>
+ *
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradlittlemips", "elf32-tradlittlemips")
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text       :
+	{
+	  *(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata  : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data  : { *(.data) }
+
+	. = ALIGN(4);
+	.sdata  : { *(.sdata) }
+
+	_gp = ALIGN(16);
+
+	__got_start = .;
+	.got  : { *(.got) }
+	__got_end = .;
+
+	.sdata  : { *(.sdata) }
+
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	uboot_end_data = .;
+	num_got_entries = (__got_end - __got_start) >> 2;
+
+	. = ALIGN(4);
+	.sbss  : { *(.sbss) }
+	.bss  : { *(.bss) }
+	uboot_end = .;
+}
diff --git a/include/configs/nanonote.h b/include/configs/nanonote.h
new file mode 100644
index 0000000..648202e
--- /dev/null
+++ b/include/configs/nanonote.h
@@ -0,0 +1,188 @@
+/*
+ * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 3 of the License, or (at your option) any later version.
+ */
+
+/*
+ * This file contains the configuration parameters for the NanoNote.
+ */
+#ifndef __CONFIG_NANONOTE_H
+#define __CONFIG_NANONOTE_H
+
+#define CONFIG_MIPS32		1  /* MIPS32 CPU core */
+#define CONFIG_JZSOC		1  /* Jz SoC */
+#define CONFIG_JZ4740		1  /* Jz4740 SoC */
+#define CONFIG_NAND_JZ4740
+#define CONFIG_NANONOTE
+
+#define BOOT_FROM_SDCARD	1
+#define BOOT_WITH_ENABLE_UART	(1 << 1)	/* Vaule for global_data.h gd->boot_option */
+
+#define CONFIG_SYS_CPU_SPEED	336000000	/* CPU clock: 336 MHz */
+#define CONFIG_SYS_EXTAL	12000000	/* EXTAL freq: 12 MHz */
+#define CONFIG_SYS_HZ		(CONFIG_SYS_EXTAL / 256) /* incrementer freq */
+#define CONFIG_SYS_MIPS_TIMER_FREQ	CONFIG_SYS_CPU_SPEED
+
+#define CONFIG_SYS_UART_BASE	UART0_BASE	/* Base of the UART channel */
+#define CONFIG_BAUDRATE		57600
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+#define CONFIG_SKIP_LOWLEVEL_INIT	1
+#define CONFIG_BOARD_EARLY_INIT_F	1
+#define CONFIG_SYS_NO_FLASH	1
+#define CONFIG_SYS_FLASH_BASE	0 /* init flash_base as 0 */
+#define CONFIG_ENV_OVERWRITE	1
+
+#define CONFIG_BOOTP_MASK	(CONFIG_BOOTP_DEFAUL)
+#define CONFIG_BOOTDELAY	0
+/*
+ * Command line configuration.
+ */
+#define CONFIG_CMD_BOOTD	/* bootd			*/
+#define CONFIG_CMD_CONSOLE	/* coninfo			*/
+#define CONFIG_CMD_ECHO		/* echo arguments		*/
+
+#define CONFIG_CMD_LOADB	/* loadb			*/
+#define CONFIG_CMD_LOADS	/* loads			*/
+#define CONFIG_CMD_MEMORY	/* md mm nm mw cp cmp crc base loop mtest */
+#define CONFIG_CMD_MISC		/* Misc functions like sleep etc*/
+#define CONFIG_CMD_RUN		/* run command in env variable	*/
+#define CONFIG_CMD_SAVEENV	/* saveenv			*/
+#define CONFIG_CMD_SETGETDCR	/* DCR support on 4xx		*/
+#define CONFIG_CMD_SOURCE	/* "source" command support	*/
+#define CONFIG_CMD_NAND
+
+/*
+ * Serial download configuration
+ */
+#define CONFIG_LOADS_ECHO	1	/* echo on for serial download */
+#define CONFIG_LOADS_BAUD_CHANGE	1	/* allow baudrate change */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define	CONFIG_SYS_LONGHELP		/* undef to save memory */
+#define	CONFIG_SYS_PROMPT		"NanoNote# "	/* Monitor Command Prompt */
+#define	CONFIG_SYS_CBSIZE		256	/* Console I/O Buffer Size */
+#define	CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+/* Print Buffer Size */
+#define	CONFIG_SYS_MAXARGS		16	/* max number of command args*/
+
+#define CONFIG_SYS_MALLOC_LEN		896 * 1024
+#define CONFIG_SYS_BOOTPARAMS_LEN	128 * 1024
+
+#define CONFIG_SYS_SDRAM_BASE		0x80000000     /* Cached addr */
+#define CONFIG_SYS_INIT_SP_OFFSET	0x400000
+#define CONFIG_SYS_LOAD_ADDR		0x80600000     /* default load address */
+#define CONFIG_SYS_MEMTEST_START	0x80100000
+#define CONFIG_SYS_MEMTEST_END		0x80800000
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_IS_IN_NAND	1	/* use NAND for environment vars */
+
+/*
+ * NAND FLASH configuration
+ */
+#define CONFIG_SYS_64BIT_VSPRINTF	/* needed for nand_util.c */
+
+/* NAND Boot config code */
+#define JZ4740_NANDBOOT_CFG	JZ4740_NANDBOOT_B8R3
+
+#define NANONOTE_NAND_SIZE	2 /* if board nand flash is 1GB, set to 1
+				   * if board nand flash is 2GB, set to 2
+				   * for change the PAGE_SIZE and BLOCK_SIZE
+				   * will delete when there is no 1GB flash
+				   */
+
+#define CONFIG_SYS_NAND_PAGE_SIZE	(2048 * NANONOTE_NAND_SIZE)
+/* nand chip block size	*/
+#define CONFIG_SYS_NAND_BLOCK_SIZE	(256 * NANONOTE_NAND_SIZE << 10)
+/* nand bad block was marked@this page in a block, start from 0 */
+#define CONFIG_SYS_NAND_BADBLOCK_PAGE	127
+/* ECC offset position in oob area, default value is 6 if it isn't defined */
+#define CONFIG_SYS_NAND_ECC_POS		(6 * NANONOTE_NAND_SIZE)
+#define CONFIG_SYS_NAND_ECCSIZE		512
+#define CONFIG_SYS_NAND_ECCBYTES	9
+
+#define CONFIG_SYS_NAND_BASE		0xB8000000
+#define CONFIG_SYS_ONENAND_BASE		CONFIG_SYS_NAND_BASE
+#define NAND_MAX_CHIPS			1
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_SELECT_DEVICE	1 /* nand driver supports mutipl.*/
+
+/*
+ * IPL (Initial Program Loader, integrated inside CPU)
+ * Will load first 8k from NAND (SPL) into cache and execute it from there.
+ *
+ * SPL (Secondary Program Loader)
+ * Will load special U-Boot version (NUB) from NAND and execute it. This SPL
+ * has to fit into 8kByte. It sets up the CPU and configures the SDRAM
+ * controller and the NAND controller so that the special U-Boot image can be
+ * loaded from NAND to SDRAM.
+ *
+ * NUB (NAND U-Boot)
+ * This NAND U-Boot (NUB) is a special U-Boot version which can be started
+ * from RAM. Therefore it mustn't (re-)configure the SDRAM controller.
+ *
+ */
+#define CONFIG_SYS_NAND_U_BOOT_DST	0x80100000	/* Load NUB to this addr */
+#define CONFIG_SYS_NAND_U_BOOT_START	CONFIG_SYS_NAND_U_BOOT_DST 
+/* Start NUB from this addr*/
+
+/*
+ * Define the partitioning of the NAND chip (only RAM U-Boot is needed here)
+ */
+#define CONFIG_SYS_NAND_U_BOOT_OFFS	(256 << 10)	/* Offset to RAM U-Boot image */
+#define CONFIG_SYS_NAND_U_BOOT_SIZE	(512 << 10)	/* Size of RAM U-Boot image */
+
+#define CONFIG_ENV_SIZE		(4 << 10)
+#define CONFIG_ENV_OFFSET	(CONFIG_SYS_NAND_BLOCK_SIZE + CONFIG_SYS_NAND_U_BOOT_SIZE)
+#define CONFIG_ENV_OFFSET_REDUND	(CONFIG_ENV_OFFSET  + CONFIG_SYS_NAND_BLOCK_SIZE)
+
+/* in board/nanonote/config.mk TEXT_BAS = 0x88000000 */
+#define CONFIG_SYS_MONITOR_BASE	TEXT_BASE
+
+/*
+ * SDRAM Info.
+ */
+#define CONFIG_NR_DRAM_BANKS	1
+
+/*
+ * Cache Configuration
+ */
+#define CONFIG_SYS_DCACHE_SIZE	16384
+#define CONFIG_SYS_ICACHE_SIZE	16384
+#define CONFIG_SYS_CACHELINE_SIZE	32
+
+/*
+ * GPIO definition
+ */
+#define GPIO_LCD_CS	(2 * 32 + 21)
+#define GPIO_AMP_EN	(3 * 32 + 4)
+
+#define GPIO_SDPW_EN	(3 * 32 + 2)
+#define	GPIO_SD_DETECT	(3 * 32 + 0)
+
+#define	GPIO_BUZZ_PWM	(3 * 32 + 27)
+#define	GPIO_USB_DETECT	(3 * 32 + 28)
+
+#define	GPIO_AUDIO_POP	(1 * 32 + 29)
+#define GPIO_COB_TEST	(1 * 32 + 30)
+
+#define	GPIO_KEYOUT_BASE	(2 * 32 + 10)
+#define	GPIO_KEYIN_BASE	(3 * 32 + 18)
+#define	GPIO_KEYIN_8	(3 * 32 + 26)
+
+#define GPIO_SD_CD_N	GPIO_SD_DETECT		/* SD Card insert detect */
+#define GPIO_SD_VCC_EN_N	GPIO_SDPW_EN	/* SD Card Power Enable */
+
+#define SPEN	GPIO_LCD_CS	/* LCDCS :Serial command enable      */
+#define SPDA	(2 * 32 + 22)	/* LCDSCL:Serial command clock input */
+#define SPCK	(2 * 32 + 23)	/* LCDSDA:Serial command data input  */
+#endif	/* __CONFIG_NANONOTE_H */
diff --git a/include/configs/qi_lb60.h b/include/configs/qi_lb60.h
new file mode 100644
index 0000000..29ec805
--- /dev/null
+++ b/include/configs/qi_lb60.h
@@ -0,0 +1,28 @@
+#ifndef __CONFIG_QI_LB60_H
+#define __CONFIG_QI_LB60_H
+
+#include <configs/nanonote.h>
+
+#define CONFIG_QI_LB60 1
+
+//#define DEBUG
+#define CONFIG_BOOTARGS		"mem=32M console=tty0 console=ttyS0,57600n8 ubi.mtd=2 rootfstype=ubifs root=ubi0:rootfs rw rootwait"
+#define CONFIG_BOOTARGSFROMSD	"mem=32M console=tty0 console=ttyS0,57600n8 rootfstype=ext2 root=/dev/mmcblk0p1 rw rootwait"
+#define CONFIG_BOOTCOMMAND	"nand read 0x80600000 0x400000 0x200000;bootm"
+#define CONFIG_BOOTCOMMANDFROMSD	"mmc init; ext2load mmc 0 0x80600000 /boot/uImage; bootm"
+
+/* SDRAM paramters */
+#define SDRAM_BW16		1	/* Data bus width: 0-32bit, 1-16bit */
+#define SDRAM_BANK4		1	/* Banks each chip: 0-2bank, 1-4bank */
+#define SDRAM_ROW		13	/* Row address: 11 to 13 */
+#define SDRAM_COL		9	/* Column address: 8 to 12 */
+#define SDRAM_CASL		2	/* CAS latency: 2 or 3 */
+
+/* SDRAM Timings, unit: ns */
+#define SDRAM_TRAS		45	/* RAS# Active Time */
+#define SDRAM_RCD		20	/* RAS# to CAS# Delay */
+#define SDRAM_TPC		20	/* RAS# Precharge Time */
+#define SDRAM_TRWL		7	/* Write Latency Time */
+#define SDRAM_TREF	        15625	/* Refresh period: 8192 cycles/64ms */
+
+#endif
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/5] those files are jz4740 base files
  2010-11-11  3:37 ` [U-Boot] [PATCH 1/5] those files are jz4740 base files Xiangfu Liu
       [not found]   ` <1289446657-12499-3-git-send-email-xiangfu@openmobilefree.net>
@ 2010-11-11  7:14   ` Wolfgang Denk
  2010-11-14 15:03   ` Shinya Kuribayashi
  2 siblings, 0 replies; 11+ messages in thread
From: Wolfgang Denk @ 2010-11-11  7:14 UTC (permalink / raw)
  To: u-boot

Dear Xiangfu Liu,

In message <1289446657-12499-2-git-send-email-xiangfu@openmobilefree.net> you wrote:
> From: Xiangfu Liu <xiangfu@sharism.cc>

Please use a more descriptive subject.

Explain what jz4740 is; also explain what xburst is. Whos is be=hind
it, what it's used for, etc.


> diff --git a/arch/mips/cpu/xburst/interrupts.c b/arch/mips/cpu/xburst/interrupts.c
> new file mode 100644
> index 0000000..87f7a9f
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/interrupts.c
...
> +void enable_interrupts(void)
> +{
> +}
> +
> +int disable_interrupts(void)
> +{
> +	return 0;
> +}

It does not seem you are using interrupts? If so, then omit this file
all together.

> diff --git a/arch/mips/cpu/xburst/jz4740.c b/arch/mips/cpu/xburst/jz4740.c
> new file mode 100644
> index 0000000..b8e9a15
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/jz4740.c
...
> +	pllout2 = (cfcr & CPM_CPCCR_PCS) ? CONFIG_SYS_CPU_SPEED : (CONFIG_SYS_CPU_SPEED / 2);

Line too long. Please fix globally.

> +	/* Init USB Host clock, pllout2 must be n*48MHz */
> +	REG_CPM_UHCCDR = pllout2 / 48000000 - 1;

What's REG_CPM_UHCCDR? This symbol is not defined anywhere in this
patch, which means that none of this code would ever compile.

If you split patches, please make sure they contain complete,
compilable code to make the commit bisectable.


To me this looks as if you are implementing these register accesses as
plain assignments to a volatile pointer, probably based on a register
base address plus offset calculation.  Please note that we will NOT
accept any such code in U-Boot.  Please use C structs to describe
functional units, and use proper I/O accessors to access any such
registers.

Please fix globally.

> +static void calc_clocks(void)
> +{
> +	DECLARE_GLOBAL_DATA_PTR;

This does not work. DECLARE_GLOBAL_DATA_PTR must never be used in
function scope; it must be used in file scope.

> +static void rtc_init(void)
> +{
> +	while ( !__rtc_write_ready()) ;

Please move semicolon to next line.

> +#if 0
> +	unsigned long rtcsta;
> +
> +	while ( !__rtc_write_ready())
> +		;
> +	rtcsta = REG_RTC_HWRSR;
> +	while ( !__rtc_write_ready())
> +		;
> +	if (rtcsta & 0x33) {
> +		if (rtcsta & 0x10) {
> +			while ( !__rtc_write_ready())
> +				;
> +			REG_RTC_RSR = 0x0;
> +		}
> +		while ( !__rtc_write_ready())
> +			;
> +		REG_RTC_HWRSR = 0x0;
> +	}
> +#endif

Please remove all such dead code.

> diff --git a/arch/mips/cpu/xburst/jz_serial.c b/arch/mips/cpu/xburst/jz_serial.c
> new file mode 100644
> index 0000000..c5cc28e
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/jz_serial.c
> @@ -0,0 +1,139 @@
> +/*
> + * Jz47xx UART support
> + *
> + * Hardcoded to UART 0 for now
> + * Options also hardcoded to 8N1
> + *
> + *  Copyright (c) 2005
> + *  Ingenic Semiconductor, <jlwei@ingenic.cn>
> + *
> + * 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 <config.h>
> +#include <common.h>
> +
> +#if defined(CONFIG_JZ4740)
> +#include <asm/jz4740.h>
> +#endif
> + 
> +#undef UART_BASE
> +#ifndef CONFIG_SYS_UART_BASE
> +#define UART_BASE  UART0_BASE
> +#else
> +#define UART_BASE  CONFIG_SYS_UART_BASE
> +#endif

This initial "#undef UART_BASE" looks fishy to me.  Please explain why
this is unavoidable here.

> +/******************************************************************************
> +*
> +* serial_init - initialize a channel

Incorrect multiline comment style. Please fix globally.

> +void serial_puts (const char *s)
> +{
> +	while (*s) {
> +		serial_putc (*s++);
> +	}

No braces needed for single line statements.  Please fix globally.

> +int serial_getc (void)
> +{
> +	volatile u8 *uart_rdr = (volatile u8 *)(UART_BASE + OFF_RDR);
> +
> +	while (!serial_tstc());

Please use a consistent style. Move the semicolon to the next line.
Please fix globally.

> +void __udelay (unsigned long usec)
> +{
> +	ulong tmo,tmp;
> +
> +	/* normalize */
> +	if (usec >= 1000) {
> +		tmo = usec / 1000;
> +		tmo *= TIMER_HZ;
> +		tmo /= 1000;
> +	}
> +	else {

Incorrect brace style.

> +		if (usec >= 1) {
> +			tmo = usec * TIMER_HZ;
> +			tmo /= (1000*1000);
> +		}
> +		else

Again. Please fix globally.

> +usb_boot:
> +	//--------------------------------------------------------------
> +	// Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
> +	//--------------------------------------------------------------
> +	la	$9, 0xB0000000		// CPCCR: Clock Control Register
> +	la	$8, 0x42041110		// I:S:M:P=1:2:2:2
> +	sw	$8, 0($9)

C++ comments are not allowed in U-Boot. Please fix globally.

Would it be possible to rewrite this file in C?


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
People have one thing in common: they are all different.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 3/5] jz4740 nand spl files
  2010-11-11  3:37     ` [U-Boot] [PATCH 3/5] jz4740 nand spl files Xiangfu Liu
  2010-11-11  3:37       ` [U-Boot] [PATCH 4/5] jz4740 nand driver Xiangfu Liu
@ 2010-11-11  7:32       ` Wolfgang Denk
  2010-11-15 22:56       ` Scott Wood
  2 siblings, 0 replies; 11+ messages in thread
From: Wolfgang Denk @ 2010-11-11  7:32 UTC (permalink / raw)
  To: u-boot

Dear Xiangfu Liu,

In message <1289446657-12499-4-git-send-email-xiangfu@openmobilefree.net> you wrote:
> From: Xiangfu Liu <xiangfu@sharism.cc>
> 
> Signed-off-by: Xiangfu Liu <xiangfu@openmobilefree.net>
> ---
>  nand_spl/board/xburst/nanonote/Makefile   |   96 +++++++
>  nand_spl/board/xburst/nanonote/u-boot.lds |   63 +++++
>  nand_spl/nand_boot_jz4740.c               |  395 +++++++++++++++++++++++++++++
>  3 files changed, 554 insertions(+), 0 deletions(-)
>  create mode 100644 nand_spl/board/xburst/nanonote/Makefile
>  create mode 100644 nand_spl/board/xburst/nanonote/u-boot.lds
>  create mode 100644 nand_spl/nand_boot_jz4740.c

You need to rework the splitting of your code into commits - as is,
these patches make no sense to me.  Please re-read
http://www.denx.de/wiki/view/U-Boot/Patches#General_Patch_Submission_Rules

> diff --git a/nand_spl/nand_boot_jz4740.c b/nand_spl/nand_boot_jz4740.c
> new file mode 100644
...
> +#define __nand_enable()		(REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
> +#define __nand_disable()	(REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
> +#define __nand_ecc_rs_encoding() \
> +	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
> +#define __nand_ecc_rs_decoding() \
> +	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
> +#define __nand_ecc_disable()	(REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
> +#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
> +#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
> +#define __nand_cmd(n)		(REG8(NAND_COMMPORT) = (n))
> +#define __nand_addr(n)		(REG8(NAND_ADDRPORT) = (n))
> +#define __nand_data8()		REG8(NAND_DATAPORT)
> +#define __nand_data16()		REG16(NAND_DATAPORT)

You seem to have a tendency to use "__" a lot in front of
indentifiers.  The C standard says:

   -- All identifiers that begin with an underscore and either an
      uppercase letter or another underscore are always reserved for
      any use.

   -- All identifiers that begin with an underscore are always
      reserved for use as identifiers with file scope in both the
      ordinary and tag name spaces.

Please recheck your identifier names with this in mind.

As mentioned before, this code needs to be converted to use I/O
accessors instead of these REG*() volatile pointer accesses.

Both comments apply globally.

...
> +		/* Check result of decoding */
> +		stat = REG_EMC_NFINTS;
> +		if (stat & EMC_NFINTS_ERR) {
> +			/* Error occurred */
> +			/* serial_puts("Error occurred\n"); */
> +			if (stat & EMC_NFINTS_UNCOR) {
> +				/* Uncorrectable error occurred */
> +				/* serial_puts("Uncorrectable error occurred\n"); */
> +			} else {
> +				unsigned int errcnt, index, mask;
> +
> +				errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
> +				switch (errcnt) {
> +				case 4:
> +					index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					/* FALL-THROUGH */
> +				case 3:
> +					index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					/* FALL-THROUGH */
> +				case 2:
> +					index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					/* FALL-THROUGH */
> +				case 1:
> +					index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					break;

Lines too long.


I stop reviewing here.

Please fix the code, and resubmit.

Thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
There's no honorable way to kill, no gentle way to destroy.  There is
nothing good in war.  Except its ending.
	-- Abraham Lincoln, "The Savage Curtain", stardate 5906.5

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 5/5] add Ben NanoNote board
  2010-11-11  3:37         ` [U-Boot] [PATCH 5/5] add Ben NanoNote board Xiangfu Liu
@ 2010-11-11  8:28           ` Wolfgang Denk
  0 siblings, 0 replies; 11+ messages in thread
From: Wolfgang Denk @ 2010-11-11  8:28 UTC (permalink / raw)
  To: u-boot

Dear Xiangfu Liu,

In message <1289446657-12499-6-git-send-email-xiangfu@openmobilefree.net> you wrote:
> From: Xiangfu Liu <xiangfu@sharism.cc>
> 
> Signed-off-by: Xiangfu Liu <xiangfu@openmobilefree.net>
> ---
>  board/xburst/nanonote/Makefile        |   45 ++++++++
>  board/xburst/nanonote/config.mk       |   31 ++++++
>  board/xburst/nanonote/nanonote.c      |  124 ++++++++++++++++++++++
>  board/xburst/nanonote/u-boot-nand.lds |   63 +++++++++++
>  include/configs/nanonote.h            |  188 +++++++++++++++++++++++++++++++++
>  include/configs/qi_lb60.h             |   28 +++++
>  6 files changed, 479 insertions(+), 0 deletions(-)
>  create mode 100644 board/xburst/nanonote/Makefile
>  create mode 100644 board/xburst/nanonote/config.mk
>  create mode 100644 board/xburst/nanonote/nanonote.c
>  create mode 100644 board/xburst/nanonote/u-boot-nand.lds
>  create mode 100644 include/configs/nanonote.h
>  create mode 100644 include/configs/qi_lb60.h

Entry to MAINTAINERS mssing.

Entry to boards.cfg missing.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Motto of the Electrical Engineer: Working computer hardware is a  lot
like an erect penis: it stays up as long as you don't fuck with it.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 1/5] those files are jz4740 base files
  2010-11-11  3:37 ` [U-Boot] [PATCH 1/5] those files are jz4740 base files Xiangfu Liu
       [not found]   ` <1289446657-12499-3-git-send-email-xiangfu@openmobilefree.net>
  2010-11-11  7:14   ` [U-Boot] [PATCH 1/5] those files are jz4740 base files Wolfgang Denk
@ 2010-11-14 15:03   ` Shinya Kuribayashi
  2 siblings, 0 replies; 11+ messages in thread
From: Shinya Kuribayashi @ 2010-11-14 15:03 UTC (permalink / raw)
  To: u-boot

On 11/11/2010 12:37 PM, Xiangfu Liu wrote:
> From: Xiangfu Liu <xiangfu@sharism.cc>

If possible, please describe what Jz4740 SoC is, an overview of JzRISC
processor, where this patch is from or where to get the original work,
and so on.

It also would be nice we could have Signed-off-by: or Acked-by: from
Ingenic people, as some files contains Ingenic copyright statements.
Please consider.

> diff --git a/arch/mips/cpu/xburst/config.mk b/arch/mips/cpu/xburst/config.mk
> new file mode 100644
> index 0000000..f43f53b
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/config.mk
> @@ -0,0 +1,33 @@
> +#
> +# (C) Copyright 2003
> +# 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
> +#
> +v=$(shell $(AS) --version | grep 'GNU assembler' | egrep -o '2\.[0-9\.]+' | cut -d. -f2)
> +MIPSFLAGS:=$(shell \
> +if [ "$v" -lt "14" ]; then \
> +	echo "-mcpu=4kc"; \
> +else \
> +	echo "-march=4kc -mtune=4kc"; \
> +fi)
> +
> +MIPSFLAGS += $(ENDIANNESS) -mabicalls -mips32

ENDIANNESS looks unused.  Jz47xx series are little endian SoCs, then
let's remove it.

> +PLATFORM_CPPFLAGS += $(MIPSFLAGS)
> diff --git a/arch/mips/cpu/xburst/cpu.c b/arch/mips/cpu/xburst/cpu.c
> new file mode 100644
> index 0000000..682debf
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/cpu.c
> @@ -0,0 +1,158 @@
[snip]
> +void flush_icache_all(void)
> +{
> +	u32 addr, t = 0;
> +
> +	asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
> +	asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
> +
> +	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE;
> +	     addr += CONFIG_SYS_CACHELINE_SIZE) {
> +		cache_op(Index_Store_Tag_I, addr);
> +	}
> +
> +	/* invalidate btb */
> +	asm volatile (
> +		".set mips32\n\t"
> +		"mfc0 %0, $16, 7\n\t"
> +		"nop\n\t"
> +		"ori %0,2\n\t"
> +		"mtc0 %0, $16, 7\n\t"
> +		".set mips2\n\t"
> +		:
> +		: "r" (t));
> +}

As pointed out before, incorrect use of assembler control.  Why set
mips32 without pushing the current control info, and why set it back
to mips2?  'noreorder' is also missing here.

	asm volatile (
		".set push\n\t"
		".set noreorder\n\t"
		".set mips32\n\t"
		"mfc0 %0, $16, 7\n\t"
		"nop\n\t"
		"ori %0, 2\n\t"
		"mtc0 %0, $16, 7\n\t"
		".set pop\n\t"
		:
		: "r" (t));
Hmm?

> +void flush_dcache_all(void)
> +{
> +	u32 addr;
> +
> +	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; 
> +	     addr += CONFIG_SYS_CACHELINE_SIZE) {
> +		cache_op(Index_Writeback_Inv_D, addr);
> +	}
> +
> +	asm volatile ("sync");
> +}
> +
> +void flush_cache_all(void)
> +{
> +	flush_dcache_all();
> +	flush_icache_all();
> +}
> diff --git a/arch/mips/cpu/xburst/jz4740.c b/arch/mips/cpu/xburst/jz4740.c
> new file mode 100644
> index 0000000..b8e9a15
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/jz4740.c

I couldn't mention about its validity of the following DRAM init code
from the technically POV.  As long as it works for you, I'm ok.  Most
of the code looks well-written conforming to the coding styles.  A few
trivial cleanups, please.

> @@ -0,0 +1,257 @@
> +/*
> + * Jz4740 common routines
> + *
> + *  Copyright (c) 2006
> + *  Ingenic Semiconductor, <jlwei@ingenic.cn>
> + *
> + * 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 <config.h>
> +#include <common.h>
> +
> +#include <asm/jz4740.h>
> +
> +/* PLL output clock = EXTAL * NF / (NR * NO)
> + *
> + * NF = FD + 2, NR = RD + 2
> + * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
> + */
> +void pll_init(void)
> +{
> +	register unsigned int cfcr, plcr1;
> +	int n2FR[33] = {
> +		0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
> +		7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
> +		9
> +	};
> +	int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
> +	int nf, pllout2;
> +
> +	cfcr = CPM_CPCCR_CLKOEN |
> +		CPM_CPCCR_PCS |
> +		(n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) |
> +		(n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) |
> +		(n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) |
> +		(n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) |
> +		(n2FR[div[4]] << CPM_CPCCR_LDIV_BIT);
> +
> +	pllout2 = (cfcr & CPM_CPCCR_PCS) ? CONFIG_SYS_CPU_SPEED : (CONFIG_SYS_CPU_SPEED / 2);

	pllout2 = (cfcr & CPM_CPCCR_PCS) ? CONFIG_SYS_CPU_SPEED :
					   (CONFIG_SYS_CPU_SPEED / 2);

> +	/* Init USB Host clock, pllout2 must be n*48MHz */
> +	REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
> +
> +	nf = CONFIG_SYS_CPU_SPEED * 2 / CONFIG_SYS_EXTAL;
> +	plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
> +		(0 << CPM_CPPCR_PLLN_BIT) |	/* RD=0, NR=2 */
> +		(0 << CPM_CPPCR_PLLOD_BIT) |    /* OD=0, NO=1 */
> +		(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
> +		CPM_CPPCR_PLLEN;                /* enable PLL */
> +
> +	/* init PLL */
> +	REG_CPM_CPCCR = cfcr;
> +	REG_CPM_CPPCR = plcr1;
> +}
> +
> +void sdram_init(void)
> +{
> +	register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
> +
> +	unsigned int cas_latency_sdmr[2] = {
> +		EMC_SDMR_CAS_2,
> +		EMC_SDMR_CAS_3,
> +	};
> +
> +	unsigned int cas_latency_dmcr[2] = {
> +		1 << EMC_DMCR_TCL_BIT,	/* CAS latency is 2 */
> +		2 << EMC_DMCR_TCL_BIT	/* CAS latency is 3 */
> +	};
> +
> +	int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
> +
> +	cpu_clk = CONFIG_SYS_CPU_SPEED;
> +	mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
> +
> +	REG_EMC_BCR = 0;	/* Disable bus release */
> +	REG_EMC_RTCSR = 0;	/* Disable clock for counting */
> +
> +	/* Fault DMCR value for mode register setting*/
> +#define SDRAM_ROW0    11
> +#define SDRAM_COL0     8
> +#define SDRAM_BANK40   0
> +
> +	dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
> +		((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
> +		(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
> +		(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
> +		EMC_DMCR_EPIN |
> +		cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];

Unless it breaks 80-charcter-wide rule, please provide whitespaces at
proper places.

	dmcr0 = ((SDRAM_ROW0 - 11) << EMC_DMCR_RA_BIT) |
		((SDRAM_COL0 - 8) << EMC_DMCR_CA_BIT) |
		(SDRAM_BANK40 << EMC_DMCR_BA_BIT) |
		(SDRAM_BW16 << EMC_DMCR_BW_BIT) |
		EMC_DMCR_EPIN |
		cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];

> +	/* Basic DMCR value */
> +	dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
> +		((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
> +		(SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
> +		(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
> +		EMC_DMCR_EPIN |
> +		cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];

Ditto.

> +	/* SDRAM timimg */
> +	ns = 1000000000 / mem_clk;
> +	tmp = SDRAM_TRAS/ns;
> +	if (tmp < 4) tmp = 4;
> +	if (tmp > 11) tmp = 11;
> +	dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
> +	tmp = SDRAM_RCD/ns;
> +	if (tmp > 3) tmp = 3;
> +	dmcr |= (tmp << EMC_DMCR_RCD_BIT);
> +	tmp = SDRAM_TPC/ns;
> +	if (tmp > 7) tmp = 7;
> +	dmcr |= (tmp << EMC_DMCR_TPC_BIT);
> +	tmp = SDRAM_TRWL/ns;
> +	if (tmp > 3) tmp = 3;
> +	dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
> +	tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
> +	if (tmp > 14) tmp = 14;
> +	dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
> +
> +	/* SDRAM mode value */
> +	sdmode = EMC_SDMR_BT_SEQ | 
> +		 EMC_SDMR_OM_NORMAL |
> +		 EMC_SDMR_BL_4 | 
> +		 cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
> +
> +	/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
> +	REG_EMC_DMCR = dmcr;
> +	REG8(EMC_SDMR0|sdmode) = 0;

	REG8(EMC_SDMR0 | sdmode) = 0;

> +	/* Wait for precharge, > 200us */
> +	tmp = (cpu_clk / 1000000) * 1000;
> +	while (tmp--);
> +
> +	/* Stage 2. Enable auto-refresh */
> +	REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
> +
> +	tmp = SDRAM_TREF/ns;
> +	tmp = tmp/64 + 1;
> +	if (tmp > 0xff) tmp = 0xff;
> +	REG_EMC_RTCOR = tmp;
> +	REG_EMC_RTCNT = 0;
> +	REG_EMC_RTCSR = EMC_RTCSR_CKS_64;	/* Divisor is 64, CKO/64 */
> +
> +	/* Wait for number of auto-refresh cycles */
> +	tmp = (cpu_clk / 1000000) * 1000;
> +	while (tmp--);
> +
> + 	/* Stage 3. Mode Register Set */
> +	REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
> +	REG8(EMC_SDMR0|sdmode) = 0;

	REG8(EMC_SDMR0 | sdmode) = 0;

> +        /* Set back to basic DMCR value */
> +	REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
> +
> +	/* everything is ok now */
> +}
> +
> +#ifndef CONFIG_NAND_SPL
> +
> +static void calc_clocks(void)
> +{
> +	DECLARE_GLOBAL_DATA_PTR;
> +
> +	unsigned int pllout;
> +	unsigned int div[10] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
> +
> +	pllout = __cpm_get_pllout();
> +
> +	gd->cpu_clk = pllout / div[__cpm_get_cdiv()];
> +	gd->sys_clk = pllout / div[__cpm_get_hdiv()];
> +	gd->per_clk = pllout / div[__cpm_get_pdiv()];
> +	gd->mem_clk = pllout / div[__cpm_get_mdiv()];
> +	gd->dev_clk = CONFIG_SYS_EXTAL;
> +}
> +
> +static void rtc_init(void)
> +{
> +	while ( !__rtc_write_ready()) ;
> +	__rtc_enable_alarm();	/* enable alarm */
> +
> +	while ( !__rtc_write_ready())
> +		;
> +	REG_RTC_RGR   = 0x00007fff; /* type value */
> +
> +	while ( !__rtc_write_ready())
> +		;
> +	REG_RTC_HWFCR = 0x0000ffe0; /* Power on delay 2s */
> +
> +	while ( !__rtc_write_ready())
> +		;
> +	REG_RTC_HRCR  = 0x00000fe0; /* reset delay 125ms */
> +#if 0
> +	unsigned long rtcsta;
> +
> +	while ( !__rtc_write_ready())
> +		;
> +	rtcsta = REG_RTC_HWRSR;
> +	while ( !__rtc_write_ready())
> +		;
> +	if (rtcsta & 0x33) {
> +		if (rtcsta & 0x10) {
> +			while ( !__rtc_write_ready())
> +				;
> +			REG_RTC_RSR = 0x0;
> +		}
> +		while ( !__rtc_write_ready())
> +			;
> +		REG_RTC_HWRSR = 0x0;
> +	}
> +#endif

Get rid of unused #if 0 code.

> +}
> +
> +/* U-Boot common routines */
> +phys_size_t initdram(int board_type)
> +{
> +	u32 dmcr;
> +	u32 rows, cols, dw, banks;
> +	ulong size;
> +
> +	dmcr = REG_EMC_DMCR;
> +	rows = 11 + ((dmcr & EMC_DMCR_RA_MASK) >> EMC_DMCR_RA_BIT);
> +	cols = 8 + ((dmcr & EMC_DMCR_CA_MASK) >> EMC_DMCR_CA_BIT);
> +	dw = (dmcr & EMC_DMCR_BW) ? 2 : 4;
> +	banks = (dmcr & EMC_DMCR_BA) ? 4 : 2;
> +
> +	size = (1 << (rows + cols)) * dw * banks;
> +
> +	return size;
> +}
> +
> +/*
> + * jz4740 board init routine
> + */
> +extern void board_early_init(void);
> +int jz_board_init(void)
> +{
> +	board_early_init();  /* init gpio, pll etc. */
> +#ifndef CONFIG_NAND_U_BOOT
> +	pll_init();          /* init PLL */
> +	sdram_init();        /* init sdram memory */
> +#endif
> +	calc_clocks();       /* calc the clocks */
> +	rtc_init();		/* init rtc on any reset: */
> +	return 0;
> +}
> +
> +#endif /* CONFIG_NAND_SPL */

Inconsistent comment indentations.  Use tabs, not spaces.

> diff --git a/arch/mips/cpu/xburst/start.S b/arch/mips/cpu/xburst/start.S
> new file mode 100644
> index 0000000..b05cc67
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/start.S
> @@ -0,0 +1,165 @@
> +/*
> + *  Startup Code for MIPS32 XBURST CPU-core
> + *
> + *  Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
> + *
> + * 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
> + */
> +
> +#include <config.h>
> +#include <version.h>
> +#include <asm/regdef.h>
> +#include <asm/mipsregs.h>
> +#include <asm/addrspace.h>
> +#include <asm/cacheops.h>
> +
> +#include <asm/jz4740.h>
> +
> +	.set noreorder
> +
> +	.globl _start
> +	.text
> +_start:
> +	/* Initialize GOT pointer.
> +	*/
> +	bal     1f
> +	nop
> +	.word   _GLOBAL_OFFSET_TABLE_
> +1:
> +	lw      gp, 0(ra) 
> +	li      sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET 
> +
> +	la	t9, board_init_f
> +	jr	t9
> +	nop
> +
> +/*
> + * void relocate_code (addr_sp, gd, addr_moni)
> + *
> + * This "function" does not return, instead it continues in RAM
> + * after relocating the monitor code.
> + *
> + * a0 = addr_sp
> + * a1 = gd
> + * a2 = destination address
> + */
> +	.globl	relocate_code
> +	.ent	relocate_code
> +relocate_code:
> +	move	sp, a0		/* Set new stack pointer	*/
> +
> +	li	t0, TEXT_BASE
> +	la	t3, in_ram
> +	lw	t2, -12(t3)	/* t2 <-- uboot_end_data	*/
> +	move	t1, a2
> +
> +	/*
> +	 * Fix GOT pointer:
> +	 *
> +	 * New GOT-PTR = (old GOT-PTR - TEXT_BASE) + Destination Address
> +	 */
> +	move	t6, gp
> +	sub	gp, TEXT_BASE
> +	add	gp, a2			/* gp now adjusted	*/
> +	sub	t6, gp, t6		/* t6 <-- relocation offset*/
> +
> +	/*
> +	 * t0 = source address
> +	 * t1 = target address
> +	 * t2 = source end address
> +	 */
> +1:
> +	lw	t3, 0(t0)
> +	sw	t3, 0(t1)
> +	addu	t0, 4
> +	ble	t0, t2, 1b
> +	addu	t1, 4			/* delay slot		*/
> +
> +	/* If caches were enabled, we would have to flush them here.
> +	 * flush d-cache */
> +	.set	push

.Set push is expected to be followed by assembler control change(s).
In this case, you probably want to set mips3 for CACHE instruction.

> +	li	t0, KSEG0
> +	addi	t1, t0, CONFIG_SYS_DCACHE_SIZE
> +2:
> +	cache	Index_Writeback_Inv_D, 0(t0)
> +	bne	t0, t1, 2b
> +	addi	t0, CONFIG_SYS_CACHELINE_SIZE
> +
> +	sync
> +
> +	/* flush i-cache */
> +	li	t0, KSEG0
> +	addi	t1, t0, CONFIG_SYS_ICACHE_SIZE
> +3:
> +	cache	Index_Invalidate_I, 0(t0)
> +	bne	t0, t1, 3b
> +	addi	t0, CONFIG_SYS_CACHELINE_SIZE
> +
> +	/* Invalidate BTB */
> +	mfc0	t0, CP0_CONFIG, 7
> +	nop
> +	ori	t0, 2
> +	mtc0	t0, CP0_CONFIG, 7
> +	nop
> +
> +	.set	pop
> +
> +	/* Jump to where we've relocated ourselves.
> +	 */
> +	addi	t0, a2, in_ram - _start
> +	j	t0
> +	nop

Use JR, not J.

> +	.word	uboot_end_data
> +	.word	uboot_end
> +	.word	num_got_entries
> +
> +in_ram:
> +	/* Now we want to update GOT  */
> +	lw	t3, -4(t0)	/* t3 <-- num_got_entries	*/
> +	addi	t4, gp, 8	/* Skipping first two entries.	*/
> +	li	t2, 2
> +1:
> +	lw	t1, 0(t4)
> +	beqz	t1, 2f
> +	add	t1, t6
> +	sw	t1, 0(t4)
> +2:
> +	addi	t2, 1
> +	blt	t2, t3, 1b
> +	addi	t4, 4		/* delay slot			*/
> +
> +	/* Clear BSS  */
> +	lw	t1, -12(t0)	/* t1 <-- uboot_end_data	*/
> +	lw	t2, -8(t0)	/* t2 <-- uboot_end		*/
> +	add	t1, t6		/* adjust pointers		*/
> +	add	t2, t6
> +
> +	sub	t1, 4
> +1:	addi	t1, 4
> +	bltl	t1, t2, 1b
> +	sw	zero, 0(t1)	/* delay slot			*/
> +
> +	move	a0, a1
> +	la	t9, board_init_r
> +	j	t9
> +	move	a1, a2		/* delay slot			*/

Use JR, not J.

> +	.end	relocate_code
> +	
> \ No newline at end of file

I checked the diffs between cpu/start.S and cpu/xburst/start.S.  The
relocation code itself looks ok.

> diff --git a/arch/mips/cpu/xburst/start_spl.S b/arch/mips/cpu/xburst/start_spl.S
> new file mode 100644
> index 0000000..f775e3a
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/start_spl.S
> @@ -0,0 +1,63 @@
> +/*
> + *  Startup Code for MIPS32 XBURST CPU-core
> + *
> + *  Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
> + *
> + * 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 3 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 <config.h>
> +#include <version.h>
> +#include <asm/regdef.h>
> +#include <asm/mipsregs.h>
> +#include <asm/addrspace.h>
> +#include <asm/cacheops.h>
> +
> +#include <asm/jz4740.h>
> +
> +	.set noreorder
> +	
> +	.globl _start
> +	.text
> +_start:
> +	.word JZ4740_NANDBOOT_CFG /* fetched during NAND Boot */
> +reset:	
> +	/* 
> +	 * STATUS register
> +	 * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
> +	 */
> +	li	t0, 0x0040FC04
> +	mtc0	t0, CP0_STATUS
> +	/* CAUSE register
> +	 * IV=1, use the specical interrupt vector (0x200) */
> +	li	t1, 0x00800000
> +	mtc0	t1, CP0_CAUSE
> +	
> +	bal     1f
> +	nop
> +	.word   _GLOBAL_OFFSET_TABLE_
> +1:
> +	move    gp, ra
> +	lw      t1, 0(ra)
> +	move	gp, t1

These three lines could be written in one-liner:

	lw	gp, 0(ra)

> +	la	sp, 0x80004000
> +	la	t9, nand_boot
> +	j	t9
> +	nop

Use JR, not J.

> diff --git a/arch/mips/cpu/xburst/usbboot.S b/arch/mips/cpu/xburst/usbboot.S
> new file mode 100644
> index 0000000..eb8faa6
> --- /dev/null
> +++ b/arch/mips/cpu/xburst/usbboot.S

I'm going to approve this code as-is, except for coding style issues.
Do not use '//' for comments.

> @@ -0,0 +1,880 @@
> +/*
> + *  for jz4740 usb boot
> + *
> + *  Copyright (c) 2009 Author: <jlwei@ingenic.cn>
> + *
> + * 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
> + */
> +    .set noreorder
> +    .globl usb_boot
> +    .text
> +
> +//----------------------------------------------------------------------
> +// Both NAND and USB boot load data to D-Cache first, then transfer
> +// data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
> +// So init caches first and then dispatch to a proper boot routine.
> +//----------------------------------------------------------------------

/*
 * Both NAND and USB boot load data to D-Cache first, then transfer
 * data from D-Cache to I-Cache, and jump to execute the code in I-Cache.
 * So init caches first and then dispatch to a proper boot routine.
 */

> +.macro load_addr reg addr
> +	li \reg, 0x80000000
> +	addiu \reg, \reg, \addr
> +	la $2, usbboot_begin
> +	subu \reg, \reg, $2
> +.endm
> +
> +usb_boot:
> +	//--------------------------------------------------------------
> +	// Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
> +	//--------------------------------------------------------------
> +	la	$9, 0xB0000000		// CPCCR: Clock Control Register
> +	la	$8, 0x42041110		// I:S:M:P=1:2:2:2
> +	sw	$8, 0($9)

usb_boot:
	/*
	 * Initialize PLL: set ICLK to 84MHz and HCLK to 42MHz.
	 */
	la	$9, 0xB0000000		# CPCCR: Clock Control Register
	la	$8, 0x42041110		# I:S:M:P=1:2:2:2
	sw	$8, 0($9)

And so on.  With such cleanups, this is ok.

> +	la	$9, 0xB0000010		// CPPCR: PLL Control Register
> +	la	$8, 0x06000120		// M=12 N=0 D=0 CLK=12*(M+2)/(N+2)
> +	sw	$8, 0($9)
> +
> +	mtc0	$0, $26			// CP0_ERRCTL, restore WST reset state
> +	nop
> +
> +	mtc0	$0, $16			// CP0_CONFIG
> +	nop
> +
> +	// Relocate code to beginning of the ram
> +
> +	la $2, usbboot_begin
> +	la $3, usbboot_end
> +	li $4, 0x80000000

[snip]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 3/5] jz4740 nand spl files
  2010-11-11  3:37     ` [U-Boot] [PATCH 3/5] jz4740 nand spl files Xiangfu Liu
  2010-11-11  3:37       ` [U-Boot] [PATCH 4/5] jz4740 nand driver Xiangfu Liu
  2010-11-11  7:32       ` [U-Boot] [PATCH 3/5] jz4740 nand spl files Wolfgang Denk
@ 2010-11-15 22:56       ` Scott Wood
  2 siblings, 0 replies; 11+ messages in thread
From: Scott Wood @ 2010-11-15 22:56 UTC (permalink / raw)
  To: u-boot

On Thu, 11 Nov 2010 11:37:35 +0800
Xiangfu Liu <xiangfu@openmobilefree.net> wrote:

> +$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl.bin
> +	dd bs=1024 count=8 if=/dev/zero of=$(nandobj)junk1
> +	cat $< $(nandobj)junk1 > $(nandobj)junk2
> +	dd bs=1024 count=8 if=$(nandobj)junk2 of=$(nandobj)junk3
> +	cat $(nandobj)junk3 $(nandobj)junk3 > $(nandobj)junk4
> +	dd bs=1024 count=256 if=/dev/zero of=$(nandobj)junk5
> +	cat $(nandobj)junk4 $(nandobj)junk5 > $(nandobj)junk6
> +	dd bs=1024 count=256 if=$(nandobj)junk6 of=$@
> +	rm -f $(nandobj)junk*

Why do you need all this?

> +#define __nand_enable()		(REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
> +#define __nand_disable()	(REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
> +#define __nand_ecc_rs_encoding() \
> +	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
> +#define __nand_ecc_rs_decoding() \
> +	(REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
> +#define __nand_ecc_disable()	(REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
> +#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
> +#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
> +#define __nand_cmd(n)		(REG8(NAND_COMMPORT) = (n))
> +#define __nand_addr(n)		(REG8(NAND_ADDRPORT) = (n))
> +#define __nand_data8()		REG8(NAND_DATAPORT)
> +#define __nand_data16()		REG16(NAND_DATAPORT)

Drop the leading underscores.

Use I/O accessors.

Consider making some of these inline functions -- or just open-coding
for the really simple ones.

> +#if (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R3)
> +	#define NAND_BUS_WIDTH 8
> +	#define NAND_ROW_CYCLE 3
> +#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B8R2)
> +	#define NAND_BUS_WIDTH 8
> +	#define NAND_ROW_CYCLE 2
> +#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R3)
> +	#define NAND_BUS_WIDTH 16
> +	#define NAND_ROW_CYCLE 3
> +#elif (JZ4740_NANDBOOT_CFG == JZ4740_NANDBOOT_B16R2)
> +	#define NAND_BUS_WIDTH 16
> +	#define NAND_ROW_CYCLE 2
> +#endif
> +
> +static inline void __nand_dev_ready(void)
> +{
> +	unsigned int timeout = 10000;
> +	while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
> +	while (!(REG_GPIO_PXPIN(2) & 0x40000000));
> +}

Hmm, why a timeout here and not on any of the other spin loops?

> +/*
> + * NAND flash parameters
> + */
> +static int page_size = 2048;
> +static int oob_size = 64;
> +static int ecc_count = 4;
> +static int page_per_block = 64;
> +static int bad_block_pos = 0;
> +static int block_size = 131072;

You initialize these here, and then you set them to other constant
values in nand_boot().  And then you test them for specific values
later.

What's going on?  If you're not dynamically detecting these, then have
them be constants (either #defines or "static const int").  It will
allow the compiler to generate smaller code.

> +static unsigned char oob_buf[128] = {0};

Be careful, this may still go into the BSS even with the assignment.
Is the BSS getting cleared in the SPL boot code on this platform?  Do
you actually rely on it being zero initially?

Either way, the assignment doesn't do much.

> +/*
> + * External routines
> + */
> +extern void flush_cache_all(void);
> +extern int serial_init(void);
> +extern void serial_puts(const char *s);
> +extern void sdram_init(void);
> +extern void pll_init(void);
> +extern void usb_boot();

Get these from the appropriate header file.

> +			/* Error occurred */
> +			/* serial_puts("Error occurred\n"); */
> +			if (stat & EMC_NFINTS_UNCOR) {
> +				/* Uncorrectable error occurred */
> +				/* serial_puts("Uncorrectable error occurred\n"); */

Why is this commented out?

If it's for space concerns, the strings could be shrunk and still get a
message out.

> +			} else {
> +				unsigned int errcnt, index, mask;
> +
> +				errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
> +				switch (errcnt) {
> +				case 4:
> +					index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					/* FALL-THROUGH */
> +				case 3:
> +					index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					/* FALL-THROUGH */
> +				case 2:
> +					index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					/* FALL-THROUGH */
> +				case 1:
> +					index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
> +					mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
> +					rs_correct(tmpbuf, index, mask);
> +					break;
> +				default:
> +					break;
> +				}

Please keep lines under 80 columns.  Consider factoring this chunk out
to its own function.

> +			}
> +		}
> +		tmpbuf += CONFIG_SYS_NAND_ECCSIZE;
> +	}
> +
> +	return 0;
> +}
> +
> +#ifndef CONFIG_SYS_NAND_BADBLOCK_PAGE
> +#define CONFIG_SYS_NAND_BADBLOCK_PAGE 0 /* NAND bad block was marked at this page in a block, starting from 0 */
> +#endif

This isn't really an aspect of the controller, but of the flash chip.
Many flash chips can have bad block markers in the first or second page
of a block.

> +static void nand_load(int offs, int uboot_size, uchar *dst)
> +{
> +	int page;
> +	int pagecopy_count;
> +
> +	__nand_enable();
> +
> +	page = offs / page_size;
> +	pagecopy_count = 0;
> +	while (pagecopy_count < (uboot_size / page_size)) {

Round up if uboot_size is not aligned?  Any reason not to take the
basic loop logic from nand_boot.c?

> +		if (page % page_per_block == 0) {
> +			nand_read_oob(page + CONFIG_SYS_NAND_BADBLOCK_PAGE, oob_buf, oob_size);
> +			if (oob_buf[bad_block_pos] != 0xff) {
> +				page += page_per_block;
> +				/* Skip bad block */
> +				continue;
> +			}

On 16-bit NAND isn't the bad-block marker 16-bit?

> +		}
> +		/* Load this page to dst, do the ECC */
> +		nand_read_page(page, dst, oob_buf);
> +
> +		dst += page_size;
> +		page++;
> +		pagecopy_count++;
> +	}
> +
> +	__nand_disable();
> +}
> +
> +static void jz_nand_init(void) {

Brace on its own line.

> + 	/* Optimize the timing of nand */
> +	REG_EMC_SMCR1 = 0x094c4400;
> +}
> +
> +static void gpio_init(void)
> +{
> +	/*
> +	 * Initialize SDRAM pins
> +	 */
> +	__gpio_as_sdram_16bit_4720();
> +
> +	/*
> +	 * Initialize UART0 pins
> +	 */
> +	__gpio_as_uart0();
> +	__gpio_jtag_to_uart0();
> +}
> +
> +static int is_usb_boot()
> +{
> +	__gpio_as_input(KEY_U_IN);
> +	__gpio_enable_pull(KEY_U_IN);
> +	__gpio_as_output(KEY_U_OUT);
> +	__gpio_clear_pin(KEY_U_OUT);
> +
> +	if (__gpio_get_pin(KEY_U_IN) == 0)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +void nand_boot(void)
> +{
> +	void (*uboot)(void);
> +
> +	/*
> +	 * Init hardware
> +	 */
> +	gpio_init();
> +	pll_init();
> +
> +	serial_init();
> +	sdram_init();
> +	jz_nand_init();
> +
> +	serial_puts("\nNAND Boot\n");
> +
> +#if defined(CONFIG_NANONOTE)
> +	if(is_usb_boot()) {

Space after "if".

> +		serial_puts("[U] pressed, goto USBBOOT mode\n");
> +		usb_boot();
> +	}
> +#endif

I wonder how much of the above stuff belongs in nand_boot(), versus a
board file.  This file should focus on the NAND controller.

> +	page_size = CONFIG_SYS_NAND_PAGE_SIZE;
> +	block_size = CONFIG_SYS_NAND_BLOCK_SIZE;
> +	page_per_block = CONFIG_SYS_NAND_BLOCK_SIZE / CONFIG_SYS_NAND_PAGE_SIZE;
> +	bad_block_pos = (page_size == 512) ? 5 : 0;
> +	oob_size = page_size / 32;
> +	ecc_count = page_size / CONFIG_SYS_NAND_ECCSIZE;
> +
> +	/*
> +	 * Load U-Boot image from NAND into RAM
> +	 */
> +	nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
> +		  (uchar *)CONFIG_SYS_NAND_U_BOOT_DST);

Consider adding support for CONFIG_NAND_ENV_DST.

-Scott

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [U-Boot] [PATCH 4/5] jz4740 nand driver
  2010-11-11  3:37       ` [U-Boot] [PATCH 4/5] jz4740 nand driver Xiangfu Liu
  2010-11-11  3:37         ` [U-Boot] [PATCH 5/5] add Ben NanoNote board Xiangfu Liu
@ 2010-11-15 23:02         ` Scott Wood
  1 sibling, 0 replies; 11+ messages in thread
From: Scott Wood @ 2010-11-15 23:02 UTC (permalink / raw)
  To: u-boot

On Thu, 11 Nov 2010 11:37:36 +0800
Xiangfu Liu <xiangfu@openmobilefree.net> wrote:

> From: Xiangfu Liu <xiangfu@sharism.cc>
> 
> Signed-off-by: Xiangfu Liu <xiangfu@openmobilefree.net>
> ---
>  drivers/mtd/nand/jz4740_nand.c |  250 ++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 250 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/jz4740_nand.c

Same comments as on nand_spl.

Also, this looks like the type of controller that could work with the
standard nand_boot.c -- is there something preventing that?

-Scott

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-11-15 23:02 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-11  3:37 [U-Boot] [PATCH 0/5] [MIPS] add jz4740 base file and Ben NanoNote Xiangfu Liu
2010-11-11  3:37 ` [U-Boot] [PATCH 1/5] those files are jz4740 base files Xiangfu Liu
     [not found]   ` <1289446657-12499-3-git-send-email-xiangfu@openmobilefree.net>
2010-11-11  3:37     ` [U-Boot] [PATCH 3/5] jz4740 nand spl files Xiangfu Liu
2010-11-11  3:37       ` [U-Boot] [PATCH 4/5] jz4740 nand driver Xiangfu Liu
2010-11-11  3:37         ` [U-Boot] [PATCH 5/5] add Ben NanoNote board Xiangfu Liu
2010-11-11  8:28           ` Wolfgang Denk
2010-11-15 23:02         ` [U-Boot] [PATCH 4/5] jz4740 nand driver Scott Wood
2010-11-11  7:32       ` [U-Boot] [PATCH 3/5] jz4740 nand spl files Wolfgang Denk
2010-11-15 22:56       ` Scott Wood
2010-11-11  7:14   ` [U-Boot] [PATCH 1/5] those files are jz4740 base files Wolfgang Denk
2010-11-14 15:03   ` Shinya Kuribayashi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox