[U-Boot] [PATCH 1/5] those files are jz4740 base files

Xiangfu Liu xiangfu at openmobilefree.net
Thu Nov 11 04:37:33 CET 2010


From: Xiangfu Liu <xiangfu at sharism.cc>

Signed-off-by: Xiangfu Liu <xiangfu at 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 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
+#
+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 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 <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 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 <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 at 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 at 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 at 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 at 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 at 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 at 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



More information about the U-Boot mailing list