Signed-off-by: Xiangfu Liu <xian...@openmobilefree.net>
---
 arch/mips/cpu/xburst/Makefile    |   50 +++
 arch/mips/cpu/xburst/config.mk   |   33 ++
 arch/mips/cpu/xburst/cpu.c       |  160 ++++++++
 arch/mips/cpu/xburst/jz4740.c    |  266 ++++++++++++
 arch/mips/cpu/xburst/jz_serial.c |  128 ++++++
 arch/mips/cpu/xburst/start.S     |  164 ++++++++
 arch/mips/cpu/xburst/start_spl.S |   63 +++
 arch/mips/cpu/xburst/timer.c     |  172 ++++++++
 arch/mips/cpu/xburst/usbboot.S   |  841 ++++++++++++++++++++++++++++++++++++++
 9 files changed, 1877 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/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..a9a6e77
--- /dev/null
+++ b/arch/mips/cpu/xburst/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, w...@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).o
+
+START  = start.o
+SOBJS-y        = 
+COBJS-y = cpu.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)
+       $(call cmd_link_o_target, $(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..fc9b255
--- /dev/null
+++ b/arch/mips/cpu/xburst/config.mk
@@ -0,0 +1,33 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, <w...@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 += -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..22261cf
--- /dev/null
+++ b/arch/mips/cpu/xburst/cpu.c
@@ -0,0 +1,160 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, <w...@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/io.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/jz4740.c b/arch/mips/cpu/xburst/jz4740.c
new file mode 100644
index 0000000..4fd9e5a
--- /dev/null
+++ b/arch/mips/cpu/xburst/jz4740.c
@@ -0,0 +1,266 @@
+/*
+ * Jz4740 common routines
+ *
+ *  Copyright (c) 2006
+ *  Ingenic Semiconductor, <jl...@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/io.h>
+#include <asm/jz4740.h>
+
+void enable_interrupts(void)
+{
+}
+
+int disable_interrupts(void) 
+{
+       return 0;
+}
+
+/* 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 */
+       writel((pllout2 / 48000000 - 1), CPM_UHCCDR);
+
+       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 */
+       writel(cfcr, CPM_CPCCR);
+       writel(plcr1, CPM_CPPCR);
+}
+
+
+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()];
+
+       writel(0, EMC_BCR);     /* Disable bus release */
+       writew(0, EMC_RTCSR);   /* 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 */
+       writel(dmcr, EMC_DMCR);
+       writeb(0, EMC_SDMR0 | sdmode);
+
+       /* Wait for precharge, > 200us */
+       tmp = (cpu_clk / 1000000) * 1000;
+       while (tmp--)
+               ;
+
+       /* Stage 2. Enable auto-refresh */
+       writel(dmcr | EMC_DMCR_RFSH, EMC_DMCR);
+
+       tmp = SDRAM_TREF / ns;
+       tmp = tmp/64 + 1;
+       if (tmp > 0xff) 
+               tmp = 0xff;
+       writew(tmp, EMC_RTCOR);
+       writew(0, EMC_RTCNT);
+       /* Divisor is 64, CKO/64 */
+       writew(EMC_RTCSR_CKS_64, EMC_RTCSR);
+
+       /* Wait for number of auto-refresh cycles */
+       tmp = (cpu_clk / 1000000) * 1000;
+       while (tmp--)
+               ;
+
+       /* Stage 3. Mode Register Set */
+       writel(dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET, EMC_DMCR);
+       writeb(0, EMC_SDMR0 | sdmode);
+
+        /* Set back to basic DMCR value */
+       writel(dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET, EMC_DMCR);
+
+       /* everything is ok now */
+}
+
+#ifndef CONFIG_NAND_SPL
+DECLARE_GLOBAL_DATA_PTR;
+
+static void calc_clocks(void)
+{
+
+       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())
+               ;
+
+       writel(0x00007fff, RTC_RGR); /* type value */
+
+       while ( !__rtc_write_ready())
+               ;
+
+       writel(0x0000ffe0, RTC_HWFCR); /* Power on delay 2s */
+
+       while ( !__rtc_write_ready())
+               ;
+
+       writel(0x00000fe0, RTC_HRCR); /* reset delay 125ms */
+}
+
+/* U-Boot common routines */
+phys_size_t initdram(int board_type)
+{
+       u32 dmcr;
+       u32 rows, cols, dw, banks;
+       ulong size;
+
+       dmcr = readl(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
+ */
+int jzsoc_init(void)
+{
+#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..59e3267
--- /dev/null
+++ b/arch/mips/cpu/xburst/jz_serial.c
@@ -0,0 +1,128 @@
+/*
+ * Jz47xx UART support
+ *
+ * Hardcoded to UART 0 for now
+ * Options also hardcoded to 8N1
+ *
+ *  Copyright (c) 2005
+ *  Ingenic Semiconductor, <jl...@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/io.h>
+#include <asm/jz4740.h>
+ 
+/*
+ * 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 *)(CONFIG_SYS_UART_BASE + OFF_FCR);
+       volatile u8 *uart_lcr = (volatile u8 *)(CONFIG_SYS_UART_BASE + OFF_LCR);
+       volatile u8 *uart_ier = (volatile u8 *)(CONFIG_SYS_UART_BASE + OFF_IER);
+       volatile u8 *uart_sircr = (volatile u8 *)(CONFIG_SYS_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 *)(CONFIG_SYS_UART_BASE + OFF_LCR);
+       volatile u8 *uart_dlhr = (volatile u8 *)(CONFIG_SYS_UART_BASE + 
OFF_DLHR);
+       volatile u8 *uart_dllr = (volatile u8 *)(CONFIG_SYS_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 *)(CONFIG_SYS_UART_BASE + OFF_LSR);
+       volatile u8 *uart_tdr = (volatile u8 *)(CONFIG_SYS_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 *)(CONFIG_SYS_UART_BASE + OFF_RDR);
+
+       while (!serial_tstc())
+               ;
+
+       return *uart_rdr;
+}
+
+int serial_tstc (void)
+{
+       volatile u8 *uart_lsr = (volatile u8 *)(CONFIG_SYS_UART_BASE + OFF_LSR);
+
+       if (*uart_lsr & UART_LSR_DR)
+               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..d999881
--- /dev/null
+++ b/arch/mips/cpu/xburst/start.S
@@ -0,0 +1,164 @@
+/*
+ *  Startup Code for MIPS32 XBURST CPU-core
+ *
+ *  Copyright (c) 2010 Xiangfu Liu <xian...@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, CONFIG_SYS_MONITOR_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 - CONFIG_SYS_MONITOR_BASE) + Destination 
Address
+        */
+       move    t6, gp
+       sub     gp, CONFIG_SYS_MONITOR_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
+       jr      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
+       jr      t9
+       move    a1, a2          /* delay slot                   */
+
+       .end    relocate_code
+
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 <xian...@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..c8926c1
--- /dev/null
+++ b/arch/mips/cpu/xburst/timer.c
@@ -0,0 +1,172 @@
+/*
+ *  Copyright (c) 2006
+ *  Ingenic Semiconductor, <jl...@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/io.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
+
+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)
+{
+       writew(TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN, 
+              TCU_TCSR(TIMER_CHAN));
+
+       writew(0, TCU_TCNT(TIMER_CHAN));
+       writew(0, TCU_TDHR(TIMER_CHAN));
+       writew(TIMER_FDATA, TCU_TDFR(TIMER_CHAN));
+
+       writel((1 << TIMER_CHAN) | (1 << (TIMER_CHAN + 16)),
+              TCU_TMSR); /* mask irqs */
+       writel((1 << TIMER_CHAN), TCU_TSCR);/* enable timer clock */
+       writeb((1 << TIMER_CHAN), TCU_TESR); /* 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 = readw(TCU_TCNT(TIMER_CHAN));
+       timestamp = 0;
+}
+
+ulong get_timer_masked (void)
+{
+       ulong now = readw(TCU_TCNT(TIMER_CHAN));
+
+       if (lastdec <= now)
+               timestamp += (now - lastdec);/* normal mode */
+       else
+               timestamp += TIMER_FDATA + now - lastdec;/* we have an overflow 
... */
+
+       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..97fcbbf
--- /dev/null
+++ b/arch/mips/cpu/xburst/usbboot.S
@@ -0,0 +1,841 @@
+/*
+ *  for jz4740 usb boot
+ *
+ *  Copyright (c) 2009 Author: <jl...@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:
+
+       /* 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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to