zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/boot/common/src/loader/drivers/Makefile b/boot/common/src/loader/drivers/Makefile
new file mode 100755
index 0000000..c07fefa
--- /dev/null
+++ b/boot/common/src/loader/drivers/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+# CFLAGS += -DET_DEBUG -DDEBUG 
+
+LIB	= libdrivers.a
+OBJS	= ddr.o uart.o 	dwc_otg_cil.o dwc_otg_cil_intr.o dwc_otg_dev_test.o \
+			dwc_otg_pcd.o dwc_otg_pcd_intr.o global.o \
+			download.o  drv_hash.o drv_rsa.o \
+			flash.o image.o efuse.o secure_verify.o
+
+ifeq ($(strip $(board)),$(filter $(board),mdl_mini mifi_mini mifi_mini_xr819 ufi_mini mifi_mini_64 mdl_mini_64))
+OBJS += nor.o
+else
+OBJS += bbt.o spifc.o
+endif	
+
+
+all:	$(LIB)
+
+$(LIB):	$(OBJS)
+	$(AR) crv $@ $(OBJS)
+
+#########################################################################
+
+sinclude .depend
+
+#########################################################################
diff --git a/boot/common/src/loader/drivers/bbt.c b/boot/common/src/loader/drivers/bbt.c
new file mode 100755
index 0000000..7c34949
--- /dev/null
+++ b/boot/common/src/loader/drivers/bbt.c
@@ -0,0 +1,249 @@
+/*
+ * (C) Copyright 2016 ZXIC Inc.
+ */
+   
+
+#include <common.h>
+#include <asm/io.h>
+#include <bbt.h>
+#include "config.h"
+#include "flash.h"
+
+
+static uint8_t block_bad_table[BBT_SIZE]={0};
+
+
+static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.offs =	4,
+	.len = 4,
+	.veroffs = 20,
+	.maxblocks = 16,
+	.pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.offs =	4,
+	.len = 4,
+	.veroffs = 20,
+	.maxblocks = 16,
+	.pattern = mirror_pattern,
+};
+
+static int nand_check_pattern(uint8_t *buf,struct nand_bbt_descr *td)
+{
+	int i;
+	uint8_t *p = buf;
+	p += td->offs;
+
+	/* Compare the pattern */
+	for (i = 0; i < td->len; i++) 
+    {
+		if (p[i] != td->pattern[i])
+			return -1;
+	}
+	
+	return 0;
+}
+
+void nand_creat_ram_bbt( void )
+{
+	uint32_t i = 0;
+	uint32_t off = 0;
+	uint32_t oob_size = flash.oob_size;
+	uint32_t block_size = flash.block_size;
+	uint8_t oob[256];   /* ÕâÀﶨÒå×î´óµÄOOB SIZE */
+#ifdef CONFIG_ZX297520V3E_MDL_AB
+	uint32_t block_nums = 72;
+#else
+	uint32_t block_nums = 17;
+#endif
+
+	for( i=0; i<block_nums; i++ )
+	{
+		flash.read_oob(&oob[0], off, oob_size);
+		if(oob[0] != 0xff)                      /* bad block */
+			block_bad_table[i] = BAD_BLOCK;
+		else 
+			block_bad_table[i] = 0x0;
+
+		off += block_size;
+	}
+}
+
+
+int nand_search_bbt(struct nand_bbt_descr *td)
+{
+
+	int  startblock, block;
+	int blocktopage = flash.block_size_shift - flash.page_size_shift;
+	
+	uint8_t oob_buffer[256]={0xFF};
+    uint32_t offs = 0;
+
+	/* Search direction down -> top */
+	 startblock = flash.block_num -1;
+	
+	td->page= -1;
+	/* Scan the maximum number of blocks */
+	for (block = 0; block < td->maxblocks; block++) 
+    {
+
+		int actblock = startblock -block;
+		offs = actblock << flash.block_size_shift;
+
+		/* Read first page */
+		flash.read_oob(oob_buffer, offs, flash.oob_size);
+		if (!nand_check_pattern(oob_buffer,td)) 
+        {
+			td->page = actblock << blocktopage;
+			td->version= oob_buffer[td->veroffs];
+			
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+
+static int nand_read_bbt(struct nand_bbt_descr  *td,int num)
+{
+	int bits=2;
+	
+	int res, i, j, act = 0;
+	int totlen;
+	int from;
+	uint8_t msk = (uint8_t) ((1 << bits) - 1);
+	totlen = (num * bits) >> 3;
+    from =(td->page)<<(flash.page_size_shift);
+	char* buf;
+	
+
+	res = flash.read_page_raw(CFG_TEMP_ADDR, from);
+	if (res < 0) 
+    {
+		return -1;
+	}
+	
+	buf =(char*) CFG_TEMP_ADDR;
+	
+
+	/* Analyse data */
+	for (i = 0; i < totlen; i++) 
+    {
+		uint8_t dat = buf[i];
+		for (j = 0; j < 8; j += bits, act += 2) 
+        {
+			uint8_t tmp = (dat >> j) & msk;
+			if (tmp == msk)
+			{
+			    block_bad_table[(act >> 1)]= 0X0;
+				continue;
+			}
+			else
+			{
+				block_bad_table[(act >> 1)]= BAD_BLOCK;
+			}
+	    }  
+     }
+	
+	  return 0;
+}
+
+
+static void nand_init_bbt_descr(struct nand_bbt_descr *td, 
+        					    	 struct nand_bbt_descr *md)
+{
+	switch(flash.manuf_id)
+	{
+		case NAND_MFR_PARAGON:
+			if(flash.device_id != NAND_DEVID_FDANWEI_1G)
+			{
+				td->offs = BBT_INFO_OOB_OFFSET_PARAGON;
+				md->offs = BBT_INFO_OOB_OFFSET_PARAGON;
+				td->veroffs = BBT_INFO_OOB_VER_OFFSET_PARAGON;
+				md->veroffs = BBT_INFO_OOB_VER_OFFSET_PARAGON;
+			}
+			break;
+		case NAND_MFR_HEYANGTEK:
+			td->offs = BBT_INFO_OOB_OFFSET_HEYANGTEK;
+			md->offs = BBT_INFO_OOB_OFFSET_HEYANGTEK;
+			td->veroffs = BBT_INFO_OOB_VER_OFFSET_HEYANGTEK; 	
+			md->veroffs =BBT_INFO_OOB_VER_OFFSET_HEYANGTEK;
+			break;
+		default: 
+			break;
+	}
+}
+
+int nand_creat_bbt( void )
+{  
+    struct nand_bbt_descr *td = &bbt_main_descr;
+	struct nand_bbt_descr *md = &bbt_mirror_descr;
+
+	nand_init_bbt_descr(td, md);
+	
+    // 2.0 search main bbt
+	nand_search_bbt(td);
+	// 2.1 search mirror bbt
+	nand_search_bbt(md);
+
+	if(td->page==-1&&md->page ==-1)
+	{
+		/* if failed found bbt, we create a ram bbt */
+		nand_creat_ram_bbt();
+	    return 0;
+	}
+
+	// 3.0 read and analyze bbt
+	if(td->page==-1)
+	{
+		nand_read_bbt(md,BBT_SIZE);	
+	}
+	else
+	{
+		if(md->page == -1)
+		{
+			nand_read_bbt(td,BBT_SIZE);	
+		}
+		else
+		{
+			if(td->version >= md->version)
+			{
+				nand_read_bbt(td,BBT_SIZE);	
+			}
+			else
+			{
+				nand_read_bbt(md,BBT_SIZE);	
+			}
+		}
+	}
+	printf("bbt ok.\n");
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+uint32_t nand_block_isbad(uint32_t offset)
+{
+    uint32_t block_offset = offset >> (flash.block_size_shift);
+    return block_bad_table[block_offset];
+}
+
+
+
diff --git a/boot/common/src/loader/drivers/config.h b/boot/common/src/loader/drivers/config.h
new file mode 100644
index 0000000..f40e927
--- /dev/null
+++ b/boot/common/src/loader/drivers/config.h
@@ -0,0 +1,96 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+*

+* ÎļþÃû³Æ£º config.h

+* Îļþ±êʶ£º /include/config.h

+* ÄÚÈÝÕªÒª£º ÒýÈ뿪·¢°åµÄÅäÖÃÎļþ

+* ÆäËü˵Ã÷£º

+* µ±Ç°°æ±¾£º 1.0

+* ×÷¡¡¡¡Õߣº ÎÌÔÆ·å

+* Íê³ÉÈÕÆÚ£º 2010-9-30

+*

+*

+*******************************************************************************/

+#ifndef __INCLUDE_CONFIG_H_

+#define __INCLUDE_CONFIG_H_

+/*********************************************************************************

+1:open 0:close

+* ¹¦ÄÜ             SIM_EN     USE_ASIC    SYNC_USB_CTRL    SYNC_USB_HSIC   SYNC_SETADDRESS

+*  FPGA                   1               0                    0                          0                              0                  

+*  usb_ctrlÑéÖ¤    0               1                    1                          1                              1

+*  usb_hsicÑéÖ¤   0               1                    1                          1                              1

+*  usbtimeoutÑéÖ¤0               1                    1                          1                              1

+*  asic                     1               1                    0                          0                              0

+**********************************************************************************/

+#define SIM_EN 1

+#define USE_ASIC 1

+#define SYNC_USB_CTRL 0

+#define SYNC_USB_HSIC 0

+#define SYNC_SETADDRESS 0

+

+#if  !USE_ASIC   ///0:fpga   1:asic

+// CPUʱÖÓÆµÂÊ

+#define SYS_CPU_FREQ							50000000		// ¶¨ÒåCPUʱÖÓ,ÓÃÓÚ¼ÆÊ±

+#define SYS_UART_CLK							25000000		// ʱÖÓÆµÂÊ

+#define SYS_UART_CLK_CONFIG_PLL					25000000		// ʱÖÓÆµÂÊ

+#else

+// CPUʱÖÓÆµÂÊ

+#define SYS_CPU_FREQ							208000000		// ¶¨ÒåCPUʱÖÓ,ÓÃÓÚ¼ÆÊ±

+#define SYS_UART_CLK							(26000000/6)		// ʱÖÓÆµÂÊ

+#define SYS_UART_CLK_CONFIG_PLL					104000000		// ʱÖÓÆµÂÊ

+#define ZX_TOP_CRM_BASE							0x0013B000

+#define ZX_SOC_SYS_BASE							0x00140000

+

+#endif

+// Æô¶¯Ä£Ê½Ñ¡Ôñ¼Ä´æÆ÷

+#define SYS_BOOTSEL_BASE						0x0013b004		// ¶¨ÒåBOOTSEL¼Ä´æÆ÷µØÖ·

+

+#define SOC_CRM_BASE            (0x0010c000)

+#define BOOT_SEL                (0x3c)

+#define NAND_CFG                (0x34)

+#define SOC_MOD_CLKEN0         ZX_TOP_CRM_BASE+0x6c

+#define SOC_MOD_CLKEN1         ZX_TOP_CRM_BASE+0x6c

+#define SOC_MOD_RSTEN           ZX_TOP_CRM_BASE + 0x80

+#define SOC_MOD_USBSTATECTRL  	ZX_TOP_CRM_BASE + 0x84

+#define SOC_MOD_RSTEN1          (0x0010c064)

+

+#define CFG_STACK_TOP							0x0008AFE0		// ¶¨ÒåÁËÕ»¶¥

+

+// UART ²ÎÊý

+#define SYS_UART_BASE							0x00102000		// »ùµØÖ·

+//#define SYS_UART_CLK							25000000		// ʱÖÓÆµÂÊ

+#define CFG_UART_BAUDRATE						115200			// ²¨ÌØÂÊ

+#define CFG_BUF_SIZE							64				// Êý¾Ý»º³åÇø´óС

+#if !USE_ASIC

+// USB ²ÎÊý

+#define SYS_USB_BASE							0x01500000		// »ùµØÖ·

+#define SYS_USB_HSIC_BASE						0x01600000		// »ùµØÖ·

+#else

+#define SYS_USB_BASE							0x01500000		// »ùµØÖ·

+#define SYS_USB_HSIC_BASE						0x01600000		// »ùµØÖ·

+#endif

+

+

+// NAND FLASH ²ÎÊý

+#define SYS_NAND_BASE                   	 	0x01207000		// ¼Ä´æÆ÷»ùµØÖ·

+#define SYS_NAND_DATA                    		0x01208000		// Êý¾Ý»ùµØÖ·

+

+// ͨÓòÎÊý

+#define CFG_LOAD_BASE                    		0x0008B000      // ¼ÓÔØ´úÂëµ½¸ÃµØÖ·,±ØÐë4K¶ÔÆë

+#define SYS_LOAD_LEN                     		0x1000          // ¼ÓÔØ³¤¶È

+#define CFG_PRINT_BUF_SIZE						256

+

+#define POWER_DOMAIN_ISO                      ZX_SOC_SYS_BASE+0x110

+#define POWER_DOMAIN_POWERON                  ZX_SOC_SYS_BASE+0x114

+#define POWER_DOMAIN_RST                      ZX_SOC_SYS_BASE+0x10C

+

+//ÑéÖ¤ÐèÒª

+#if SYNC_USB_CTRL

+#define ARM_PORTA				(0x102040)

+#endif

+

+#if SYNC_USB_HSIC

+#define REG_GPIO_OUT  0x01400014     

+#define REG_GPIO_IN   0x01409020  

+#endif

+#endif

diff --git a/boot/common/src/loader/drivers/ddr.c b/boot/common/src/loader/drivers/ddr.c
new file mode 100644
index 0000000..0bcec12
--- /dev/null
+++ b/boot/common/src/loader/drivers/ddr.c
@@ -0,0 +1,811 @@
+/*
+ * ddr.c
+ *
+ * Copyright(c) 2016 ZXIC Inc.   All rights reserved.
+ *
+ */
+ 
+#include <common.h>
+#include <asm/io.h>
+#include <board.h>
+#include <ddr.h>
+#include <asm/arch/top_clock.h>
+
+#define _DDR_BYPASS_MODE	1	//1//1: 312m; 0:400m
+#if !_DDR_BYPASS_MODE
+#define _DDR_DS_48om
+#endif
+
+#define _DDR32M_BYPASS_MODE	0	//1//1: 312m; 0:400m
+#if !_DDR32M_BYPASS_MODE
+//#define _DDR32M_DS_48om   //-40du 48ohm has problem,modify to 60ohm
+#endif
+/*****************************************
+ * Routine: nsdelay
+ * Description: Configure DDR
+ *****************************************/
+
+void nsdelay(volatile int count)
+{
+    volatile int cnt = 0;
+
+	while(cnt<count)
+	{
+		cnt++;
+	}
+	return;
+}
+
+
+/*****************************************
+ * Routine: ddr_init
+ * Description: Configure DDR
+ *****************************************/
+#ifdef DDR_FFC
+static UINT32 g_PhyReg[DDR_CLKEND][4]={0};//g_PhyReg[N][0]~PHY_PHYREGN[N][3]·Ö±ð´æ´¢PHYREGFB~FE
+
+void pow_DdrClkConfig(T_zDrvPow_DDRCLK clock_value)
+{
+	UINT32  rdata;
+	
+	if(clock_value>=DDR_CLKEND)
+		return;
+
+	rdata = __REG(MOD_CLK_SEL)&0xfffffffc;
+    switch (clock_value)
+    {
+       //DDR top clock select, bit0-1, 0=156, 1=200, 2=104, 3=78
+	case DDR_156M:
+	{
+		__REG(MOD_CLK_SEL) = rdata|3;
+		break;
+        }
+        case DDR_208M:
+        {
+		__REG(MOD_CLK_SEL) = rdata|2;
+		break;
+        }
+	 case DDR_312M:
+        {
+		__REG(MOD_CLK_SEL) = rdata|0;
+		break;
+        }
+	 case DDR_400M:
+        {
+		__REG(MOD_CLK_SEL) = rdata|1;
+		break;
+        }
+        default:
+			break;
+    }
+
+}
+
+void pow_DdrFreqDivFactorConfig(T_zDrvPow_DDRCLK clock_value)
+{
+   if(clock_value>=DDR_CLKEND)
+	return;
+
+   //pow_DdrPllPowerdown();
+
+   __REG(DDR_PHY_BASE+0x3b0) =0;
+   __REG(DDR_PHY_BASE+0x3b4) &= ~0x1;//fbdiv[8]=0
+   __REG(DDR_PHY_BASE+0x3b8) =0;
+
+   /******************************************
+   	 Fclk4x = Fref ¡Á N ¡Â M ¡Â P
+	 0x013043b0:bit7~0--fbdiv[7:0]
+	 0x013043b4:bit4--PLL clock out enable,
+				bit1--PLL power down enable
+				bit0--fbdiv[8]
+        0x013043b8:bit7~5--postdiv,
+                           bit4~0--prediv 
+        N=fbdiv[8:0]
+   	 M=prediv[4:0]
+   	 P=2^postdiv[2:0];
+   	 
+         fref                          N         M         P
+         10~20m                   64        1         16
+         21~50M                    32        1         8
+         51~100M                  32        2         4
+         101~200M                16         2         2
+         201~400M                16         4         1 
+     ******************************************/
+	switch (clock_value)
+	{
+		case DDR_156M://Fref=78m
+		{
+			__REG(DDR_PHY_BASE+0x3b0) =32 ;//N=fbdiv[7:0]=32
+			__REG(DDR_PHY_BASE+0x3b8) =(2<<5)|(2<<0) ;//postdiv=2; M=prediv=2	
+			break;
+		}
+		case DDR_208M:////Fref=104m
+		{
+			__REG(DDR_PHY_BASE+0x3b0) =16 ;//N=fbdiv[7:0]=16
+			__REG(DDR_PHY_BASE+0x3b8) =(1<<5)|(2<<0) ;//postdiv=1; M=prediv=2	
+			break;
+		}
+		case DDR_312M://Fref=156m
+		{
+			__REG(DDR_PHY_BASE+0x3b0) =16 ;//N=fbdiv[7:0]=16
+			__REG(DDR_PHY_BASE+0x3b8) =(1<<5)|(2<<0) ;//postdiv=1; M=prediv=2				
+			break;
+		}
+		case DDR_400M://Fref=200m
+		{
+			__REG(DDR_PHY_BASE+0x3b0) =16 ;//N=fbdiv[7:0]=16
+			__REG(DDR_PHY_BASE+0x3b8) =(1<<5)|(2<<0) ;//postdiv=0; M=prediv=4				
+			break;
+		}
+		default:
+			break;
+	}
+
+	//pow_DdrPllPoweron();
+
+}
+
+
+void pow_DdrPllDllLock(void)
+{
+
+	//ʹÄÜÁË0x00146000+0x4c*4µÄbit7£¬Ôò½øÈí¼þ×Ôˢкópll»ápowerdown£¬lockÐźÅûÓÐÁË
+	//Í˳ö×ÔˢкóÓ²¼þ»á×Ô¶¯´¥·¢pll lock£¬Èí¼þÖ»ÐèÒªµÈlockÐźÅ
+    //wait phy pll lock
+    while((__REG(DDR_PHY_BASE + 0x3e0)&0x1)!=0x1);
+    //start  dll init ,ϽµÑØ´¥·¢
+   	__REG(DDR_PHY_BASE + 0x17c)  = 0x2a; 
+	__REG(DDR_PHY_BASE + 0x17c)  = 0xa;
+	nsdelay(2);
+	//wait phy dll lock,phy init done,
+	while((__REG(DDR_PHY_BASE + 0x3e0)&0x3)!=0x3);
+}
+
+void pow_DdrTraining(T_zDrvPow_DDRCLK clock_value)
+{	
+	//phy DQS gate training start
+	__REG(DDR_PHY_BASE+0x02*4)=0x1;;
+	nsdelay(1);
+	//Ñ­»·¼ì²âtraining over
+	while( (__REG(DDR_PHY_BASE+ 0xff*4)&0xf) != 0xf);
+	
+	g_PhyReg[clock_value][0]=__REG(DDR_PHY_BASE+0xfb*4);
+	g_PhyReg[clock_value][1]=__REG(DDR_PHY_BASE+0xfc*4);
+	g_PhyReg[clock_value][2]=__REG(DDR_PHY_BASE+0xfd*4);	
+	g_PhyReg[clock_value][3]=__REG(DDR_PHY_BASE+0xfe*4);
+		
+	//phy DQS gate training stop
+	__REG(DDR_PHY_BASE+0x02*4)=0x0;
+}
+
+
+/*******************************************************************************
+* Function:pow_DdrChangeClk
+* Description:
+* Parameters:
+*   Input:
+*
+*   Output:
+*
+* Returns:
+*
+*
+* Others:
+********************************************************************************/
+void  pow_DdrChangeClk(T_zDrvPow_DDRCLK clock_value)
+{
+
+	/* PWRCTL[5].selfref_sw=1, ʹ¿ØÖÆÆ÷½øÈëÈí¼þ×ÔË¢ÐÂģʽ*/
+	__REG(CRTL_PWRCTL) |= (1<<SELFREF_SW);   
+
+	/*Ñ­»·¼ì²âÖ±µ½STAT[2:0]==3'b011ÇÒSTAT[5:4]==2'b10£¬DDR´¦ÓÚÈí¼þ×ÔË¢ÐÂ״̬*/
+	while( (__REG(CTRL_STAT) & 0x37 ) !=0x23); 	
+	
+	//ÅäÖÃϵͳCRM½øÐÐʱÖÓÇл»
+	pow_DdrClkConfig(clock_value);
+
+	//¸ù¾ÝƵÂÊÅäÖÃPHY PLLÄ¿±êƵµãµÄ·ÖƵϵÊý
+	pow_DdrFreqDivFactorConfig(clock_value);
+
+	
+	//Ö»¹ØÊ±ÖÓ/ÇÐÆµ²»¶Ïµç£¬½øÈëÈí¼þ×ÔˢУ¬phy½øÉî˯Ãߣ¬pll»á¹Ø±Õ£¬
+	//Í˳öʱ»á×Ô¶¯´ò¿ªÆÚ¼ä²»ÓöÔpll½øÐпª¹Ø,ÒªµÈpll/dll lock,
+	pow_DdrPllDllLock();
+	
+	//Éϵç³õʼ»¯½øÐÐÇÐÆµtrainingѵÁ·Ê±£¬
+	//ÔòÅäÖüĴæÆ÷PHYREG02[0]=1£¬â§·¢dqs gate training¡£
+	//È»ºóÑ­»·¶ÁÈ¡PHYREGFF£¬Ö±µ½bit[3:0]Ϊ0xf£¬training¹ý³ÌÍê³É£¬
+	//¼Ç¼¼Ä´æÆ÷PHYREGFB~FEµÄÖµ
+	
+	/* PWRCTL[5].selfref_sw=0, ʹ¿ØÖÆÆ÷Í˳öÈí¼þ×ÔË¢ÐÂģʽ*/
+    __REG(CRTL_PWRCTL) &= ~(1<<SELFREF_SW); 
+
+	/*  Ñ­»·¼ì²âÖ±µ½STAT[2:0]==3'b001ÇÒSTAT[5:4]==2'b00£¬DDRÍ˳öÈí¼þ×ÔˢУ¬´¦ÓÚnormal״̬*/
+    while( (__REG(CTRL_STAT) & 0x37 ) !=0x1); 
+	/*traning*/
+	pow_DdrTraining(clock_value);
+	
+
+}
+
+
+void save_ddr_training(UINT32 count, T_zDrvPow_DDRCLK clock_value)
+{
+	__REG(DDR_FFC_ADDR_BASE+0x70*count+0x54) = g_PhyReg[clock_value][0];
+	__REG(DDR_FFC_ADDR_BASE+0x70*count+0x58) = g_PhyReg[clock_value][1];
+	__REG(DDR_FFC_ADDR_BASE+0x70*count+0x5c) = g_PhyReg[clock_value][2];
+	__REG(DDR_FFC_ADDR_BASE+0x70*count+0x60) = g_PhyReg[clock_value][3];
+
+}
+
+void ddr_ffc_init(void)
+{
+	UINT32 count;
+	__REG(STD_CRM_REG_BASE + 0x100) |= (0xf << 24); //release ddr ffc work and apb
+	for(count = 0; count <= 3; count++)
+	{       
+	    pow_DdrChangeClk(count);
+		save_ddr_training(count,count);
+	}
+    pow_DdrChangeClk(DDR_312M);
+}
+#endif
+
+#define ABSa_b(a,b)    (((a) > (b)) ? (a-b) : (b-a))
+
+int ddr_clk_init(int flag)
+{
+	//DDR top clock select top clk 156M, bit0-1, 0=156, 1=200, 2=104, 3=78
+	// 0: top clk=156M,      ddr use mission mode , dram io clk=312M
+	// 1: top clk=200M,     ddr use mission mode , dram io clk=400M
+	// 2: top clk=104M,     ddr use mission mode , dram io clk=208M
+	// 3: top clk=78M,     ddr use mission mode , dram io clk=156M
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		#if _DDR32M_BYPASS_MODE
+		__REG( 0x01306050 ) = 0x00000000  ; //·ÖƵÉèÖ㬶ÔÓ¦ÐèÒªÐÞ¸ÄÂð
+		#else
+		__REG( 0x01306050 ) = 0x00000001  ; //·ÖƵÉèÖ㬶ÔÓ¦ÐèÒªÐÞ¸ÄÂð	
+		#endif
+	}
+	else
+	{
+		#if _DDR_BYPASS_MODE
+		__REG( 0x01306050 ) = 0x00000000  ; //·ÖƵÉèÖ㬶ÔÓ¦ÐèÒªÐÞ¸ÄÂð
+		#else
+		__REG( 0x01306050 ) = 0x00000001  ; //·ÖƵÉèÖ㬶ÔÓ¦ÐèÒªÐÞ¸ÄÂð	
+		#endif
+	}
+	
+    return 0;
+	
+}
+
+int ddr_phy_init(int flag)
+{
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		__REG( 0x00154000 ) = 0x0000003f  ; //VALUE_PHYREG00    0x0000003f(16bit ddr)	default: 0x000000ff(32bit ddr)
+	}
+	
+	__REG( 0x00154004 ) = 0x00000007  ; //VALUE_PHYREG01   / Reserved:RW:2:6:=0x1, PHY_MODE:RW:0:2:=0x2(LPDDR2:0x3,LPDDR3:0x2)
+	__REG( 0x0015402c ) = 0x00000080  ; //VALUE_PHYREG0B   / RL:RW:4:4:=0x8
+	__REG( 0x00154030 ) = 0x00000004  ; //VALUE_PHYREG0C   / WL:RW:0:4:=0x4
+
+	__REG( 0x001543b0 ) = 0x00000010  ; //VALUE_PHYREGEC   / fbdiv[7:0]=0x10
+	__REG( 0x001543b4 ) = 0x0000001a  ; //VALUE_PHYREGED   / PLLCLKOUTEN:RW:4:1:=0x1,Reserved:RW:2:2:=0x2, pllpd:RW:1:1:=0x1, fbdiv[8]:RW:0:1:=0x0
+	__REG( 0x001543b8 ) = 0x00000022  ; //VALUE_PHYREGEE   / prediv[4:0]:RW:0:5:=0x2,postdiv[2:0]:RW:5:3:=0x1
+	
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		#ifndef _DDR32M_DS_48om //60ohm
+		__REG( 0x00154044 )= 0x00000008;  //VALUE_PHYREG11   / CMD drive strength: cmd_nrcomp[4:0]:RW:0:5:=0xa
+		__REG(0x00154058 )= 0x00000008;  //VALUE_PHYREG16   / CK  drive strength: ck_nrcomp [4:0]:RW:0:5:=0xa
+		__REG(0x00154064 )= 0x00000008;  //VALUE_PHYREG19   / CK  pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG(0x00154068 )= 0x00000008;  //VALUE_PHYREG1A   / CMD pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG(0x00154080 )= 0x00000008;  //VALUE_PHYREG20   / A_DQ0~A_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG(0x00154084 )= 0x00000004;  //VALUE_PHYREG21   / A_DQ0~A_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG(0x001540b8 )= 0x00000088;  //VALUE_PHYREG2E   / A_DQ0~A_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x001540bc )= 0x00000084;  //VALUE_PHYREG2F   / A_DQ0~A_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG(0x001540c0 )= 0x00000088;  //VALUE_PHYREG30   / A_DQ8~A_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x001540c4 )= 0x00000084;  //VALUE_PHYREG31   / A_DQ8~A_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG(0x001540f8 )= 0x00000008;  //VALUE_PHYREG3E   / A_DQ8~A_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG(0x001540fc )= 0x00000004;  //VALUE_PHYREG3F   / A_DQ8~A_DQ15 pull_up   ODT:RW:0:5:=0xa
+
+		__REG(0x00154100 )= 0x00000008;  //VALUE_PHYREG40   / B_DQ0~B_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG(0x00154104 )= 0x00000004;  //VALUE_PHYREG41   / B_DQ0~B_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG(0x00154138 )= 0x00000088;  //VALUE_PHYREG4E   / B_DQ0~B_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x0015413c )= 0x00000084;  //VALUE_PHYREG4F   / B_DQ0~B_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+
+		__REG(0x00154140 )= 0x00000088;  //VALUE_PHYREG50   / B_DQ8~B_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x00154144 )= 0x00000084;  //VALUE_PHYREG51   / B_DQ8~B_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG(0x00154178 )= 0x00000008;  //VALUE_PHYREG5E   / B_DQ8~B_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG(0x0015417c )= 0x00000024;  //VALUE_PHYREG5F   / B_DQ8~B_DQ15 pull_up   ODT:RW:0:5:=0xa  	
+		#else //48om                          
+		//Drive strength(defualt) ODT µÈЧ48om     
+		__REG( 0x00154044 ) = 0x0000000a  ; //VALUE_PHYREG11   / CMD drive strength: cmd_prcomp[3:0]:RW:4:4:=0xa,cmd_nrcomp[3:0]:RW:0:4:=0xa
+		__REG( 0x00154058 ) = 0x0000000a  ; //VALUE_PHYREG16   / CK  drive strength: ck_prcomp [3:0]:RW:4:4:=0xa,ck_nrcomp [3:0]:RW:0:4:=0xa
+		__REG( 0x00154064 ) = 0x0000000a  ; //VALUE_PHYREG19   / CK  pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG( 0x00154068 ) = 0x0000000a  ; //VALUE_PHYREG1A   / CMD pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG( 0x00154080 ) = 0x0000000a  ; //VALUE_PHYREG20   / A_DQ0~A_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG( 0x00154084 ) = 0x00000005  ; //VALUE_PHYREG21   / A_DQ0~A_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG( 0x001540b8 ) = 0x0000008a  ; //VALUE_PHYREG2E   / A_DQ0~A_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540bc ) = 0x00000085  ; //VALUE_PHYREG2F   / A_DQ0~A_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540c0 ) = 0x0000008a  ; //VALUE_PHYREG30   / A_DQ8~A_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540c4 ) = 0x00000085  ; //VALUE_PHYREG31   / A_DQ8~A_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540f8 ) = 0x0000000a  ; //VALUE_PHYREG3E   / A_DQ8~A_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG( 0x001540fc ) = 0x00000005  ; //VALUE_PHYREG3F   / A_DQ8~A_DQ15 pull_up   ODT:RW:0:5:=0xa
+
+		__REG( 0x00154100 ) = 0x0000000a  ; //VALUE_PHYREG40   / B_DQ0~B_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG( 0x00154104 ) = 0x00000005  ; //VALUE_PHYREG41   / B_DQ0~B_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG( 0x00154138 ) = 0x0000008a  ; //VALUE_PHYREG4E   / B_DQ0~B_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x0015413c ) = 0x00000085  ; //VALUE_PHYREG4F   / B_DQ0~B_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+
+		__REG( 0x00154140 ) = 0x0000008a  ; //VALUE_PHYREG50   / B_DQ8~B_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x00154144 ) = 0x00000085  ; //VALUE_PHYREG51   / B_DQ8~B_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG( 0x00154178 ) = 0x0000000a  ; //VALUE_PHYREG5E   / B_DQ8~B_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG( 0x0015417c ) = 0x00000025  ; //VALUE_PHYREG5F   / B_DQ8~B_DQ15 pull_up   ODT:RW:0:5:=0xa  
+		#endif
+ 
+	}
+	else
+	{
+		#ifndef _DDR_DS_48om //60ohm
+		__REG( 0x00154044 )= 0x00000008;  //VALUE_PHYREG11   / CMD drive strength: cmd_nrcomp[4:0]:RW:0:5:=0xa
+		__REG(0x00154058 )= 0x00000008;  //VALUE_PHYREG16   / CK  drive strength: ck_nrcomp [4:0]:RW:0:5:=0xa
+		__REG(0x00154064 )= 0x00000008;  //VALUE_PHYREG19   / CK  pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG(0x00154068 )= 0x00000008;  //VALUE_PHYREG1A   / CMD pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG(0x00154080 )= 0x00000008;  //VALUE_PHYREG20   / A_DQ0~A_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG(0x00154084 )= 0x00000004;  //VALUE_PHYREG21   / A_DQ0~A_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG(0x001540b8 )= 0x00000088;  //VALUE_PHYREG2E   / A_DQ0~A_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x001540bc )= 0x00000084;  //VALUE_PHYREG2F   / A_DQ0~A_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG(0x001540c0 )= 0x00000088;  //VALUE_PHYREG30   / A_DQ8~A_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x001540c4 )= 0x00000084;  //VALUE_PHYREG31   / A_DQ8~A_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG(0x001540f8 )= 0x00000008;  //VALUE_PHYREG3E   / A_DQ8~A_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG(0x001540fc )= 0x00000004;  //VALUE_PHYREG3F   / A_DQ8~A_DQ15 pull_up   ODT:RW:0:5:=0xa
+
+		__REG(0x00154100 )= 0x00000008;  //VALUE_PHYREG40   / B_DQ0~B_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG(0x00154104 )= 0x00000004;  //VALUE_PHYREG41   / B_DQ0~B_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG(0x00154138 )= 0x00000088;  //VALUE_PHYREG4E   / B_DQ0~B_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x0015413c )= 0x00000084;  //VALUE_PHYREG4F   / B_DQ0~B_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+
+		__REG(0x00154140 )= 0x00000088;  //VALUE_PHYREG50   / B_DQ8~B_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG(0x00154144 )= 0x00000084;  //VALUE_PHYREG51   / B_DQ8~B_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG(0x00154178 )= 0x00000008;  //VALUE_PHYREG5E   / B_DQ8~B_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG(0x0015417c )= 0x00000024;  //VALUE_PHYREG5F   / B_DQ8~B_DQ15 pull_up   ODT:RW:0:5:=0xa  	
+		#else //48om                          
+		//Drive strength(defualt) ODT µÈЧ48om     
+		__REG( 0x00154044 ) = 0x0000000a  ; //VALUE_PHYREG11   / CMD drive strength: cmd_prcomp[3:0]:RW:4:4:=0xa,cmd_nrcomp[3:0]:RW:0:4:=0xa
+		__REG( 0x00154058 ) = 0x0000000a  ; //VALUE_PHYREG16   / CK  drive strength: ck_prcomp [3:0]:RW:4:4:=0xa,ck_nrcomp [3:0]:RW:0:4:=0xa
+		__REG( 0x00154064 ) = 0x0000000a  ; //VALUE_PHYREG19   / CK  pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG( 0x00154068 ) = 0x0000000a  ; //VALUE_PHYREG1A   / CMD pull_up   drive strength(DS):RW:0:5:=0xa
+		__REG( 0x00154080 ) = 0x0000000a  ; //VALUE_PHYREG20   / A_DQ0~A_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG( 0x00154084 ) = 0x00000005  ; //VALUE_PHYREG21   / A_DQ0~A_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG( 0x001540b8 ) = 0x0000008a  ; //VALUE_PHYREG2E   / A_DQ0~A_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540bc ) = 0x00000085  ; //VALUE_PHYREG2F   / A_DQ0~A_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540c0 ) = 0x0000008a  ; //VALUE_PHYREG30   / A_DQ8~A_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540c4 ) = 0x00000085  ; //VALUE_PHYREG31   / A_DQ8~A_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG( 0x001540f8 ) = 0x0000000a  ; //VALUE_PHYREG3E   / A_DQ8~A_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG( 0x001540fc ) = 0x00000005  ; //VALUE_PHYREG3F   / A_DQ8~A_DQ15 pull_up   ODT:RW:0:5:=0xa
+
+		__REG( 0x00154100 ) = 0x0000000a  ; //VALUE_PHYREG40   / B_DQ0~B_DQ7 pull_down DS :RW:0:5:=0xa
+		__REG( 0x00154104 ) = 0x00000005  ; //VALUE_PHYREG41   / B_DQ0~B_DQ7 pull_down ODT:RW:0:5:=0xa
+		__REG( 0x00154138 ) = 0x0000008a  ; //VALUE_PHYREG4E   / B_DQ0~B_DQ7 pull_up   DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x0015413c ) = 0x00000085  ; //VALUE_PHYREG4F   / B_DQ0~B_DQ7 pull_up   ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+
+		__REG( 0x00154140 ) = 0x0000008a  ; //VALUE_PHYREG50   / B_DQ8~B_DQ15 pull_down DS :RW:0:5:=0xa, falling edge slew rate:RW:5:3:=0x4
+		__REG( 0x00154144 ) = 0x00000085  ; //VALUE_PHYREG51   / B_DQ8~B_DQ15 pull_down ODT:RW:0:5:=0xa, rising  edge slew rate:RW:5:3:=0x4
+		__REG( 0x00154178 ) = 0x0000000a  ; //VALUE_PHYREG5E   / B_DQ8~B_DQ15 pull_up   DS :RW:0:5:=0xa
+		__REG( 0x0015417c ) = 0x00000025  ; //VALUE_PHYREG5F   / B_DQ8~B_DQ15 pull_up   ODT:RW:0:5:=0xa  
+		#endif
+	}
+
+    return 0;
+	
+}
+
+int ddr_ctrl_init(int flag)
+{
+	
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		__REG( 0x00150000 ) = 0x01041004;  // 0x01041004(16bit)   ; //VALUE_MSTR        / device_config:RW:30:2:=0x0 frequency_mode:RW:29:1:=0x0 active_ranks:RW:24:4:=0x3 burst_rdwr:RW:16:4:=0x4 dll_off_mode:RW:15:1:=0x0 data_bus_width:RW:12:2:=0x0 geardown_mode:RW:11:1:=0x0 en_2t_timing_mode:RW:10:1:=0x0 burstchop:RW:9:1:=0x0 burst_mode:RW:8:1:=0x0 lpddr4:RW:5:1:=0x0 ddr4:RW:4:1:=0x0 lpddr3:RW:3:1:=0x0 lpddr2:RW:2:1:=0x1 mobile:RW:1:1:=0x0 ddr3:RW:0:1:=0x0
+	}
+	else
+	{
+		__REG( 0x00150000 ) = 0x01040004; // 0x01040004(32bit) 
+	}
+	
+	__REG( 0x00150010 ) = 0x00000030     ; //VALUE_MRCTRL0     / mr_wr:RW:31:1:=0x0 mr_addr:RW:12:4:=0x0 mr_rank:RW:4:4:=0x3 sw_init_int:RW:3:1:=0x0 pda_en:RW:2:1:=0x0 mpr_en:RW:1:1:=0x0 mr_type:RW:0:1:=0x0
+	__REG( 0x00150014 ) = 0x00000000     ; //VALUE_MRCTRL1     /mr_data:RW:0:16:=0x0
+	__REG( 0x00150020 ) = 0x00000000     ; //VALUE_DERATEEN    /rc_derate_value:RW:8:2:=0x0 derate_byte:RW:4:4:=0x0 derate_value:RW:1:1:=0x0 derate_enable:RW:0:1:=0x0
+	__REG( 0x00150024 ) = 0x00800000     ; //VALUE_DERATEINT   /mr4_read_interval:RW:0:32:=0x800000
+
+	__REG( 0x00150030 ) = 0x00000000     ; //VALUE_PWRCTL      / stay_in_selfref:RW:6:1:=0x0 selfref_sw:RW:5:1:=0x0 mpsm_en:RW:4:1:=0x0 en_dfi_dram_clk_disable:RW:3:1:=0x0 deeppowerdown_en:RW:2:1:=0x0 powerdown_en:RW:1:1:=0x1 selfref_en:RW:0:1:=0x1
+	__REG( 0x00150034 ) = 0x00052002     ; //VALUE_PWRTMG      / selfref_to_x32:RW:16:8:=0x5 deeppowerdown_to_x1024:RW:8:8:=0x20 powerdown_to_x32:RW:0:5:=0x2
+	__REG( 0x00150038 ) = 0x00040003     ; //VALUE_HWLPCTL     / hw_lp_idle_x32:RW:16:12:=0x4 hw_lp_exit_idle_en:RW:1:1:=0x1 hw_lp_en:RW:0:1:=0x1
+	__REG( 0x00150050 ) = 0x00210000     ; //VALUE_RFSHCTL0    / refresh_margin:RW:20:4:=0x2 refresh_to_x32:RW:12:5:=0x10 refresh_burst:RW:4:5:=0x0 per_bank_refresh:RW:2:1:=0x0
+	__REG( 0x00150054 ) = 0x00000000     ; //VALUE_RFSHCTL1    / refresh_timer1_start_value_x32:RW:16:12:=0x0 refresh_timer0_start_value_x32:RW:0:12:=0x0
+	__REG( 0x00150058 ) = 0x00000000     ; //VALUE_RFSHCTL2    / refresh_timer3_start_value_x32:RW:16:12:=0x0 refresh_timer2_start_value_x32:RW:0:12:=0x0
+	__REG( 0x00150060 ) = 0x00000000     ; //VALUE_RFSHCTL3    / refresh_mode:RW:4:3:=0x0 refresh_update_level:RW:1:1:=0x0 dis_auto_refresh:RW:0:1:=0x0
+	
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		#if _DDR32M_BYPASS_MODE
+		__REG( 0x00150064 ) = 0x00260014     ; //VALUE_RFSHTMG     / t_rfc_nom_x32(trefi):RW:16:12:=0x26 lpddr3_trefbw_en:RW:15:1:=0x0 t_rfc_min:RW:0:9:=0x14
+		__REG( 0x001500d0 ) = 0x001f0001     ; //VALUE_INIT0       / skip_dram_init:RW:31:2:=0x0 post_cke_x1024:RW:16:10:=0x1f pre_cke_x1024:RW:0:11:=0x1
+		__REG( 0x001500d4 ) = 0x00000000     ; //VALUE_INIT1       / dram_rstn_x1024:RW:16:8:=0x0 final_wait_x32:RW:8:7:=0x0 pre_ocd_x32:RW:0:4:=0x0
+		__REG( 0x001500d8 ) = 0x00000405     ; //VALUE_INIT2       / idle_after_reset_x32:RW:8:8:=0x4 min_stable_clock_x1:RW:0:4:=0x5
+		//MR2=RL/WL£¬1£ºRL3/WL1£¬2£ºRL4/WL2£¬3£ºRL:5/WL2£¬4£ºRL6/WL3:£¬5£ºRL7/WL4£¬6£ºRL8/WL4
+		__REG( 0x001500dc ) = 0x00630006     ; //VALUE_INIT3       / mr:RW:16:16:=0x63 emr:RW:0:16:=0x6
+		//bit16-31£¬LPDDR2 MR3 value£¬Æ÷¼þDSĬÈÏÊÇ40ohm£¬£¨1=34.3£¬2=40,3=48,4=60,6=80£©
+		#ifndef _DDR32M_DS_48om //60ohm
+		__REG( 0x001500e0 ) = 0x00040000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#else //48ohm
+		__REG( 0x001500e0 ) = 0x00030000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#endif
+		__REG( 0x001500e4 ) = 0x00050002     ; //VALUE_INIT5       / dev_zqinit_x32:RW:16:8:=0x5 max_auto_init_x1024:RW:0:10:=0x2
+		__REG( 0x001500f4 ) = 0x0000066f     ; //VALUE_RANKCTL     / diff_rank_wr_gap:RW:8:4:=0x6 diff_rank_rd_gap:RW:4:4:=0x6 max_rank_rd:RW:0:4:=0xf
+		__REG( 0x00150100 ) = 0x06080a07     ; //VALUE_DRAMTMG0    / wr2pre:RW:24:6:=0x6 t_faw:RW:16:6:=0x8 t_ras_max:RW:8:7:=0xa t_ras_min:RW:0:6:=0x7
+		__REG( 0x00150104 ) = 0x0002020a     ; //VALUE_DRAMTMG1    / t_xp:RW:16:5:=0x2 rd2pre:RW:8:5:=0x2 t_rc:RW:0:6:=0x9
+		//RL=bit16-21£¬1£ºRL=2£¬2£ºRL=4£¬3£ºRL=6£¬4£ºR=8£¬WL=bit24-29£¬1£ºWL=2£¬2£ºWL=4
+		//ÕâÀïµ¼ÖÂMR2µÄÅäÖã¨0x012160dc£©²»ÄÜÑ¡Ôñº¬ÓÐÆæÊýµÄÖµ?
+		__REG( 0x00150108 ) = 0x02040606     ; //VALUE_DRAMTMG2    / write_latency:RW:24:6:=0x2 read_latency:RW:16:6:=0x4 rd2wr:RW:8:6:=0x6 wr2rd:RW:0:6:=0x6
+		__REG( 0x0015010c ) = 0x00501000     ; //VALUE_DRAMTMG3    / t_mrw:RW:20:10:=0x5 t_mrd:RW:12:6:=0x1 t_mod:RW:0:10:=0x0
+		__REG( 0x00150110 ) = 0x03010204     ; //VALUE_DRAMTMG4    / t_rcd:RW:24:5:=0x3 t_ccd:RW:16:4:=0x1 t_rrd:RW:8:4:=0x2 t_rp:RW:0:5:=0x4
+		__REG( 0x00150114 ) = 0x01010303     ; //VALUE_DRAMTMG5    / t_cksrx:RW:24:4:=0x1 t_cksre:RW:16:4:=0x1 t_ckesr:RW:8:6:=0x3 t_cke:RW:0:4:=0x3
+		__REG( 0x00150118 ) = 0x02020003     ; //VALUE_DRAMTMG6    / t_ckdpde:RW:24:4:=0x2 t_ckdpdx:RW:16:4:=0x2 t_ckcsx:RW:0:4:=0x3
+		__REG( 0x0015011c ) = 0x00000202     ; //VALUE_DRAMTMG7    / t_ckpde:RW:8:4:=0x2 t_ckpdx:RW:0:4:=0x2
+		__REG( 0x00150138 ) = 0x00000016     ; //VALUE_DRAMTMG14   / t_xsr:RW:0:12:=0x16
+		//bit30=1 Disable issuing of ZQCL/MPC(ZQ calibration) command at Self-Refresh/SR-Powerdown exit £¬7520×ʼÅäÖÃΪ0£¬µ¼ÖÂ×Ô¶¯×Ôˢй¦ÄÜÍ˳öʱÑÓʱºÜ´ó£¬sdio¶ÁÊý¾Ý³ö´í
+		__REG( 0x00150180 ) = 0x4039000f     ; //VALUE_ZQCTL0      / dis_auto_zq:RW:31:1:=0x0 dis_srx_zqcl:RW:30:1:=0x1 zq_resistor_shared:RW:29:1:=0x0 dis_mpsmx_zqcl:RW:28:1:=0x0 t_zq_long_nop:RW:16:10:=0x39 t_zq_short_nop:RW:0:10:=0xf
+		__REG( 0x00150184 ) = 0x00800100     ; //VALUE_ZQCTL1      / t_zq_reset_nop:RW:20:10:=0x8 t_zq_short_interval_x1024:RW:0:20:=0x100
+
+		#else
+		__REG( 0x00150064 ) = 0x0030001a     ; //VALUE_RFSHTMG     / t_rfc_nom_x32(trefi):RW:16:12:=0x26 lpddr3_trefbw_en:RW:15:1:=0x0 t_rfc_min:RW:0:9:=0x14
+		__REG( 0x001500d0 ) = 0x00280001     ; //VALUE_INIT0       / skip_dram_init:RW:31:2:=0x0 post_cke_x1024:RW:16:10:=0x1f pre_cke_x1024:RW:0:11:=0x1
+		__REG( 0x001500d4 ) = 0x00000000     ; //VALUE_INIT1       / dram_rstn_x1024:RW:16:8:=0x0 final_wait_x32:RW:8:7:=0x0 pre_ocd_x32:RW:0:4:=0x0
+		__REG( 0x001500d8 ) = 0x00000605     ; //VALUE_INIT2       / idle_after_reset_x32:RW:8:8:=0x4 min_stable_clock_x1:RW:0:4:=0x5
+		//MR2=RL/WL£¬1£ºRL3/WL1£¬2£ºRL4/WL2£¬3£ºRL:5/WL2£¬4£ºRL6/WL3:£¬5£ºRL7/WL4£¬6£ºRL8/WL4
+		__REG( 0x001500dc ) = 0x00830006     ; //VALUE_INIT3       / mr:RW:16:16:=0x63 emr:RW:0:16:=0x6
+		//bit16-31£¬LPDDR2 MR3 value£¬Æ÷¼þDSĬÈÏÊÇ40ohm£¬£¨1=34.3£¬2=40,3=48,4=60,6=80£©
+		#ifndef _DDR32M_DS_48om //60ohm
+		__REG( 0x001500e0 ) = 0x00040000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#else //48ohm
+		__REG( 0x001500e0 ) = 0x00030000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#endif
+		__REG( 0x001500e4 ) = 0x00070002     ; //VALUE_INIT5       / dev_zqinit_x32:RW:16:8:=0x5 max_auto_init_x1024:RW:0:10:=0x2
+		__REG( 0x001500f4 ) = 0x0000066f     ; //VALUE_RANKCTL     / diff_rank_wr_gap:RW:8:4:=0x6 diff_rank_rd_gap:RW:4:4:=0x6 max_rank_rd:RW:0:4:=0xf
+		__REG( 0x00150100 ) = 0x070a0d08     ; //VALUE_DRAMTMG0    / wr2pre:RW:24:6:=0x6 t_faw:RW:16:6:=0x8 t_ras_max:RW:8:7:=0xa t_ras_min:RW:0:6:=0x7
+		__REG( 0x00150104 ) = 0x0002020d     ; //VALUE_DRAMTMG1    / t_xp:RW:16:5:=0x2 rd2pre:RW:8:5:=0x2 t_rc:RW:0:6:=0x9
+		//RL=bit16-21£¬1£ºRL=2£¬2£ºRL=4£¬3£ºRL=6£¬4£ºR=8£¬WL=bit24-29£¬1£ºWL=2£¬2£ºWL=4
+		//ÕâÀïµ¼ÖÂMR2µÄÅäÖã¨0x012160dc£©²»ÄÜÑ¡Ôñº¬ÓÐÆæÊýµÄÖµ?
+		__REG( 0x00150108 ) = 0x02040607     ; //VALUE_DRAMTMG2    / write_latency:RW:24:6:=0x2 read_latency:RW:16:6:=0x4 rd2wr:RW:8:6:=0x6 wr2rd:RW:0:6:=0x6
+		__REG( 0x0015010c ) = 0x00501000     ; //VALUE_DRAMTMG3    / t_mrw:RW:20:10:=0x5 t_mrd:RW:12:6:=0x1 t_mod:RW:0:10:=0x0
+		__REG( 0x00150110 ) = 0x04010205     ; //VALUE_DRAMTMG4    / t_rcd:RW:24:5:=0x3 t_ccd:RW:16:4:=0x1 t_rrd:RW:8:4:=0x2 t_rp:RW:0:5:=0x4
+		__REG( 0x00150114 ) = 0x01010303     ; //VALUE_DRAMTMG5    / t_cksrx:RW:24:4:=0x1 t_cksre:RW:16:4:=0x1 t_ckesr:RW:8:6:=0x3 t_cke:RW:0:4:=0x3
+		__REG( 0x00150118 ) = 0x02020003     ; //VALUE_DRAMTMG6    / t_ckdpde:RW:24:4:=0x2 t_ckdpdx:RW:16:4:=0x2 t_ckcsx:RW:0:4:=0x3
+		__REG( 0x0015011c ) = 0x00000202     ; //VALUE_DRAMTMG7    / t_ckpde:RW:8:4:=0x2 t_ckpdx:RW:0:4:=0x2
+		__REG( 0x00150138 ) = 0x0000001c     ; //VALUE_DRAMTMG14   / t_xsr:RW:0:12:=0x16
+		//bit30=1 Disable issuing of ZQCL/MPC(ZQ calibration) command at Self-Refresh/SR-Powerdown exit £¬7520×ʼÅäÖÃΪ0£¬µ¼ÖÂ×Ô¶¯×Ôˢй¦ÄÜÍ˳öʱÑÓʱºÜ´ó£¬sdio¶ÁÊý¾Ý³ö´í
+		__REG( 0x00150180 ) = 0x40480012     ; //VALUE_ZQCTL0      / dis_auto_zq:RW:31:1:=0x0 dis_srx_zqcl:RW:30:1:=0x1 zq_resistor_shared:RW:29:1:=0x0 dis_mpsmx_zqcl:RW:28:1:=0x0 t_zq_long_nop:RW:16:10:=0x39 t_zq_short_nop:RW:0:10:=0xf
+		__REG( 0x00150184 ) = 0x00a00100     ; //VALUE_ZQCTL1      / t_zq_reset_nop:RW:20:10:=0x8 t_zq_short_interval_x1024:RW:0:20:=0x100
+		#endif
+		
+	}
+	else
+	{
+		#if _DDR_BYPASS_MODE
+		if(flag == CHIP_DDR_IS_256M)
+			__REG( 0x00150064 ) = 0x00130014     ; //VALUE_RFSHTMG     / t_rfc_nom_x32(trefi):RW:16:12:=0x13 lpddr3_trefbw_en:RW:15:1:=0x0 t_rfc_min:RW:0:9:=0x0a
+		else
+			__REG( 0x00150064 ) = 0x00260014     ; //VALUE_RFSHTMG     / t_rfc_nom_x32(trefi):RW:16:12:=0x26 lpddr3_trefbw_en:RW:15:1:=0x0 t_rfc_min:RW:0:9:=0x14
+		__REG( 0x001500d0 ) = 0x001f0001     ; //VALUE_INIT0       / skip_dram_init:RW:31:2:=0x0 post_cke_x1024:RW:16:10:=0x1f pre_cke_x1024:RW:0:11:=0x1
+		__REG( 0x001500d4 ) = 0x00000000     ; //VALUE_INIT1       / dram_rstn_x1024:RW:16:8:=0x0 final_wait_x32:RW:8:7:=0x0 pre_ocd_x32:RW:0:4:=0x0
+		__REG( 0x001500d8 ) = 0x00000405     ; //VALUE_INIT2       / idle_after_reset_x32:RW:8:8:=0x4 min_stable_clock_x1:RW:0:4:=0x5
+		//MR2=RL/WL£¬1£ºRL3/WL1£¬2£ºRL4/WL2£¬3£ºRL:5/WL2£¬4£ºRL6/WL3:£¬5£ºRL7/WL4£¬6£ºRL8/WL4
+		__REG( 0x001500dc ) = 0x00630006     ; //VALUE_INIT3       / mr:RW:16:16:=0x63 emr:RW:0:16:=0x6
+		//bit16-31£¬LPDDR2 MR3 value£¬Æ÷¼þDSĬÈÏÊÇ40ohm£¬£¨1=34.3£¬2=40,3=48,4=60,6=80£©
+		#ifndef _DDR_DS_48om //60ohm
+		__REG( 0x001500e0 ) = 0x00040000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#else //48ohm
+		__REG( 0x001500e0 ) = 0x00030000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#endif
+		__REG( 0x001500e4 ) = 0x00050002     ; //VALUE_INIT5       / dev_zqinit_x32:RW:16:8:=0x5 max_auto_init_x1024:RW:0:10:=0x2
+		__REG( 0x001500f4 ) = 0x0000066f     ; //VALUE_RANKCTL     / diff_rank_wr_gap:RW:8:4:=0x6 diff_rank_rd_gap:RW:4:4:=0x6 max_rank_rd:RW:0:4:=0xf
+		__REG( 0x00150100 ) = 0x06080a07     ; //VALUE_DRAMTMG0    / wr2pre:RW:24:6:=0x6 t_faw:RW:16:6:=0x8 t_ras_max:RW:8:7:=0xa t_ras_min:RW:0:6:=0x7
+		__REG( 0x00150104 ) = 0x0002020a     ; //VALUE_DRAMTMG1    / t_xp:RW:16:5:=0x2 rd2pre:RW:8:5:=0x2 t_rc:RW:0:6:=0x9
+		//RL=bit16-21£¬1£ºRL=2£¬2£ºRL=4£¬3£ºRL=6£¬4£ºR=8£¬WL=bit24-29£¬1£ºWL=2£¬2£ºWL=4
+		//ÕâÀïµ¼ÖÂMR2µÄÅäÖã¨0x012160dc£©²»ÄÜÑ¡Ôñº¬ÓÐÆæÊýµÄÖµ?
+		__REG( 0x00150108 ) = 0x02040606     ; //VALUE_DRAMTMG2    / write_latency:RW:24:6:=0x2 read_latency:RW:16:6:=0x4 rd2wr:RW:8:6:=0x6 wr2rd:RW:0:6:=0x6
+		__REG( 0x0015010c ) = 0x00501000     ; //VALUE_DRAMTMG3    / t_mrw:RW:20:10:=0x5 t_mrd:RW:12:6:=0x1 t_mod:RW:0:10:=0x0
+		__REG( 0x00150110 ) = 0x03010204     ; //VALUE_DRAMTMG4    / t_rcd:RW:24:5:=0x3 t_ccd:RW:16:4:=0x1 t_rrd:RW:8:4:=0x2 t_rp:RW:0:5:=0x4
+		__REG( 0x00150114 ) = 0x01010303     ; //VALUE_DRAMTMG5    / t_cksrx:RW:24:4:=0x1 t_cksre:RW:16:4:=0x1 t_ckesr:RW:8:6:=0x3 t_cke:RW:0:4:=0x3
+		__REG( 0x00150118 ) = 0x02020003     ; //VALUE_DRAMTMG6    / t_ckdpde:RW:24:4:=0x2 t_ckdpdx:RW:16:4:=0x2 t_ckcsx:RW:0:4:=0x3
+		__REG( 0x0015011c ) = 0x00000202     ; //VALUE_DRAMTMG7    / t_ckpde:RW:8:4:=0x2 t_ckpdx:RW:0:4:=0x2
+		__REG( 0x00150138 ) = 0x00000016     ; //VALUE_DRAMTMG14   / t_xsr:RW:0:12:=0x16
+		//bit30=1 Disable issuing of ZQCL/MPC(ZQ calibration) command at Self-Refresh/SR-Powerdown exit £¬7520×ʼÅäÖÃΪ0£¬µ¼ÖÂ×Ô¶¯×Ôˢй¦ÄÜÍ˳öʱÑÓʱºÜ´ó£¬sdio¶ÁÊý¾Ý³ö´í
+		__REG( 0x00150180 ) = 0x4039000f     ; //VALUE_ZQCTL0      / dis_auto_zq:RW:31:1:=0x0 dis_srx_zqcl:RW:30:1:=0x1 zq_resistor_shared:RW:29:1:=0x0 dis_mpsmx_zqcl:RW:28:1:=0x0 t_zq_long_nop:RW:16:10:=0x39 t_zq_short_nop:RW:0:10:=0xf
+		__REG( 0x00150184 ) = 0x00800100     ; //VALUE_ZQCTL1      / t_zq_reset_nop:RW:20:10:=0x8 t_zq_short_interval_x1024:RW:0:20:=0x100
+
+		#else
+		if(flag == CHIP_DDR_IS_256M)
+			__REG( 0x00150064 ) = 0x0018001a     ; //VALUE_RFSHTMG     / t_rfc_nom_x32(trefi):RW:16:12:=0x18 lpddr3_trefbw_en:RW:15:1:=0x0 t_rfc_min:RW:0:9:=0x0d
+		else
+			__REG( 0x00150064 ) = 0x0030001a     ; //VALUE_RFSHTMG     / t_rfc_nom_x32(trefi):RW:16:12:=0x26 lpddr3_trefbw_en:RW:15:1:=0x0 t_rfc_min:RW:0:9:=0x14
+		__REG( 0x001500d0 ) = 0x00280001     ; //VALUE_INIT0       / skip_dram_init:RW:31:2:=0x0 post_cke_x1024:RW:16:10:=0x1f pre_cke_x1024:RW:0:11:=0x1
+		__REG( 0x001500d4 ) = 0x00000000     ; //VALUE_INIT1       / dram_rstn_x1024:RW:16:8:=0x0 final_wait_x32:RW:8:7:=0x0 pre_ocd_x32:RW:0:4:=0x0
+		__REG( 0x001500d8 ) = 0x00000605     ; //VALUE_INIT2       / idle_after_reset_x32:RW:8:8:=0x4 min_stable_clock_x1:RW:0:4:=0x5
+		//MR2=RL/WL£¬1£ºRL3/WL1£¬2£ºRL4/WL2£¬3£ºRL:5/WL2£¬4£ºRL6/WL3:£¬5£ºRL7/WL4£¬6£ºRL8/WL4
+		__REG( 0x001500dc ) = 0x00830006     ; //VALUE_INIT3       / mr:RW:16:16:=0x63 emr:RW:0:16:=0x6
+		//bit16-31£¬LPDDR2 MR3 value£¬Æ÷¼þDSĬÈÏÊÇ40ohm£¬£¨1=34.3£¬2=40,3=48,4=60,6=80£©
+		#ifndef _DDR_DS_48om //60ohm
+		__REG( 0x001500e0 ) = 0x00040000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#else //48ohm
+		__REG( 0x001500e0 ) = 0x00030000     ; //VALUE_INIT4       / emr2:RW:16:16:=0x2 emr3:RW:0:16:=0x0
+		#endif
+		__REG( 0x001500e4 ) = 0x00070002     ; //VALUE_INIT5       / dev_zqinit_x32:RW:16:8:=0x5 max_auto_init_x1024:RW:0:10:=0x2
+		__REG( 0x001500f4 ) = 0x0000066f     ; //VALUE_RANKCTL     / diff_rank_wr_gap:RW:8:4:=0x6 diff_rank_rd_gap:RW:4:4:=0x6 max_rank_rd:RW:0:4:=0xf
+		__REG( 0x00150100 ) = 0x070a0d08     ; //VALUE_DRAMTMG0    / wr2pre:RW:24:6:=0x6 t_faw:RW:16:6:=0x8 t_ras_max:RW:8:7:=0xa t_ras_min:RW:0:6:=0x7
+		__REG( 0x00150104 ) = 0x0002020d     ; //VALUE_DRAMTMG1    / t_xp:RW:16:5:=0x2 rd2pre:RW:8:5:=0x2 t_rc:RW:0:6:=0x9
+		//RL=bit16-21£¬1£ºRL=2£¬2£ºRL=4£¬3£ºRL=6£¬4£ºR=8£¬WL=bit24-29£¬1£ºWL=2£¬2£ºWL=4
+		//ÕâÀïµ¼ÖÂMR2µÄÅäÖã¨0x012160dc£©²»ÄÜÑ¡Ôñº¬ÓÐÆæÊýµÄÖµ?
+		__REG( 0x00150108 ) = 0x02040607     ; //VALUE_DRAMTMG2    / write_latency:RW:24:6:=0x2 read_latency:RW:16:6:=0x4 rd2wr:RW:8:6:=0x6 wr2rd:RW:0:6:=0x6
+		__REG( 0x0015010c ) = 0x00501000     ; //VALUE_DRAMTMG3    / t_mrw:RW:20:10:=0x5 t_mrd:RW:12:6:=0x1 t_mod:RW:0:10:=0x0
+		__REG( 0x00150110 ) = 0x04010205     ; //VALUE_DRAMTMG4    / t_rcd:RW:24:5:=0x3 t_ccd:RW:16:4:=0x1 t_rrd:RW:8:4:=0x2 t_rp:RW:0:5:=0x4
+		__REG( 0x00150114 ) = 0x01010303     ; //VALUE_DRAMTMG5    / t_cksrx:RW:24:4:=0x1 t_cksre:RW:16:4:=0x1 t_ckesr:RW:8:6:=0x3 t_cke:RW:0:4:=0x3
+		__REG( 0x00150118 ) = 0x02020003     ; //VALUE_DRAMTMG6    / t_ckdpde:RW:24:4:=0x2 t_ckdpdx:RW:16:4:=0x2 t_ckcsx:RW:0:4:=0x3
+		__REG( 0x0015011c ) = 0x00000202     ; //VALUE_DRAMTMG7    / t_ckpde:RW:8:4:=0x2 t_ckpdx:RW:0:4:=0x2
+		__REG( 0x00150138 ) = 0x0000001c     ; //VALUE_DRAMTMG14   / t_xsr:RW:0:12:=0x16
+		//bit30=1 Disable issuing of ZQCL/MPC(ZQ calibration) command at Self-Refresh/SR-Powerdown exit £¬7520×ʼÅäÖÃΪ0£¬µ¼ÖÂ×Ô¶¯×Ôˢй¦ÄÜÍ˳öʱÑÓʱºÜ´ó£¬sdio¶ÁÊý¾Ý³ö´í
+		__REG( 0x00150180 ) = 0x40480012     ; //VALUE_ZQCTL0      / dis_auto_zq:RW:31:1:=0x0 dis_srx_zqcl:RW:30:1:=0x1 zq_resistor_shared:RW:29:1:=0x0 dis_mpsmx_zqcl:RW:28:1:=0x0 t_zq_long_nop:RW:16:10:=0x39 t_zq_short_nop:RW:0:10:=0xf
+		__REG( 0x00150184 ) = 0x00a00100     ; //VALUE_ZQCTL1      / t_zq_reset_nop:RW:20:10:=0x8 t_zq_short_interval_x1024:RW:0:20:=0x100
+		#endif
+	}	
+
+	__REG( 0x00150188 ) = 0x00000000     ; //VALUE_ZQCTL2      / zq_reset:RW:0:1:=0x0
+	//dfi_t_rddata_en=3,֮ǰ7520ÉÏÉè³É2»áµ¼Ö¶Ámr¶Á´í
+	__REG( 0x00150190 ) = 0x04030001     ; //VALUE_DFITMG0     / dfi_t_ctrl_delay:RW:24:5:=0x4 dfi_rddata_use_sdr:RW:23:1:=0x0 dfi_t_rddata_en:RW:16:6:=0x3 dfi_wrdata_use_sdr:RW:15:1:=0x0 dfi_tphy_wrdata:RW:8:6:=0x0 dfi_tphy_wrlat:RW:0:6:=0x1
+	__REG( 0x00150194 ) = 0x00020404     ; //VALUE_DFITMG1     / dfi_t_cmd_lat:RW:28:4:=0x0 dfi_t_parin_lat:RW:24:2:=0x0 dfi_t_wrdata_delay:RW:16:5:=0x2 dfi_t_dram_clk_disable:RW:8:4:=0x4 dfi_t_dram_clk_enable:RW:0:4:=0x4
+	__REG( 0x00150198 ) = 0x09001111     ; //VALUE_DFILPCFG0   / dfi_tlp_resp:RW:24:4:=0x9 dfi_lp_wakeup_dpd:RW:20:4:=0x0 dfi_lp_en_dpd:RW:16:1:=0x0 dfi_lp_wakeup_sr:RW:12:4:=0x1 dfi_lp_en_sr:RW:8:1:=0x1 dfi_lp_wakeup_pd:RW:4:4:=0x1 dfi_lp_en_pd:RW:0:1:=0x1
+	__REG( 0x001501a0 ) = 0x80400003     ; //VALUE_DFIUPD0     / dis_auto_ctrlupd:RW:31:1:=0x1 dfi_t_ctrlup_max:RW:16:10:=0x40 dfi_t_ctrlup_min:RW:0:10:=0x3
+	__REG( 0x001501a4 ) = 0x00000000     ; //VALUE_DFIUPD1     / dfi_t_ctrlupd_interval_min_x1024:RW:16:8:=0x0 dfi_t_ctrlupd_interval_max_x1024:RW:0:8:=0x0
+	__REG( 0x001501a8 ) = 0x80100010     ; //VALUE_DFIUPD2     / dfi_phyupd_en:RW:31:1:=0x1 dfi_phyupd_type1:RW:16:12:=0x10 dfi_phyupd_type0:RW:0:12:=0x10
+	__REG( 0x001501b0 ) = 0x00000000     ; //VALUE_DFIMISC     / dfi_data_cs_polarity:RW:2:1:=0x0 phy_dbi_mode:RW:1:1:=0x0 dfi_init_complete_en:RW:0:1:=0x0
+	__REG( 0x00150200 ) = 0x0000001f     ; //VALUE_ADDRMAP0    / addrmap_dch_bit0:RW:16:5:=0x0 addrmap_cs_bit1:RW:8:5:=0x0 addrmap_cs_bit0:RW:0:5:=0x1f
+
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		__REG( 0x00150204 ) = 0x001f0606	 ; //VALUE_ADDRMAP1    / addrmap_bank_b2:RW:16:4:=0x7 addrmap_bank_b1:RW:8:4:=0x7 addrmap_bank_b0:RW:0:4:=0x7
+		__REG( 0x00150208 ) = 0x00000000     ; //VALUE_ADDRMAP2    / addrmap_col_b5:RW:24:4:=0x0 addrmap_col_b4:RW:16:4:=0x0 addrmap_col_b3:RW:8:4:=0x0 addrmap_col_b2:RW:0:4:=0x0
+		__REG( 0x0015020c ) = 0x0f0f0000     ; //VALUE_ADDRMAP3    / addrmap_col_b9:RW:24:4:=0xf addrmap_col_b8:RW:16:4:=0x0 addrmap_col_b7:RW:8:4:=0x0 addrmap_col_b6:RW:0:4:=0x0
+		__REG( 0x00150210 ) = 0x00000f0f     ; //VALUE_ADDRMAP4    / addrmap_col_b11:RW:8:4:=0xf addrmap_col_b10:RW:0:4:=0xf
+
+	}
+	else if(flag == CHIP_DDR_IS_64M)
+	{		
+		__REG( 0x00150204 ) = 0x001f0707	 ; //VALUE_ADDRMAP1    / addrmap_bank_b2:RW:16:4:=0x7 addrmap_bank_b1:RW:8:4:=0x7 addrmap_bank_b0:RW:0:4:=0x7
+		__REG( 0x00150208 ) = 0x00000000     ; //VALUE_ADDRMAP2    / addrmap_col_b5:RW:24:4:=0x0 addrmap_col_b4:RW:16:4:=0x0 addrmap_col_b3:RW:8:4:=0x0 addrmap_col_b2:RW:0:4:=0x0
+		__REG( 0x0015020c ) = 0x0f000000     ; //VALUE_ADDRMAP3    / addrmap_col_b9:RW:24:4:=0xf addrmap_col_b8:RW:16:4:=0x0 addrmap_col_b7:RW:8:4:=0x0 addrmap_col_b6:RW:0:4:=0x0
+		__REG( 0x00150210 ) = 0x00000f0f     ; //VALUE_ADDRMAP4    / addrmap_col_b11:RW:8:4:=0xf addrmap_col_b10:RW:0:4:=0xf
+		
+	}
+	else
+	{		
+		__REG( 0x00150204 ) = 0x00070707	 ; //VALUE_ADDRMAP1    / addrmap_bank_b2:RW:16:4:=0x7 addrmap_bank_b1:RW:8:4:=0x7 addrmap_bank_b0:RW:0:4:=0x7
+		__REG( 0x00150208 ) = 0x00000000     ; //VALUE_ADDRMAP2    / addrmap_col_b5:RW:24:4:=0x0 addrmap_col_b4:RW:16:4:=0x0 addrmap_col_b3:RW:8:4:=0x0 addrmap_col_b2:RW:0:4:=0x0
+		__REG( 0x0015020c ) = 0x0f000000     ; //VALUE_ADDRMAP3    / addrmap_col_b9:RW:24:4:=0xf addrmap_col_b8:RW:16:4:=0x0 addrmap_col_b7:RW:8:4:=0x0 addrmap_col_b6:RW:0:4:=0x0
+		__REG( 0x00150210 ) = 0x00000f0f     ; //VALUE_ADDRMAP4    / addrmap_col_b11:RW:8:4:=0xf addrmap_col_b10:RW:0:4:=0xf
+	
+	}
+
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		__REG( 0x00150214 ) = 0x04040404	 ; //VALUE_ADDRMAP5    / addrmap_row_b11:RW:24:4:=0x6 addrmap_row_b2_10:RW:16:4:=0x6 addrmap_row_b1:RW:8:4:=0x6 addrmap_row_b0:RW:0:4:=0x6
+		__REG( 0x00150218 ) = 0x0f0f0f04	 ; //VALUE_ADDRMAP6    / addrmap_row_b15:RW:24:4:=0xf addrmap_row_b14:RW:16:4:=0xf addrmap_row_b13:RW:8:4:=0xf addrmap_row_b12:RW:0:4:=0x6
+	}
+	else if(flag == CHIP_DDR_IS_64M)
+	{	
+		__REG( 0x00150214 ) = 0x05050505	 ; //VALUE_ADDRMAP5    / addrmap_row_b11:RW:24:4:=0x6 addrmap_row_b2_10:RW:16:4:=0x6 addrmap_row_b1:RW:8:4:=0x6 addrmap_row_b0:RW:0:4:=0x6
+		__REG( 0x00150218 ) = 0x0f0f0f05	 ; //VALUE_ADDRMAP6    / addrmap_row_b15:RW:24:4:=0xf addrmap_row_b14:RW:16:4:=0xf addrmap_row_b13:RW:8:4:=0xf addrmap_row_b12:RW:0:4:=0x6
+	}
+
+	else if(flag == CHIP_DDR_IS_256M) 
+	{	
+		__REG( 0x00150214 ) = 0x06060606	 ; //VALUE_ADDRMAP5    / addrmap_row_b11:RW:24:4:=0x6 addrmap_row_b2_10:RW:16:4:=0x6 addrmap_row_b1:RW:8:4:=0x6 addrmap_row_b0:RW:0:4:=0x6
+		__REG( 0x00150218 ) = 0x0f0f0606	 ; //VALUE_ADDRMAP6    / addrmap_row_b15:RW:24:4:=0xf addrmap_row_b14:RW:16:4:=0xf addrmap_row_b13:RW:8:4:=0x6 addrmap_row_b12:RW:0:4:=0x6
+	}
+	else
+	{	
+		__REG( 0x00150214 ) = 0x06060606	 ; //VALUE_ADDRMAP5    / addrmap_row_b11:RW:24:4:=0x6 addrmap_row_b2_10:RW:16:4:=0x6 addrmap_row_b1:RW:8:4:=0x6 addrmap_row_b0:RW:0:4:=0x6
+		__REG( 0x00150218 ) = 0x0f0f0f06	 ; //VALUE_ADDRMAP6    / addrmap_row_b15:RW:24:4:=0xf addrmap_row_b14:RW:16:4:=0xf addrmap_row_b13:RW:8:4:=0xf addrmap_row_b12:RW:0:4:=0x6
+	}
+	__REG( 0x00150240 ) = 0x04000400     ; //VALUE_ODTCFG      / wr_odt_hold:RW:24:4:=0x4 wr_odt_delay:RW:16:4:=0x0 rd_odt_hold:RW:8:4:=0x4 rd_odt_delay:RW:2:4:=0x0
+	__REG( 0x00150244 ) = 0x00000000     ; //VALUE_ODTMAP      / rank3_rd_odt:RW:28:4:=0x0 rank3_wr_odt:RW:24:4:=0x0 rank2_rd_odt:RW:20:4:=0x0 rank2_wr_odt:RW:16:4:=0x0 rank1_rd_odt:RW:12:4:=0x0 rank1_wr_odt:RW:8:4:=0x0 rank0_rd_odt:RW:4:4:=0x0 rank0_wr_odt:RW:0:4:=0x0
+	__REG( 0x00150250 ) = 0x00001805     ; //VALUE_SCHED       / rdwr_idle_gap:RW:24:7:=0x0 go2critical_hysteresis:RW:16:8:=0x0 lpr_num_entries:RW:8:6:=0x18 pageclose:RW:2:1:=0x1 prefer_write:RW:1:1:=0x0 force_low_pri_n:RW:0:1:=0x1
+	__REG( 0x00150254 ) = 0x00000000     ; //VALUE_SCHED1      / pageclose_timer:RW:0:8:=0x0
+
+	__REG( 0x00150300 ) = 0x00000000     ; //VALUE_DBG0        / dis_collision_page_opt:RW:4:1:=0x0 dis_act_bypass:RW:2:1:=0x0 dis_rd_bypass:RW:1:1:=0x0 dis_wc:RW:0:1:=0x0
+	__REG( 0x00150304 ) = 0x00000000     ; //VALUE_DBG1        / dis_dq:RW:1:1:=0x0 dis_hig:RW:0:1:=0x0
+	__REG( 0x0015030c ) = 0x00000000     ; //VALUE_DBGCMD      / ctrlupd:RWSC:5:1:=0x0 zq_calib_short:RWSC:4:1:=0x0 rank3_refresh:RWSC:3:1:=0x0 rank2_refresh:RWSC:2:1:=0x0 rank1_refresh:RWSC:1:1:=0x0 rank0_refresh:RWSC:0:1:=0x0
+
+	__REG( 0x00150400 ) = 0x00000000     ; //VALUE_PCCFG       / bl_exp_mode:RW:8:1:=0x0 pagematch_limit:RW:1:1:=0x0 go2critical_en:RW:0:1:=0x0
+
+    return 0;
+
+}
+
+int ddr_prio_init(int flag)
+{
+	//port read static priority bit0-9, bit0-4 timeout, bit5-9 priority
+	__REG( 0x00150404 ) = 0x000013ff     ; //VALUE_PCFGR_0     / rdwr_ordered_en:RW:16:1:=0x0 rd_port_pagematch_en:RW:14:1:=0x0 rd_port_urgent_en:RW:13:1:=0x0 rd_port_aging_en:RW:12:1:=0x1 read_reorder_bypass_en:RW:11:1:=0x0 rd_port_priority:RW:0:10:=0x3ff
+	__REG( 0x001504b4 ) = 0x00001020     ; //VALUE_PCFGR_1     / rdwr_ordered_en:RW:16:1:=0x0 rd_port_pagematch_en:RW:14:1:=0x0 rd_port_urgent_en:RW:13:1:=0x0 rd_port_aging_en:RW:12:1:=0x1 read_reorder_bypass_en:RW:11:1:=0x0 rd_port_priority:RW:0:10:=0x20
+	__REG( 0x00150564 ) = 0x00001000     ; //VALUE_PCFGR_2     / rdwr_ordered_en:RW:16:1:=0x0 rd_port_pagematch_en:RW:14:1:=0x0 rd_port_urgent_en:RW:13:1:=0x0 rd_port_aging_en:RW:12:1:=0x1 read_reorder_bypass_en:RW:11:1:=0x0 rd_port_priority:RW:0:10:=0x0
+	__REG( 0x00150614 ) = 0x00001004     ; //VALUE_PCFGR_3     / rdwr_ordered_en:RW:16:1:=0x0 rd_port_pagematch_en:RW:14:1:=0x0 rd_port_urgent_en:RW:13:1:=0x0 rd_port_aging_en:RW:12:1:=0x1 read_reorder_bypass_en:RW:11:1:=0x0 rd_port_priority:RW:0:10:=0x4
+	 //port write static priority bit0-9
+	__REG( 0x00150408 ) = 0x000013ff     ; //VALUE_PCFGW_0     / wr_port_pagematch_en:RW:14:1:=0x0 wr_port_urgent_en:RW:13:1:=0x0 wr_port_aging_en:RW:12:1:=0x1 wr_port_priority:RW:0:10:=0x3ff
+	__REG( 0x001504b8 ) = 0x000010ff     ; //VALUE_PCFGW_1     / wr_port_pagematch_en:RW:14:1:=0x0 wr_port_urgent_en:RW:13:1:=0x0 wr_port_aging_en:RW:12:1:=0x1 wr_port_priority:RW:0:10:=0xff
+	__REG( 0x00150568 ) = 0x0000103f     ; //VALUE_PCFGW_2     / wr_port_pagematch_en:RW:14:1:=0x0 wr_port_urgent_en:RW:13:1:=0x0 wr_port_aging_en:RW:12:1:=0x1 wr_port_priority:RW:0:10:=0x3f
+	__REG( 0x00150618 ) = 0x0000105f     ; //VALUE_PCFGW_3     / wr_port_pagematch_en:RW:14:1:=0x0 wr_port_urgent_en:RW:13:1:=0x0 wr_port_aging_en:RW:12:1:=0x1 wr_port_priority:RW:0:10:=0x5f
+	//port read region set
+	__REG( 0x00150494 ) = 0x0020000e     ; //VALUE_PCFGQOS0_0  / rqos_map_region2:RW:24:2:=0x0 rqos_map_region1:RW:20:2:=0x2 rqos_map_region0:RW:16:2:=0x0 rqos_map_level2:RW:8:4:=0x0 rqos_map_level1:RW:0:4:=0xe
+	__REG( 0x00150544 ) = 0x0020000e     ; //VALUE_PCFGQOS0_1  / rqos_map_region2:RW:24:2:=0x0 rqos_map_region1:RW:20:2:=0x2 rqos_map_region0:RW:16:2:=0x0 rqos_map_level2:RW:8:4:=0x0 rqos_map_level1:RW:0:4:=0xe
+	__REG( 0x001505f4 ) = 0x0020000e     ; //VALUE_PCFGQOS0_2  / rqos_map_region2:RW:24:2:=0x0 rqos_map_region1:RW:20:2:=0x2 rqos_map_region0:RW:16:2:=0x0 rqos_map_level2:RW:8:4:=0x0 rqos_map_level1:RW:0:4:=0xe
+	__REG( 0x001506a4 ) = 0x0020000e     ; //VALUE_PCFGQOS0_3  / rqos_map_region2:RW:24:2:=0x0 rqos_map_region1:RW:20:2:=0x2 rqos_map_region0:RW:16:2:=0x0 rqos_map_level2:RW:8:4:=0x0 rqos_map_level1:RW:0:4:=0xe
+	//port write region set
+	__REG( 0x0015049c ) = 0x00000000     ; //VALUE_PCFGWQOS0_0 / wqos_map_region1:RW:20:2:=0x0 wqos_map_region0:RW:16:2:=0x0 wqos_map_level:RW:0:4:=0x0
+	__REG( 0x0015054c ) = 0x00000000     ; //VALUE_PCFGWQOS0_1 / wqos_map_region1:RW:20:2:=0x0 wqos_map_region0:RW:16:2:=0x0 wqos_map_level:RW:0:4:=0x0
+	__REG( 0x001505fc ) = 0x00000000     ; //VALUE_PCFGWQOS0_2 / wqos_map_region1:RW:20:2:=0x0 wqos_map_region0:RW:16:2:=0x0 wqos_map_level:RW:0:4:=0x0
+	__REG( 0x001506ac ) = 0x00000000     ; //VALUE_PCFGWQOS0_3 / wqos_map_region1:RW:20:2:=0x0 wqos_map_region0:RW:16:2:=0x0 wqos_map_level:RW:0:4:=0x0
+	//vpr timeout, region2 is red queue
+	__REG( 0x00150498 ) = 0x00000000     ; //VALUE_PCFGQOS1_0  / rqos_map_timeoutr:RW:16:11:=0x0 rqos_map_timeoutb:RW:0:11:=0x0
+	__REG( 0x00150548 ) = 0x00000000     ; //VALUE_PCFGQOS1_1  / rqos_map_timeoutr:RW:16:11:=0x0 rqos_map_timeoutb:RW:0:11:=0x0
+	__REG( 0x001505f8 ) = 0x00000000     ; //VALUE_PCFGQOS1_2  / rqos_map_timeoutr:RW:16:11:=0x0 rqos_map_timeoutb:RW:0:11:=0x0
+	__REG( 0x001506a8 ) = 0x00000000     ; //VALUE_PCFGQOS1_3  / rqos_map_timeoutr:RW:16:11:=0x0 rqos_map_timeoutb:RW:0:11:=0x0
+	//vpw timeout
+	__REG( 0x001504a0 ) = 0x00000000     ; //VALUE_PCFGWQOS1_0 / wqos_map_timeout:RW:0:11:=0x0
+	__REG( 0x00150550 ) = 0x00000000     ; //VALUE_PCFGWQOS1_1 / wqos_map_timeout:RW:0:11:=0x0
+	__REG( 0x00150600 ) = 0x00000000     ; //VALUE_PCFGWQOS1_2 / wqos_map_timeout:RW:0:11:=0x0
+	__REG( 0x001506b0 ) = 0x00000000     ; //VALUE_PCFGWQOS1_3 / wqos_map_timeout:RW:0:11:=0x0
+	//in CAM set
+	__REG( 0x0015025c ) = 0x0f000001     ; //VALUE_PERFHPR1    / hpr_xact_run_length:RW:24:8:=0xf hpr_max_starve:RW:0:16:=0x1
+	__REG( 0x00150264 ) = 0x0f00007f     ; //VALUE_PERFLPR1    / lpr_xact_run_length:RW:24:8:=0xf lpr_max_starve:RW:0:16:=0x7f
+	__REG( 0x0015026c ) = 0x0f00007f     ; //VALUE_PERFWR1     / w_xact_run_length:RW:24:8:=0xf w_max_starve:RW:0:16:=0x7f
+	__REG( 0x00150274 ) = 0x00000000     ; //VALUE_PERFVPR1    / vpr_timeout_range:RW:0:11:=0x0
+	__REG( 0x00150278 ) = 0x00000000     ; //VALUE_PERFVPW1    / vpw_timeout_range:RW:0:11:=0x0
+	//port extern static priority	
+	//__REG( 0x0013d034 ) = 0xf0f00000 ; //port0,1 rqos=0(LPR); port2,3 rqos=F(HPR)       
+	
+    return 0;
+	
+}
+
+int ddr_init(int flag)
+{	
+	UINT32 g_PhyJZ[6]={0};
+	
+	//__REG( 0x01306100 ) = 0xffffe000 ; //ddr all reset enable  bit6-12=0   
+	__REG( 0x01306100 ) = 0x0affe000 ; //ddr all reset enable  bit6-12=0 
+	nsdelay(200000);//0.01s 
+	__REG( 0x01306100 ) = 0x0affe400 ; //release ddr apb(bit10)
+	nsdelay(200000);//0.01s
+
+	//ddr clk init
+	ddr_clk_init(flag);
+	
+	//phy register init  
+	ddr_phy_init(flag);
+
+	//controller register init
+	ddr_ctrl_init(flag);
+
+	//ddr_priority_config
+	ddr_prio_init(flag);
+                                                                                           
+	//wait all register configer done in hardware
+	nsdelay(200000);//0.01s
+
+
+	//***********************************************************
+	//ctroller and inno phy registers configer done
+	//***********************************************************
+	__REG( 0x01306100 ) = 0x0affffc0 ; //release ddr ctl(bit11) and axi_sn reset(bit6-9)  and phy reset(bit12)  ; //ÉèÖÃϵͳ¼Ä´æÆ÷Öµ
+	nsdelay(200000);//0.01s
+
+
+	//sw config done
+	__REG( 0x00150320 ) = 0x00000000 ; //SWCTL      ; // sw_done:RW:0:1:=0x0
+	//check phy auto init done, wait 0x00150324 bit0 =0
+	nsdelay(200000);//0.01s
+
+
+	//power on PHY PLL 
+	__REG( 0x001543b4 ) = 0x00000018 ; //PHYREGED,PLLCLKOUTEN:RW:4:1:=0x1,Reserved:RW:2:2:=0x2, pll_pd_en:RW:1:1:=0x0, fbdiv[8]:RW:0:1:=0x0                                                                              
+	//wait PHY PLL  lock,PHYREGF8[0]Pll lock indicate signal
+
+	nsdelay(200000);//0.01s
+
+
+	//PHY DLL init start, fall edge trigger
+	if(flag == CHIP_DDR_IS_32M)	
+	{
+		#ifndef _DDR32M_DS_48om //60ohm
+		__REG( 0x0015417c ) = 0x00000004 ; //PHYREG5F,  PHY init start:5:1:=0x1   
+		#else //48ohm
+		__REG( 0x0015417c ) = 0x00000005 ; //PHYREG5F,  PHY init start:5:1:=0x1   
+		#endif
+	}
+	else	
+	{
+		#ifndef _DDR_DS_48om //60ohm
+		__REG( 0x0015417c ) = 0x00000004 ; //PHYREG5F,  PHY init start:5:1:=0x1   
+		#else //48ohm
+		__REG( 0x0015417c ) = 0x00000005 ; //PHYREG5F,  PHY init start:5:1:=0x1   
+		#endif
+	}
+	//wait dll lock, phy init done, PHYREGF8[1]Phy init complete signal
+	nsdelay(200000);//0.01s
+
+
+	//enable controller dfi_init_complete_en to start sdram init, then will send dram init cmd
+	__REG( 0x001501b0 ) = 0x00000001 ; //DFIMISC    ; // phy_dbi_mode:RW:1:1:=0x0 dfi_init_complete_en:RW:0:1:=0x1	    ÊÇ·ñÈ¥µô£¬»òÕß¶ÔÓ¦ÐÞ¸Ä                                                                                                     
+	//check controller status is sdram init done,wait 0x00150004 bit0-2 !=0
+	nsdelay(200000);//0.01s
+
+	__REG( 0x001501b0 ) = 0x00000000 ; //dfimisc[0] phy_dbi_mode:RW:1:1:=0x0 dfi_init_complete_en:RW:0:1:=0x0
+
+	if(flag == CHIP_DDR_IS_32M)
+	{
+		do
+		{
+			//phy DQS gate training start
+			__REG( 0x00154008 ) = 0x00000001 ; //PHYREG02,bit0:DQS gating calibration control=1, bit1:DQS gating bypass mode select=0
+			//wait training done
+			nsdelay(200000);//0.01s
+
+			//phy DQS gate training stop
+			__REG( 0x00154008 ) = 0x00000000 ; //PHYREG02,bit0:DQS gating calibration control=0, bit1:DQS gating bypass mode select=0
+
+			nsdelay(200000);//0.01s
+			g_PhyJZ[0]=ABSa_b(__REG(0x001543ec),__REG(0x001543f0));
+
+		}while((g_PhyJZ[0]>4)|(__REG(0x001543ec)&0x80));
+	}
+	else
+	{
+		do
+		{
+			//phy DQS gate training start
+			__REG( 0x00154008 ) = 0x00000001 ; //PHYREG02,bit0:DQS gating calibration control=1, bit1:DQS gating bypass mode select=0
+			//wait training done
+			nsdelay(200000);//0.01s
+
+			//phy DQS gate training stop
+			__REG( 0x00154008 ) = 0x00000000 ; //PHYREG02,bit0:DQS gating calibration control=0, bit1:DQS gating bypass mode select=0
+
+			nsdelay(200000);//0.01s
+			g_PhyJZ[0]=ABSa_b(__REG(0x001543ec),__REG(0x001543f0));
+			g_PhyJZ[1]=ABSa_b(__REG(0x001543ec),__REG(0x001543f4));
+			g_PhyJZ[2]=ABSa_b(__REG(0x001543ec),__REG(0x001543f8));
+
+			g_PhyJZ[3]=ABSa_b(__REG(0x001543f0),__REG(0x001543f4));
+			g_PhyJZ[4]=ABSa_b(__REG(0x001543f0),__REG(0x001543f8));
+
+			g_PhyJZ[5]=ABSa_b(__REG(0x001543f4),__REG(0x001543f8));
+		}while((g_PhyJZ[0]>4)|(g_PhyJZ[1]>4)|(g_PhyJZ[2]>4)|(g_PhyJZ[3]>4)|(g_PhyJZ[4]>4)|(g_PhyJZ[5]>4)|(__REG(0x001543ec)&0x80));
+	}
+
+	//enable port_n
+	__REG( 0x00150490 ) = 0x00000001     ; //VALUE_PCTRL_0     / port_en:RW:0:1:=0x1
+	__REG( 0x00150540 ) = 0x00000001     ; //VALUE_PCTRL_1     / port_en:RW:0:1:=0x1
+	__REG( 0x001505f0 ) = 0x00000001     ; //VALUE_PCTRL_2     / port_en:RW:0:1:=0x1
+	__REG( 0x001506a0 ) = 0x00000001     ; //VALUE_PCTRL_3     / port_en:RW:0:1:=0x1
+
+#ifdef DDR_FFC
+	ddr_ffc_init();
+#endif	
+    return 0;
+    
+}
+
+
diff --git a/boot/common/src/loader/drivers/debug.c b/boot/common/src/loader/drivers/debug.c
new file mode 100644
index 0000000..d295abc
--- /dev/null
+++ b/boot/common/src/loader/drivers/debug.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 ZXIC Inc.
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <load_mode.h>
+#include <asm/arch/top_clock.h>
+#include <asm/arch/cpu.h>
+#include <board.h>
+#include <jtag.h>
+
+#if _ZLOADER_TRACE_DEBUG
+
+uint32_t patch = 0; /* ûÓÐÈκÎ×÷Óã¬ÓÃÀ´ÅäºÏBSS¶ÎÇåÁã */
+
+void debug_config(void)
+{
+	unsigned int tmp = 0;
+	int ret = 0;
+	patch = patch;
+
+/*¿½±´½Å±¾µÄʱÖÓ³õʼ»¯*/
+#ifdef CONFIG_BOARD_7520_UFI
+	/*
+	 * Jtag0
+	 * 0:M0Jtag, 1:function, 2:gpio, 3:psJtag, 4:phyJtag, 5:dspJtag, 6:ufiJtag, 7:gpio
+	 */
+	
+ #ifdef CONFIG_BOARD_7520_JTAG0_M0
+#define JTAG0_CONNECT   0
+ #endif
+	
+ #ifdef CONFIG_BOARD_7520_JTAG0_PS
+#define JTAG0_CONNECT   3
+ #endif
+	tmp = __REG(0x00143030);
+	tmp &= 0xff0000f0;
+	tmp |= JTAG0_CONNECT|(JTAG0_CONNECT<<8)|(JTAG0_CONNECT<<12)|(JTAG0_CONNECT<<16)|(JTAG0_CONNECT<<20);
+	__REG(0x00143030) = tmp;
+
+	__REG(0x100000) = 0xeafffffe; /*ps release*/
+	writel(CPU_UFI_SW_RSTEN, CPU_R7_SUBSYS_CFG);	
+#endif	
+
+	/*
+	 * D0/Jtag1 
+	 * 0:gpio, 1:sd0, 2:M0Jtag, 3:psJtag, 4:phyJtag, 5:dspJtag, 6:ufiJtag, 7:testpin
+	 */
+#ifdef CONFIG_BOARD_7520_EVB
+#define JTAG1_CONNECT   3
+	tmp=__REG(0x00143028);
+	tmp=tmp&0xf0000ff0|0x03333003;
+	__REG(0x00143028) = tmp;
+
+	__REG(0x100000) = 0xeafffffe; /*ps release*/
+	writel(CPU_UFI_SW_RSTEN, CPU_R7_SUBSYS_CFG);
+#endif
+
+#if 0
+    /* ps */
+    __REG(SYS_IRAM2_BASE) = 0xEAFFFFFE;                 /* while(1) */
+    __REG(CPU_PS_SUBSYS_CFG) = CPU_PS_SW_RSTEN;
+
+    /* phy */
+    __REG(SYS_IRAM3_BASE) = 0xEAFFFFFE;                 /* while(1) */                /* while(1) */
+    __REG(CPU_PHY_SUBSYS_CFG) = CPU_PHY_SW_RSTEN;
+    
+    /* A9 */
+    __REG(SYS_IRAM6_BASE) = 0xEAFFFFFE;                 /* while(1) */
+    __REG(CPU_UFI_SUBSYS_CFG) = CPU_UFI_SW_RSTEN;
+
+	/* release core reset */
+	__REG(0x0010c044) = 1; // phy
+	__REG(0x0010c048) = 1; // ps
+	__REG(0x0010c04c) = 1; // ufi
+    __REG(0x0010c050) = 1; // zsp
+
+    ret = nand_init();
+    if( ret != 0 )
+        while(1);
+        
+    ddr_init();
+	
+#ifdef CONFIG_BOARD_7520_EVB
+    /*light gpio9*/
+    tmp = __REG(0x10d440);  /* ¹¦ÄÜÒý½Å */
+    tmp |= (0x1 << 24);
+    __REG(0x10d440) = tmp;
+
+    
+    tmp = __REG(0x10dC04);  /* config OUT */
+    tmp &= (~(0x1<<9));
+    __REG(0x10dC04) = tmp;
+
+    tmp = __REG(0x10dC08);  
+    tmp |= (0x1<<9);     /* OUT 1 */
+    __REG(0x10dC08) = tmp;
+#endif
+#endif
+	while(1);
+}
+
+#endif
diff --git a/boot/common/src/loader/drivers/denali.c b/boot/common/src/loader/drivers/denali.c
new file mode 100644
index 0000000..f4ddfd9
--- /dev/null
+++ b/boot/common/src/loader/drivers/denali.c
@@ -0,0 +1,496 @@
+/*
+ * (C) Copyright 2016 ZXIC Inc.
+ */
+   
+
+#include <common.h>
+#include <asm/arch/denali.h>
+#include <asm/io.h>
+#include <bbt.h>
+
+#include "flash.h"
+
+
+static struct nand_flash_device_para *nand_info = NULL;
+/* nand flash parameter config */
+static const struct nand_flash_device_para nand_flash_para[] = {
+	/* MT29F4G08ABBDAH4 for 7520V5 evb 512MB X 8 */
+	{0x2C, 0xAC, 0x90, 0, 4, 2048,11, 64, 17, 4096, 0x20000},
+    /* MT29F2G08ABBEA for 7520 evb 256MB X 8 */
+    {0x2C, 0xAA, 0x90, 0, 4, 2048,11, 64, 17, 2048, 0x20000},
+    
+    /* K9F2G08U0B for 7520 FPGA */
+    {0xEC, 0xDA, 0x10, 0, 4, 2048,11, 64, 17,2048, 0x20000},
+
+	/* JSFBA3YHABB for 7510 evb 256MB X 8  ---> DDR 128M*/
+	{0xAD, 0xAA, 0x90, 0, 8, 2048, 11, 128, 17,2048, 0x20000},
+
+	/* FM6BD2G1GA for 7510 evb 256MB X 8 ---> DDR 128M */
+	{0xC8, 0xAA, 0x90, 0, 4, 2048, 11, 64, 17, 2048, 0x20000},
+
+	/* H9TA4GG4GDMCPR for 7510 evb 512MB X 8 ---> DDR 512M */
+	{0xAD, 0xAC, 0x90, 0, 8, 2048, 11, 128, 17, 4096, 0x20000},
+
+	/* JSFCBX3Y7ABB for 7510 evb 512MB X 8 ---> DDR 256M */
+	{0x01, 0xAC, 0x90, 0, 8, 2048, 11, 128, 17, 4096, 0x20000},
+
+	/* FM6BD4G2GA for 7510 evb 512MB X 8 ---> DDR 256M*/
+	{0xC8, 0xAC, 0x90, 0, 4, 2048, 11, 64, 17, 4096, 0x20000},
+
+	/* NM1281KSLAXAJ for 7510 evb 256MB X 8  ---> DDR 128M*/
+	{0x98, 0xAA, 0x90, 0, 8, 2048, 11, 128, 17, 2048, 0x20000},
+
+	/* W71NW20GF3FW  for 7520 evb 256MB X 8 */	
+	{0xEF, 0xAA, 0x90, 0, 4, 2048,11, 64, 17, 2048, 0x20000},	
+	{0}
+};
+
+
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ static uint32_t wait_for_ready(uint32_t status_type)
+{
+    uint32_t status = 0;
+    while (!(readl(INTR_STATUS(0)) & status_type));
+    status = readl(INTR_STATUS(0));  
+    writew(0xffff, INTR_STATUS(0));
+	return status;
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+static void index_addr(uint32_t address, uint32_t data)
+{
+	writel(address, NAND_DATA);
+	writel(data, NAND_DATA_10);
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+static void index_addr_read_data(uint32_t address, uint32_t *pdata)
+{
+	writel(address, NAND_DATA);
+	*pdata = readl(NAND_DATA_10);
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+void nand_read_oob(uint8_t *buf, uint32_t offset, uint32_t len)
+{
+    uint32_t cmd, i, status_type; 
+    uint32_t *buf32 = NULL; 
+    uint32_t addr = offset >> (nand_info->page_size_shift);     //addr = bank0 | page
+    
+    /* 0. disable ECC */
+    writel(ECC_DISABLE__FLAG, ECC_ENABLE);
+
+	writel(0xffff, INTR_STATUS(0));
+
+    writel(TRANSFER_SPARE_REG__FLAG, TRANSFER_SPARE_REG);
+
+    /* setup page read request for SPARE_ACCESS read */
+	cmd = MODE_10 | addr;
+	index_addr((uint32_t)cmd, SPARE_ACCESS);
+
+	cmd = MODE_10 | addr;
+	index_addr((uint32_t)cmd, 0x2001);
+
+    /* page 33 of the NAND controller spec indicates we should not
+	    use the pipeline commands in Spare area only mode. So we
+		don't.
+	 */
+    cmd = MODE_01 | addr;
+    writel(cmd, NAND_DATA);
+
+    status_type = wait_for_ready(INTR_STATUS__LOAD_COMP | INTR_STATUS__TIME_OUT);
+	if (status_type & INTR_STATUS__TIME_OUT)
+		printf("[OT]\n");   /* OOB TIMEOUT */
+
+	/* 0. read oob data */
+    buf32 = (uint32_t *)buf;
+	for (i = 0; i < len / 4; i++)
+		*buf32++ = readl(NAND_DATA_10);
+
+	/* We set the device back to MAIN_ACCESS here as I observed
+	 * instability with the controller if you do a block erase
+	 * and the last transaction was a SPARE_ACCESS. Block erase
+	 * is reliable (according to the MTD test infrastructure)
+	 * if you are in MAIN_ACCESS.
+	 */
+	cmd = MODE_10 | addr;
+	index_addr((uint32_t)cmd, MAIN_ACCESS);
+    
+}
+
+
+void clear_intr(void)
+{
+	while(readl(INTR_STATUS(0)))
+	{
+		writew(0xffff, INTR_STATUS(0));
+		
+	}
+	writew(0xffff, INTR_STATUS(0));
+	
+	nsdelay(400000);//0.02s
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t read_page(uint32_t buf, uint32_t offset)
+{
+    uint32_t status = 0;
+	int32_t ecc_status = 0;
+    uint32_t page = offset >> (nand_info->page_size_shift);
+    uint32_t mode = MODE_10;         /* MODE_10 | BANK(denali->flash_bank) */
+
+    if((buf & 0x3) != 0)          /* DMAµØÖ·ÒªÇó4×Ö½Ú¶ÔÆë */
+    {
+        printf("[AE]\n"); /* [read_page]:ADDR ERROR */
+        return -1;      
+    }
+
+	ecc_status =readl(ECC_CORRECTION);
+
+	if(page < 64)
+	{
+		writel(0x8, ECC_CORRECTION);
+	}
+    
+    /* clear status */
+    writew(0xffff, INTR_STATUS(0));
+    
+	writel(TRANSFER_MAIN_REG__FLAG, TRANSFER_SPARE_REG);
+    
+    /* enable DMA */
+    writel(DMA_ENABLE__FLAG, DMA_ENABLE); 
+
+	/* setup transfer type and # of pages -FOR DMA */
+    index_addr(mode | page, 0x2001);    //mode10(0x08000000) | bank0(0) | page, 
+                                         //  0x2000 | DENALI_READ(0) | 1
+
+	/* set memory high address bits 23:8 -FOR DMA */
+    index_addr(mode | ((uint16_t)(buf >> 16) << 8), 0x2200);
+
+	/* set memory low address bits 23:8 -FOR DMA */
+    index_addr(mode | ((uint16_t)buf << 8), 0x2300);
+
+	/* interrupt when complete, burst len = 64 bytes -FOR DMA*/
+    index_addr( mode | 0x14000, 0x2400);     //zhouqi not interrupt 0X40
+
+    /* wait_for_ready */
+    status = wait_for_ready (INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__ECC_ERR);
+    if (status & INTR_STATUS__ECC_ERR )
+    {
+        printf("[EE]\n");     /* [read_page]: ECC ERROR */
+		/* 0. clear status */
+    	clear_intr();
+        return -1;        
+    }
+        
+
+    if (status & INTR_STATUS__TIME_OUT)
+    {
+        printf("TO\n");  /* [read_page]: TIME OUT */
+		/* clear status */
+    	clear_intr();
+        return -1;      
+    }
+
+	writel(ecc_status, ECC_CORRECTION);
+
+    /* disable DMA */
+    writel(DMA_DISABLE__FLAG, DMA_ENABLE);
+    
+    return 0;
+}
+
+
+/*******************************************************************************
+ * from: must page align
+   len:  must page align
+ */
+ /*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t nand_read(uint32_t from, uint32_t len, uint32_t to)
+{
+    uint32_t offset = from;
+    uint32_t left_to_read = len;
+    uint32_t p_to = to;
+    int32_t ret = 0;
+    int32_t page_size = (nand_info->page_size);
+
+    if((offset & (page_size - 1)) || (len & (page_size - 1)))
+    {
+        printf("param err.\n");
+        return -1;       
+    }
+
+    while(left_to_read > 0)
+    {       
+        ret = read_page(p_to, offset);
+		if(ret != 0)
+		{
+			return -1;
+		}
+        
+        left_to_read -= page_size;
+        offset += page_size;
+        p_to += page_size;          
+    }
+    return 0;
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t read_data(uint32_t from, uint32_t len, uint32_t to)
+{
+    uint32_t offset = from;
+    uint32_t left_to_read = len;
+    uint32_t p_to = to;
+    int32_t ret = 0;
+    int32_t block_size = (nand_info->block_size);
+            
+    while( left_to_read > 0 )
+    {
+        uint32_t block_offset = offset & (block_size - 1);
+		uint32_t read_length;
+
+        if( nand_block_isbad(offset) )
+        {
+            offset += block_size;
+            continue;
+        }
+            
+        if (left_to_read < (block_size - block_offset))
+			read_length = left_to_read;
+		else
+			read_length = block_size - block_offset;
+      
+        ret = nand_read(offset, read_length, p_to);
+		if(ret != 0)
+		{
+			return -1;
+		}
+
+        left_to_read -= read_length;
+        offset += read_length;
+        p_to += read_length;         
+    }
+    
+    return 0;
+}
+
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int32_t nand_read_id (void)
+{
+    uint32_t id[5];
+    uint32_t i = 0;
+	uint32_t addr = (uint32_t)MODE_11;      /*  | BANK(0) */
+    struct nand_flash_device_para *nand = &nand_flash_para[0];
+
+    index_addr(addr | 0, 0x90);
+	index_addr(addr | 1, 0);
+	for (i = 0; i < 5; i++) 
+    {
+		index_addr_read_data(addr | 2,	&id[i]);
+	}
+
+    i = 0;
+    while( nand->manuf_id != 0 )
+    {   
+        if( ((uint8_t)id[0] == nand->manuf_id) && 
+                ((uint8_t)id[1] == nand->device_id) &&
+                    ((uint8_t)id[2] == nand->res_id))
+        {
+            nand_info = nand;
+
+			writel(nand_info->bus_num, DEVICE_WIDTH);
+			writel(nand_info->page_size, DEVICE_MAIN_AREA_SIZE);
+			writel(nand_info->page_size, LOGICAL_PAGE_DATA_SIZE);
+			writel(nand_info->oob_size, DEVICE_SPARE_AREA_SIZE);
+			writel(nand_info->ecc_strength, ECC_CORRECTION);   
+            return 0;
+        };
+        nand++;
+        i++;
+    }
+    
+    return 1;   
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t nand_init (void)
+{
+    int32_t ret = 0;
+    writel(ECC_DISABLE__FLAG, ECC_ENABLE);      /*  ecc_enable */
+    writel(2, SPARE_AREA_SKIP_BYTES);
+
+    ret = nand_read_id();
+    if( ret != 0 )
+        return -1;
+
+	flash.flash_type = NAND_BOOT;
+	flash.manuf_id = nand_info->manuf_id;
+	flash.device_id = nand_info->device_id;
+	flash.page_size = nand_info->page_size;
+	flash.page_size_shift = nand_info->page_size_shift;
+	flash.oob_size = nand_info->oob_size;
+	flash.block_size = nand_info->block_size;
+	flash.block_size_shift = nand_info->block_size_shift;
+	flash.block_num = nand_info->block_num;
+	flash.read = read_data;
+	flash.read_oob = nand_read_oob;
+
+    return 0;
+    
+}
+
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int board_flash_init(void)
+{
+	int ret = 0;
+	char boot_mode = 0;
+
+	boot_mode = get_boot_mode();
+	if(boot_mode != NAND_BOOT)
+	{
+		printf("not nand flash.\n");
+		return -1;
+	}
+	
+	writel(CFG_START_MODE_NAND, CFG_BOOT_MODE_START_MODE_FOR_UBOOT); 
+	ret = nand_init(); 
+	if(ret != 0)
+	{  
+		printf("nand init err.\n");
+		return -1;
+	}	
+	printf("nand init ok.\n");
+	
+	nand_creat_bbt();
+		
+	return 0;
+}
+
+
diff --git a/boot/common/src/loader/drivers/download.c b/boot/common/src/loader/drivers/download.c
new file mode 100644
index 0000000..9b47131
--- /dev/null
+++ b/boot/common/src/loader/drivers/download.c
@@ -0,0 +1,357 @@
+#include "global.h"

+#include <asm/arch/cpu.h>

+#include <asm/io.h>

+#include "common.h"

+

+#define ST_WAIT_SYNC_FLAG   (0x0)

+#define ST_WAIT_REG_CONFIG  (0x1)

+#define ST_REG_CONFIG       (0x2)

+#define ST_WAIT_DOWNLOAD    (0x3)

+#define ST_DOWNLOAD_HEAD    (0x4)

+#define ST_DOWNLOAD_DATA    (0x5)

+#define ST_DOWNLOAD_ADDR    (0x6)

+

+#define SYNC_FLAG           (0x5a) // "Z"

+#define REG_CONFIG_FLAG     (0x6a) // ""

+#define DOWNLOAD_FLAG       (0x7a) // "z"

+#define RUN_FLAG            (0x8a) // ""

+#define GET_ID			    (0x9a) // new added

+

+extern void USB3Slave_boot(void);

+extern WORD32 usb_read(BYTE *pchBuf, WORD32 dwLen);

+extern WORD32 usb_write(BYTE *pchBuf, WORD32 dwLen);

+extern int UART_Read(char *pchBuf, int dwLen);

+extern int UART_Write(char *pchBuf, int dwLen);

+

+WORD32 Para_Section SyncACK=0xa5;

+__align(4) BYTE Para_Section CHIP_ID[8]={'Z','X','7','5','2','0','V','2'};

+WORD32 Para_Section  UsbACK = 0;

+

+

+

+void Boot_Process(BYTE *pkt,int len)

+{

+    int i=0;

+    static int count=0;

+    static int addr;

+    static int value;

+    char cTmp=0;

+    //WORD32 SyncACK=0xa5;

+    int case_state;

+    if(0==len)

+        return ;

+    while(i<len)

+    {

+        cTmp=pkt[i++];

+

+           case_state = global.g_State;

+           if( ST_WAIT_SYNC_FLAG == case_state)

+           	{

+                if(SYNC_FLAG==cTmp)

+                {

+                    global.g_State=ST_WAIT_DOWNLOAD;

+#if CFG_USB

+                    usb_write((BYTE *)&SyncACK,1);

+#else

+                    UART_Write((BYTE *)&SyncACK,1);

+#endif

+                }

+           	}

+            else if(ST_REG_CONFIG ==case_state)

+            	{

+                if(count<4)    // 4 bytes addr

+                {

+                    addr<<=8;

+                    addr|=cTmp;

+                }

+                else if(count<8)    // 4 byte data

+                {

+                    value<<=8;

+                    value|=cTmp;

+                }

+

+                count++;

+

+                if(4==count)

+                {

+                    if(0==addr)

+                    {

+                       global.g_State=ST_WAIT_DOWNLOAD;

+					   UsbACK=0xA6;

+#if CFG_USB					  

+                       usb_write(&UsbACK,1);

+#else

+						UART_Write(&UsbACK,1);

+#endif

+                    }

+                }

+                else if(8==count)

+                {

+                    REG32(addr)=value;

+                    count=0;

+                }

+

+            	}

+            else if (ST_WAIT_DOWNLOAD==case_state)

+            	{

+                if(REG_CONFIG_FLAG==cTmp)

+                {

+                    global.g_State=ST_REG_CONFIG;

+                    count=0;

+                }

+                else if(DOWNLOAD_FLAG==cTmp)

+                {

+                    global.g_State=ST_DOWNLOAD_HEAD;

+                    count=0;

+                    value=0;

+                }

+                else if(RUN_FLAG==cTmp)    //Ö§³Ö¶à´ÎÏÂÔØ0818

+                {

+                    global.g_State=ST_DOWNLOAD_ADDR;

+                    count=0;

+                    value=0;

+                }

+            	}

+            else if( ST_DOWNLOAD_HEAD==case_state)

+            	{

+                if(count<4)    // 4 byte addr

+                {

+                    addr<<=8;

+                    addr|=cTmp;

+                }

+                else if(count<8) // 4 byte size

+                {

+                    value<<=8;

+                    value|=cTmp;

+                }

+

+                count++;

+

+                if(count==8)

+                {

+                    count=0;

+                    global.g_bootaddr=addr; //µØÖ·

+                    global.g_bootsize=value;//³¤¶È

+                    global.g_State=ST_DOWNLOAD_DATA;

+					UsbACK=0xA1;

+#if CFG_USB

+

+                    usb_write(&UsbACK,1);

+#else

+					UART_Write(&UsbACK,1);

+#endif

+                }

+            	}

+            else if( ST_DOWNLOAD_DATA==case_state)

+            	{

+                if(global.g_bootsize==len)

+                {

+                    if(global.g_bootaddr==(int)pkt)

+                        {

+                        global.g_State=ST_WAIT_DOWNLOAD;//Ö§³Ö¶à´ÎÏÂÔØ0818

+                        UsbACK=0xA7;

+#if CFG_USB

+						usb_write(&UsbACK,1);

+#else

+						UART_Write(&UsbACK,1);

+#endif

+

+                            return;

+                        }

+                    }

+                    else

+                    {

+                    global.g_bootaddr+=len;

+                    global.g_bootsize-=len;

+                        return ;

+                }

+            	}

+            else if( ST_DOWNLOAD_ADDR==case_state)

+            	{

+                if(count<4)    // 4 byte addr

+                {

+                    addr<<=8;

+                    addr|=cTmp;

+                }

+

+                count++;

+

+                if(count==4)

+                {

+                    count=0;

+                    global.g_bootaddr=addr;

+                    global.g_bootfinish=1;

+					UsbACK=0xA8;

+#if CFG_USB

+					usb_write(&UsbACK,1);

+#else

+					UART_Write(&UsbACK,1);

+#endif

+                    return ;

+                }

+            	}

+		else

+		{

+

+		}

+

+           }

+     

+}

+__align(4) BYTE Para_Section tmp[64]={0};

+

+void USB_Boot(void)

+{

+    WORD32			dwLen;

+    WORD32  		dwMaxLen;

+    BYTE 			*pbyBuf;

+    printf("USB_Boot\n");

+    global.g_State	= ST_WAIT_SYNC_FLAG;

+    pbyBuf 			= (BYTE*)tmp;

+

+    for(dwMaxLen = 0; dwMaxLen < 64; dwMaxLen++)

+    {

+    	tmp[dwMaxLen] = 0;

+    }

+

+	dwMaxLen = 512;  //¿ØÖÆÆ÷ÓÐÒªÇóbulk outʱ£¬½ÓÊÕ³¤¶È´óÓÚµÈÓÚ512

+/* µ±usb_mode =1ʱ£¬ÓÃÓÚHSIC,µ±usb_mode =0ʱ£¬ÓÃÓÚUSB */

+    if(global.g_USB_MODE == 0)

+    {

+        dwLen=USB_Check_Sync(pbyBuf,dwMaxLen);

+

+        if(0==dwLen)

+        {

+            return ;

+        }

+

+        Boot_Process(pbyBuf,dwLen);

+    }

+    while(0 == global.g_bootfinish)

+    {

+        dwLen=usb_read(pbyBuf,dwMaxLen);

+

+        Boot_Process(pbyBuf,dwLen);

+

+        if((ST_DOWNLOAD_DATA==global.g_State)&&(global.g_bootaddr!=0))

+        {

+            pbyBuf=(BYTE *)global.g_bootaddr;

+            dwMaxLen= 512;//global.g_bootsize;

+        }

+        else

+        {

+            pbyBuf=tmp;

+            dwMaxLen=512;//½ÓÊÕµØÖ·£¬³¤¶ÈÐÅÏ¢

+        }

+

+    }

+

+    if(1==global.g_bootfinish)

+    {

+#if 0 /*shield dma function*/

+        dwc_otg_core_dev_disconnet(global.g_dwc_otg_pcd_tp.core_if);

+        printf("disconnect usb controller\n");

+#endif

+    	writel(0xE59ff000, SYS_IRAM1_BASE);                 /* Ìø×ªµ½r7Ö´ÐÐtboot */

+        writel(global.g_bootaddr, SYS_IRAM1_BASE + 8); 

+	    printf("Starting the tboot...\n");

+        writel(0xf, CPU_A9_SUBSYS_CFG);

+	}

+}

+

+void usb_boot(WORD32 USB_ADDR)

+{

+	global.g_USB_TIMEOUT = 0xff;

+

+	//USB3Slave_boot();

+	tsp_usb_init();

+

+	USB_Boot();    /*usb bootÏÂÔØÄ£Ê½*/

+}

+

+

+

+/*******************************************************************************

+ * Function:     uart_boot

+ * Description: download from uart-bootrom

+ * Parameters:

+ *	 Input:

+ *

+ *	 Output:

+ *

+ * Returns:

+ *

+ *

+ * Others:

+ ********************************************************************************/

+

+void UART_Boot(void)

+{

+    WORD32			dwLen;

+    WORD32  		dwMaxLen;

+    BYTE 			*pbyBuf;

+    printf("UART_Boot\n");

+    global.g_State	= ST_WAIT_SYNC_FLAG;

+    pbyBuf 			= (BYTE*)tmp;

+

+    for(dwMaxLen = 0; dwMaxLen < 64; dwMaxLen++)

+    {

+    	tmp[dwMaxLen] = 0;

+    }

+

+	dwMaxLen = 512;  //¿ØÖÆÆ÷ÓÐÒªÇóbulk outʱ£¬½ÓÊÕ³¤¶È´óÓÚµÈÓÚ512

+/* µ±usb_mode =1ʱ£¬ÓÃÓÚHSIC,µ±usb_mode =0ʱ£¬ÓÃÓÚUSB */

+    if(global.g_USB_MODE == 0)

+    {

+        dwLen=UART_Check_Sync(pbyBuf,dwMaxLen);

+

+        if(0==dwLen)

+        {

+            return ;

+        }

+

+        Boot_Process(pbyBuf,dwLen);

+    }

+    while(0 == global.g_bootfinish)

+    {

+    

+        dwLen=UART_Read(pbyBuf,1); //0x7a uart

+	    if(*pbyBuf == 0x7a)

+	    {

+		    dwLen=UART_Read(pbyBuf,4);

+			global.g_bootaddr = pbyBuf[3]|pbyBuf[2]<<8|pbyBuf[1]<<16|pbyBuf[0]<<24;

+            

+			dwLen=UART_Read(pbyBuf,4);

+			global.g_bootsize = pbyBuf[3]|pbyBuf[2]<<8|pbyBuf[1]<<16|pbyBuf[0]<<24;

+	    }

+

+		dwLen=UART_Read(global.g_bootaddr,global.g_bootsize);

+		dwLen=UART_Read(pbyBuf,1); //0x8a

+	    if(*pbyBuf == 0x8a)

+	    {

+		    global.g_bootfinish = 1;

+			dwLen=UART_Read(pbyBuf,4);

+			global.g_bootaddr = pbyBuf[3]|pbyBuf[2]<<8|pbyBuf[1]<<16|pbyBuf[0]<<24;

+	    }	

+

+    }

+

+    if(1==global.g_bootfinish)

+    {

+      

+    	writel(0xE59ff000, SYS_IRAM1_BASE);                 /* Ìø×ªµ½r7Ö´ÐÐtboot */

+        writel(global.g_bootaddr, SYS_IRAM1_BASE + 8); 

+	    printf("Starting the tboot ...\n");

+        writel(0xf, CPU_A9_SUBSYS_CFG);

+    }

+}

+

+

+void uart_boot(void)

+{

+	global.g_USB_TIMEOUT = 0xff;

+

+	UART_Boot();    /*uart bootÏÂÔØÄ£Ê½*/

+}

+

+

diff --git a/boot/common/src/loader/drivers/drv_hash.c b/boot/common/src/loader/drivers/drv_hash.c
new file mode 100644
index 0000000..3d89edb
--- /dev/null
+++ b/boot/common/src/loader/drivers/drv_hash.c
@@ -0,0 +1,162 @@
+/* -------------------------------------------------------------------------------------------------------------------@udN

+ * °æÈ¨ËùÓÐ(C)2012, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾ 

+ * 

+ * ÎÄ ¼þ Ãû: drv_hash.c

+ * 

+------------------------------------------------------------------------------------------------------------*/

+

+#include "drv_hash.h"

+#include <sdio.h>

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ *Hash_set_len ¹¦ÄÜÏêÊö:

+	½«ÏûÏ¢³¤¶ÈÒÔbitΪµ¥Î»ÅäÖõ½³¤¶È¼Ä´æÆ÷ÖÐ

+       --------------------------------------------------------------

+ ×¢Òâ:

+	±¾º¯Êý¿¼Âǵ½¼ÆËãhashµÄÊý¾Ý³¤¶ÈÒ»°ã¶¼Êǰ´byte´«È룬ÇÒ×ÜÁ¿²»»á³¬¹ý4G byte£¬

+	Òò´Ë¼ò»¯Á˺¯Êý¹¦ÄÜ¡£

+	byte_Len ×ÜÊý²»Äܳ¬¹ý4G£¬·ñÔò¸Ãº¯ÊýÐèÒªÖØÐÂÐ޸ġ£

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void hash_SetLen(u32 byte_Len)

+{

+    REG32(HASH_LENGTH0) = byte_Len<<3;

+    REG32(HASH_LENGTH1) = byte_Len>>29;

+    REG32(HASH_LENGTH2) = 0;

+    REG32(HASH_LENGTH3) = 0;

+}

+

+#ifdef HASH_CODE_SUPPORT_ALL

+static void hash_SetHmacKey(u32* pHmacKey, u32* HmacKey_len)

+{

+    u32 udI;

+	

+    for(udI=0;udI<32;udI++)

+    {

+    	//¼Ä´æÆ÷¸ßµØÖ·´æ·ÅµÍλÊý¾Ý£¬Êý¾Ý´æ·ÅÊǵ͵ØÖ··Å¸ßλÊý¾Ý

+    	if(udI<(32-HmacKey_len))

+		REG32(HASH_HMACKEY+udI*4) = 0;

+	else

+		REG32(HASH_HMACKEY+udI*4) = pHmacKey[udI-(32-HmacKey_len)];

+    }

+}

+#endif

+

+/* ·µ»Øhash ¼ÆËã½á¹ûºÍ½á¹ûµÄ³¤¶È£¬³¤¶Èµ¥Î»ÊÇword */

+static void hash_GetResult(u32 udMode, u32* HashResult, u32* ResultLen)

+{

+    u32 udI, udResultLen=0;

+	

+#ifdef HASH_CODE_SUPPORT_ALL	

+    switch(udMode)

+    {

+        case HASH_MODE_MD5:

+	 case HASH_MODE_HMAC_MD5:

+            udResultLen = 4;  /* 4*4bytes = 128bit*/

+            break;

+            

+        case HASH_MODE_SHA1:

+        case HASH_MODE_HMAC_SHA1:

+            udResultLen = 5;  /* 160 bit */

+            break;

+            

+        case HASH_MODE_SHA224:

+	 case HASH_MODE_HMAC_SHA224:

+            udResultLen = 7;  /* 224 bit */

+            break;

+            

+        case HASH_MODE_SHA256:

+	 case HASH_MODE_HMAC_SHA256:

+            udResultLen = 8; /*  256 bit */

+            break;

+            

+        case HASH_MODE_SHA384:

+        case HASH_MODE_HMAC_SHA384: 	

+            udResultLen = 12; /* 384 bit */

+            break;

+            

+        case HASH_MODE_SHA512:

+        case HASH_MODE_HMAC_SHA512:

+            udResultLen = 16; /* 512 bit */

+            break;

+            

+        default:

+            break;

+    }

+#else

+    udResultLen = 4;

+#endif

+

+    *ResultLen = udResultLen;

+	

+    for(udI=0;udI<udResultLen;udI++)   //hash¼ÆËãÖ§³Ö128bitÊý¾Ý

+    {

+        //¼Ä´æÆ÷µÍµØÖ·´æ·Åresult µÄ¸ßλ

+        HashResult[udI] = REG32(HASH_RESULT+(16-udResultLen+udI)*4);

+    }

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief HASHÄ£¿éÇý¶¯½Ó¿Ú

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - Hash_Computeº¯ÊýÊôÓÚ½Ó¿Úº¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - HASHÄ£¿éÇý¶¯½Ó¿Ú

+ *     

+ * ²ÎÊý¸ÅÊö:

+ input:

+ 	udMode--------hashģʽ

+ 	udBigEndian----´óС¶Ë¸ñʽ

+ 	ploadAddr------¼ÆËãhashµÄÔ´Êý¾ÝÖ¸Õë

+ 	loadLen--------Ô´Êý¾Ý³¤¶È

+ 	pHmacKey------HMACģʽϵÄÃÜÔ¿

+ 	HmacKey_len---ÃÜÔ¿³¤¶È

+ output:

+	HashResult-----hash¼ÆËã½á¹û

+ 	ResultLen------hash½á¹ûµÄ³¤¶È

+ * ·µ »Ø Öµ: 0:³É¹¦ 1:ʧ°Ü

+

+ *--------------------------------------------------------------------------------------------------------------------*/

+u32 Hash_Calculate(u32 udMode, u32 udBigEndian, u32* ploadAddr, u32 loadLen, u32* pHmacKey, u32* HmacKey_len, u32* HashResult, u32* ResultLen)

+{

+	u32 udMessageLen_word;

+	u32 udI;

+

+	if((loadLen == 0) || (ploadAddr == NULL) || (HashResult == NULL) )

+	{

+		return 1;

+	}

+	

+	//config hash mode and enable module

+	REG32(HASH_CONTROL) = (udMode<<4)|(udBigEndian<<12)|1;

+

+	hash_SetLen(loadLen);

+	

+#ifdef HASH_CODE_SUPPORT_ALL

+	//write HMAC key

+	if(udMode&0x10)

+	{

+		hash_SetHmacKey(pHmacKey, HmacKey_len);

+	}

+#endif

+

+	REG32(HASH_START) = 1;//Hash_Start   

+

+	//start write message data into fifo

+	udMessageLen_word = (loadLen+3)/4;

+	for(udI=0;udI<udMessageLen_word;udI++)

+	{

+		REG32(HASH_DATA) = ploadAddr[udI];

+	}

+

+	while(REG32(HASH_START) & 0x1); /* if cal busy, continue to wait*/

+

+	//read Result

+	hash_GetResult(udMode, HashResult, ResultLen);

+

+	REG32(HASH_CONTROL) = 0;//Hash_DisableModule;

+

+	return 0;

+}

+     

+/** @} */

+      

diff --git a/boot/common/src/loader/drivers/drv_hash.h b/boot/common/src/loader/drivers/drv_hash.h
new file mode 100644
index 0000000..86bd99a
--- /dev/null
+++ b/boot/common/src/loader/drivers/drv_hash.h
@@ -0,0 +1,67 @@
+/**---------------------------------------------------------------@n

+ * °æÈ¨ËùÓÐ(C)2011, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾ 

+ * 

+ * ÎļþÃû³Æ:  drv_hash.h

+ * ÄÚÈÝÕªÒª:  HASHÉ豸linuxÇý¶¯³ÌÐòÍ·Îļþ

+ * ÆäËû˵Ã÷: 

+ * 

+ *  -------------------------------------------------------------- 

+ * Ð޸ļǼ1: // ÐÞ¸ÄÀúÊ·¼Ç¼£¬°üÀ¨ÐÞ¸ÄÈÕÆÚ¡¢ÐÞ¸ÄÕß¼°ÐÞ¸ÄÄÚÈÝ

+ *   ÐÞ¸ÄÈÕÆÚ: 

+ *   °æ ±¾ ºÅ: 

+ *   ÐÞ ¸Ä ÈË: 

+ *   ÐÞ¸ÄÄÚÈÝ: 

+ *     

+ * ---------------------------------------------------------*/

+ 

+#ifndef DRV_HASH_H

+#define DRV_HASH_H

+

+#include <common.h>

+

+#define SYS_HASH_BASE					0x0121d000

+

+

+#define HASH_CONTROL    (SYS_HASH_BASE+0x04)

+#define HASH_START      (SYS_HASH_BASE+0x08)

+#define HASH_DATA       (SYS_HASH_BASE+0x10)

+#define HASH_INTSTATUS  (SYS_HASH_BASE+0x1c)

+#define HASH_LENGTH0    (SYS_HASH_BASE+0x2c)

+#define HASH_LENGTH1    (SYS_HASH_BASE+0x28)

+#define HASH_LENGTH2    (SYS_HASH_BASE+0x24)

+#define HASH_LENGTH3    (SYS_HASH_BASE+0x20)

+#define HASH_RESULT      (SYS_HASH_BASE+0x30)

+#define HASH_HMACKEY   (SYS_HASH_BASE+0x70)

+

+//Çý¶¯ÊÇ·ñÖ§³ÖËùÓеÄģʽ£¬ÓÃÓÚ¼ò»¯´úÂëÁ¿

+//#define HASH_CODE_SUPPORT_ALL

+

+#define HASH_MODE_MD5                          0x0

+#ifdef HASH_CODE_SUPPORT_ALL

+#define HASH_MODE_SHA1                        0x1

+#define HASH_MODE_SHA224                    0x2

+#define HASH_MODE_SHA256                    0x3

+#define HASH_MODE_SHA384                    0x4

+#define HASH_MODE_SHA512                    0x5

+#define HASH_MODE_HMAC_MD5               (HASH_MODE_MD5|0x10)

+#define HASH_MODE_HMAC_SHA1             (HASH_MODE_SHA1|0x10)

+#define HASH_MODE_HMAC_SHA224         (HASH_MODE_SHA224|0x10)

+#define HASH_MODE_HMAC_SHA256         (HASH_MODE_SHA256|0x10)

+#define HASH_MODE_HMAC_SHA384         (HASH_MODE_SHA384|0x10)

+#define HASH_MODE_HMAC_SHA512         (HASH_MODE_SHA512|0x10)

+#endif

+

+#define HASH_SMALL_ENDIAN  0

+#define HASH_BIG_ENDIAN       1

+

+u32 Hash_Calculate(u32 udMode, u32 udBigEndian, u32* ploadAddr, u32 loadLen, u32* pHmacKey, u32* HmacKey_len, u32* HashResult, u32* ResultLen);

+

+#endif

+

+

+

+

+

+

+

+

diff --git a/boot/common/src/loader/drivers/drv_rsa.c b/boot/common/src/loader/drivers/drv_rsa.c
new file mode 100644
index 0000000..892fb83
--- /dev/null
+++ b/boot/common/src/loader/drivers/drv_rsa.c
@@ -0,0 +1,469 @@
+

+#include "drv_rsa.h"

+#include <sdio.h>

+

+/*  º¯Êý¹¦ÄÜ: ʵÏÖ- N^-1 mod 2^32 µÄËã·¨*/

+static u32 get_N_inv(u32 N0)

+{

+	u32 N_inv=1;

+	u32 i,a,b;

+

+	for(i=1; i<32; i++)

+	{

+		a = 1<<i;

+		b = (N0*N_inv)&((2<<i)-1);

+		if(a<b)

+		{

+		  N_inv = N_inv+ a;

+		}

+	}

+	

+	return (0xffffffff-N_inv+1);

+}

+

+static void rsa_WriteDataToReg(u32* pudAddr, u32 udReg, u32 Len)

+{

+    u32 udI;

+    for(udI=0;udI<Len;udI++)

+    {

+	//Ä£¿éµÍµØÖ·¼Ä´æÆ÷´æ·ÅµÍµØÖ·Êý¾Ý£¬Êý¾Ý´æ·ÅÊǵ͵ØÖ··Å¸ßλÊý¾Ý

+	REG32(udReg + udI*4) = *(pudAddr+Len-1-udI);

+    }

+}

+

+static void rsa_ReadDataFromReg(u32* pudAddr, u32 udReg, u32 Len)

+{

+    u32 udI;

+    for(udI=0;udI<Len;udI++)

+    {

+	//Ä£¿éµÍµØÖ·¼Ä´æÆ÷´æ·ÅµÍµØÖ·Êý¾Ý£¬Êý¾Ý´æ·ÅÊǵ͵ØÖ··Å¸ßλÊý¾Ý

+	*(pudAddr+Len-1-udI) = REG32(udReg + udI*4);

+    }

+}

+

+#ifdef RSA_CODE_SUPPORT_ALL

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´óÊý³Ë·¨¼ÆËã

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - Rsa_BigNumMultipleº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - ¼ÆËãÁ½¸ö´óÊýÏà³Ë

+ *     

+ * ²ÎÊý¸ÅÊö:

+ * 

+ * 

+ * ·µ »Ø Öµ: ÎÞ 

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 rsa_BigNumMultiple(u32 udNbitLen, u32* pudInputM, u32* pudInputE, u32* pudOutputP)

+{

+    u32 Nlen_word, Elen_word;

+    //input M, E, udNbitLen

+    if(udNbitLen>2048||udNbitLen==0\

+	||pudInputM==NULL||pudInputE==NULL||pudOutputP==NULL)

+    {

+        return 1;

+    }

+	

+    REG32(RSA_INT_MASK)   = 0;                          /*unmask interrupt*/    

+    REG32(RSA_INT_ENABLE) = 0;                          /*disable interrupt*/

+    REG32(RSA_CALC_MODE)  = RSA_BIG_NUM_MULTIPLE;      /* set computemode*/

+    

+    //ÅäÖÃM,E µ½RAM¼Ä´æÆ÷ÖÐ	

+    Nlen_word = (udNbitLen+31)/32;

+    rsa_WriteDataToReg(pudInputM, RSA_M_RAM, Nlen_word);

+    rsa_WriteDataToReg(pudInputE, RSA_E_RAM, Nlen_word);

+    //ÅäÖÃN µÄbit ³¤¶È

+   REG32(RSA_MODULAR_LENGTH) = udNbitLen-1;/*set modelength, µ¥Î»bit*/

+

+    //enable compute

+    REG32(RSA_MODULE_ENABLE) = 1;  

+

+   /*check interrupt status, waiting for calculating finished*/

+    while(!(REG32(RSA_INT_STATUS)& 0x01));

+    

+   /* clear the interrupt,input any */

+    REG32(RSA_INT_STATUS) = 1;

+   

+    /* read the result */

+    rsa_ReadDataFromReg(pudOutputP, RSA_RESULT_RAM, Nlen_word);

+	

+    /*close mode enable*/

+    REG32(RSA_MODULE_ENABLE) = 0;  

+

+    return 0;

+

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ³õʼ»¯¼ÆËã

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - Rsa_InitComputeº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - ³õʼ»¯¼ÆËã c= r*r mod N

+ *     

+ * ²ÎÊý¸ÅÊö:

+ *

+ * 

+ * ·µ »Ø Öµ: ÎÞ 

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 rsa_InitCompute(u32 udNbitLen, u32* pudInputN, u32* pudOutputP)

+{

+    u32 Nlen_word;

+    //input N, udNbitLen

+    if(udNbitLen>2048||udNbitLen==0\

+		||pudInputN==NULL||pudOutputP==NULL)

+    {

+        return 1;

+    }

+		

+    REG32(RSA_INT_MASK)   = 0;                          /*unmask interrupt*/    

+    REG32(RSA_INT_ENABLE) = 0;                          /*disable interrupt*/

+    REG32(RSA_CALC_MODE)  = RSA_INIT_COMPUTE;      /* set computemode*/

+    

+    //ÅäÖÃN µ½RAM¼Ä´æÆ÷ÖÐ	

+    Nlen_word = (udNbitLen+31)/32;

+    rsa_WriteDataToReg(pudInputN, RSA_N_RAM, Nlen_word);

+	

+    //ÅäÖÃN µÄbit ³¤¶È

+    if((pudInputN[0]&0x80000000) == 0)

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-2;/*set modelength, µ¥Î»bit*/

+    }

+    else

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-1;/*set modelength, µ¥Î»bit*/

+    }

+	

+    //enable compute

+    REG32(RSA_MODULE_ENABLE) = 1;  

+

+   /*check interrupt status, waiting for calculating finished*/

+    while(!(REG32(RSA_INT_STATUS)& 0x01));

+    

+   /* clear the interrupt,input any */

+    REG32(RSA_INT_STATUS) = 1;

+   

+    /* read the result */

+    rsa_ReadDataFromReg(pudOutputP, RSA_INIT_CALC_RAM, Nlen_word);

+	

+    /*close mode enable*/

+    REG32(RSA_MODULE_ENABLE) = 0;  

+

+    return 0;

+

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ²»´ø³õʼ»¯¼ÆËãµÄÄ£³Ë

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - Rsa_ModMultipleNoInitº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - ÔÚÄ£³ËÖУ¬²»½øÐгõʼ»¯¼ÆËã

+ *     

+ * ²ÎÊý¸ÅÊö:

+ * 

+ * 

+ * ·µ »Ø Öµ: ÎÞ 

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void rsa_ModMultipleNoInit(u32 udNbitLen, u32 udEbitLen, u32* pudInputM, u32* pudInputE, u32* pudInputN, u32* pudInputC, u32* pudOutputP)

+{

+    u32 Nlen_word, Elen_word;

+    //input M, E, N, C, udNbitLen, udEbitLen

+    if(udNbitLen>2048||udNbitLen==0||udEbitLen>2048||udEbitLen==0\

+	||pudInputM==NULL||pudInputE==NULL||pudInputN==NULL||pudInputC==NULL||pudOutputP==NULL)

+    {

+        return 1;

+    }

+		

+    REG32(RSA_INT_MASK)   = 0;                          /*unmask interrupt*/    

+    REG32(RSA_INT_ENABLE) = 0;                          /*disable interrupt*/

+    REG32(RSA_CALC_MODE)  = RSA_MOD_MULTIPLE_NO_INIT;      /* set computemode*/

+    

+    Nlen_word = (udNbitLen+31)/32;

+    Elen_word = (udEbitLen+31)/32;

+	

+    //ÉèÖòÎÊýN0, µÈÓÚ²ÎÊýN µÄ×îµÍλ

+    REG32(RSA_NZORE) = pudInputN[Nlen_word-1];

+    // ÉèÖòÎÊýN0'  ,    µÈÓÚ- N^-1 mod 2^32

+    REG32(RSA_NZORE_INV) = get_N_inv(pudInputN[Nlen_word-1]);

+

+    //ÅäÖÃM,E,N µ½RAM¼Ä´æÆ÷ÖÐ	

+    rsa_WriteDataToReg(pudInputM, RSA_M_RAM, Nlen_word);

+    rsa_WriteDataToReg(pudInputE, RSA_E_RAM, Elen_word);

+    rsa_WriteDataToReg(pudInputN, RSA_N_RAM, Nlen_word);

+    rsa_WriteDataToReg(pudInputC, RSA_INIT_CALC_RAM, Nlen_word);

+	

+    //ÅäÖÃN,E µÄbit ³¤¶È

+    if((pudInputN[0]&0x80000000) == 0)

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-2;/*set modelength, µ¥Î»bit*/

+    }

+    else

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-1;/*set modelength, µ¥Î»bit*/

+    }

+    REG32(RSA_EXP_LENGTH)          = (Elen_word-1)<<5;      /*set expolength, µ¥Î»word*/

+

+    //enable compute

+    REG32(RSA_MODULE_ENABLE) = 1;  

+

+   /*check interrupt status, waiting for calculating finished*/

+    while(!(REG32(RSA_INT_STATUS)& 0x01));

+    

+   /* clear the interrupt,input any */

+    REG32(RSA_INT_STATUS) = 1;

+   

+    /* read the result */

+    rsa_ReadDataFromReg(pudOutputP, RSA_RESULT_RAM, Nlen_word);

+	

+    /*close mode enable*/

+    REG32(RSA_MODULE_ENABLE) = 0;  

+

+    return 0;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´ø³õʼ»¯¼ÆËãµÄÄ£³Ë

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - Rsa_ModMultipleWithInitº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - ÔÚÄ£³ËÖУ¬½øÐгõʼ»¯¼ÆËã

+ *     

+ * ²ÎÊý¸ÅÊö:

+ * 

+ * 

+ * ·µ »Ø Öµ: ÎÞ 

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 rsa_ModMultipleWithInit(u32 udNbitLen, u32 udEbitLen, u32* pudInputM, u32* pudInputE, u32* pudInputN, u32* pudOutputP)

+{

+    u32 Nlen_word, Elen_word;

+    //input M, E, N, udNbitLen, udEbitLen

+    if(udNbitLen>2048||udNbitLen==0||udEbitLen>2048||udEbitLen==0\

+	||pudInputM==NULL||pudInputE==NULL||pudInputN==NULL||pudOutputP==NULL)

+    {

+        return 1;

+    }

+		

+    REG32(RSA_INT_MASK)   = 0;                          /*unmask interrupt*/    

+    REG32(RSA_INT_ENABLE) = 0;                          /*disable interrupt*/

+    REG32(RSA_CALC_MODE)  = RSA_MOD_MULTIPLE_WITH_INIT;      /* set computemode*/

+    

+    Nlen_word = (udNbitLen+31)/32;

+    Elen_word = (udEbitLen+31)/32;

+	

+    //ÉèÖòÎÊýN0, µÈÓÚ²ÎÊýN µÄ×îµÍλ

+    REG32(RSA_NZORE) = pudInputN[Nlen_word-1];

+    // ÉèÖòÎÊýN0'  ,    µÈÓÚ- N^-1 mod 2^32

+    REG32(RSA_NZORE_INV) = get_N_inv(pudInputN[Nlen_word-1]);

+

+    //ÅäÖÃM,E,N µ½RAM¼Ä´æÆ÷ÖÐ	

+    rsa_WriteDataToReg(pudInputM, RSA_M_RAM, Nlen_word);

+    rsa_WriteDataToReg(pudInputE, RSA_E_RAM, Elen_word);

+    rsa_WriteDataToReg(pudInputN, RSA_N_RAM, Nlen_word);

+	

+    //ÅäÖÃN,E µÄbit ³¤¶È

+    if((pudInputN[0]&0x80000000) == 0)

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-2;/*set modelength, µ¥Î»bit*/

+    }

+    else

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-1;/*set modelength, µ¥Î»bit*/

+    }

+    REG32(RSA_EXP_LENGTH)          = (Elen_word-1)<<5;      /*set expolength, µ¥Î»word*/

+

+    //enable compute

+    REG32(RSA_MODULE_ENABLE) = 1;  

+

+   /*check interrupt status, waiting for calculating finished*/

+    while(!(REG32(RSA_INT_STATUS)& 0x01));

+    

+   /* clear the interrupt,input any */

+    REG32(RSA_INT_STATUS) = 1;

+   

+    /* read the result */

+    rsa_ReadDataFromReg(pudOutputP, RSA_RESULT_RAM, Nlen_word);

+	

+    /*close mode enable*/

+    REG32(RSA_MODULE_ENABLE) = 0;  

+

+    return 0;

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ²»´ø³õʼ»¯¼ÆËãµÄÄ£ÃÝÔËËã

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - Rsa_ModExpoNoInitº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - ÔÚÄ£ÃÝÔËËãÖУ¬²»½øÐгõʼ»¯¼ÆËã

+ *     

+ * ²ÎÊý¸ÅÊö:

+ *

+ * 

+ * ·µ »Ø Öµ: ÎÞ 

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 rsa_ModExpoNoInit(u32 udNbitLen, u32 udEbitLen, u32* pudInputM, u32* pudInputE, u32* pudInputN, u32* pudInputC, u32* pudOutputP)

+{

+    u32 Nlen_word, Elen_word;

+    //input M, E, N, C, udNbitLen, udEbitLen

+    if(udNbitLen>2048||udNbitLen==0||udEbitLen>2048||udEbitLen==0\

+	||pudInputM==NULL||pudInputE==NULL||pudInputN==NULL||pudInputC==NULL||pudOutputP==NULL)

+    {

+        return 1;

+    }

+		

+    REG32(RSA_INT_MASK)   = 0;                          /*unmask interrupt*/    

+    REG32(RSA_INT_ENABLE) = 0;                          /*disable interrupt*/

+    REG32(RSA_CALC_MODE)  = RSA_MOD_EXPO_NO_INIT;      /* set computemode*/

+    

+    Nlen_word = (udNbitLen+31)/32;

+    Elen_word = (udEbitLen+31)/32;

+	

+    //ÉèÖòÎÊýN0, µÈÓÚ²ÎÊýN µÄ×îµÍλ

+    REG32(RSA_NZORE) = pudInputN[Nlen_word-1];

+    // ÉèÖòÎÊýN0'  ,    µÈÓÚ- N^-1 mod 2^32

+    REG32(RSA_NZORE_INV) = get_N_inv(pudInputN[Nlen_word-1]);

+

+    //ÅäÖÃM,E,N µ½RAM¼Ä´æÆ÷ÖÐ	

+    rsa_WriteDataToReg(pudInputM, RSA_M_RAM, Nlen_word);

+    rsa_WriteDataToReg(pudInputE, RSA_E_RAM, Elen_word);

+    rsa_WriteDataToReg(pudInputN, RSA_N_RAM, Nlen_word);

+    rsa_WriteDataToReg(pudInputC, RSA_INIT_CALC_RAM, Nlen_word);

+	

+    //ÅäÖÃN,E µÄbit ³¤¶È

+    if((pudInputN[0]&0x80000000) == 0)

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-2;/*set modelength, µ¥Î»bit*/

+    }

+    else

+    {

+        REG32(RSA_MODULAR_LENGTH) = udNbitLen-1;/*set modelength, µ¥Î»bit*/

+    }

+    REG32(RSA_EXP_LENGTH)          = (Elen_word-1)<<5;      /*set expolength, µ¥Î»word*/

+

+    //enable compute

+    REG32(RSA_MODULE_ENABLE) = 1;  

+

+   /*check interrupt status, waiting for calculating finished*/

+    while(!(REG32(RSA_INT_STATUS)& 0x01));

+    

+   /* clear the interrupt,input any */

+    REG32(RSA_INT_STATUS) = 1;

+   

+    /* read the result */

+    rsa_ReadDataFromReg(pudOutputP, RSA_RESULT_RAM, Nlen_word);

+	

+    /*close mode enable*/

+    REG32(RSA_MODULE_ENABLE) = 0;  

+

+    return 0;

+}

+#endif

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´ø³õʼ»¯¼ÆËãµÄÄ£ÃÝÔËËã

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - Rsa_ModExpoWithInitº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - ÔÚÄ£ÃÝÔËËãÖУ¬½øÐгõʼ»¯¼ÆËã

+ *     

+ * ²ÎÊý¸ÅÊö:

+ * 

+ * 

+ * ·µ »Ø Öµ: ÎÞ 

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 rsa_ModExpoWithInit(u32 udNbitLen, u32 udEbitLen, u32* pudInputM, u32* pudInputE, u32* pudInputN, u32* pudOutputP)

+{

+	u32 Nlen_word, Elen_word;

+	//input M, E, N, udNbitLen, udEbitLen

+	if(udNbitLen>2048||udNbitLen==0||udEbitLen>2048||udEbitLen==0\

+		||pudInputM==NULL||pudInputE==NULL||pudInputN==NULL||pudOutputP==NULL)

+	{

+		return 1;

+	}

+

+	REG32(RSA_INT_MASK) = 0;    /*unmask interrupt*/    

+	REG32(RSA_INT_ENABLE) = 0;    /*disable interrupt*/

+	REG32(RSA_CALC_MODE) = RSA_MOD_EXPO_WITH_INIT;    /* set computemode*/

+

+	Nlen_word = (udNbitLen+31)/32;

+	Elen_word = (udEbitLen+31)/32;

+

+	//ÉèÖòÎÊýN0, µÈÓÚ²ÎÊýN µÄ×îµÍλ

+	REG32(RSA_NZORE) = pudInputN[Nlen_word-1];

+	// ÉèÖòÎÊýN0'  ,    µÈÓÚ- N^-1 mod 2^32

+	REG32(RSA_NZORE_INV) = get_N_inv(pudInputN[Nlen_word-1]);

+

+	//ÅäÖÃM,E,N µ½RAM¼Ä´æÆ÷ÖÐ

+	rsa_WriteDataToReg(pudInputM, RSA_M_RAM, Nlen_word);

+	rsa_WriteDataToReg(pudInputE, RSA_E_RAM, Elen_word);

+	rsa_WriteDataToReg(pudInputN, RSA_N_RAM, Nlen_word);

+

+	//ÅäÖÃN,E µÄbit ³¤¶È

+	if((pudInputN[0]&0x80000000) == 0)

+	{

+		REG32(RSA_MODULAR_LENGTH) = udNbitLen - 2;    /*set modelength, µ¥Î»bit*/

+	}

+	else

+	{

+		REG32(RSA_MODULAR_LENGTH) = udNbitLen -1;    /*set modelength, µ¥Î»bit*/

+	}

+	REG32(RSA_EXP_LENGTH) = (Elen_word-1)<<5;    /*set expolength, µ¥Î»word*/

+

+	//enable compute

+	REG32(RSA_MODULE_ENABLE) = 1;  

+

+	/*check interrupt status, waiting for calculating finished*/

+	while(!(REG32(RSA_INT_STATUS)& 0x01));

+

+	/* clear the interrupt,input any */

+	REG32(RSA_INT_STATUS) = 1;

+

+	/* read the result */

+	rsa_ReadDataFromReg(pudOutputP, RSA_RESULT_RAM, Nlen_word);

+

+	/*close mode enable*/

+	REG32(RSA_MODULE_ENABLE) = 0;  

+

+	return 0;

+}

+/*  

+¹¦ÄÜÏêÊö:RSA ¸÷ÖÖ¼ÆËãµÄ½Ó¿Úº¯Êý

+¸÷²ÎÊý:

+	ptInput Ïê¼û½á¹¹Ìå˵Ã÷

+*/

+u32 Rsa_Calculate(T_Rsa_Paramter ptInput)

+{

+	switch(ptInput.udCalMode)

+	{

+#ifdef RSA_CODE_SUPPORT_ALL

+		case RSA_BIG_NUM_MULTIPLE: //input M, E, udNbitLen

+			return rsa_BigNumMultiple(ptInput.udNbitLen, ptInput.pudInputM, ptInput.pudInputE, ptInput.pudOutputP);

+	            

+		case RSA_INIT_COMPUTE: //input N, udNbitLen

+			return rsa_InitCompute(ptInput.udNbitLen, ptInput.pudInputN, ptInput.pudOutputP);

+				

+		case RSA_MOD_MULTIPLE_NO_INIT: //input M, E, N, C, udNbitLen, udEbitLen

+			return rsa_ModMultipleNoInit(ptInput.udNbitLen, ptInput.udEbitLen, ptInput.pudInputM, ptInput.pudInputE, ptInput.pudInputN, ptInput.pudInputC, ptInput.pudOutputP);

+				

+		case RSA_MOD_EXPO_NO_INIT: 	//input M, E, N, C, udNbitLen, udEbitLen

+			return rsa_ModExpoNoInit(ptInput.udNbitLen, ptInput.udEbitLen, ptInput.pudInputM, ptInput.pudInputE, ptInput.pudInputN, ptInput.pudInputC, ptInput.pudOutputP);

+				

+		case RSA_MOD_MULTIPLE_WITH_INIT: //input M, E, N, udNbitLen, udEbitLen

+			return rsa_ModMultipleWithInit(ptInput.udNbitLen, ptInput.udEbitLen, ptInput.pudInputM, ptInput.pudInputE, ptInput.pudInputN, ptInput.pudOutputP);

+#endif		

+		case RSA_MOD_EXPO_WITH_INIT:       //input M, E, N, udNbitLen, udEbitLen

+			return rsa_ModExpoWithInit(ptInput.udNbitLen, ptInput.udEbitLen, ptInput.pudInputM, ptInput.pudInputE, ptInput.pudInputN, ptInput.pudOutputP);

+				

+		default:

+			return 1;

+	}

+}

+

diff --git a/boot/common/src/loader/drivers/drv_rsa.h b/boot/common/src/loader/drivers/drv_rsa.h
new file mode 100644
index 0000000..379f155
--- /dev/null
+++ b/boot/common/src/loader/drivers/drv_rsa.h
@@ -0,0 +1,72 @@
+

+#ifndef RSA_DRV_H

+#define RSA_DRV_H

+

+#include <common.h>

+

+

+#define SYS_RSA_BASE					0x0121c000

+

+

+/**< offset:000  RW        °æ±¾ÐÅÏ¢¼Ä´æÆ÷                */

+/**< offset:004  RW        Ä£¿éʹÄܼĴæÆ÷                */

+/**< offset:008  RW        Ä£³¤¼Ä´æÆ÷                    */

+/**< offset:00C  RW        Ãݳ¤¼Ä´æÆ÷                    */

+/**< offset:010  RW        ÖжÏ״̬¼Ä´æÆ÷                */

+/**< offset:014  RW        ÖжÏʹÄܼĴæÆ÷                */

+/**< offset:018  RW        ÖÐ¶ÏÆÁ±Î¼Ä´æÆ÷                */

+/**< offset:01C  RW        N0¼Ä´æÆ÷                      */

+/**< offset:020  RW        N0¡¯¼Ä´æÆ÷                    */

+/**< offset:024  RW        ¼ÆËãģʽ                      */

+/**< offset:028  RW        ռλ·û                        */     

+/**< offset:100  RW        M data RAM¼Ä´æÆ÷0x100~0x1FF   */

+/**< offset:200  RW        E data RAM¼Ä´æÆ÷0x200~0x2FF   */

+/**< offset:300  RW        N data RAM¼Ä´æÆ÷0x300~0x3FF   */

+/**< offset:400  RW        ³õʼ»¯¼ÆËãRAM¼Ä´æÆ÷0x400~0x4FF*/

+/**< offset:500  RW        ½á¹ûRAM¼Ä´æÆ÷0x500~0x5FF      */

+

+

+#define RSA_REV_INFO        		(SYS_RSA_BASE)

+#define RSA_MODULE_ENABLE   	(SYS_RSA_BASE+0x4)

+#define RSA_MODULAR_LENGTH 	(SYS_RSA_BASE+0x8)

+#define RSA_EXP_LENGTH      		(SYS_RSA_BASE+0xc)

+#define RSA_INT_STATUS      		(SYS_RSA_BASE+0x10)

+#define RSA_INT_ENABLE      		(SYS_RSA_BASE+0x14)

+#define RSA_INT_MASK        		(SYS_RSA_BASE+0x18)

+#define RSA_NZORE           			(SYS_RSA_BASE+0x1c)

+#define RSA_NZORE_INV       		(SYS_RSA_BASE+0x20)

+#define RSA_CALC_MODE       		(SYS_RSA_BASE+0x24)

+#define RSA_M_RAM           		(SYS_RSA_BASE+0x100)

+#define RSA_E_RAM           		(SYS_RSA_BASE+0x200)

+#define RSA_N_RAM           		(SYS_RSA_BASE+0x300)

+#define RSA_INIT_CALC_RAM   	(SYS_RSA_BASE+0x400)

+#define RSA_RESULT_RAM      		(SYS_RSA_BASE+0x500)

+

+//Çý¶¯ÊÇ·ñÖ§³ÖËùÓеÄģʽ£¬ÓÃÓÚ¼ò»¯´úÂëÁ¿

+//#define RSA_CODE_SUPPORT_ALL

+

+#ifdef RSA_CODE_SUPPORT_ALL

+#define RSA_BIG_NUM_MULTIPLE             	9	//input M, E, udNbitLen

+#define RSA_INIT_COMPUTE                 		2	//input N, udNbitLen

+#define RSA_MOD_MULTIPLE_NO_INIT         8	//input M, E, N, C, udNbitLen, udEbitLen

+#define RSA_MOD_EXPO_NO_INIT             	4	//input M, E, N, C, udNbitLen, udEbitLen

+#define RSA_MOD_MULTIPLE_WITH_INIT     10	//input M, E, N, udNbitLen, udEbitLen

+#endif

+#define RSA_MOD_EXPO_WITH_INIT    	       6	//input M, E, N, udNbitLen, udEbitLen

+

+/** RSAÇý¶¯¼ÆËã½Ó¿Ú´«Èë²ÎÊý*/

+typedef struct

+{

+    u32 udCalMode;    /**< RSA¼ÆËãģʽ     */                                         

+    u32 udNbitLen;     /**< Ä£ÊýN µÄλÊý»òÕßM µÄλÊý , ¿ÉÑ¡512, 1024, 1536, 2048 */

+    u32 udEbitLen;     /**< ÃÝÊýE µÄλÊý, СÓÚ64   */

+    u32 *pudInputM;   /**< ÊäÈëM»º´æÇø    --ÏûÏ¢M          */

+    u32 *pudInputE;   /**< ÊäÈëE»º´æÇø     --ÃÝÊýE          */

+    u32 *pudInputN;   /**< ÊäÈëÄ£»º´æÇø --Ä£ÊýN  (Á½ËØÊýµÄ³Ë»ý)  */

+    u32 *pudInputC;   /**< ÊäÈëÔ¤¼ÆËãÖµ»º´æÇø,µÈÓÚr^2 mod N   */

+    u32 *pudOutputP;  /**< Êä³ö½á¹û»º´æÇø */

+}T_Rsa_Paramter;

+

+u32 Rsa_Calculate(T_Rsa_Paramter ptInput);

+#endif

+

diff --git a/boot/common/src/loader/drivers/drv_usb3slave.c b/boot/common/src/loader/drivers/drv_usb3slave.c
new file mode 100644
index 0000000..3b1df60
--- /dev/null
+++ b/boot/common/src/loader/drivers/drv_usb3slave.c
@@ -0,0 +1,2117 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+*

+* ÎļþÃû³Æ£º drv_usb3slave.c

+* Îļþ±êʶ£º 

+* ÄÚÈÝÕªÒª£º 

+* ÆäËü˵Ã÷£º zx297520 project

+* µ±Ç°°æ±¾£º 1.0

+* ×÷¡¡¡¡Õߣº tangjian

+* Íê³ÉÈÕÆÚ£º 

+*

+*

+*******************************************************************************/

+   

+

+/*

+**==================================================================

+** 	               		Include files

+**==================================================================

+*/

+#include <commond.h>

+#include "drv_usb3slave.h"

+#include "config.h"

+#include <asm/string.h>

+

+/*zloader±àÒëÑ¡ÏîΪnostdlib,ÆÁ±ÎµôÏÂÃæµÄÍ·Îļþ*/

+//#include <stdlib.h>

+//#include <string.h>

+

+/*

+**==================================================================

+** 	          	  		Global Variables

+**==================================================================

+*/

+/* Èí¼þÓÃÀ´¼Ç¼ËùÓÐdeviceÏà¹ØµÄÐÅÏ¢µÄÈ«¾Ö½á¹¹Ìå*/

+

+extern __align(4) dwc_device_descriptor_t  Para_Section device_desc ;

+extern __align(4) dwc_config_all_t  Para_Section desc ;

+extern __align(4) dwc_string_descriptor_t Para_Section * pStrDescIdx[] ;

+extern __align(4) dwc_dev_qual_descriptor_t Para_Section dev_qual_desc ;

+__align(EVENT_BUFFERS_SIZE*4) T_USB3Slave_EventBuf Para_Section *gp_USB3Slave_EventBuf;   //EventBufÒÔEVENT_BUFFERS_SIZE*4×Ö½Ú¶ÔÆë

+__align(16) T_USB3Slave_TRBToHW  Para_Section USB3Slave_TRB ;  //TRBÒÔ16×Ö½Ú¶ÔÆë

+__align(16) T_USB3Slave_TRBToHW  Para_Section USB3Slave_TRB_EP[4] ;  //TRBÒÔ16×Ö½Ú¶ÔÆë

+__align(16) T_USB3Slave_CtrlReq Para_Section pCtrlReq ;   /**< ¿ØÖÆÇëÇó */

+T_USB3Slave_SlaveObj Para_Section g_USB3Slave={0};

+u8 g_needSetStall = 0;

+u32 g_debugFaultVal = 0;

+

+__align(EVENT_BUFFERS_SIZE*4) T_USB3Slave_EventBuf Para_Section USB3Slave_EventBuf;   //EventBufÒÔEVENT_BUFFERS_SIZE*4×Ö½Ú¶ÔÆë

+

+extern void usb_timeout_usdelay(u32 us);

+#if 0

+static inline void delay(unsigned long loops)

+{

+    /*

+	__asm__ volatile ("1:\n" "subs %0, %1, #1\n"

+			  "bne 1b":"=r" (loops):"0"(loops));

+	*/

+}

+

+static inline void udelay(unsigned long us)

+{

+	delay(us * 200); /* approximate */

+}

+

+void usdelay(unsigned us)

+{

+	udelay(us);

+}

+#endif

+

+static T_USB3Slave_Ep *USB3Slave_GetEpObj(T_USB3Slave_SlaveObj *ptUsb3Slave, u16 uwIndex_le)

+{

+    T_USB3Slave_Ep		*ptDep;

+    u32        udEpnum;

+

+    udEpnum = (uwIndex_le & USB_ENDPOINT_NUMBER_MASK) << 1;

+    

+    if ( USB_DIR_IN == (uwIndex_le & USB_ENDPOINT_DIR_MASK))

+        udEpnum |= 1;

+

+    ptDep = &(ptUsb3Slave->tEps[udEpnum]);

+    

+    /*if (ptDep->udFlags & EP_ENABLED)*/

+        return (T_USB3Slave_Ep*)ptDep;

+

+    //return (T_USB3Slave_Ep*)NULL;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief Ïò¶ËµãдÃüÁîµÄͨÓú¯Êý

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_SendDevEpCmd º¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - Ïò¶ËµãдÃüÁîµÄͨÓú¯Êý

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: usb3 É豸½á¹¹Ìå

+ *     - udEp: ¶ËµãºÅ

+ *     - udCmd: ÃüÁî,ÊÇÓÉDEPCMD¼Ä´æÆ÷µÄCmdTypÓò·¢ÆðµÄ¡£

+ *        -00h: Reserved

+ *        -01h: Set Endpoint Configuration

+ *        -02h: Set Endpoint Resource Configuration

+ *        -03h: Get Endpoint State

+ *        -04h: Set Stall

+ *        -05h: Clear Stall

+ *        -06h: Start Transfer

+ *        -07h: Update Transfer

+ *        -08h: End Transfer

+ *        -09h: Start New Configuration

+ *     - ptParams: ÃüÁî²ÎÊý

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+

+static u32 USB3Slave_SendDevEpCmd(T_USB3Slave_SlaveObj *ptUsb3Slave, u32 udEp,

+                               u32 udCmd, T_USB3Slave_EpCmdPara *ptParams)

+{

+    volatile u32			udTimeout = 500;

+    u32			udRegValue;

+

+

+    REG32(ptUsb3Slave->udRegs_base + DEPCMDPAR0(udEp)) = ptParams->Parameter0;

+    REG32(ptUsb3Slave->udRegs_base + DEPCMDPAR1(udEp)) = ptParams->Parameter1;

+    REG32(ptUsb3Slave->udRegs_base + DEPCMDPAR2(udEp)) = ptParams->Parameter2;

+

+    REG32(ptUsb3Slave->udRegs_base +  DEPCMD(udEp)) = udCmd | USB3Slave_DEPCMD_CMDACT_1;

+    // Ïòcmd¼Ä´æÆ÷µÚ10λд1ºó(command active)£¬¿ØÖÆÆ÷»á×Ô¶¯°Ñ¸ÃλÖÃ0

+

+    do

+    {

+        udRegValue = REG32(ptUsb3Slave->udRegs_base + DEPCMD(udEp));

+

+        if(!(udRegValue & USB3Slave_DEPCMD_CMDACT_1)) break;

+

+        udTimeout--;

+

+        if(!udTimeout)

+        {

+            return ERR_FAIL;

+        }

+    } while(1);

+

+    return SOK;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief TRB½á¹¹ÌåλÓòÐÎʽת»»³ÉTRBÕûÌå½á¹¹ÌåÐÎʽ£¬±ãÓÚ¶ÔTRBÕûÌå²Ù×÷¡£

+ * 

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_TrbToHWº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - TRB½á¹¹ÌåλÓòÐÎʽת»»³ÉTRB½á¹¹ÌåÕûÌåÐÎʽ£¬±ãÓÚ¶ÔTRBÕûÌå²Ù×÷¡£

+ *     

+ * ²ÎÊý¸ÅÊö:

+ *     - ptTrbBit: TRBλÓòÐÎʽ½á¹¹Ìå

+ *     - ptTrbRaw: TRB ÕûÌå½á¹¹ÌåÐÎʽ

+ * 

+ * ·µ »Ø Öµ: ÎÞ 

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_TrbToHW(T_USB3Slave_TRB *ptTrbBit, T_USB3Slave_TRBToHW *ptTrbRaw)

+{

+        ptTrbRaw->udBpl = ptTrbBit->bplh & DATA_32BIT_MASK;

+        ptTrbRaw->udBph = 0;

+        ptTrbRaw->udSize = ptTrbBit->len_pcm.udVal;

+        /* HWO is written last */

+        ptTrbRaw->udCtrl = ptTrbBit->control.udVal;

+}

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÔÚ¿ªÊ¼ÅäÖÃ֮ǰ£¬ÒªÏȸøep0дÃüÁî9:¿ªÊ¼ÐµÄÅäÖÃstart new configuration

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_StartCfg º¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - ÔÚ¿ªÊ¼ÅäÖÃ֮ǰ£¬ÒªÏȸøep0дÃüÁî9£¬´ËÃüÁî²ÎÊýΪ0

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: usb 3.0É豸½á¹¹Ìå

+ *     - ptDep: ¶ËµãÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_StartCfg(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_Ep *ptDep)

+{

+    T_USB3Slave_EpCmdPara tParams = {0};

+    u32		  udCmd;

+

+    /* ÏòDEPCMD дÃüÁî9 */  /*Ö´ÐÐCMD9£¬Ôڶ˵ã0ºÍ2µÄÇé¿ö£¬Ò»°ãÖ»Ôڶ˵ã0£¬¶Ëµã2ÓеãÑо¿*/

+    if (0 == ptDep->udEpNum)

+    {

+        udCmd = USB3Slave_DEPCMD_DEPSTARTCFG;        

+        return USB3Slave_SendDevEpCmd(ptUsb3Slave, ptDep->udEpNum, udCmd, &tParams);

+    }

+    return SOK;

+}

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¶Ô¶Ëµã½øÐÐÅäÖÃ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_SetEpCfgCmdº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¶Ô¶Ëµã½øÐÐÅäÖÃ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptDep: ¶ËµãÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_SetEpCfgCmd(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_Ep *ptDep)

+{

+    T_USB3Slave_EpCmdPara tParams = {0};

+  

+    if((0 == ptDep->udEpNum)||(1 == ptDep->udEpNum))

+		ptDep->ucType = USB_ENDPOINT_XFER_CONTROL;    //¼Ç¼¶ËµãµÄ´«ÊäÀàÐÍ

+    else

+        ptDep->ucType = USB_ENDPOINT_XFER_BULK;

+    

+

+    tParams.Parameter0 = DEPCFG_EP_TYPE(ptDep->ucType & USB_ENDPOINT_XFERTYPE_MASK) \

+                    | DEPCFG_MAX_PACKET_SIZE(ptDep->udMaxPacket & 0xffff)

+                    | DEPCFG_BURST_SIZE(ptDep->udMaxBurst);

+    /*

+     * We must use the lower 16 TX FIFOs even though

+     * HW might have more

+     */

+    if (ptDep->udDirection)

+        tParams.Parameter0 |= DEPCFG_FIFO_NUMBER(ptDep->udEpNum >> 1);

+

+    if((0 == ptDep->udEpNum)||(1 == ptDep->udEpNum))

+		tParams.Parameter1 = DEPCFG_XFER_COMPLETE_EN | DEPCFG_XFER_NOT_READY_EN;                     

+    else

+        tParams.Parameter1 = DEPCFG_XFER_COMPLETE_EN;

+                      

+    /*

+     * We are doing 1:1 mapping for endpoints, meaning

+     * Physical Endpoints 2 maps to Logical Endpoint 2 and

+     * so on. We consider the direction bit as part of the physical

+     * endpoint number. So USB endpoint 0x81 is 0x03.

+     */

+    tParams.Parameter1 |= DEPCFG_EP_NUMBER(ptDep->udEpNum);

+

+    return USB3Slave_SendDevEpCmd(ptUsb3Slave, ptDep->udEpNum,

+                                   USB3Slave_DEPCMD_SETEPCONFIG, &tParams);

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief Ϊÿ¸ö¶ËµãÉèÖô«Êä×ÊÔ´¸öÊý

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_SetXferResourceº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - Ϊÿ¸ö¶ËµãÉèÖô«Êä×ÊÔ´¸öÊý

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptDep: ¶ËµãÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_SetXferResource(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_Ep *ptDep)

+{

+    T_USB3Slave_EpCmdPara tParams;

+

+    memset(&tParams, 0x00, sizeof(tParams));

+

+    tParams.Parameter0 = DEPXFERCFG_NUM_XFER_RES(1);

+   /* ÉèÖô«Êä×ÊÔ´*/

+    return USB3Slave_SendDevEpCmd(ptUsb3Slave, ptDep->udEpNum,

+                                   USB3Slave_DEPCMD_SETTRANSFRESOURCE, &tParams);

+}

+

+

+/**

+ * __dwc3_gadget_ep_enable - Initializes a HW endpoint

+ * @ptDep: endpoint to be initialized

+ * @ptDesc: USB Endpoint Descriptor

+ *

+ * Caller should take care of locking

+ */

+/**-------------------------------------------------------------------------------------------------------------------@n

+* @brief ³õʼ»¯Ò»¸öÓ²¼þ¶Ëµã£¬°üÀ¨¿ªÊ¼ÅäÖá¢Èý²ÎÅäÖᢴ«Êä×ÊÔ´ÅäÖã¬Èí¼þtrbÉèÖø³Öµµ½Ó²¼þÉ豸trbÖÐ

+*

+* ¹¦ÄÜÏêÊö:

+*     - USB3Slave_CfgEpº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+*     - ʹÄÜÒ»¸öÓ²¼þ¶Ëµã£¬°üÀ¨¿ªÊ¼ÅäÖá¢Èý²ÎÅäÖᢴ«Êä×ÊÔ´ÅäÖã¬Èí¼þtrbÉèÖø³Öµµ½Ó²¼þÉ豸trbÖÐ

+*

+* ²ÎÊý¸ÅÊö:

+*     - ptDep: ³õʼ»¯¶Ëµã£¬¶ËµãÐÅÏ¢½á¹¹Ìå

+*     - ptDesc: USB ¶ËµãÃèÊö·û

+*     - ptComp_desc: ¶Ëµãcompanion ÃèÊö·û

+*

+* ·µ »Ø Öµ: ÀàÐÍ:u32

+*     - ´íÎóÂë

+*

+*--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_CfgEp(T_USB3Slave_Ep *ptDep)

+{

+    T_USB3Slave_SlaveObj *pUSB3Slv = &g_USB3Slave;

+    

+    if (!(ptDep->udFlags & EP_ENABLED))

+    {

+//step0:ep0¶ËµãÅäÖÿªÊ¼£¬Ö´ÐÐcmd=9£¬start new conguration

+        USB3Slave_StartCfg(pUSB3Slv, ptDep);

+    }

+

+//step1:Ö´ÐÐcmd1£¬SET EP CONFIG

+    USB3Slave_SetEpCfgCmd(pUSB3Slv, ptDep);

+

+//step2:Ö´ÐÐcmd2£¬Set Endpoint Transfer Resource Configuration £¬param0 = 1

+

+    if (!(ptDep->udFlags & EP_ENABLED))

+    {        

+        USB3Slave_SetXferResource(pUSB3Slv, ptDep);

+

+        ptDep->udFlags |= EP_ENABLED;

+	if(global.need_enum ==1)

+	{

+

+//step3:active ep ,0xc720 £¬Ò»¸ö¶Ëµã¶ÔÓÚÒ»¸öbit   

+        REG32(pUSB3Slv->udRegs_base + DWC3_DALEPENA)|= (1u<<ptDep->udEpNum);

+	}

+ 

+    }

+

+    return SOK;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ep0·¢ËÍÊý¾Ý

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0StartXferº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ep0·¢ËÍÊý¾Ý

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÀàÐÅÏ¢µÄ½á¹¹Ìå

+ *     - ucEpnum: ¶ËµãºÅ

+ *     - udBufAddr: ÊäÈëµØÖ·

+ *     - udLen: ³¤¶È

+ *     - udType: TRB¿ØÖÆÀàÐÍ

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ÀàÐÍÂë

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_Ep0StartXfer(T_USB3Slave_SlaveObj *ptUsb3Slave, u8 ucEpnum, u32 udBufAddr,

+                            u32 udLen, u32 udType)

+{

+    T_USB3Slave_EpCmdPara        tParams;

+    T_USB3Slave_TRBToHW          *ptTrbRaw;

+    T_USB3Slave_TRB              tTrbBit;

+    T_USB3Slave_Ep               *ptDep;

+

+    ptDep = &(ptUsb3Slave->tEps[ucEpnum]);

+

+    ptUsb3Slave->ptEp0TRB = ptDep->ptTRB;

+    ptTrbRaw = ptUsb3Slave->ptEp0TRB;

+

+    memset(&tTrbBit, 0, sizeof(tTrbBit));

+

+    tTrbBit.control.bit.TRBCTL = udType;

+    tTrbBit.bplh =udBufAddr ;

+    tTrbBit.len_pcm.bit.BUFSIZ = udLen;

+

+    tTrbBit.control.bit.HWO	= 1;

+    tTrbBit.control.bit.LST	= 1;

+    /*tTrbBit.control.bit.IOC	= 1;

+      tTrbBit.control.bit.ISP_IMI = 1;*/

+   

+    USB3Slave_TrbToHW(&tTrbBit, ptTrbRaw);

+

+    memset(&tParams, 0, sizeof(tParams));

+    tParams.Parameter0 = 0;   /*tTrbBit¸ß32λµØÖ·£¬Ä¬ÈÏΪ0*/

+    tParams.Parameter1 = (u32)((u32)(ptUsb3Slave->ptEp0TRB)& (u32)0xFFFFFFFF);/* ys */

+

+    USB3Slave_SendDevEpCmd(ptUsb3Slave, ptDep->udEpNum,

+                                       USB3Slave_DEPCMD_STARTTRANSFER, &tParams);

+    ptDep->udFlags |= EP_BUSY;

+

+//»ñµÃ´«Êä×ÊÔ´Ë÷Òý

+    ptDep->ucResTransIdx = (REG32(ptUsb3Slave->udRegs_base + ((u32)DEPCMD(ptDep->udEpNum)>>16)));

+

+    ptUsb3Slave->eEp0NextEvent = EP0_COMPLETE;

+

+    return SOK;

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ch 9.4.5,״̬½×¶Î·µ»ØµÄÊý¾Ý

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0HandleStatusº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ch 9.4.5,״̬½×¶Î·µ»ØµÄÊý¾Ý

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÀàÐÅÏ¢µÄ½á¹¹Ìå

+ *     - ptCtrlReq: ±ê×¼ÇëÇóÃüÁî²ÎÊý

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_Ep0HandleStatus(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_CtrlReq *ptCtrlReq)

+{

+    T_USB3Slave_Ep                            *ptDep;

+    u32                                    udRetVal,udRecip;

+    u16                                    uwUsb_status = 0;

+    u16                                    *puwResponse_pkt;

+    u32                                    udDirection;

+

+    udRecip = ptCtrlReq->bmRequestType & USB_RECIP_MASK;

+    switch (udRecip)

+    {

+        case USB_RECIP_DEVICE:

+        {

+            /*

+            * We are self-powered. U1/U2/LTM will be set later

+            * once we handle this states. RemoteWakeup is 0 on SS

+            */

+            uwUsb_status |= ptUsb3Slave->udIsSelfPowered << USB_DEVICE_SELF_POWERED;

+            break;

+        }

+        case USB_RECIP_INTERFACE:

+        {

+            /*

+            * Function Remote Wake Capable	D0

+            * Function Remote Wakeup	D1

+            */

+            break;

+        }

+        case USB_RECIP_ENDPOINT:

+        {

+            ptDep = USB3Slave_GetEpObj(ptUsb3Slave, ptCtrlReq->wIndex);

+            if (!ptDep)

+            return ERR_INVPARAMS;

+            if (ptDep->udFlags & EP_STALL)

+                uwUsb_status = 1 << USB_ENDPOINT_HALT;

+            break;

+        }

+        default:

+        {

+            return ERR_INVPARAMS;

+        }

+    };

+

+    puwResponse_pkt = (u16 *) ptUsb3Slave->aucSetupBuf;

+    *puwResponse_pkt = uwUsb_status;

+

+    ptDep = &(ptUsb3Slave->tEps[0]);

+

+    udDirection = ptDep->udFlags & EP0_DIR_IN;

+

+    if (ptUsb3Slave->eEp0State != EP0_DATA_PHASE) //ÕâÀïµÈ´ýµÄ״̬¿ÉÄÜÓÐÎÊÌ⣬ÓдýÑо¿£¬pxp

+    {

+        return 0;

+    }

+

+    udRetVal = USB3Slave_Ep0StartXfer(ptUsb3Slave, udDirection,

+                                    (u32)ptUsb3Slave->aucSetupBuf, sizeof(*puwResponse_pkt),

+                                    TRBCTL_CONTROL_DATA);

+    ptDep->udFlags &= ~(EP_PENDING_REQUEST | EP0_DIR_IN);

+    return udRetVal;

+}

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÉèÖÃhaltÌØÐÔ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_EpSetHaltº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ÉèÖÃhaltÌØÐÔ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptDep: ¶ËµãÐÅÏ¢½á¹¹Ìå

+ *     - udValue: 0ʱÇå³ýstallÌØÐÔ£¬1ʱÉèÖÃstallÌØÐÔ

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_EpSetHalt(T_USB3Slave_Ep *ptDep, u32 udValue)

+{

+    T_USB3Slave_EpCmdPara	tParams;

+    T_USB3Slave_SlaveObj *pUSB3Slv = &g_USB3Slave;

+    u32        udRetVal;

+

+    memset(&tParams, 0x00, sizeof(tParams));

+

+    if (udValue)

+    {

+        if (0 == ptDep->udEpNum || 1 == ptDep->udEpNum)

+        {

+            /*

+             * Whenever EP0 is stalled, we will restart

+             * the state machine, thus moving back to

+             * Setup Phase

+             */

+            pUSB3Slv->eEp0State = EP0_SETUP_PHASE;

+        }

+         printf("USB3Slave_EpSetHalt");

+//		 udRetVal = USB3Slave_SendDevEpCmd(pUSB3Slv, ptDep->udEpNum,

+ //                                          USB3Slave_DEPCMD_CLEARSTALL, &tParams);

+        if(((global.need_enum ==0) || (1 == g_USB3Slave.udUSBSate))&&g_needSetStall!=1)

+        {

+            udRetVal = USB3Slave_SendDevEpCmd(pUSB3Slv, ptDep->udEpNum,

+            							  USB3Slave_DEPCMD_CLEARSTALL, &tParams);

+        }

+        else

+        {

+            g_needSetStall = 0;

+            pUSB3Slv->eEp0NextEvent = EP0_COMPLETE;

+            udRetVal = USB3Slave_SendDevEpCmd(pUSB3Slv, ptDep->udEpNum,

+                                               USB3Slave_DEPCMD_SETSTALL, &tParams);

+            

+            USB3Slave_Ep0StartXfer(pUSB3Slv, 0, (u32)(pUSB3Slv->tCtrlReq), 8,

+                             TRBCTL_CONTROL_SETUP);

+        }

+

+    }

+

+    return udRetVal;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÉèÖÃep0ÌØÐÔ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0HandleFeatureº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ÉèÖÃep0ÌØÐÔ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢µÄ½á¹¹Ìå

+ *     - ptCtrlReq: ±ê×¼ÇëÇóÃüÁî²ÎÊý

+ *     - udSet: 1ʱÉèÖÃÌØÐÔ£¬0ʱÇå³ýÌØÐÔ

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_Ep0HandleFeature(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_CtrlReq *ptCtrlReq, u32 udSet)

+{

+    T_USB3Slave_Ep		*ptDep;

+    u32			udRecip;

+    u32			udIndex;

+    u32			udRet;

+

+    udIndex = ptCtrlReq->wIndex;

+    udRecip = ptCtrlReq->bmRequestType & USB_RECIP_MASK;

+    switch (udRecip)

+    {

+        case USB_RECIP_ENDPOINT:

+        {    

+           

+            ptDep =  USB3Slave_GetEpObj(ptUsb3Slave, udIndex);

+            if (!ptDep)

+                return ERR_INVPARAMS;

+           udRet = USB3Slave_EpSetHalt(ptDep, udSet);

+            if (udRet)

+            return ERR_INVPARAMS;

+            break;                      

+        }

+        default:

+            return ERR_INVPARAMS;

+    };

+

+    return SOK;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÉèÖÃep0µØÖ·

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0SetAddrº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ÉèÖÃep0µØÖ·

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptCtrlReq: ±ê×¼ÇëÇóÃüÁî²ÎÊý

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_Ep0SetAddr(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_CtrlReq *ptCtrlReq)

+{

+    u32 udAddr;

+    u32 udRegVal;

+

+    udAddr = ptCtrlReq->wValue;

+   

+    udRegVal = REG32(ptUsb3Slave->udRegs_base + DWC3_DCFG);

+    udRegVal &= ~(DWC3_DCFG_DEVADDR_MASK);

+    udRegVal |= DWC3_DCFG_DEVADDR(udAddr);

+    REG32(ptUsb3Slave->udRegs_base + DWC3_DCFG) = udRegVal;

+

+    if (udAddr)

+        ptUsb3Slave->eDevState = ADDRESS_STATE;

+    else

+        ptUsb3Slave->eDevState = DEFAULT_STATE;

+

+    return SOK;

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief »ñÈ¡É豸ÃèÊö·û£¬ÉèÖÃÃèÊö·ûÁôÓнӿڣ¬µ«Ôݲ»ÊµÏÖ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0HandleDescº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - »ñÈ¡É豸ÃèÊö·û£¬ÉèÖÃÃèÊö·ûÁôÓнӿڣ¬µ«Ôݲ»ÊµÏÖ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptCtrlReq:  ±ê×¼ÇëÇóÃüÁî²ÎÊý

+ *     - udIsSet:

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_Ep0HandleDesc(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_CtrlReq *ptCtrlReq, u32 udIsSet)

+{

+    

+    u32 udLen = 0;

+    u32 udDirection = 0;

+    u16 uwValue = ptCtrlReq->wValue;

+    u8  ucIdx =(u8)(ptCtrlReq->wValue &0xff);

+    u32 udRetVal = 0;

+    T_USB3Slave_Ep * ptDep = &ptUsb3Slave->tEps[1];

+    u16 temp = uwValue >> 8;

+

+        if( USB_DT_DEVICE == temp )

+        {

+            udDirection = 1;

+            udLen    = MIN(sizeof(dwc_device_descriptor_t), ptCtrlReq->wLength);

+            udRetVal = USB3Slave_Ep0StartXfer(ptUsb3Slave, udDirection,

+                                        (u32)&device_desc, udLen,

+                                        TRBCTL_CONTROL_DATA);

+            ptUsb3Slave->eEp0State = EP0_DATA_PHASE;

+

+        }

+        else if( USB_DT_CONFIG == temp)

+        {

+            udDirection = 1;

+            udLen = MIN(sizeof(dwc_config_all_t), ptCtrlReq->wLength);

+            udRetVal = USB3Slave_Ep0StartXfer(ptUsb3Slave, udDirection,

+                                        (u32)&desc, udLen,

+                                        TRBCTL_CONTROL_DATA);

+            ptUsb3Slave->eEp0State=EP0_DATA_PHASE;

+          

+        }

+        else if( USB_DT_STRING == temp)

+        {   

+            udDirection = 1;

+            if(ucIdx > 5)

+            {

+                USB3Slave_EpSetHalt(ptDep,1);

+            }

+            else

+            {

+                udLen = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[ucIdx]))->bLength, ptCtrlReq->wLength);

+                udRetVal = USB3Slave_Ep0StartXfer(ptUsb3Slave, udDirection,

+                                        (u32)pStrDescIdx[ucIdx], udLen, 

+                                        TRBCTL_CONTROL_DATA);

+                ptUsb3Slave->eEp0State=EP0_DATA_PHASE;

+            }

+         

+        }  

+        

+        else if( USB_DT_DEVICE_QUALIFIER == temp)

+        {

+            udDirection = 1;

+            udLen    =MIN(sizeof(dwc_dev_qual_descriptor_t), ptCtrlReq->wLength);

+            udRetVal = USB3Slave_Ep0StartXfer(ptUsb3Slave, udDirection,

+                                        (u32)&dev_qual_desc, udLen,

+                                        TRBCTL_CONTROL_DATA);

+            ptUsb3Slave->eEp0State = EP0_DATA_PHASE;

+        

+        }

+        else

+			

+        {

+            USB3Slave_EpSetHalt(ptDep,1);

+            

+        }

+    

+    return udRetVal;

+

+}

+

+/*¸Ãº¯Êý¾ßÌåʵÏÖÓдýÌÖÂÛ£¬pxp */

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÉèÖÃep0ÅäÖÃ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0HandleCfgº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ÉèÖÃep0ÅäÖÃ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptCtrlReq: ±ê×¼ÇëÇóÃüÁî²ÎÊý

+ *     - udIsSet:

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_Ep0HandleCfg(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_CtrlReq *ptCtrlReq, u32 udIsSet)

+{

+    u32 udCfg;

+    udCfg = ptCtrlReq->wValue;

+

+    if (udIsSet && udCfg)

+    {

+        ptUsb3Slave->eDevState = CONFIGURED_STATE;

+		REG32(ptUsb3Slave->udRegs_base + DWC3_DALEPENA) = 0x3f;

+

+#if SIM_EN == EMULATION

+    REG32(ARM_PORTA)=0x30;

+#endif

+

+        return SOK;

+    }

+    return SOK;

+}

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ep0±ê×¼ÇëÇóÀàÐÍ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0Requestº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ep0±ê×¼ÇëÇóÀàÐÍ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptCtrlReq: ±ê×¼ÇëÇóÃüÁî²ÎÊý

+ *        -bmRequestType: ¾ö¶¨Êý¾Ý´«Êä·½ÏòºÍ½ÓÊÕÕßÀàÐÍ¡£

+ *        -bRequest     : ¾ßÌåÇëÇóÀàÐÍ¡£

+ *        -wValue       : ×Ö³¤Óò,¸ù¾Ý²»Í¬µÄÇëÇóº¬Òå¸Ä±ä

+ *        -wIndex       : ×Ö³¤Óò,¸ù¾Ý²»Í¬µÄÇëÇóº¬Òå¸Ä±ä.µäÐÍÓÃÓÚ´«ËÍË÷Òý»òÆ«ÒÆ.

+ *        -wLength      : ÈçÓÐÊý¾Ý´«Ëͽ׶Î,´ËΪÊý¾Ý×Ö½ÚÊý.

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static u32 USB3Slave_Ep0Request(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_CtrlReq *ptCtrlReq)

+{

+    u32 udRet 				= 0;

+    T_USB3Slave_Ep *ptDep0	= 0;

+    u8 temp = 0;

+   //tj Ôö¼ÓÅжÏbmRequestTypeÊÇ·ñΪ±ê×¼ÃüÁÈç¹û²»ÊÇ£¬Ö±½Ó»Østall

+    if(UT_GET_TYPE(ptCtrlReq->bmRequestType)!=UT_STANDARD)

+	{

+        ptDep0 = USB3Slave_GetEpObj(ptUsb3Slave,ptCtrlReq->wIndex);

+        USB3Slave_EpSetHalt(ptDep0, 1);

+        printf"command err.\n");

+        return 1;

+	}

+    temp = ptCtrlReq->bRequest;

+        if( USB_REQ_GET_STATUS == temp)

+			

+        {

+            printf("USB_REQ_GET_STATUS\n");

+            udRet = USB3Slave_Ep0HandleStatus(ptUsb3Slave, ptCtrlReq);

+           

+        }

+		else if(USB_REQ_CLEAR_FEATURE == temp)

+        {

+            printf("USB_REQ_CLEAR_FEATURE\n");

+//            udRet = USB3Slave_Ep0HandleFeature(ptUsb3Slave, ptCtrlReq, 0);		  

+         udRet = USB3Slave_Ep0HandleFeature(ptUsb3Slave, ptCtrlReq, 1);

+           

+        }

+        else if( USB_REQ_SET_ADDRESS == temp)

+        {

+        

+		printf("USB_REQ_SET_ADDRESS\n");

+            udRet = USB3Slave_Ep0SetAddr(ptUsb3Slave, ptCtrlReq);

+            

+        }

+        else if( USB_REQ_GET_DESCRIPTOR == temp)

+        {

+            printf("USB_REQ_GET_DESCRIPTOR\n");

+            udRet = USB3Slave_Ep0HandleDesc(ptUsb3Slave, ptCtrlReq,0);

+            

+        }

+        else if( USB_REQ_SET_CONFIGURATION == temp)

+        {

+        

+		printf("USB_REQ_SET_CONFIGURATION\n");

+            udRet = USB3Slave_Ep0HandleCfg(ptUsb3Slave, ptCtrlReq,1);

+        

+        }

+        else 

+        {

+        

+		printf("USB3Slave_EpSetHalt\n");

+            USB3Slave_EpSetHalt(ptDep0, 1);

+        }

+    

+

+    return udRet;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ep0 setup ½×¶Î

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0InspectSetupº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ep0 setup ½×¶Î

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0InspectSetup(T_USB3Slave_SlaveObj *ptUsb3Slave,

+                                   const T_USB3Slave_EpEvt *ptEpEvt)

+{

+    u32 udRetVal = 0;

+    u16 uwLen = 0;

+    T_USB3Slave_CtrlReq *ptCtrlReq = (ptUsb3Slave->tCtrlReq);

+	

+    uwLen = ptCtrlReq->wLength;

+    /*Èç¹ûÊý¾Ý³¤¶ÈΪ0£¬±íʾûÓÐÊý¾Ý½×¶Î,Á½¸ö½×¶Î£¬Èç¹ûÓÐÊý¾Ý½×¶Î£¬Èý¸ö½×¶Î*/

+    if (!uwLen)

+    {

+        ptUsb3Slave->udThreeStageSetup = FALSE;

+        ptUsb3Slave->udEp0ExpectIn = FALSE;

+        ptUsb3Slave->eEp0NextEvent = EP0_NRDY_STATUS;

+    }

+    else

+    {

+        ptUsb3Slave->udThreeStageSetup = TRUE;

+        ptUsb3Slave->udEp0ExpectIn = !!(ptCtrlReq->bmRequestType & USB_DIR_IN);

+        ptUsb3Slave->eEp0NextEvent = EP0_NRDY_DATA;

+    }

+    printf("USB3Slave_Ep0Request\n");

+    udRetVal = USB3Slave_Ep0Request(ptUsb3Slave,ptCtrlReq);

+

+    if (udRetVal == USB_GADGET_DELAYED_STATUS)

+        ptUsb3Slave->udDelayedStatus = TRUE;

+ }

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ep0 data½×¶Î

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0CmpltDataº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ep0 data½×¶Î

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0CmpltData(T_USB3Slave_SlaveObj *ptUsb3Slave,

+                                   const T_USB3Slave_EpEvt *ptEpEvt)

+{

+    /*bootÀïÃæÃ»ÓеȺò¶ÓÁУ¬ÕâÀïÔݲ»×öÈκδ¦Àí*/

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ep0 status ½×¶Î£¬½áÊø±¾´Î¿ØÖÆ´«Ê䣬״̬»Ø¹é

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0CmpltRequestº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ep0 status ½×¶Î£¬½áÊø±¾´Î¿ØÖÆ´«Ê䣬״̬»Ø¹é

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0CmpltRequest(T_USB3Slave_SlaveObj *ptUsb3Slave,

+                                  const T_USB3Slave_EpEvt *ptEpEvt)

+{

+    if(ptUsb3Slave->eDevState == CONFIGURED_STATE)

+    {

+		ptUsb3Slave->udUSBSate = 1;

+#if SIM_EN == EMULATION

+    REG32(ARM_PORTA)=0x31;

+#endif

+

+    }

+    ptUsb3Slave->eEp0State = EP0_SETUP_PHASE;

+    USB3Slave_Ep0StartXfer(ptUsb3Slave, 0, (u32)(ptUsb3Slave->tCtrlReq), 8,

+                         TRBCTL_CONTROL_SETUP);

+

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´¦Àíxfercompleteʼþ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0XferCmpltº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ´¦Àíxfercompleteʼþ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+/*´¦Àíxfercompleteʼþ*/

+static void USB3Slave_Ep0XferCmplt(T_USB3Slave_SlaveObj *ptUsb3Slave,

+                                   const T_USB3Slave_EpEvt *ptEpEvt)

+{

+    T_USB3Slave_Ep *ptDep = &(ptUsb3Slave->tEps[ptEpEvt->udEndpoint_number]);

+

+    ptDep->udFlags &= ~EP_BUSY;

+    ptUsb3Slave->udSetupPacketPending = 0;

+    switch (ptUsb3Slave->eEp0State)

+    {

+        case EP0_SETUP_PHASE:

+        {

+            USB3Slave_Ep0InspectSetup(ptUsb3Slave, ptEpEvt);

+            break;

+        }

+        case EP0_DATA_PHASE:

+        {

+            USB3Slave_Ep0CmpltData(ptUsb3Slave, ptEpEvt);

+            break;

+        }

+        case EP0_STATUS_PHASE:

+        {

+            USB3Slave_Ep0CmpltRequest(ptUsb3Slave, ptEpEvt);

+            break;

+        }

+        default:

+        {

+            break;

+        }

+    }

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¿ªÊ¼´«Ê䣬¿ØÖƽ¨Á¢½×¶Î

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0OutStartº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¿ªÊ¼´«Ê䣬¿ØÖƽ¨Á¢½×¶ÎµÄͨÓýӿÚ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0OutStart(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+    USB3Slave_Ep0StartXfer(ptUsb3Slave, 0, (u32)(ptUsb3Slave->tCtrlReq), 8,

+                         TRBCTL_CONTROL_SETUP);

+

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¿ØÖƽ¨Á¢½×¶ÎͨÓýӿÚ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0DoCtrlSetupº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¿ØÖƽ¨Á¢½×¶ÎͨÓýӿÚ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0DoCtrlSetup(T_USB3Slave_SlaveObj *ptUsb3Slave,

+                                      const T_USB3Slave_EpEvt *ptEpEvt)

+{

+    USB3Slave_Ep0OutStart(ptUsb3Slave);

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¿ØÖÆ×´Ì¬½×¶Î£¬¿ªÊ¼´«Ê䣬ÕÙ»½¶Ëµã½á¹¹Ìå½øÐд¦Àí

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0DoCtrlStatusº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¿ØÖÆ×´Ì¬½×¶Î£¬¿ªÊ¼´«Ê䣬ÕÙ»½¶Ëµã½á¹¹Ìå½øÐд¦Àí

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - udEpnum: ¶ËµãºÅ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0DoCtrlStatus(T_USB3Slave_SlaveObj *ptUsb3Slave, u32 udEpnum)

+{

+    u32 udType;

+    T_USB3Slave_Ep		*ptDep = &(ptUsb3Slave->tEps[udEpnum]);

+    /* È·¶¨¿ØÖÆ´«ÊäµÄ״̬ÀàÐÍ */

+    udType = ptUsb3Slave->udThreeStageSetup ? TRBCTL_CONTROL_STATUS3

+             : TRBCTL_CONTROL_STATUS2;

+    /* ·¢Æð¿ªÊ¼´«ÊäÃüÁµÈ´ýÖжϲúÉú */

+    USB3Slave_Ep0StartXfer(ptUsb3Slave, ptDep->udEpNum,

+                         (u32)(ptUsb3Slave->tCtrlReq), 0, udType);

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¿ØÖÆÊý¾Ý½×¶Î

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0DoCtrlDataº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¿ØÖÆÊý¾Ý½×¶Î

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0DoCtrlData(T_USB3Slave_SlaveObj *ptUsb3Slave,

+                                     const T_USB3Slave_EpEvt *ptEpEvt)

+{

+    if (ptEpEvt->udEndpoint_number)

+        ptUsb3Slave->tEps[ptEpEvt->udEndpoint_number].udFlags |= EP0_DIR_IN;

+    

+    /* linuxÇý¶¯ÀﻹÊÇÈ¥ÅжÏÇëÇó¶ÓÁÐÊÇ·ñΪ¿Õ½øÐд¦Àí£¬ÂãÇýûÓÐÇëÇó¶ÓÁУ¬ÏÈ·Å×Å  */

+

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´¦Àíxfernotreadyʼþ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0XferNotReadyº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ´¦Àíxfernotreadyʼþ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0XferNotReady(T_USB3Slave_SlaveObj *ptUsb3Slave,

+                                  const T_USB3Slave_EpEvt *ptEpEvt)

+{

+    u8 usb3Event = 0;

+    T_USB3Slave_Ep * ptDep = &ptUsb3Slave->tEps[0];

+    ptUsb3Slave->udSetupPacketPending = 1;

+    /*

+     * This part is very tricky: If we has just handled

+     * XferNotReady(Setup) and we're now expecting a

+     * XferComplete but, instead, we receive another

+     * XferNotReady(Setup), we should STALL and restart

+     * the state machine.

+     *

+     * In all other cases, we just continue waiting

+     * for the XferComplete event.

+     *

+     * We are a little bit unsafe here because we're

+     * not trying to ensure that last event was, indeed,

+     * XferNotReady(Setup).

+     *

+     * Still, we don't expect any condition where that

+     * should happen and, even if it does, it would be

+     * another error condition.

+     */

+     /*

+    if ((1 == ptUsb3Slave->udEventsequence) && (EP0_COMPLETE == ptUsb3Slave->eEp0NextEvent))

+    {

+        switch (ptEpEvt->EventStatus)

+        {

+            case DEPEVT_STATUS_CONTROL_SETUP:

+            {

+                IC_DBG(IC_DEBUG_INFO, "Unexpected XferNotReady(Setup)\n");

+                break;

+            }

+            case DEPEVT_STATUS_CONTROL_DATA:

+            {

+                IC_DBG(IC_DEBUG_INFO, "DEPEVT_STATUS_CONTROL_DATA: XferNotReady\n");

+                break;

+            }

+            case DEPEVT_STATUS_CONTROL_STATUS:

+                break;

+            default:

+                IC_DBG(IC_DEBUG_INFO, "Uwaiting for XferComplete\n");

+        }

+        return;

+    }

+    */

+    usb3Event = (u8)(ptEpEvt->EventStatus);

+    if (DEPEVT_STATUS_CONTROL_SETUP == usb3Event)

+    {

+        printf("USB3Slave event DEPEVT_STATUS_CONTROL_SETUP\n");

+        ptUsb3Slave->eEp0State = EP0_SETUP_PHASE;

+        USB3Slave_Ep0DoCtrlSetup(ptUsb3Slave, ptEpEvt);

+    }

+    else if (DEPEVT_STATUS_CONTROL_DATA == usb3Event)

+    {

+        printf("USB3Slave event DEPEVT_STATUS_CONTROL_DATA\n");

+        if ( ptUsb3Slave->eEp0NextEvent == EP0_COMPLETE)

+        {

+            return;

+        }

+        ptUsb3Slave->eEp0State = EP0_DATA_PHASE;

+        USB3Slave_Ep0DoCtrlData(ptUsb3Slave, ptEpEvt);

+    }

+    else if (DEPEVT_STATUS_CONTROL_STATUS == usb3Event)

+    {

+        printf("USB3Slave event DEPEVT_STATUS_CONTROL_STATUS\n");

+        ptUsb3Slave->eEp0State = EP0_STATUS_PHASE;

+        USB3Slave_Ep0DoCtrlStatus(ptUsb3Slave, ptEpEvt->udEndpoint_number);

+    }

+    else if (DEPEVT_STATUS_STATUS_SETUP == usb3Event)

+    {

+        printf("USB3Slave event DEPEVT_STATUS_STATUS_SETUP\n");

+        g_needSetStall = 1;

+        USB3Slave_EpSetHalt(ptDep,1);

+    }

+    else

+    {

+        g_debugFaultVal = ptEpEvt->EventStatus;

+        printf("USB3Slave event default\n");

+    }

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´¦Àíep0¿ØÖÆÖжÏ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Ep0ISRº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ´¦Àí¿ØÖÆÖжÏ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_Ep0ISR(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_EpEvt *ptEpEvt)

+{

+    switch (ptEpEvt->udEndpoint_event)

+    {

+        case DEPEVT_XFERCOMPLETE:

+        {

+            USB3Slave_Ep0XferCmplt(ptUsb3Slave, ptEpEvt);

+            break;

+        }

+        case DEPEVT_XFERNOTREADY:

+        {

+            USB3Slave_Ep0XferNotReady(ptUsb3Slave, ptEpEvt);

+            break;

+        }

+        default:

+            break;

+    }

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ָʾ´«ÊäÍê³É

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_EpXferCmpltº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ָʾ´«ÊäÍê³É

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptDep: ¶ËµãÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *     - udStart_new:

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_EpXferCmplt(T_USB3Slave_SlaveObj *ptUsb3Slave,

+        T_USB3Slave_Ep *ptDep, const T_USB3Slave_EpEvt *ptEpEvt,u32 udStart_new)

+{

+

+		u32 udXfercount;

+		T_USB3Slave_TRB *tTrbBit;

+	

+		tTrbBit = (T_USB3Slave_TRB *)ptDep->ptTRB ;

+		udXfercount = ptDep->udLen - tTrbBit->len_pcm.bit.BUFSIZ;

+	  	

+		if((0x0 == ptDep->udDirection) && (0x2 == ptDep->ucType))

+			ptUsb3Slave->eDevState	= BULKOUT_CMPL;  

+		if((0x1 == ptDep->udDirection) && (0x2 == ptDep->ucType))

+			ptUsb3Slave->eDevState = BULKIN_CMPL;

+		

+		ptDep->udFlags &= ~EP_BUSY;

+		ptDep->ucResTransIdx = 0;

+	  

+	

+		if(ptDep->fnUsbCb)

+		    ptDep->fnUsbCb((u32)(ptDep->pPara), 0, udXfercount, ptDep->udLen);

+}

+

+static void USB3Slave_Init_TRB(T_USB3Slave_Ep *ptDep)

+{

+    T_USB3Slave_TRBToHW	*ptTrbRaw;

+    T_USB3Slave_TRB		tTrbBit;

+

+    ptTrbRaw = ptDep->ptTRB;

+

+    memset(&tTrbBit, 0, sizeof(tTrbBit));

+

+    tTrbBit.control.bit.CHN    = 0;

+    tTrbBit.control.bit.LST    = 1;

+    tTrbBit.control.bit.TRBCTL = TRBCTL_NORMAL;

+	tTrbBit.control.bit.HWO    = 1;

+

+    tTrbBit.len_pcm.bit.BUFSIZ	= ptDep->udLen;

+

+    tTrbBit.bplh=(u64)(ptDep->pudAddrData);

+    

+

+    USB3Slave_TrbToHW(&tTrbBit, ptTrbRaw);

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÆÕͨ¶Ëµã½øÐÐÊý¾Ý´«Êä

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_EpStartXferº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ÆÕͨ¶Ëµã½øÐÐÊý¾Ý´«Êä

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptDep: ¶ËµãÐÅÏ¢½á¹¹Ìå

+ *     - uwCmd_param: ÃüÁî²ÎÊý

+ *     - udStart_new:

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:INT

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+/*ÆÕͨ¶Ëµã½øÐÐÊý¾Ý´«Êä*/

+static u32 USB3Slave_EpStartXfer(T_USB3Slave_Ep *ptDep, u16 uwCmd_param,

+		u32 udStart_new)

+{

+	T_USB3Slave_EpCmdPara tParams;

+	T_USB3Slave_SlaveObj *pUSB3Slv = &g_USB3Slave;

+	u32  udCmd;

+

+    USB3Slave_Init_TRB(ptDep);   //ÅäÖÃTRB

+	memset(&tParams, 0, sizeof(tParams));

+

+	tParams.Parameter0 = 0;   /*trb¸ß32λµØÖ·£¬Ä¬ÈÏΪ0*/

+	tParams.Parameter1 = (u32)((u32)(ptDep->ptTRB)& (u32)0xFFFFFFFF);/* ys */

+

+	if (udStart_new)

+		udCmd = USB3Slave_DEPCMD_STARTTRANSFER;

+	else

+		udCmd = USB3Slave_DEPCMD_UPDATETRANSFER;

+

+	udCmd |= USB2Slave_DEPCMD_PARAM(uwCmd_param);   //0

+    

+	USB3Slave_SendDevEpCmd(pUSB3Slv, ptDep->udEpNum, udCmd, &tParams);

+

+	return SOK;

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¶ËµãÀàÐ͵ÄeventÖжϴ¦Àí³ÌÐò

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_EpISRº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¶ËµãÀàÐ͵ÄeventÖжϴ¦Àí³ÌÐò

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEpEvt: ¶ËµãÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_EpISR(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_EpEvt *ptEpEvt)

+{

+    T_USB3Slave_Ep *ptDep;

+

+    u8 ucEpnum = ptEpEvt->udEndpoint_number;

+ 

+    ptDep = &(ptUsb3Slave->tEps[ucEpnum]);

+

+    if (0 == ucEpnum || 1 == ucEpnum)

+    {

+        USB3Slave_Ep0ISR(ptUsb3Slave, ptEpEvt);

+        return;

+    }

+

+    switch (ptEpEvt->udEndpoint_event)

+    {

+        case DEPEVT_XFERCOMPLETE:

+        {

+            USB3Slave_EpXferCmplt(ptUsb3Slave, ptDep, ptEpEvt, 1);

+            break;

+        }

+        default:

+            break;

+    }

+

+}

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief É豸¸´Î»Öжϴ¦Àí

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_ResetISRº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - É豸¸´Î»Öжϴ¦Àí

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_ResetISR(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+    u32    udRegVal;

+

+    printf("R");

+//tangjian:±êÖ¾usbÁ¬½Ó

+	global.g_Connet = 1;

+

+/* Reset device address to zero */

+    udRegVal = REG32(ptUsb3Slave->udRegs_base + DWC3_DCFG);

+    udRegVal &= ~(0x7f<<3);

+    REG32(ptUsb3Slave->udRegs_base + DWC3_DCFG) = udRegVal;

+

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief »ñÈ¡usb 3.0×ÜÏßʱÖÓ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_UpdateRamClkSelº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - »ñÈ¡usb 3.0×ÜÏßʱÖÓ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ucSpeed: ָʾÁ¬½ÓËÙ¶È

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_UpdateRamClkSel(T_USB3Slave_SlaveObj *ptUsb3Slave, u32 ucSpeed)

+{

+    u32 udRegVal;

+    /*

+     * RAMClkSel is reset to 0 after USB reset, so it must be reprogrammed

+     * each time on Connect Done.

+     */

+

+    /* ÅäÖÃGCTL¼Ä´æÆ÷,sel bus = 0*/

+    udRegVal = REG32(ptUsb3Slave->udRegs_base + DWC3_GCTL);

+    udRegVal &= ~(0x3<<6);

+    REG32(ptUsb3Slave->udRegs_base + DWC3_GCTL) = udRegVal;

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief É豸Á¬½ÓÖжϴ¦Àí

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_ConnectdoneISR º¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - É豸Á¬½ÓÖжϴ¦Àí

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÀàÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_ConnectdoneISR(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+    T_USB3Slave_Ep		*ptDep;

+    u32    udRegVal;

+    u8 ucSpeed;

+

+    printf("D");

+

+

+    udRegVal = REG32(ptUsb3Slave->udRegs_base + DWC3_DSTS); 

+    ucSpeed = udRegVal&0x7;

+	

+    ptUsb3Slave->ucSpeed = ucSpeed;    

+    USB3Slave_UpdateRamClkSel(ptUsb3Slave, ucSpeed);

+    if(USB3_HIGHSPEED == ucSpeed)

+    {

+		

+        printf("2");

+		ptUsb3Slave->tEps[2].udMaxPacket = 512;

+		ptUsb3Slave->tEps[3].udMaxPacket = 512;

+		ptUsb3Slave->tEps[4].udMaxPacket = 512;

+		ptUsb3Slave->tEps[5].udMaxPacket = 512;

+	    ptUsb3Slave->eDeviceSpeedType = USB30_SPEED_HIGH;

+        desc.atTxEP[0].wMaxPacketSize  = USB_HIGHSPEED_BULK_MAXSIZE;

+        desc.atRxEP[0].wMaxPacketSize  = USB_HIGHSPEED_BULK_MAXSIZE;

+        desc.atTxEP1[0].wMaxPacketSize = USB_HIGHSPEED_BULK_MAXSIZE;

+        desc.atRxEP1[0].wMaxPacketSize = USB_HIGHSPEED_BULK_MAXSIZE;

+    }

+    else if(USB3_FULLSPEED == ucSpeed)

+    {

+		

+        printf("1");

+        ptUsb3Slave->tEps[2].udMaxPacket = 64;

+		ptUsb3Slave->tEps[3].udMaxPacket = 64;

+		ptUsb3Slave->tEps[4].udMaxPacket = 64;

+		ptUsb3Slave->tEps[5].udMaxPacket = 64; 

+        ptUsb3Slave->eDeviceSpeedType = USB30_SPEED_FULL;

+        desc.atTxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;

+        desc.atRxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;

+        desc.atTxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;

+        desc.atRxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;

+    }

+//tangjian:ÉèÖÃep0µÄ¶ËµãÐÅÏ¢

+

+    ptDep = &(ptUsb3Slave->tEps[0]);    

+    USB3Slave_SetEpCfgCmd(ptUsb3Slave, ptDep);

+    ptDep = &(ptUsb3Slave->tEps[1]);

+    USB3Slave_SetEpCfgCmd(ptUsb3Slave, ptDep);

+

+#if SIM_EN == EMULATION

+

+	REG32(REG_GPIO_OUT)=5;

+//	while(REG32(REG_GPIO_IN)!=0xFF);

+	usdelay(1);

+	REG32(REG_GPIO_OUT)=0;

+

+	REG32(REG_GPIO_OUT)=6;

+//	while(REG32(REG_GPIO_IN)!=0xFF);

+	usdelay(1);

+	REG32(REG_GPIO_OUT)=0;

+

+	REG32(REG_GPIO_OUT)=7;

+//	while(REG32(REG_GPIO_IN)!=0xFF);

+	usdelay(1);

+	REG32(REG_GPIO_OUT)=0;

+

+	REG32(REG_GPIO_OUT)=8;

+//	while(REG32(REG_GPIO_IN)!=0xFF);

+	usdelay(1);

+	REG32(REG_GPIO_OUT)=0;

+

+#endif

+

+    

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief É豸Öжϴ¦Àí(¶Ï¿ª¡¢¸´Î»¡¢Á¬½Ó¡¢»½ÐÑ¡¢Á¬½Ó״̬¸Ä±ä¡¢EOPF¡¢ÃüÁîÍê³É¡¢Òç³ö¡¢´íÎó)

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_DevISRº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *      - É豸Öжϴ¦Àí(¶Ï¿ª¡¢¸´Î»¡¢Á¬½Ó¡¢»½ÐÑ¡¢Á¬½Ó״̬¸Ä±ä¡¢EOPF¡¢ÃüÁîÍê³É¡¢Òç³ö¡¢´íÎó)

+  *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptDevEvt: É豸ÀàÐÍʼþ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+

+static void USB3Slave_DevISR(T_USB3Slave_SlaveObj *ptUsb3Slave, const  T_USB3Slave_DevEvt *ptDevEvt)

+{

+    switch (ptDevEvt->udType)

+    {

+        case DEVICE_EVENT_RESET:

+        {

+            USB3Slave_ResetISR(ptUsb3Slave);

+            break;  

+        }

+        case DEVICE_EVENT_CONNECT_DONE:

+        {

+            USB3Slave_ConnectdoneISR(ptUsb3Slave);

+            break;

+        }

+        case DEVICE_EVENT_EOPF:

+        {

+            printf("S");

+            break;

+        }

+        default:

+            break;

+    }

+}

+

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´¦Àí²»Í¬µÄÖжϺ¯ÊýÈë¿Ú

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_ProcessEvtEntryº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ´¦Àí²»Í¬µÄÖжϺ¯ÊýÈë¿Ú

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - ptEvt: ±íʾevent buffer ÄÚÈÝ

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_ProcessEvtEntry(T_USB3Slave_SlaveObj *ptUsb3Slave, T_USB3Slave_Event *ptEvt)

+{

+    /* Endpoint IRQ, handle it and return early */

+    /*0bit 0ÊÇÉ豸¶ËµãÖÐ¶Ï 1ÊÇÉ豸ÖжÏ*/

+    if (0 == ptEvt->tType.udIs_devspec)

+        USB3Slave_EpISR(ptUsb3Slave, &ptEvt->tEpEvt);  /* tDepevt */

+    else

+        USB3Slave_DevISR(ptUsb3Slave, &ptEvt->tDevEvt);

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ´¦Àíevent buffer ÖеÄevent,·Ö·¢²»Í¬event bufferÖмǼµÄÖжϣ¬ÔÙµ÷ÓÃÕæÕýµÄÖжÏÈë¿Ú³ÌÐò

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_ProcessEvtBufº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ´¦Àíevent buffer ÖеÄevent,·Ö·¢²»Í¬event bufferÖмǼµÄÖжϣ¬ÔÙµ÷ÓÃÕæÕýµÄÖжÏÈë¿Ú³ÌÐò

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *     - udBufNum: ±íʾevent bufferÖÐij¸öevent

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_ProcessEvtBuf(T_USB3Slave_SlaveObj *ptUsb3Slave, u32 udBufNum)

+{

+    T_USB3Slave_EventBuf *ptevt;

+    T_USB3Slave_Event ptEvt;

+    u32 udLeft;

+    u32 udCount;

+    

+//step0:ÔÚÖжϴ¦Àíº¯ÊýÖлñÈ¡event count£¬À´ÅжÏÓм¸¸öʼþ£¬²¢×÷ÏàÓ¦µÄ´¦Àí	

+    udCount = REG32((ptUsb3Slave->udRegs_base + GEVNTCOUNT(udBufNum)));

+    if(!udCount)

+        return;

+    ptevt = ptUsb3Slave->ptEvtBuffs;

+    udLeft = udCount;

+    ptUsb3Slave->udEventsequence = 1;/* ys */

+//step1:´¦ÀíÏàÓ¦µÄʼþ    

+    while (udLeft > 0)

+    {

+        ptEvt.udRaw = ptevt->EvtBuf[ptevt->udLpos];

+

+        USB3Slave_ProcessEvtEntry(ptUsb3Slave, &ptEvt);

+        /*

+         * XXX we wrap around correctly to the next entry as almost all

+         * entries are 4 bytes in size. There is one entry which has 12

+         * bytes which is a regular entry followed by 8 bytes data. ATM

+         * I don't know how things are organized if were get next to the

+         * a boundary so I worry about that once we try to handle that.

+         */

+        ptevt->udLpos = (ptevt->udLpos + 1) % EVENT_BUFFERS_SIZE;

+        udLeft -= 4;

+        ptUsb3Slave->udEventsequence++;

+    }

+

+	/*When read, returns the number of valid events in the Event Buffer (in bytes).

+      When written, hardware decrements the count by the value written.

+      The interrupt line remains high when count is not 0.*/

+    REG32(ptUsb3Slave->udRegs_base + GEVNTCOUNT(udBufNum)) = udCount;    

+}

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÖжÏÈë¿Úº¯Êý

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_ISRº¯ÊýÊôÓÚ½Ó¿Úº¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ÖжÏÈë¿Úº¯Êý

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - udIntNo: ÖжϺÅ

+ *     - udPara: ÖжϲÎÊý

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+void USB3Slave_ISR(u32 udIntNo,u32 udPara)

+{

+    T_USB3Slave_SlaveObj *pUSB3Slv = &g_USB3Slave;

+    u32    udIndex ;

+

+	for (udIndex = 0; udIndex < pUSB3Slv->udNumEvtBufs; udIndex++)

+    {

+        USB3Slave_ProcessEvtBuf(pUSB3Slv,udIndex);

+    }

+

+}

+

+/*³õʼ»¯ÓÃÓڼǼÉ豸ËùÓÐÐÅÏ¢µÄÈ«¾Ö½á¹¹Ìå*/

+/*Ò»´ÎÐÔд²»ÍêÕû£¬ ÔÚ´úÂë²¹³äµÄ¹ý³ÌÖÐÂýÂýÌí¼Ó*/

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ³õʼ»¯È«¾Ö½á¹¹ÌåptUsb3Slave

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Initº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ³õʼ»¯½á¹¹ÌåÄÚÈ«¾Ö±äÁ¿

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void  USB3Slave_Init(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+	T_USB3Slave_HWPARAMS	*parms = &ptUsb3Slave->tHwParams;

+

+    gp_USB3Slave_EventBuf = &USB3Slave_EventBuf;

+    ptUsb3Slave->udRegs_base = SYS_USB_BASE;

+    ptUsb3Slave->eSpeedMode  = USB3_HIGHSPEED;

+

+    parms->udHwparams0 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS0);

+    parms->udHwparams1 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS1);

+    parms->udHwparams2 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS2);

+    parms->udHwparams3 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS3);

+    parms->udHwparams4 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS4);

+    parms->udHwparams5 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS5);

+    parms->udHwparams6 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS6);

+    parms->udHwparams7 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS7);

+    parms->udHwparams8 = REG32(ptUsb3Slave->udRegs_base + GHWPARAMS8);

+ 

+    ptUsb3Slave->udNumEvtBufs = (parms->udHwparams1&(0x3f<<15))>>15;  //»ñÈ¡event_int_num

+//	if(global.need_enum ==0)

+    {

+        gp_USB3Slave_EventBuf->udLength = EVENT_BUFFERS_SIZE*4;

+        gp_USB3Slave_EventBuf->udLpos	 = 0;

+    }

+

+    ptUsb3Slave->ptEvtBuffs  = gp_USB3Slave_EventBuf;  

+

+    ptUsb3Slave->tCtrlReq = &pCtrlReq;

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¼Ç¼event bufferµØÖ·µ½¿ØÖÆÆ÷¼Ä´æÆ÷ÖÐ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_EvtBufSetupº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¼Ç¼event bufferµØÖ·µ½¿ØÖÆÆ÷¼Ä´æÆ÷ÖÐ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:INT

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_EvtBufSetup(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+    T_USB3Slave_EventBuf *ptevt;

+    u32 udIndex = 0;

+    u32 udTemp_data;/*ÓÃÀ´±£´æµØÖ·µÄ*/

+

+    ptevt = ptUsb3Slave->ptEvtBuffs;

+    udTemp_data = (u32)&ptevt->EvtBuf;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTADRLO(udIndex)) = udTemp_data;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTADRHI(udIndex)) = 0;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTSIZ(udIndex)) = ptevt->udLength & 0xffff;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTCOUNT(udIndex)) = ptevt->udLpos;

+}

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ¼Ç¼event bufferµØÖ·µ½¿ØÖÆÆ÷¼Ä´æÆ÷ÖÐ

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_EvtBufSetupº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ¼Ç¼event bufferµØÖ·µ½¿ØÖÆÆ÷¼Ä´æÆ÷ÖÐ

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:INT

+ *     - ´íÎóÂë

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+

+static void USB3Slave_EvtBufRestore(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+    /*T_USB3Slave_EventBuf *ptevt;

+    u32 udIndex = 0;

+    u32 udTemp_data;

+    ptevt = ptUsb3Slave->ptEvtBuffs;

+    udTemp_data = (u32)&ptevt->EvtBuf;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTADRLO(udIndex)) = udTemp_data;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTADRHI(udIndex)) = 0;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTSIZ(udIndex)) = ptevt->udLength & 0xffff;

+    REG32(ptUsb3Slave->udRegs_base + GEVNTCOUNT(udIndex)) = ptevt->udLpos;*/

+    u32 udRegVal;

+    u8 ucSpeed;

+

+    T_USB3Slave_EventBuf *ptevt;

+    u32 udIndex = 0;

+    ptevt = ptUsb3Slave->ptEvtBuffs;

+    ptUsb3Slave->ptEvtBuffs = (T_USB3Slave_EventBuf *)(REG32(ptUsb3Slave->udRegs_base + GEVNTADRLO(udIndex))); 

+    ptevt->udLength =REG32(ptUsb3Slave->udRegs_base + GEVNTSIZ(udIndex)); 

+    //  ptevt->udLpos = REG32(ptUsb3Slave->udRegs_base + GEVNTCOUNT(udIndex)) ;

+    ptUsb3Slave->tCtrlReq = (T_USB3Slave_CtrlReq *)(*(u32 *)(*(u32 *)(0x0200c804)));

+

+    udRegVal = REG32(ptUsb3Slave->udRegs_base + DWC3_DSTS); 

+    ucSpeed = udRegVal&0x7;

+    ptUsb3Slave->ucSpeed = ucSpeed;

+}

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ÅäÖö˵ã0£¬¿ªÊ¼µÈ´ý½øÐпØÖÆ´«Êä

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_StartCtrlXferº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ÅäÖö˵ã0£¬¿ªÊ¼µÈ´ý½øÐпØÖÆ´«Êä

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_StartCtrlXfer(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+    T_USB3Slave_Ep *ptDep;

+    u32 udIndex;

+

+    for (udIndex=0; udIndex < 2; udIndex++)  /*//MAX_EPS*2  2¶Ëµãbulk out£¬3¶Ëµãbulk in 4¶Ëµãintr out£¬5¶Ëµã intr in*/

+    {

+        ptDep = &(ptUsb3Slave->tEps[udIndex]);

+        ptDep->ptTRB= &USB3Slave_TRB;  //tjÿ¸ö¶ËµãʹÓÃͬһ¸ötrb mem

+		ptDep->udEpNum = udIndex;

+        if(global.need_enum ==1)

+        {

+            USB3Slave_CfgEp(ptDep);

+        }

+    }

+    ptUsb3Slave->eEp0State = EP0_SETUP_PHASE;

+//Ö´ÐÐcmd6±íʾstart transfer¡£

+    USB3Slave_Ep0StartXfer(ptUsb3Slave, 0, (u32)(ptUsb3Slave->tCtrlReq), 8, TRBCTL_CONTROL_SETUP);

+}

+

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ³õʼ»¯¶Ëµã½á¹¹Ì壬ÒÔ¼°¶ÔÓ¦¼Ä´æÆ÷ÅäÖÃ(¶ËµãºÅ£¬¶Ëµã״̬£¬´«Êä·½Ïò£¬°ü´óС)

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_InitEpº¯ÊýÊôÓÚÄÚ²¿º¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ³õʼ»¯¶Ëµã½á¹¹Ì壬ÒÔ¼°¶ÔÓ¦¼Ä´æÆ÷ÅäÖÃ(¶ËµãºÅ£¬¶Ëµã״̬£¬´«Êä·½Ïò£¬°ü´óС)

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - ptUsb3Slave: É豸ÐÅÏ¢½á¹¹Ìå

+ *

+ * ·µ »Ø Öµ: ÎÞ

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+static void USB3Slave_InitEp(T_USB3Slave_SlaveObj *ptUsb3Slave)

+{

+    T_USB3Slave_Ep *ptDep;

+    u32 udIndex;

+    /* u32 udFifoNum = 0,udTxfram_space; */

+    for (udIndex = 0; udIndex < ENDPOINTS_NUM; udIndex++)

+    {

+        ptDep = &(ptUsb3Slave->tEps[udIndex]);

+        ptDep->udEpNum = udIndex;

+        ptDep->eEpState = EP_IDLE;

+        ptDep->udFlags  = 0;   //tj add ¶¨ÒåflagĬÈÏΪ0

+        ptDep->udMaxBurst = 0; //tj add ÓÃÓÚburst size 0-15 : 1-16

+        ptDep->udDirection = udIndex & 1;/*¶¨Òå´«Êä·½Ïò*/

+        if (0 == udIndex|| 1 == udIndex)

+        {

+            ptDep->udMaxPacket = EP0_PACKET_SIZE;/*ЭÒ鹿¶¨¿ØÖÆ´«Êä×î´ó°ü´óС512*/

+        }

+        else

+        {

+            ptDep->udMaxPacket = HS_MAX_PACKET_SIZE;

+        }

+    }

+}

+

+

+

+/**-------------------------------------------------------------------------------------------------------------------@n

+ * @brief ³õʼ»¯¼Ä´æÆ÷

+ *

+ * ¹¦ÄÜÏêÊö:

+ *     - USB3Slave_Init º¯ÊýÊôÓÚ½Ó¿Úº¯Êý, Æä¹¦ÄÜÊÇ:

+ *     - ³õʼ»¯¼Ä´æÆ÷

+ *

+ * ²ÎÊý¸ÅÊö:

+ *     - eUSBSpeedType: USB É豸ËÙ¶ÈÀàÐÍ

+ *

+ * ·µ »Ø Öµ: ÀàÐÍ:u32

+ *     - ´íÎóÂë

+ *

+ * ÆäËû˵Ã÷:

+ *     -

+ *

+ *--------------------------------------------------------------------------------------------------------------------*/

+u32 USB3Slave_Ctrl_Init(void)

+{

+    u32 udRegValue, i = 0;

+

+    T_USB3Slave_SlaveObj *pUSB3Slv = &g_USB3Slave;

+//step0: ¶Ô½á¹¹Ìåg_USB3Slave½øÐи³Öµ

+    USB3Slave_Init(pUSB3Slv);

+    

+//step1:DCTL£¬¶Ô¿ØÖÆÆ÷½øÐÐÈí¸´Î»

+	if(global.need_enum ==1)

+{

+

+    REG32(pUSB3Slv->udRegs_base + DWC3_DCTL) |= DWC3_DCTL_CSFTRST; 

+    while(1)

+    {

+       i++;

+       usdelay(10);

+       udRegValue =REG32(pUSB3Slv->udRegs_base + DWC3_DCTL);

+       if ((!(udRegValue & DWC3_DCTL_CSFTRST))||(i>0x1000))/*¸´Î»Íê±Ïºó¸Ãλ×Ô¶¯ÇåÁã*/

+  	   break;

+    }

+}

+//step2:ÅäÖÃUSB2 PHY */   //0x0007a510

+    /*bit3: 0:8bit 1:16bit

+      bit4: 0:utmi 1:ulpi

+      bit[13:10] 5:16bit utmi 9:8bit utim/ulpi*/

+ if(global.need_enum ==1)

+{

+    #if(SIM_EN == FPGA)

+        #if (USB_PHY == ULPI)

+            udRegValue  = 0x7a510|(1<<9); //0xf<<15+0x9<<10+0x1<<4+0x0<<3;

+        #elif (USB_PHY == UTMI)

+            udRegValue  = 0x00001408|(1<<9);//0x0<<15|0x5<<10|0x0<<4+0x1<<3;

+        #endif

+    #elif ((SIM_EN == ASIC) || (SIM_EN == EMULATION))

+        udRegValue  = 0x00002400|(1<<9);//0x0<<15|0x9<<10|0x0<<4+0x0<<3;

+    #endif

+

+

+	REG32(pUSB3Slv->udRegs_base + DWC3_GUSB2PHYCFG(0)) = udRegValue;

+

+//step3:DCTL£¬¶Ô¿ØÖÆÆ÷ÔٴνøÐÐÈí¸´Î»

+	REG32(pUSB3Slv->udRegs_base + DWC3_DCTL) |= DWC3_DCTL_CSFTRST; 

+	while(1)

+	{

+	   i++;

+	   usdelay(10);

+	   udRegValue =REG32(pUSB3Slv->udRegs_base + DWC3_DCTL);

+	   if ((!(udRegValue & DWC3_DCTL_CSFTRST))||(i>0x1000))/*¸´Î»Íê±Ïºó¸Ãλ×Ô¶¯ÇåÁã*/

+	   break;

+	}

+

+}

+//step4:´Óparams1ÖлñÈ¡eventnum£¬Ó²¼þĬÈÏΪ1,ÅäÖÃevent_buffer

+	 if(global.need_enum ==1)

+{

+

+    USB3Slave_EvtBufSetup(pUSB3Slv);

+}

+	 else

+{

+	USB3Slave_EvtBufRestore(pUSB3Slv);

+}

+

+//step5: ÅäÖüĴæÆ÷c110£¬°üº¬ÅäÖÃdev mode,ÅäÖÃc700,°üº¬high speed

+if(global.need_enum ==1)

+{

+

+    udRegValue = REG32(pUSB3Slv->udRegs_base + DWC3_GCTL);

+    udRegValue = (udRegValue & 0xffff0000) | 0x200c;//Ô­À´ÊÇ0x2008 scaledown

+    udRegValue = udRegValue & (~(1<<17)); // In the real hardware, this bit must be set to 1'b0

+    udRegValue = udRegValue & (~(1<<16));//2012.11.9,never attempts three more times to connect at SS

+#if SIM_EN == EMULATION

+    udRegValue = (udRegValue & 0xffff0000) | 0x2008;

+    udRegValue = udRegValue|(0x3<<4);      //lanxiang   scaledown

+    udRegValue = udRegValue|(1<<16);

+#endif

+    REG32(pUSB3Slv->udRegs_base + DWC3_GCTL) = udRegValue;

+

+    udRegValue = REG32(pUSB3Slv->udRegs_base + DWC3_DCFG);

+	udRegValue &= ~(DWC3_DCFG_SPEED_MASK);  //0Ϊhigh speed

+	udRegValue &= (~(0x1f<<17));

+	udRegValue |= pUSB3Slv->eSpeedMode | (1<<17) ;  /*1×óÒÆ17ΪÀ´×ÔÑéÖ¤ÂãÇý£¬Óдý·ÖÎö£¬pxp*/

+	REG32(pUSB3Slv->udRegs_base + DWC3_DCFG)= udRegValue;

+}

+    pUSB3Slv->eDeviceSpeedType = USB30_SPEED_UNKNOWN;

+

+//step6:³õʼ»¯EP¶Ëµã£¬bootÖÐÖ»Óõ½0£¬1£¬2£¬3£¬4£¬5£¬ÆäËüµÄ¿ÉÒÔ¿¼ÂDz»Òª¡£

+

+    USB3Slave_InitEp(pUSB3Slv);

+

+//step7:ÅäÖÃÖжÏ(reset , connect done)ʹÄÜ£¬ÈíÁ¬½Ó£¬µÚ31bitÅäÖÃΪrun

+if(global.need_enum ==1)

+{

+	udRegValue = REG32(pUSB3Slv->udRegs_base + DWC3_DEVTEN);

+	udRegValue = udRegValue | (DWC3_DEVTEN_CONNECTDONEEN | DWC3_DEVTEN_USBRSTEN|DWC3_DEVTEN_USBSUSPENDEN);

+	//udRegValue = udRegValue & (~(1<<6)) & (~(1<<7));

+	REG32(pUSB3Slv->udRegs_base + DWC3_DEVTEN) = udRegValue; 

+}

+//step8:start control tranfer

+    USB3Slave_StartCtrlXfer(pUSB3Slv);

+	if(global.need_enum ==1)

+{

+

+//step9:run softconnect

+	udRegValue = REG32(pUSB3Slv->udRegs_base + DWC3_DCTL);

+	udRegValue |= (1U<<31);	//tj add 31bit for run or stop,correspond to softdisconnect

+	REG32(pUSB3Slv->udRegs_base + DWC3_DCTL) = udRegValue;

+

+

+#if SIM_EN == EMULATION

+	//for hsic

+	REG32(REG_GPIO_OUT)=2;

+//	while(REG32(REG_GPIO_IN)!=0xFF);

+	usdelay(1);

+	REG32(REG_GPIO_OUT)=0;

+#endif

+}

+

+    return SOK;

+}

+

+

+u32 USB3_RecvOutData(u32 dwEPNo, u8 *pchBuf, u32 dwLen, F_USB_CB fnUsbCb, void *pPara)

+{

+    T_USB3Slave_Ep *ptDep;

+    T_USB3Slave_SlaveObj *ptUsb3Slave = &g_USB3Slave;

+

+    ptDep = &(ptUsb3Slave->tEps[dwEPNo]);

+

+    ptDep->pudAddrData =(u32*)pchBuf;

+    ptDep->udLen = dwLen;

+    ptDep->fnUsbCb    = fnUsbCb;

+	ptDep->pPara      = pPara;

+

+    USB3Slave_EpStartXfer(ptDep, 0, 1);

+

+#if SIM_EN == EMULATION

+    REG32(ARM_PORTA)=0x80;

+#endif

+

+    return SOK;

+}

+

+

+

+u32 USB3_SendInData(u32 dwEPNo, u8 *pchBuf, u32 dwLen, F_USB_CB fnUsbCb, void *pPara)

+{

+

+    T_USB3Slave_Ep *ptDep;

+    T_USB3Slave_SlaveObj *ptUsb3Slave = &g_USB3Slave;

+

+    ptDep = &(ptUsb3Slave->tEps[dwEPNo]);

+

+    ptDep->pudAddrData = (u32*)pchBuf;

+    ptDep->udLen = dwLen;

+    ptDep->fnUsbCb    = fnUsbCb;

+	ptDep->pPara      = pPara;

+

+    USB3Slave_EpStartXfer(ptDep, 0, 1);

+

+#if SIM_EN == EMULATION

+	REG32(ARM_PORTA)=0x82;

+#endif

+    

+    return SOK;

+}

+

+u32 USB3Slave_IsNeedZero(u32 dwLen)

+{

+    T_USB3Slave_Ep *ptDep;

+    T_USB3Slave_SlaveObj *ptUsb3Slave = &g_USB3Slave;

+    u32 udMaxPacket;

+    

+    if (ptUsb3Slave->ucSpeed == USB3_HIGHSPEED)

+    {

+        udMaxPacket = HS_MAX_PACKET_SIZE;

+    }

+    else if (ptUsb3Slave->ucSpeed == USB3_FULLSPEED)

+    {

+        udMaxPacket = FS_MAX_PACKET_SIZE;

+    }

+    if (dwLen%udMaxPacket == 0)

+    {

+        return TRUE;

+    }

+    else

+    {

+        return FALSE;

+    }

+}

+

+/*ö¾Ùº¯Êý*/

+u32 USB3Slave_CDC_Enum(void)

+{

+    T_USB3Slave_Ep *ptDep;

+    u32 dwCount=0;

+    u32 dwCount1=0;

+    u32 udIndex;

+    

+    

+    global.g_Connet = 0; 

+    USB3Slave_Ctrl_Init();

+	if(global.need_enum ==0)

+	{

+		for (udIndex=2; udIndex < 6; udIndex++)  /*//MAX_EPS*2  2¶Ëµãbulk out£¬3¶Ëµãbulk in 4¶Ëµãintr out£¬5¶Ëµã intr in*/

+        {

+            ptDep = &(g_USB3Slave.tEps[udIndex]);

+            ptDep->ptTRB= &USB3Slave_TRB_EP[udIndex-2];  //tjÿ¸ö¶ËµãʹÓÃͬһ¸ötrb mem

+    		ptDep->udEpNum = udIndex;

+			

+			//USB3Slave_CfgEp(ptDep);

+		}

+	}

+if(global.need_enum ==1)

+{

+    while(1)

+    {

+		USB3Slave_ISR(0,0);

+        if(0 == global.g_Connet)

+        {

+            dwCount++;

+            usb_timeout_usdelay(50000);

+            if(dwCount>(4000*global.g_USB_TIMEOUT))

+                return 1;

+

+        }

+        else if(1 == g_USB3Slave.udUSBSate)

+        {

+            for (udIndex=2; udIndex < 6; udIndex++)  /*//MAX_EPS*2  2¶Ëµãbulk out£¬3¶Ëµãbulk in 4¶Ëµãintr out£¬5¶Ëµã intr in*/

+            {

+                ptDep = &(g_USB3Slave.tEps[udIndex]);

+                ptDep->ptTRB= &USB3Slave_TRB_EP[udIndex-2];  //tjÿ¸ö¶ËµãʹÓÃͬһ¸ötrb mem

+        		ptDep->udEpNum = udIndex;

+                USB3Slave_CfgEp(ptDep);

+            }

+            break;

+        }

+        else

+        {

+            dwCount1++;

+            usb_timeout_usdelay(50000);

+            if(dwCount1>(200000*global.g_USB_TIMEOUT))

+            {

+                return 1;

+            }

+

+        }

+    }

+}

+    return 0;

+}

+

+extern void USB_Boot(void);

+extern void USB_Pll_Clk_Rst_InitEnv(void);

+

+void USB3Slave_boot(void)

+{

+    u32 dwConnect;

+    global.g_USB_MODE = 0;

+    global.need_enum = 0;

+// 1:config clock

+    if(global.need_enum ==1)

+    {

+        USB_Pll_Clk_Rst_InitEnv();

+    }

+// 2:USB30_CDC_Enum

+    dwConnect = USB3Slave_CDC_Enum();

+    if(1==dwConnect)

+    {

+        printf("NOLINK\n");

+        return ;

+    }

+    

+#if 0//SIM_EN == EMULATION

+    REG32(ARM_PORTA)=0x32;

+#endif

+    printf("FAILED\n");

+}

+      

+/** @} */

+

+      

diff --git a/boot/common/src/loader/drivers/drv_usb3slave.h b/boot/common/src/loader/drivers/drv_usb3slave.h
new file mode 100644
index 0000000..a851b15
--- /dev/null
+++ b/boot/common/src/loader/drivers/drv_usb3slave.h
@@ -0,0 +1,643 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+*

+* ÎļþÃû³Æ£º drv_usb3slave.h

+* Îļþ±êʶ£º 

+* ÄÚÈÝÕªÒª£º 

+* ÆäËü˵Ã÷£º zx297520 project

+* µ±Ç°°æ±¾£º 1.0

+* ×÷¡¡¡¡Õߣº tangjian

+* Íê³ÉÈÕÆÚ£º 

+*

+*

+*******************************************************************************/

+

+#ifndef __USB3_SLAVE_DRV_H

+#define __USB3_SLAVE_DRV_H

+  

+/* *INDENT-OFF* */

+#ifdef __cplusplus

+extern "C" {

+#endif

+/* *INDENT-ON* */

+

+/*

+**==================================================================

+** 	               		Include files

+**==================================================================

+*/

+#include "usb.h"

+#include "global.h"

+#include "drv_usb3slave_reg.h"

+

+#include "dwc_otg_cil.h"   //ÓÃÓÚ¶¨Ò廨µ÷º¯Êý

+

+/* DRV´íÎóÂë */

+#define SOK                         (0)         /**< ÕýÈ· */

+#define ERR_FAIL                    (0x01)      /**< Ò»°ã´íÎó */

+#define ERR_INUSE                   (0x02)      /**< ÍâÉè×ÊÔ´ÕýÔÚʹÓà */

+#define ERR_XIO                     (0x03)      /**< ¹²Ïí×ÊÔ´¾ºÕù */

+#define ERR_OVFL                    (0x04)      /**< ¿ÉÓÃ×ÊÔ´ºÄ¾¡ */

+#define ERR_INVHANDLE               (0x05)      /**< ´«Èë¾ä±úÎÞЧ */

+#define ERR_INVPARAMS               (0x06)      /**< ²ÎÊýÎÞЧ */

+#define ERR_INVCMD                  (0x07)      /**< ÃüÁîÎÞЧ */

+#define ERR_NOMEM                   (0x08)      /**< ÄÚ´æºÄ¾¡ */

+#define ERR_UNSUPPORTED             (0x09)      /**< ÐÐΪ²»Ö§³Ö */

+#define ERR_INVHWVERSION            (0x10)      /**< Ó²¼þ°æ±¾²»Æ¥Åä */

+

+#define FALSE                        0

+#define TRUE                         1

+

+#define DWC3_DCFG_SPEED_MASK	(7 << 0)

+

+#define DWC3_DCFG		0xc700

+#define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)

+#define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)

+#define DWC3_DCTL		0xc704

+#define DWC3_DCTL_CSFTRST	(1 << 30)

+/*0x200-0x23c*/

+#define DWC3_GUSB2PHYCFG(n)	(0xc200 + (n * 0x04))

+/*0x2C0-0x2fc*/

+#define DWC3_GUSB3PIPECTL(n)	(0xc2c0 + (n * 0x04))

+

+/*0x300-0x37C*/

+#define DWC3_GTXFIFOSIZ(n)	(0xc300 + (n * 0x04))

+

+/*0x380-0x3fc*/

+#define DWC3_GRXFIFOSIZ(n)	(0xc380 + (n * 0x04))

+

+#define DWC3_GCTL		0xc110

+#define DWC3_DCTL_RUN_STOP	(1 << 31)

+

+#define DWC3_DEVTEN_USBSUSPENDEN    (1 << 6)

+#define DWC3_DEVTEN_WKUPEVTEN		(1 << 4)

+#define DWC3_DEVTEN_ULSTCNGEN		(1 << 3)

+#define DWC3_DEVTEN_CONNECTDONEEN	(1 << 2)

+#define DWC3_DEVTEN_USBRSTEN		(1 << 1)

+#define DWC3_DEVTEN_DISCONNEVTEN	(1 << 0)

+

+#define DWC3_DEVTEN		0xc708

+#define DWC3_DSTS		0xc70c

+

+#define DWC3_DALEPENA   0xc720

+/** ¶¨ÒåÃèÊö·ûÀàÐÍ */  

+#define USB_DT_DEVICE                           0x01

+#define USB_DT_CONFIG                           0x02

+#define USB_DT_STRING                           0x03

+#define USB_DT_INTERFACE                        0x04

+#define USB_DT_ENDPOINT	                        0x05

+#define USB_DT_DEVICE_QUALIFIER                 0x06

+#define USB_DT_OTHER_SPEED_CONFIG               0x07

+#define USB_DT_INTERFACE_POWER                  0x08

+/** these are from a minor usb 2.0 revision (ECN) */   

+#define USB_DT_OTG                              0x09

+#define USB_DT_DEBUG                            0x0a

+#define USB_DT_INTERFACE_ASSOCIATION            0x0b

+/** these are from the Wireless USB spec */  

+#define USB_DT_SECURITY                         0x0c

+#define USB_DT_KEY                              0x0d

+#define USB_DT_ENCRYPTION_TYPE                  0x0e

+#define USB_DT_BOS                              0x0f

+#define USB_DT_DEVICE_CAPABILITY                0x10

+#define USB_DT_WIRELESS_ENDPOINT_COMP           0x11

+#define USB_DT_WIRE_ADAPTER                     0x21

+#define USB_DT_RPIPE                            0x22

+#define USB_DT_CS_RADIO_CONTROL                 0x23

+/** From the T10 UAS specification */   

+#define USB_DT_PIPE_USAGE                       0x24

+/** From the USB 3.0 spec */   

+#define	USB_DT_SS_ENDPOINT_COMP                 0x30

+/** USB directions */

+#define USB_DIR_OUT                             0       /* to device */

+#define USB_DIR_IN                              0x80    /* to host */

+/** USB types, the second of three bmRequestType fields, ЭÒé9.3.1 */

+#define USB_TYPE_MASK                           (0x03 << 5)

+#define USB_TYPE_STANDARD                       (0x00 << 5)

+#define USB_TYPE_CLASS                          (0x01 << 5)

+#define USB_TYPE_VENDOR                         (0x02 << 5)

+#define USB_TYPE_RESERVED                       (0x03 << 5)

+/** USB recipients, the third of three bmRequestType fields */

+#define USB_RECIP_MASK                          0x1f

+#define USB_RECIP_DEVICE                        0x00

+#define USB_RECIP_INTERFACE                     0x01

+#define USB_RECIP_ENDPOINT                      0x02

+#define USB_RECIP_OTHER                         0x03

+/** From Wireless USB 1.0 */ 

+#define USB_RECIP_PORT                          0x04

+#define USB_RECIP_RPIPE                         0x05

+/*

+* Standard requests, for the bRequest field of a SETUP packet.

+*

+* These are qualified by the bmRequestType field, so that for example

+* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved

+* by a GET_STATUS request.

+*/

+#define USB_REQ_GET_STATUS                      0x00

+#define USB_REQ_CLEAR_FEATURE                   0x01

+#define USB_REQ_SET_FEATURE                     0x03

+#define USB_REQ_SET_ADDRESS                     0x05

+#define USB_REQ_GET_DESCRIPTOR                  0x06

+#define USB_REQ_SET_DESCRIPTOR                  0x07

+#define USB_REQ_GET_CONFIGURATION               0x08

+#define USB_REQ_SET_CONFIGURATION               0x09

+#define USB_REQ_GET_INTERFACE                   0x0A

+#define USB_REQ_SET_INTERFACE                   0x0B

+#define USB_REQ_SYNCH_FRAME                     0x0C

+#define USB_REQ_GET_MAX_LUN                     0xFE

+/*

+* USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and

+* are read as a bit array returned by USB_REQ_GET_STATUS.  (So there

+* are at most sixteen features of each type.)  Hubs may also support a

+* new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.

+*/

+#define USB_DEVICE_SELF_POWERED                 0	/**< (read only) */

+#define USB_DEVICE_REMOTE_WAKEUP                1	/**< dev may initiate wakeup */

+#define USB_DEVICE_TEST_MODE                    2	/**< (wired high speed only) */

+#define USB_DEVICE_BATTERY                      2	/**< (wireless) */

+#define USB_DEVICE_B_HNP_ENABLE                 3	/**< (otg) dev may initiate HNP */

+#define USB_DEVICE_WUSB_DEVICE                  3	/**< (wireless)*/

+#define USB_DEVICE_A_HNP_SUPPORT                4	/**< (otg) RH port supports HNP */

+#define USB_DEVICE_A_ALT_HNP_SUPPORT            5	/**< (otg) other RH port does */

+#define USB_DEVICE_DEBUG_MODE                   6	/**< (special devices only) */

+/*

+* New Feature Selectors as added by USB 3.0

+* See USB 3.0 spec Table 9-7

+* Suspend Options, Table 9-7 USB 3.0 spec

+*/

+#define USB_DEVICE_U1_ENABLE                    48	/**< dev may initiate U1 transition */

+#define USB_DEVICE_U2_ENABLE                    49	/**< dev may initiate U2 transition */

+#define USB_DEVICE_LTM_ENABLE                   50	/**< dev may send LTM */

+

+#define USB_INTRF_FUNC_SUSPEND                  0	/**< function suspend */

+#define USB_INTR_FUNC_SUSPEND_OPT_MASK          0xFF00

+#define USB_INTRF_FUNC_SUSPEND_LP               (1 << (8 + 0))

+#define USB_INTRF_FUNC_SUSPEND_RW               (1 << (8 + 1))

+

+#define USB_ENDPOINT_HALT                       0	/**< IN/OUT will STALL */

+

+/** Bit array elements as returned by the USB_REQ_GET_STATUS request */

+#define USB_DEV_STAT_U1_ENABLED                 2	/**< transition into U1 state */

+#define USB_DEV_STAT_U2_ENABLED                 3	/**< transition into U2 state */

+#define USB_DEV_STAT_LTM_ENABLED                4	/**< Latency tolerance messages */

+/**

+* USB function drivers should return USB_GADGET_DELAYED_STATUS if they

+* wish to delay the data/status stages of the control transfer till they

+* are ready. The control transfer will then be kept from completing till

+* all the function drivers that requested for USB_GADGET_DELAYED_STAUS

+* invoke usb_composite_setup_continue().

+*/

+#define USB_GADGET_DELAYED_STATUS               0x7fff	/**< Impossibly large value */

+//#define EP0_PACKET_SIZE                         64 

+//#define	MAX_EPS				(0x8)

+

+/**

+* struct usb_ctrlrequest - SETUP data for a USB device control request

+* Note that the driver for any interface can issue control requests.

+* For most devices, interfaces don't coordinate with each other, so

+* such requests may be made at any time.

+*/

+

+ typedef struct T_USB3Slave_CtrlReq

+{

+    u8 bmRequestType;                         /**< Æ¥Åäsetup°übmRequestTypeÓò */

+    u8 bRequest;                              /**< Æ¥Åäsetup°übRequestÓò  */

+    u16 wValue;                              /**< Æ¥Åäsetup°üwValueÓò */

+    u16 wIndex;                              /**< Æ¥Åäsetup°üwIndexÓò */

+    u16 wLength;                             /**< Æ¥Åäsetup°üwLengthÓò */

+}__attribute__ ((__packed__)) T_USB3Slave_CtrlReq;

+

+/** ¶Ëµã´«ÊäÀàÐ͵Ⱥ궨Òå */

+#define USB_ENDPOINT_NUMBER_MASK                0x0f	/* in bEndpointAddress */

+#define USB_ENDPOINT_DIR_MASK                   0x80

+

+#define USB_ENDPOINT_XFERTYPE_MASK              0x03	/* in bmAttributes */

+#define USB_ENDPOINT_XFER_CONTROL               0

+#define USB_ENDPOINT_XFER_ISOC                  1

+#define USB_ENDPOINT_XFER_BULK                  2

+#define USB_ENDPOINT_XFER_INT                   3

+#define USB_ENDPOINT_MAX_ADJUSTABLE             0x80

+

+/** ×î´ó°ü´óС£¬²ÎÕÕЭÒ飬¾ù¿ÉÉèÖÃΪ1024 */

+#define HS_MAX_PACKET_SIZE                         512  

+#define FS_MAX_PACKET_SIZE                         64

+/** ¿ØÖÆ´«Êä×î´ó°ü´óС */

+/** ¶ËµãÊýÄ¿ */

+#define ENDPOINTS_NUM                      6   

+/** ЭÒé¶ËµãÃèÊö·û */

+

+/** TRB¿ØÖÆÖи÷¸öλ¶ÎµÄºê¶¨Òå*/

+#define TRBCTL_NORMAL                           1

+#define TRBCTL_CONTROL_SETUP                    2

+#define TRBCTL_CONTROL_STATUS2                  3

+#define TRBCTL_CONTROL_STATUS3                  4

+#define TRBCTL_CONTROL_DATA                     5

+#define TRBCTL_ISOCHRONOUS_FIRST                6

+#define TRBCTL_ISOCHRONOUS                      7

+#define TRBCTL_LINK_TRB                         8

+/** struct T_USB3Slave_TRBToHW - transfer request block (hw format) */

+typedef struct T_USB3Slave_TRBToHW

+{

+    u32  udBpl;                              /**< Ö¸ÏòbufferµÄµÍ32λµØÖ· */

+    u32  udBph;                              /**< Ö¸ÏòbufferµÄ¸ß32λµØÖ·  */

+    u32  udSize;                             /**< Êý¾Ý´«ÊäµÄ³¤¶È */

+    u32  udCtrl;                             /**< TRB¿ØÖÆ */

+}__attribute__ ((__packed__)) T_USB3Slave_TRBToHW;

+

+/** struct T_USB3Slave_TRB - transfer request block */ 

+ typedef struct T_USB3Slave_TRB

+{

+    u64    bplh;                              /**< Ö¸ÏòbufferµØÖ· */

+

+     union

+    {

+         struct

+        {

+             u32    BUFSIZ:24;                /**< Êý¾Ý´«ÊäµÄ³¤¶È */

+             u32    PCM1:2;                   /**< Packet Count M1 */

+             u32    Reserved27_26:2;

+             u32    TRBSTS:4;                 /**< TRB״̬ */

+        }bit;

+        u32 udVal;

+    }len_pcm;

+

+     union

+    {

+         struct

+        {

+             u32    HWO:1;                    /**< ָʾӲ¼þÓµÓеÄTRB */

+             u32    LST:1;                    /**< ×îºóÒ»¸öTRB */

+             u32    CHN:1;                    /**< ´ËTRBÓëÏÂÒ»¸öTRBÏà¹ØÁª */

+             u32    CSP:1;                    /**< µ±½ÓÊÕµ½Ò»¸ö¶Ì°ücore½«»á¼ÌÐøµ½ÏÂÒ»¸öBuffer Descriptor */

+             u32    TRBCTL:6;                 /**< TRB ¿ØÖÆ */

+             u32    ISP_IMI:1;                /**< Interrupt on Short Packet/Interrupt on Missed ISOC */

+             u32    IOC:1;                    /**< Èç¹û±»ÉèÖ㬱íʾ´«ÊäÍê³Éºó²úÉúÖÐ¶Ï */

+             u32    Reserved13_12:2;

+             u32    StreamID_SOFNum:16;       /**< Stream ID/SOF Number */

+             u32    Reserved31_30:2;

+        }bit;

+        u32 udVal;

+    }control;

+}__attribute__ ((__packed__)) T_USB3Slave_TRB;

+

+/** EVENT buffer´óС */

+#define EVENT_BUFFERS_SIZE                 256//256  

+

+/**

+* struct T_USB3Slave_EventBuf - Software event buffer representation

+*/

+

+typedef struct

+{

+    u32  EvtBuf[EVENT_BUFFERS_SIZE];         /**< ·ÖÅäµÄEVENT Buffer */

+    u32  udLength;                           /**< ·ÖÅäEVENT Buffer ´óС */

+    u32  udLpos;                             /**< ÓÃÓÚָʾµ±Ç°EVENTµÄÆðʼλÖà */

+}T_USB3Slave_EventBuf;

+

+

+/** EVENTÀàÐÍ  */

+#define EVENT_TYPE_MASK                         0xfe

+#define EVENT_TYPE_DEV	                        0

+#define EVENT_TYPE_CARKIT	                    3

+#define EVENT_TYPE_I2C	                        4

+typedef struct T_USB3Slave_EventType

+{

+    u32	udIs_devspec:1;                     /**< ÓÃÓÚÅжÏÊǶ˵ãÀàÐÍEVENT»¹ÊÇÉ豸ÀàÐÍEVENT */

+    u32	udType:6;                           /**< EVENT ÀàÐÍ */

+    u32	udReserved8_31:25;

+}__attribute__ ((__packed__)) T_USB3Slave_EventType;

+

+/** ¶ËµãÀàÐÍEVENTÀàÐÍ */

+#define DEPEVT_XFERCOMPLETE                     0x01

+#define DEPEVT_XFERINPROGRESS                   0x02

+#define DEPEVT_XFERNOTREADY                     0x03

+#define DEPEVT_RXTXFIFOEVT                      0x04

+#define DEPEVT_STREAMEVT                        0x06

+#define DEPEVT_EPCMDCMPLT                       0x07

+

+#define DEPEVT_STATUS_BUSERR                    (1 << 0)

+#define DEPEVT_STATUS_SHORT                     (1 << 1)

+#define DEPEVT_STATUS_IOC                       (1 << 2)

+#define DEPEVT_STATUS_LST                       (1 << 3)

+/** Stream event only */

+#define DEPEVT_STREAMEVT_FOUND                  1

+#define DEPEVT_STREAMEVT_NOTFOUND               2

+/** Control-only Status */

+#define DEPEVT_STATUS_CONTROL_SETUP	            0

+#define DEPEVT_STATUS_CONTROL_DATA	            1

+#define DEPEVT_STATUS_CONTROL_STATUS            2

+#define DEPEVT_STATUS_STATUS_SETUP             10

+

+/**

+* struct dwc3_event_depvt - Device Endpoint Events

+* @udOne_bit: indicates this is an endpoint event (not used)

+* @udEndpoint_number: number of the endpoint

+* @udEndpoint_event: The event we have:

+*	0x00	- Reserved

+*	0x01	- XferComplete

+*	0x02	- XferInProgress

+*	0x03	- XferNotReady

+*	0x04	- RxTxFifoEvt (IN->Underrun, OUT->Overrun)

+*	0x05	- Reserved

+*	0x06	- StreamEvt

+*	0x07	- EPCmdCmplt

+* @udReserved11_10: Reserved, don't use.

+* @EventStatus: Indicates the status of the event. Refer to databook for more information.

+* @EventParam: Parameters of the current event. Refer to databook for more information.

+*/

+/** ²Î¼ûÊÖ²á7.2.8.1ÃèÊö¶ËµãÀàÐÍEVENT */

+ typedef struct T_USB3Slave_EpEvt

+{

+    u32	udOne_bit:1;                        /**< 1bitÓÃÓÚÅжÏÊǶ˵ãÀàÐÍevent»¹ÊÇÉ豸ÀàÐÍevent */

+    u32	udEndpoint_number:5;                /**< ָʾÎïÀí¶ËµãºÅ */

+    u32	udEndpoint_event:4;                 /**< ָʾ¶ËµãÀàÐÍevent */

+    u32	udReserved11_10:2;

+    u32	EventStatus:4;                      /**< ָʾevent״̬£¬Refer to databook for more information*/

+    u32	EventParam:16;                      /**< µ±Ç°event²ÎÊý. Refer to databook for more information */

+}__attribute__ ((__packed__)) T_USB3Slave_EpEvt;

+

+/**

+* struct T_USB3Slave_DevEvt - Device Events

+* @udOne_bit: indicates this is a non-endpoint event (not used)

+* @udDevice_event: indicates it's a device event. Should read as 0x00

+* @udType: indicates the type of device event.

+*	0	- DisconnEvt

+*	1	- USBRst

+*	2	- ConnectDone

+*	3	- ULStChng

+*	4	- WkUpEvt

+*	5	- Reserved

+*	6	- EOPF

+*	7	- SOF

+*	8	- Reserved

+*	9	- ErrticErr

+*	10	- CmdCmplt

+*	11	- EvntOverflow

+*	12	- VndrDevTstRcved

+* @udReserved15_12: Reserved, not used

+* @udEvtInfo: Information about this event

+* @udReserved31_24: Reserved, not used

+*/

+/** DEVICE EVENT ÀàÐÍ */

+#define DEVICE_EVENT_DISCONNECT                 0

+#define DEVICE_EVENT_RESET	                    1

+#define DEVICE_EVENT_CONNECT_DONE               2

+#define DEVICE_EVENT_LINK_STATUS_CHANGE         3

+#define DEVICE_EVENT_WAKEUP                     4

+#define DEVICE_EVENT_EOPF                       6

+#define DEVICE_EVENT_SOF                        7

+#define DEVICE_EVENT_ERRATIC_ERROR              9

+#define DEVICE_EVENT_CMD_CMPL                   10

+#define DEVICE_EVENT_OVERFLOW                   11

+

+typedef struct T_USB3Slave_DevEvt

+{

+    u32	udOne_bit:1;                        /**< 1bitÓÃÓÚÅжÏÊǶ˵ãÀàÐÍevent»¹ÊÇÉ豸ÀàÐÍevent */

+    u32	udDevice_event:7;                   /**< É豸ÀàÐÍevent */

+    u32	udType:4;                           /**< ָʾ·¢ÉúµÄ¸÷ÖÖevent */

+    u32	udReserved15_12:4;

+    u32	udEvtInfo:8;                        /**< event ÐÅÏ¢±ÈÌØ¡£ÓÃÓÚָʾÊÇ·ñÊÇSSºÍlink state */

+    u32	udReserved31_24:8;

+}__attribute__ ((__packed__)) T_USB3Slave_DevEvt;

+

+/**

+* struct T_USB3Slave_Event_GEvt - Other Core Events

+* @udOne_bit: indicates this is a non-endpoint event (not used)

+* @udDevice_event: indicates it's (0x03) Carkit or (0x04) I2C event.

+* @udPhy_port_number: self-explanatory

+* @udReserved31_12: Reserved, not used.

+*/

+

+ typedef struct T_USB3Slave_Event_GEvt

+{

+    u32	udOne_bit:1;

+    u32	udDevice_event:7;

+    u32	udPhy_port_number:4;

+    u32	udReserved31_12:20;

+}__attribute__ ((__packed__)) T_USB3Slave_Event_GEvt;

+

+/** union T_USB3Slave_Event - representation of Event Buffer contents */

+

+typedef union

+{

+    u32                  udRaw;              /**< ָʾµ±Ç°eventµÄÖµ */

+    T_USB3Slave_EventType   tType;              /**< ָʾevent ÀàÐÍ(00h±íʾdevice specific event) */

+    T_USB3Slave_EpEvt       tEpEvt;             /**< ¶ËµãÀàÐÍevent */

+    T_USB3Slave_DevEvt      tDevEvt;            /**< É豸ÀàÐÍevent */

+    T_USB3Slave_Event_GEvt  tGetEvt;            /**< Other Core Events */

+}T_USB3Slave_Event;

+

+/** ¶¨ÒåEPµÄ±ê¼Çºê */

+#define EP_ENABLED                              (1 << 0)

+#define EP_STALL                                (1 << 1)

+#define EP_WEDGE                                (1 << 2)

+#define EP_BUSY                                 (1 << 4)

+#define EP_PENDING_REQUEST                      (1 << 5)

+/** This last one is specific to EP0 */

+#define EP0_DIR_IN                             ((u32)1 << 31)

+/** EP񈬀 */

+#define EP_FLAG_STALLED                         (1 << 0)

+#define EP_FLAG_WEDGED                          (1 << 1)

+/** EP·½Ïò */

+#define EP_DIRECTION_TX                         true

+#define EP_DIRECTION_RX                         false

+

+/** ¶ËµãµÄ״̬±ä»¯*/

+typedef enum

+{

+    EP_IDLE = 0,                            /**< EP¿ÕÏÐ */

+    EP_HALTED,                              /**< EP halt */

+    EP0_CTRLIN_SETUP,                       /**< EP0¿ØÖƽ¨Á¢IN½×¶Î */

+    EP0_CTRLOUT_SETUP,                      /**< EP0¿ØÖƽ¨Á¢OUT½×¶Î */

+    EP0_CTRLNULL_SETUP,                     /**< EP0¿ØÖƽ¨Á¢Îª¿Õ */

+    EP0_CTRL_INDATA,                        /**< EP0¿ØÖÆINÊý¾Ý½×¶Î */

+    EP0_CTRL_OUTDATA,                       /**< EP0¿ØÖÆOUTÊý¾Ý½×¶Î */

+    EP0_CTRL_INSTATUS,                      /**< EP0¿ØÖÆIN״̬½×¶Î */

+    EP0_CTRL_OUTSTATUS,                     /**< EP0¿ØÖÆOUT״̬½×¶Î */

+    EP_RX,                                  /**< EP½ÓÊÕ״ָ̬ʾ */

+    EP_TX                                   /**< EP·¢ËÍ״ָ̬ʾ */

+}E_USB3Slave_EpState;

+

+/** ָʾEp0ÏÂÒ»¸öEVENTÀàÐÍ */

+typedef enum

+{

+    EP0_UNKNOWN = 0,

+    EP0_COMPLETE,                               /**< EP0״ָ̬ʾΪÍê³É*/

+    EP0_NRDY_SETUP,                             /**< EP0״̬NRDYָʾΪ½¨Á¢½×¶Î*/

+    EP0_NRDY_DATA,                              /**< EP0״̬NRDYָʾΪÊý¾Ý½×¶Î*/

+    EP0_NRDY_STATUS,                            /**< EP0״̬NRDYָʾΪ״̬½×¶Î*/

+} E_USB3Slave_Ep0Next;

+/** ָʾEP0¿ØÖÆ´«ÊäµÄÈý¸ö½×¶Î */

+typedef enum

+{

+    EP0_UNCONNECTED	= 0,

+    EP0_SETUP_PHASE,                            /**< EP0¿ØÖÆ´«ÊäµÄ½¨Á¢½×¶Î */

+    EP0_DATA_PHASE,                             /**< EP0¿ØÖÆ´«ÊäµÄÊý¾Ý½×¶Î */

+    EP0_STATUS_PHASE,                           /**< EP0¿ØÖÆ´«ÊäµÄ״̬½×¶Î */

+}E_USB3Slave_Ep0State;

+/** ³¬¸ßËÙģʽϵÄÁ¬½Ó״̬ */

+

+

+/** ¿ØÖÆ´«ÊäÖÐö¾ÙËù´¦µÄ״̬½×¶Î */

+typedef enum

+{

+    DEFAULT_STATE = 0,                          /**< ȱʡ״̬ */

+    ADDRESS_STATE,                              /**< µØÖ·×´Ì¬ */

+    CONFIGURED_STATE,                           /**< ÅäÖÃ״̬ */

+    SETINTERFACE_STATE,                         /**< ÉèÖýӿÚ״̬*/

+    GETMAXLUN_STATE,                            /**<GET MAX lUN*/

+    BULKIN_CMPL,                                /**< BULK IN´«ÊäÍê³É״̬ */

+    BULKOUT_CMPL,                               /**< BULK OUT´«ÊäÍê³É״̬ */

+    IntrIN_CMPL,                                /**< Interrupt IN´«ÊäÍê³É״̬ */

+    IntrOUT_CMPL,                               /**< Interrupt OUT´«ÊäÍê³É״̬ */

+}E_USB3Slave_ReqState;

+

+/** ¶¨ÒåUSB3.0µÄËÙ¶ÈÀàÐÍ£¬²ÎÕÕ¿ØÖÆÆ÷ÊÖ²áP513, DCFG¼Ä´æÆ÷0:2±ÈÌØ */

+typedef enum

+{

+    USB3_HIGHSPEED  = 0,                        /**< 3'b000 USB2.0 PHY clock is 30 MHz or 60 MHz */ 

+    USB3_FULLSPEED  = 1,                        /**< 3'b001 USB2.0 PHY clock is 30 MHz or 60 MHz */

+    USB3_SUPERSPEED = 4,                        /**< 3'b100 USB3.0 PHY clock is 30 MHz or 60 MH */

+}E_USB3Slave_SpeedMode;

+/** ָʾÁ¬½ÓµÄÉ豸µÄËÙ¶ÈÀàÐÍ */

+typedef enum

+{

+    USB30_SPEED_UNKNOWN = 0,                      /**< enumerating */

+    USB30_SPEED_LOW, USB30_SPEED_FULL,              /**< usb 1.1 */

+    USB30_SPEED_HIGH,                             /**< usb 2.0 */

+    USB30_SPEED_WIRELESS,                         /**< wireless (usb 2.5) */

+    USB30_SPEED_SUPER,                            /**< usb 3.0 */

+}E_USB3Slave_Speed;

+

+/** T_USB3Slave_HWPARAMS - copy of HWPARAMS registers */

+

+typedef struct

+{

+    u32	udHwparams0;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS0¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams1;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS1¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams2;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS2¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams3;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS3¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams4;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS4¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams5;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS5¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams6;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS6¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams7;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS7¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+    u32	udHwparams8;                        /**< ¶ÔÓ¦ÓÚGHWPARAMS8¼Ä´æÆ÷¶ÁÈ¡µÄÖµ */

+}T_USB3Slave_HWPARAMS;

+

+

+/** ÓÃÓڶ˵ãÃüÁîµÄÈý¸ö²ÎÊý */

+ typedef struct T_USB3Slave_EpCmdPara

+{

+    u32	Parameter2;                         /**< ָʾÉ豸ÎïÀí¶ËµãÃüÁî²ÎÊý2 */

+    u32	Parameter1;                         /**< ָʾÉ豸ÎïÀí¶ËµãÃüÁî²ÎÊý1 */

+    u32	Parameter0;                         /**< ָʾÉ豸ÎïÀí¶ËµãÃüÁî²ÎÊý0 */

+}__attribute__ ((__packed__)) T_USB3Slave_EpCmdPara;

+

+/** DEPCFG parameter 1 */ 

+#define DEPCFG_INT_NUM(n)                       ((n) << 0)

+#define DEPCFG_XFER_COMPLETE_EN                 (1   << 8)

+#define DEPCFG_XFER_IN_PROGRESS_EN              (1   << 9)

+#define DEPCFG_XFER_NOT_READY_EN                (1   << 10)

+#define DEPCFG_FIFO_ERROR_EN                    (1   << 11)

+#define DEPCFG_STREAM_EVENT_EN                  (1   << 13)

+#define DEPCFG_BINTERVAL_M1(n)                  ((n) << 16)

+#define DEPCFG_STREAM_CAPABLE                   (1   << 24)

+#define DEPCFG_EP_NUMBER(n)                     ((n) << 25)

+#define DEPCFG_BULK_BASED                       (1   << 30)

+#define DEPCFG_FIFO_BASED                       (1   << 31)

+

+/** DEPCFG parameter 0 */

+#define DEPCFG_EP_TYPE(n)                       ((n) << 1)

+#define DEPCFG_MAX_PACKET_SIZE(n)               ((n) << 3)

+#define DEPCFG_FIFO_NUMBER(n)                   ((n) << 17)

+#define DEPCFG_BURST_SIZE(n)                    ((n) << 22)

+#define DEPCFG_DATA_SEQ_NUM(n)                  ((n) << 26)

+#define DEPCFG_IGN_SEQ_NUM                      (1   << 31)

+

+/** DEPXFERCFG parameter 0 */

+#define DEPXFERCFG_NUM_XFER_RES(n)              ((n) & 0xffff)

+

+/** ¶ËµãÐÅÏ¢½á¹¹Ìå */

+#pragma pack (4) /*Ö¸¶¨°´4×Ö½Ú¶ÔÆë*/

+typedef struct

+{

+

+    u32                  udEpNum;            /**< µ±Ç°epºÅ  */

+    u8                   *pucBuf;            /**< »º³åÇøÖ¸Õë */

+    u32                  udPos;              /**< »º³åÇø¶ÁдָÕë */

+    u32                  udLen;              /**< »º³åÇø×ܳ¤¶È */

+    u32                  udMaxPacket;        /**< ×î´ó°üµÄ´óС */

+    u32                  udMaxStream;        /**< Ö§³ÖµÄ×î´óÁ÷Êý */

+    u32                  udMaxBurst;         /**< ¸Ã¶ËµãÖ§³ÖµÄ×î´óburstÊý */

+    T_USB3Slave_TRBToHW     *ptTRB;           /**< ×¼±¸ÓÃÓÚtrbµÄ»º³åÇø */

+    u32                  udDMAChannel;       /**< ¶ËµãʹÓõÄdmaͨµÀ, ¸ß16Ϊģʽ£¬µÍ16ΪͨµÀºÅ */

+    u8                   ucType;             /**< Ö§³ÖµÄ´«ÊäÀàÐÍ */

+    void                    *pPara;             /**< »Øµ÷º¯ÊýµÄ²ÎÊý */

+    E_USB3Slave_EpState     eEpState;           /**< ¶Ëµã״̬ */

+    u32                  udDirection;        /**< ¶Ëµã´«Êä·½Ïò * @direction: true for TX, false for RX */

+    void                    *DriverData;        /**< Êý¾ÝÓÃÓÚ´«Êä,ºóÐøµ÷ÊÔ¿ÉÄÜ»áÓõ½*/

+    u32                  udInterval;         /**< ¶ËµãµÄInterval */

+    u32                  udBusySlot;         /**< ´¦ÓÚæ״̬TRB¸öÊý */

+    u32                  udFreeSlot;         /**< ´¦ÓÚ¿ÕÏÐ״̬TRB¸öÊý */

+    u32                  *pudAddrData;       /**< ĿǰÖ÷ÒªÊÇBULK´«ÊäÓÃÓÚ½ÓÊպͷ¢ËÍÊý¾ÝµÄµØÖ· */    

+    u8                   ucAddress;          /**< µØÖ· */

+    u32                  udFlags;            /**< ¶Ëµã±ê¼Ç */

+    u32                  udCurrentTrb;       /**< µ±Ç°TRB */

+    u8                   ucResTransIdx;      /**< ´«Êä×ÊÔ´Ë÷Òý */

+    u32                  udStreamCapable;    /**< ÊÇ·ñ¾ßÓÐÁ÷ÄÜÁ¦ */

+    F_USB_CB	             fnUsbCb;	    //¶Ëµã²Ù×÷Íê³ÉºóµÄ»Øµ÷º¯Êý

+

+}T_USB3Slave_Ep;

+#pragma pack () /*È¡Ïû¶ÔÆë*/

+/** struct dwc3 - representation of our controller */

+/** È«¾ÖdeviceÐÅÏ¢½á¹¹Ì壬ÓÃÓÚÈí¼þ */

+#pragma pack (4) /*Ö¸¶¨°´4×Ö½Ú¶ÔÆë*/

+typedef struct

+{

+

+    u32                   udRegs_base;                  /**< ¼Ç¼¼Ä´æÆ÷»ùÖ· */

+    E_USB3Slave_SpeedMode    eSpeedMode;                   /**< µ±Ç°É豸µÄËÙ¶È */

+    E_USB3Slave_Speed        eDeviceSpeedType;             /**< ËÙ¶ÈÀàÐÍ£¬¼æÈÝlinuxÇý¶¯Ëù×÷£¬¾ßÌåʹÓôýÒé */

+    T_USB3Slave_HWPARAMS     tHwParams;                    /**< ±£´æËùÓÐÓ²¼þ²ÎÊý */

+    u32                   udMode;                       /**< ±£´æ¿ØÖÆÆ÷µ±Ç°Ëù´¦Ä£Ê½ */

+    T_USB3Slave_EventBuf     *ptEvtBuffs;                /**< ±£´æevent */ 

+    u32                   udNumEvtBufs;          /**< ¼Ç¼evnet¸öÊý£¬´ÓÓ²¼þ²ÎÊýÖлñµÃ*/

+    T_USB3Slave_Ep           tEps[ENDPOINTS_NUM];          /**< ±£´æ¶ËµãÐÅÏ¢ */

+    u32                   udIsSelfPowered;             /**< ×Ô¹©µçture*/

+    u32                   udThreeStageSetup;          /**< Èý½×¶ÎÉèÖÃ*/

+    u32                   udEp0Bounced;                /**< bounce buffer for ep0 */

+    u32                   udEp0ExpectIn;              /**< true when we expect a DATA IN transfer */

+    u32                   udSetupPacketPending;       /**< true when there's a Setup Packet in FIFO. Workaround */

+    u32                   udDelayedStatus;             /**< ÑÓ³Ù״̬*/

+    u32                   udEventsequence;              /**< eventÐòºÅ */

+    E_USB3Slave_Ep0Next	     eEp0NextEvent;                /**< ָʾ¶ËµãµÄÏÂÒ»¸öEVENT */

+    E_USB3Slave_Ep0State     eEp0State;                    /**< ep0״̬*/

+    E_USB3Slave_ReqState     eDevState;                    /**< É豸״̬ */

+    u32                   udUSBSate;                    /**< ö¾Ù״̬ */

+/*ÒÔÏÂÊý¾Ý³ÉÔ±³¤¶ÈÉèÖòÎÕÕlinux 3.3.6ÖжÔusb3¿ØÖÆÆ÷µÄ³õʼº¯Êý*/

+    T_USB3Slave_CtrlReq	     *tCtrlReq;                     /**< ¿ØÖÆÇëÇó */

+    T_USB3Slave_TRBToHW	     *ptEp0TRB;                    /**< ep0 TRBÉèÖÃ*/

+    u8                    aucSetupBuf[2];              /**< ½¨Á¢buffer  δÓÃĿǰ */

+    u8                    ucSpeed;                      /**< ËÙ¶È */

+    u32                   *pudTxData;                   /**< Ö¸Ïò·¢Ë͵ÄÊý¾Ý´óС */

+}T_USB3Slave_SlaveObj;

+#pragma pack () /*È¡Ïû¶ÔÆë*/

+

+/** ¶¨ÒåSlaveObj ¶ÔÏóµÄÈ«¾Ö±äÁ¿*/

+

+/** DWC3 Features to be used as Driver Data ĿǰûÓÐÓõ½ÔÝʱ·ÅÔÚÕâÀï*/

+/*#define HAS_PERIPHERAL		   BIT(0)

+#define HAS_XHCI			       BIT(1)

+#define HAS_OTG			           BIT(3)*/

+#define DATA_32BIT_MASK            0xFFFFFFFF

+#define ADDRESS_MAX                127

+

+/* *INDENT-OFF* */

+#ifdef __cplusplus

+}

+#endif

+/* *INDENT-ON* */

+  

+#endif  /* __USB3_SLAVE_DRV_H */

+

+

+/** @} */

diff --git a/boot/common/src/loader/drivers/drv_usb3slave_reg.h b/boot/common/src/loader/drivers/drv_usb3slave_reg.h
new file mode 100644
index 0000000..3ec2de5
--- /dev/null
+++ b/boot/common/src/loader/drivers/drv_usb3slave_reg.h
@@ -0,0 +1,95 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+*

+* ÎļþÃû³Æ£º drv_usb3slave_reg.h

+* Îļþ±êʶ£º 

+* ÄÚÈÝÕªÒª£º 

+* ÆäËü˵Ã÷£º zx297520 project

+* µ±Ç°°æ±¾£º 1.0

+* ×÷¡¡¡¡Õߣº tangjian

+* Íê³ÉÈÕÆÚ£º 

+*

+*

+*******************************************************************************/

+   

+

+#ifndef __DRV_USB3SLAVE_REG_H

+#define __DRV_USB3SLAVE_REG_H

+  

+/* *INDENT-OFF* */

+#ifdef __cplusplus

+extern "C" {

+#endif

+/* *INDENT-ON* */

+

+#include "common.h"

+

+

+/** ÏÂÃæµÄ¼¸¸ö¼Ä´æÆ÷µÄ¸ñʽÓÐÐ©ÌØ±ð£¬¼Ä´æÆ÷ÊDz»Á¬ÐøµÄ£¬¹Ê±£ÁôÁËlinuxÖмĴæÆ÷µÄ¸ñʽ*/

+       

+    /*0x200-0x23c*/

+#define GUSB2PHYCFG(n)	   (0xc200 + (n * 0x04))

+

+    /*0x240-0x27c*/

+#define GUSB2I2CCTL(n)	   (0xc240 + (n * 0x04))

+

+    /*0x280-0x2bc*/

+#define GUSB2PHYACC(n)	   (0xc280 + (n * 0x04))

+

+    /*0x2C0-0x2fc*/

+#define GUSB3PIPECTL(n)   (0xc2c0 + (n * 0x04))

+

+    /*0x300-0x37C*/

+#define GTXFIFOSIZ(n)	   (0xc300 + (n * 0x04))

+

+    /*0x380-0x3fc*/

+#define GRXFIFOSIZ(n)	   (0xc380 + (n * 0x04))

+

+#define GHWPARAMS0    0xc140

+#define GHWPARAMS1    0xc144

+#define GHWPARAMS2    0xc148

+#define GHWPARAMS3    0xc14c

+#define GHWPARAMS4    0xc150

+#define GHWPARAMS5    0xc154

+#define GHWPARAMS6    0xc158

+#define GHWPARAMS7    0xc15c

+#define GHWPARAMS8    0xc600

+

+#define GEVNTADRLO(n)	   (0xc400 + (n * 0x10))

+#define GEVNTADRHI(n)	   (0xc404 + (n * 0x10))

+#define GEVNTSIZ(n)        (0xc408 + (n * 0x10))

+#define GEVNTCOUNT(n)      (0xc40c + (n * 0x10))

+

+#define DEPCMDPAR2(n)	   (0xc800 + (n * 0x10))

+#define DEPCMDPAR1(n)	   (0xc804 + (n * 0x10))

+#define DEPCMDPAR0(n)	   (0xc808 + (n * 0x10))

+#define DEPCMD(n)		   (0xc80c + (n * 0x10))

+

+/** @} */

+/* RAMʱÖÓÑ¡Ôñλ */

+#define USB3Slave_GCTL_RAMCLKSEL_POS                             (6)

+#define USB3Slave_GCTL_CLK_BUS                                   (0 << USB3Slave_GCTL_RAMCLKSEL_POS)

+

+#define USB3Slave_DEPCMD_COMMANDPARAM_POS                       (16)

+#define USB2Slave_DEPCMD_PARAM(x)		(x << USB3Slave_DEPCMD_COMMANDPARAM_POS)

+/* ÃüÁ»îÉèÖÃλ */

+//#define USB3Slave_DEPCMD_CMDACT                                 USB3Slave_DEPCMD_CMDACT

+#define USB3Slave_DEPCMD_CMDACT_POS                             (10)

+#define USB3Slave_DEPCMD_CMDACT_1		                            (1 << USB3Slave_DEPCMD_CMDACT_POS)

+/* ÃüÁîÀàÐÍ */

+//#define USB3Slave_DEPCMD_CMDTYP                                 USB3Slave_DEPCMD_CMDTYP

+#define USB3Slave_DEPCMD_CMDTYP_POS                             (0)

+#define USB3Slave_DEPCMD_DEPSTARTCFG                            (0x09 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_ENDTRANSFER		                    (0x08 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_UPDATETRANSFER	                        (0x07 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_STARTTRANSFER	                        (0x06 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_CLEARSTALL		                        (0x05 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_SETSTALL		                        (0x04 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_GETSEQNUMBER	                        (0x03 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_SETTRANSFRESOURCE	                    (0x02 << USB3Slave_DEPCMD_CMDTYP_POS)

+#define USB3Slave_DEPCMD_SETEPCONFIG		                    (0x01 << USB3Slave_DEPCMD_CMDTYP_POS)

+

+#endif  /* __DRV_USB3SLAVE_REG_H */

+      

+

+      

diff --git a/boot/common/src/loader/drivers/dwc_otg_cil.c b/boot/common/src/loader/drivers/dwc_otg_cil.c
new file mode 100644
index 0000000..22fd410
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_cil.c
@@ -0,0 +1,1174 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
+ * $Revision: #191 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+/** @file
+ *
+ * The Core Interface Layer provides basic services for accessing and
+ * managing the DWC_otg hardware. These services are used by both the
+ * Host Controller Driver and the Peripheral Controller Driver.
+ *
+ * The CIL manages the memory map for the core so that the HCD and PCD
+ * don't have to do this separately. It also handles basic tasks like
+ * reading/writing the registers and data FIFOs in the controller.
+ * Some of the data access functions provide encapsulation of several
+ * operations required to perform a task, such as writing multiple
+ * registers to start a transfer. Finally, the CIL performs basic
+ * services that are not specific to either the host or device modes
+ * of operation. These services include management of the OTG Host
+ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
+ * Diagnostic API is also provided to allow testing of the controller
+ * hardware.
+ *
+ * The Core Interface Layer has the following requirements:
+ * - Provides basic controller operations.
+ * - Minimal use of OS services.
+ * - The OS services used will be abstracted by using inline functions
+ *	 or macros.
+ *
+ */
+
+#include <common.h>
+ 
+#include "global.h"
+#include "dwc_otg_regs.h"
+#include "dwc_otg_cil.h"
+#include "dwc_otg_driver.h"
+
+
+
+static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
+
+void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
+{
+    DWC_WRITE_REG32(reg,(DWC_READ_REG32(reg) & ~clear_mask) | set_mask);
+}
+
+dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
+{
+    dwc_otg_core_if_t *core_if = (&global.core_if_t);
+    dwc_otg_dev_if_t *dev_if = (&global.dev_if_t);
+    uint8_t *pt_core_if = ( uint8_t *)(&global.core_if_t);
+    uint8_t *pt_dev_if = ( uint8_t *)(&global.dev_if_t);
+    uint8_t *reg_base = (uint8_t *) reg_base_addr;
+    int i = 0;
+    for(i= 0;i<sizeof(global.core_if_t);i++)
+    {
+        pt_core_if[i] = 0;
+    }
+    core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
+
+    for(i= 0;i<sizeof(global.dev_if_t);i++)
+    {
+        pt_dev_if[i] = 0;
+    }
+
+    dev_if->dev_global_regs = (dwc_otg_device_global_regs_t *) (reg_base +DWC_DEV_GLOBAL_REG_OFFSET);
+
+    for (i = 0; i < MAX_EPS_CHANNELS; i++)
+    {
+        dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
+                                (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
+                                 (i * DWC_EP_REG_OFFSET));
+
+        dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
+                                 (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
+                                  (i * DWC_EP_REG_OFFSET));
+
+        core_if->data_fifo[i] =(uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +(i * DWC_OTG_DATA_FIFO_SIZE));
+    }
+
+    dev_if->speed = 0;	
+
+    core_if->dev_if = dev_if;
+
+    core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+    core_if->hwcfg1.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
+    core_if->hwcfg2.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
+    core_if->hwcfg3.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
+    core_if->hwcfg4.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
+
+    core_if->dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+
+    dwc_otg_setup_params(core_if);
+
+
+    return core_if;
+}
+
+/**
+ * Initializes the DevSpd field of the DCFG register depending on the PHY type
+ * and the enumeration speed of the device.
+ */
+void init_devspd(dwc_otg_core_if_t * core_if,uint8_t speed)
+{
+    uint32_t val;
+    dcfg_data_t dcfg;
+
+    val = speed;
+    dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+    dcfg.b.devspd = val;
+		if(global.g_enum == NEED_ENUM)
+	{
+    DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
+			}
+}
+
+/**
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param core_if Programming view of the DWC_otg controller
+ *
+ */
+void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    gahbcfg_data_t ahbcfg;
+    gotgctl_data_t gotgctl;
+
+    gusbcfg_data_t usbcfg;
+    ahbcfg.d32 = 0;
+    usbcfg.d32 = 0;
+    gotgctl.d32 = 0;
+
+
+    usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+if(global.g_enum == NEED_ENUM)
+{
+
+#if !USE_ASIC
+    usbcfg.b.ulpi_ext_vbus_drv =(core_if->core_params->phy_ulpi_ext_vbus == DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
+
+    usbcfg.b.term_sel_dl_pulse = (core_if->core_params->ts_dline == 1) ? 1 : 0;
+
+
+    DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+#endif
+    dwc_otg_core_reset(core_if);
+	}
+
+
+    dev_if->num_in_eps =  2;//calc_num_in_eps(core_if);
+    dev_if->num_out_eps = 2;//calc_num_out_eps(core_if);
+
+    core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
+    core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
+    core_if->nperio_tx_fifo_size = DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
+    {
+        /* High speed PHY. */
+        if (!core_if->phy_init_done)
+        {
+            core_if->phy_init_done = 1;
+            /* HS PHY parameters.  These parameters are preserved
+             * during soft reset so only program the first time.  Do
+             * a soft reset immediately after setting phyif.  */
+         #if !USE_ASIC
+            if (core_if->core_params->phy_type == 2)
+            {
+                /* ULPI interface */
+                usbcfg.b.ulpi_utmi_sel = 1;
+                usbcfg.b.phyif = 0;
+                usbcfg.b.ddrsel = core_if->core_params->phy_ulpi_ddr;
+            }
+          #else
+            if (core_if->core_params->phy_type == 1)
+            {
+                /* UTMI+ interface */
+                usbcfg.b.ulpi_utmi_sel = 0;
+                if (core_if->core_params->phy_utmi_width == 16)
+                {
+                    usbcfg.b.phyif = 1;
+
+                }
+                else
+                {
+                    usbcfg.b.phyif = 0;
+                }
+            }
+            #endif
+	if(global.g_enum == NEED_ENUM)
+	{
+            DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+            /* Reset after setting the PHY parameters */
+            dwc_otg_core_reset(core_if);
+	}
+        }
+    }
+	if(global.g_enum == NEED_ENUM)
+		{
+#if !USE_ASIC
+    if ((core_if->hwcfg2.b.hs_phy_type == 2) &&(core_if->hwcfg2.b.fs_phy_type == 1) &&(core_if->core_params->ulpi_fs_ls))
+    {
+        usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+        usbcfg.b.ulpi_fsls = 1;
+        usbcfg.b.ulpi_clk_sus_m = 1;
+        DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+    }
+    else
+    {
+        usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+        usbcfg.b.ulpi_fsls = 0;
+        usbcfg.b.ulpi_clk_sus_m = 0;
+        DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+    }
+#endif
+		}
+
+
+    ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+    ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+
+
+    ahbcfg.b.dmaenable = 0;
+//  ÅäÖÃÈ«¿ÕFIFO²úÉúÖжÏ
+    ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_EMPTY ;
+	if(global.g_enum == NEED_ENUM)
+	{
+
+         DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
+	}
+
+
+    core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
+
+    core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
+    core_if->multiproc_int_enable = dwc_param_mpi_enable_default;//core_if->core_params->mpi_enable;
+    /*
+     * Program the GUSBCFG register.
+     */
+    usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+    usbcfg.b.hnpcap = 0;
+    usbcfg.b.srpcap = 0;
+	
+	if(global.g_enum == NEED_ENUM)
+    {
+    	DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+    }
+    {
+        gotgctl.b.otgver = core_if->core_params->otg_ver;
+	if(global.g_enum == NEED_ENUM)
+      {
+        	DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, gotgctl.d32);
+      }
+        /* Set OTG version supported */
+        core_if->otg_ver = core_if->core_params->otg_ver;
+    }
+	if(global.g_enum == NEED_ENUM)
+   {
+       dwc_otg_core_dev_init(core_if);
+   }
+
+}
+
+/**
+ * This function enables the Device mode interrupts.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ */
+void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
+{
+    gintmsk_data_t intr_mask ;
+
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    intr_mask.d32 = 0;
+    /* Disable all interrupts. */
+    DWC_WRITE_REG32(&global_regs->gintmsk, 0);
+
+    /* Clear any pending interrupts */
+    DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
+
+    /* Enable the common interrupts */
+    intr_mask.b.rxstsqlvl = 1;
+    intr_mask.b.usbsuspend = 1;
+    DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
+    
+    intr_mask.d32 = 0x1e3400;
+    DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
+
+}
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * device mode.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ *
+ */
+void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
+{
+    int i;
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    dcfg_data_t dcfg;
+    grstctl_t resetctl;
+    dctl_data_t dctl;
+    diepmsk_data_t msk;
+    dcfg.d32 = 0;
+    resetctl.d32 = 0;
+    dctl.d32 = 0;
+    msk.d32 = 0;
+    /* Restart the Phy Clock */
+
+     DWC_WRITE_REG32(core_if->pcgcctl, 0);
+
+
+    /* Device configuration register */
+    init_devspd(core_if,0);//ĬÈÏÅäÖóɸßËÙ
+    dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
+    dcfg.b.descdma = 0;
+    dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
+
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
+		
+
+    /* Flush the FIFOs */
+    dwc_otg_flush_tx_fifo(core_if, 0x10);	/* all Tx FIFOs */
+    dwc_otg_flush_rx_fifo(core_if);
+
+    /* Flush the Learning Queue. */
+    resetctl.b.intknqflsh = 1;
+    DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
+			
+    /* Clear all pending Device Interrupts */
+    /** @todo - if the condition needed to be checked
+     *  or in any case all pending interrutps should be cleared?
+     */
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
+    
+    for (i = 0; i <= dev_if->num_in_eps; i++)
+    {
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl,0);
+
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
+
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl,0);
+
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
+    }
+			
+ //ÓÃÓÚhsic
+    if(1==global.g_USB_MODE)
+    {
+        DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, 0x40000000);
+    }
+    dwc_otg_enable_device_interrupts(core_if);
+    msk.b.txfifoundrn = 1;
+    DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,msk.d32, msk.d32);
+    dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+    dctl.b.sftdiscon = 0;
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);	
+
+}
+
+void dwc_otg_core_dev_disconnet(dwc_otg_core_if_t * core_if)
+{
+    dctl_data_t dctl;
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+    dctl.b.sftdiscon = 1;
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+}
+/**
+ * This function reads a setup packet from the Rx FIFO into the destination
+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
+ * Interrupt routine when a SETUP packet has been received in Slave mode.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param dest Destination buffer for packet data.
+ */
+void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
+{
+    dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
+    dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
+
+}
+
+/**
+ * This function enables EP0 OUT to receive SETUP packets and configures EP0
+ * IN for transmitting packets. It is normally called when the
+ * "Enumeration Done" interrupt occurs.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP0 data.
+ */
+void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    dsts_data_t dsts;
+    depctl_data_t diepctl;
+    dctl_data_t dctl;
+    ep->stp_rollover = 0;
+    dctl.d32 = 0;
+
+    /* Read the Device Status and Endpoint 0 Control registers */
+    dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
+    diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
+
+    /* Set the MPS of the IN EP based on the enumeration speed */
+    switch (dsts.b.enumspd)
+    {
+    case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
+    case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
+    case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
+        diepctl.b.mps = DWC_DEP0CTL_MPS_64;
+        break;
+    }
+
+    DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
+    dctl.b.cgnpinnak = 1;
+
+    DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
+
+}
+
+/**
+ * This function activates an EP.  The Device EP control register for
+ * the EP is configured as defined in the ep structure. Note: This
+ * function is not used for EP0.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to activate.
+ */
+void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    depctl_data_t depctl;
+    volatile uint32_t *addr;
+    daint_data_t daintmsk;
+
+    daintmsk.d32 = 0;
+    /* Read DEPCTLn register */
+    if (ep->is_in == 1)
+    {
+        addr = &dev_if->in_ep_regs[ep->num]->diepctl;
+        daintmsk.ep.in = 1 << ep->num;
+    }
+    else
+    {
+        addr = &dev_if->out_ep_regs[ep->num]->doepctl;
+        daintmsk.ep.out = 1 << ep->num;
+    }
+
+    /* If the EP is already active don't change the EP Control
+     * register. */
+    depctl.d32 = DWC_READ_REG32(addr);
+    if (!depctl.b.usbactep)
+    {
+        depctl.b.mps = ep->maxpacket;
+        depctl.b.eptype = ep->type;
+        depctl.b.txfnum = ep->tx_fifo_num;
+
+
+        depctl.b.setd0pid = 1;
+
+        depctl.b.usbactep = 1;
+
+        DWC_WRITE_REG32(addr, depctl.d32);
+    }
+    {
+
+        DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,0, daintmsk.d32);
+    }
+
+    ep->stall_clear_flag = 0;
+
+    return;
+}
+/**
+ * This function does the setup for a data transfer for an EP and
+ * starts the transfer. For an IN transfer, the packets will be
+ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
+ * the packets are unloaded from the Rx FIFO in the ISR.  the ISR.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to start the transfer on.
+ */
+
+void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+    depctl_data_t depctl;
+    deptsiz_data_t deptsiz;
+
+    if (ep->is_in == 1)
+    {
+        dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[ep->num];
+
+        depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
+        deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
+
+        if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
+            ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?\
+                            ep->maxxfer : (ep->total_len - ep->xfer_len);
+        else
+            ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?\
+                            MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
+
+
+        /* Zero Length Packet? */
+        if ((ep->xfer_len - ep->xfer_count) == 0)
+        {
+            deptsiz.b.xfersize = 0;
+            deptsiz.b.pktcnt = 1;
+        }
+        else
+        {
+            deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
+            deptsiz.b.pktcnt = (ep->xfer_len - ep->xfer_count - 1 + ep->maxpacket) / ep->maxpacket;
+			#if 0/*unsigned the max value is 1023*/
+            if (deptsiz.b.pktcnt > MAX_PKT_CNT)
+            {
+                deptsiz.b.pktcnt = MAX_PKT_CNT;
+                deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
+            }
+			#endif
+        }
+	
+		if((ep->xfer_len - ep->xfer_count)% ep->maxpacket== 0)
+		{
+		printf("sent_zlp = 1\n");
+		ep->sent_zlp = 1;
+		}
+
+        DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
+
+        if (ep->xfer_len > 0)
+        {
+            uint32_t fifoemptymsk = 0;
+            fifoemptymsk = 1 << ep->num;
+            DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+
+        }
+    
+        /* EP enable, IN data in FIFO */
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+        DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+#if SYNC_USB_CTRL
+        REG32(ARM_PORTA)=0x87;
+#endif
+
+    }
+    else
+    {
+        /* OUT endpoint */
+        dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[ep->num];
+
+        depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
+        deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
+
+
+        if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
+            ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ep->maxxfer : (ep->total_len - ep->xfer_len);
+        else
+            ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
+
+
+        if ((ep->xfer_len - ep->xfer_count) == 0)
+        {
+            deptsiz.b.xfersize = ep->maxpacket;
+            deptsiz.b.pktcnt = 1;
+        }
+        else
+        {
+            deptsiz.b.pktcnt = (ep->xfer_len - ep->xfer_count + (ep->maxpacket - 1)) / ep->maxpacket;
+			#if 0/*unsigned the max value is 1023*/
+            if (deptsiz.b.pktcnt > MAX_PKT_CNT)
+            {
+                deptsiz.b.pktcnt = MAX_PKT_CNT;
+            }
+			#endif
+            ep->xfer_len = deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
+            deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
+        }
+
+        {
+
+            DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+        }
+        /* EP enable */
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+
+        DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
+#if SYNC_USB_CTRL
+        REG32(ARM_PORTA)=0x76;
+#endif
+
+    }
+}
+
+/**
+ * This function setup a zero length transfer in Buffer DMA and
+ * Slave modes for usb requests with zero field set
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to start the transfer on.
+ *
+ */
+void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+
+    depctl_data_t depctl;
+    deptsiz_data_t deptsiz;
+
+    /* IN endpoint */
+    if (ep->is_in == 1)
+    {
+        dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[ep->num];
+
+        depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
+        deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
+
+        deptsiz.b.xfersize = 0;
+        deptsiz.b.pktcnt = 1;
+        {
+            DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
+            {
+                /* Enable the Tx FIFO Empty Interrupt for this EP */
+                if (ep->xfer_len > 0)
+                {
+                    uint32_t fifoemptymsk = 0;
+                    fifoemptymsk = 1 << ep->num;
+                    DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+                }
+            }
+        }
+
+        /* EP enable, IN data in FIFO */
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+        DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+
+    }
+    else
+    {
+        /* OUT endpoint */
+        dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[ep->num];
+
+        depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
+        deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
+
+        /* Zero Length Packet */
+        deptsiz.b.xfersize = ep->maxpacket;
+        deptsiz.b.pktcnt = 1;
+        {
+            DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+        }
+
+        /* EP enable */
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+
+        DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
+
+    }
+}
+
+/**
+ * This function does the setup for a data transfer for EP0 and starts
+ * the transfer.  For an IN transfer, the packets will be loaded into
+ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
+ * unloaded from the Rx FIFO in the ISR.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP0 data.
+ */
+void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+    depctl_data_t depctl;
+    deptsiz0_data_t deptsiz;
+    uint32_t fifoemptymsk;
+
+    ep->total_len = ep->xfer_len;
+
+    /* IN endpoint */
+    if (ep->is_in == 1)
+    {
+        printf("ep0 tx data\n");
+       dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[0];
+       depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
+       if (depctl.b.epena)
+           return;
+
+
+        /* If dedicated FIFO every time flush fifo before enable ep*/
+        dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
+
+        depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
+        deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
+
+        /* Zero Length Packet? */
+        if (ep->xfer_len == 0)
+        {
+            deptsiz.b.xfersize = 0;
+            deptsiz.b.pktcnt = 1;
+        }
+        else
+        {
+            /* Program the transfer size and packet count
+             *      as follows: xfersize = N * maxpacket +
+             *      short_packet pktcnt = N + (short_packet
+             *      exist ? 1 : 0)
+             */
+            if (ep->xfer_len > ep->maxpacket)
+            {
+                ep->xfer_len = ep->maxpacket;
+                deptsiz.b.xfersize = ep->maxpacket;
+            }
+            else
+            {
+                deptsiz.b.xfersize = ep->xfer_len;
+            }
+            deptsiz.b.pktcnt = 1;
+
+        }
+
+
+        {
+            DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
+        }
+
+        /* EP enable, IN data in FIFO */
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+        DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+
+        /**
+         * Enable the Non-Periodic Tx FIFO empty interrupt, the
+         * data will be written into the fifo by the ISR.
+         */
+
+      /* Enable the Tx FIFO Empty Interrupt for this EP */
+      if (ep->xfer_len > 0)
+      {
+          fifoemptymsk = 0;
+          fifoemptymsk |= 1 << ep->num;
+          DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+      }
+
+    }
+    else
+    {
+
+        /* OUT endpoint */
+        dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[0];
+
+        depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
+        deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
+
+        /* Program the transfer size and packet count as follows:
+         *      xfersize = N * (maxpacket + 4 - (maxpacket % 4))
+         *      pktcnt = N                                                                                      */
+        /* Zero Length Packet */
+        deptsiz.b.xfersize = ep->maxpacket;
+        deptsiz.b.pktcnt = 1;
+        deptsiz.b.supcnt = 3;
+        DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+
+        /* EP enable */
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+        DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
+
+    }
+}
+
+/**
+ * This function continues control IN transfers started by
+ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
+ * single packet.  NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
+ * bit for the packet count.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP0 data.
+ */
+void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+    depctl_data_t depctl;
+    deptsiz0_data_t deptsiz;
+
+    if (ep->is_in == 1)
+    {
+        dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[0];
+
+        depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
+        deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
+
+        deptsiz.b.xfersize = (ep->total_len - ep->xfer_count) > ep->maxpacket ? ep->maxpacket : (ep->total_len - ep->xfer_count);
+        deptsiz.b.pktcnt = 1;
+
+        ep->xfer_len += deptsiz.b.xfersize;
+
+        DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
+
+
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+        DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
+
+        /**
+         * Enable the Non-Periodic Tx FIFO empty interrupt, the
+         * data will be written into the fifo by the ISR.
+         */
+
+        /* Enable the Tx FIFO Empty Interrupt for this EP */
+        if (ep->xfer_len > 0)
+        {
+            uint32_t fifoemptymsk = 0;
+            fifoemptymsk |= 1 << ep->num;
+            DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
+        }
+
+    }
+    else
+    {
+        dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[0];
+
+        depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
+        deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
+
+        deptsiz.b.xfersize = ep->maxpacket;
+        deptsiz.b.pktcnt = 1;
+        DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
+        depctl.b.cnak = 1;
+        depctl.b.epena = 1;
+        DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
+
+    }
+}
+
+
+/**
+ * This function writes a packet into the Tx FIFO associated with the
+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written.  For
+ * periodic EPs the periodic Tx FIFO associated with the EP is written
+ * with all packets for the next micro-frame.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to write packet for.
+ * @param dma Indicates if DMA is being used.
+ */
+void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
+                             int dma)
+{
+    uint32_t i;
+    uint32_t byte_count;
+    uint32_t dword_count;
+    uint32_t *fifo;
+    uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
+
+    if (ep->xfer_count >= ep->xfer_len)
+    {
+        return;
+    }
+
+    /* Find the byte length of the packet either short packet or MPS */
+    if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket)
+    {
+        byte_count = ep->xfer_len - ep->xfer_count;
+    }
+    else
+    {
+        byte_count = ep->maxpacket;
+    }
+
+    /* Find the DWORD length, padded by extra bytes as neccessary if MPS
+     * is not a multiple of DWORD */
+    dword_count = (byte_count + 3) / 4;
+
+    /**@todo NGS Where are the Periodic Tx FIFO addresses
+     * intialized?	What should this be? */
+
+    fifo = core_if->data_fifo[ep->num];
+    for (i = 0; i < dword_count; i++, data_buff++)
+    {
+        DWC_WRITE_REG32(fifo, *data_buff);
+
+    }
+
+
+    ep->xfer_count += byte_count;
+    ep->xfer_buff += byte_count;
+}
+
+/**
+ * Set the EP STALL.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to set the stall on.
+ */
+void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+    depctl_data_t depctl;
+    volatile uint32_t *depctl_addr;
+    if (ep->is_in == 1)
+    {
+        depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
+        depctl.d32 = DWC_READ_REG32(depctl_addr);
+
+        /* set the disable and stall bits */
+        if (depctl.b.epena)
+        {
+            depctl.b.epdis = 1;
+        }
+        depctl.b.stall = 1;
+        DWC_WRITE_REG32(depctl_addr, depctl.d32);
+    }
+    else
+    {
+        depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
+        depctl.d32 = DWC_READ_REG32(depctl_addr);
+
+        depctl.b.stall = 1;
+        DWC_WRITE_REG32(depctl_addr, depctl.d32);
+    }
+
+    return;
+}
+
+/**
+ * Clear the EP STALL.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param ep The EP to clear stall from.
+ */
+void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
+{
+    depctl_data_t depctl;
+    volatile uint32_t *depctl_addr;
+
+    if (ep->is_in == 1)
+    {
+        depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
+    }
+    else
+    {
+        depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
+    }
+
+    depctl.d32 = DWC_READ_REG32(depctl_addr);
+
+    /* clear the stall bits */
+    depctl.b.stall = 0;
+
+    /*
+     * USB Spec 9.4.5: For endpoints using data toggle, regardless
+     * of whether an endpoint has the Halt feature set, a
+     * ClearFeature(ENDPOINT_HALT) request always results in the
+     * data toggle being reinitialized to DATA0.
+     */
+    if (ep->type == DWC_OTG_EP_TYPE_INTR ||
+            ep->type == DWC_OTG_EP_TYPE_BULK)
+    {
+        depctl.b.setd0pid = 1;	/* DATA0 */
+    }
+
+    DWC_WRITE_REG32(depctl_addr, depctl.d32);
+    return;
+}
+
+/**
+ * This function reads a packet from the Rx FIFO into the destination
+ * buffer. To read SETUP data use dwc_otg_read_setup_packet.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param dest	  Destination buffer for the packet.
+ * @param bytes  Number of bytes to copy to the destination.
+ */
+void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
+                         uint8_t * dest, uint16_t bytes)
+{
+    int i;
+    int word_count = (bytes + 3) / 4;
+
+    volatile uint32_t *fifo = core_if->data_fifo[0];
+    uint32_t *data_buff = (uint32_t *) dest;
+
+
+    for (i = 0; i < word_count; i++, data_buff++)
+    {
+        *data_buff = DWC_READ_REG32(fifo);
+    }
+
+    return;
+}
+
+/**
+ * Flush a Tx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    volatile grstctl_t greset;
+    int count = 0;
+    greset.d32 = 0;
+
+    greset.b.txfflsh = 1;
+    greset.b.txfnum = num;
+if(global.g_enum == NEED_ENUM)
+{
+    DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+			
+
+    do
+    {
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 10000)
+        {
+            break;
+        }
+        usdelay(10);
+    }
+    while (greset.b.txfflsh == 1);
+
+    /* Wait for 3 PHY Clocks */
+    usdelay(10);
+}
+
+}
+
+/**
+ * Flush Rx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    volatile grstctl_t greset;
+    int count = 0;
+    greset.d32 = 0;
+    greset.b.rxfflsh = 1;
+if(global.g_enum == NEED_ENUM)
+{
+    DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+
+    do
+    {
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 10000)
+        {
+            break;
+        }
+        usdelay(10);   
+     }
+    while (greset.b.rxfflsh == 1);
+
+    /* Wait for 3 PHY Clocks */
+
+    usdelay(10);
+}
+}
+
+/**
+ * Do core a soft reset of the core.  Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
+{
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    volatile grstctl_t greset;
+    int count = 0;
+    greset.d32 =0;
+    /* Wait for AHB master IDLE state. */
+    do
+    {
+        usdelay(10);
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 100000)
+        {
+            return;
+        }
+    }
+    while (greset.b.ahbidle == 0);
+
+    /* Core Soft Reset */
+    count = 0;
+    greset.b.csftrst = 1;
+    DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+    do
+    {
+        greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+        if (++count > 10000)
+        {
+            break;
+        }
+        usdelay(10);
+    }
+    while (greset.b.csftrst == 1);
+/* Wait for 3 PHY Clocks */
+    usdelay(10);
+}
+
+static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
+{
+    int i;
+    core_if->core_params = &global.g_core_params;
+    core_if->core_params->otg_cap = DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE;
+    #if !USE_ASIC
+    core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_ULPI;
+    #else
+    core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_UTMI;
+    #endif
+    core_if->core_params->speed = DWC_SPEED_PARAM_HIGH;//DWC_SPEED_PARAM_FULL
+    core_if->core_params->phy_ulpi_ddr = dwc_param_phy_ulpi_ddr_default;
+    core_if->core_params->phy_ulpi_ext_vbus = dwc_param_phy_ulpi_ext_vbus_default;
+    core_if->core_params->phy_utmi_width = 8;
+    core_if->core_params->ts_dline = dwc_param_ts_dline_default;
+    core_if->core_params->ulpi_fs_ls = dwc_param_ulpi_fs_ls_default;
+    core_if->core_params->en_multiple_tx_fifo = dwc_param_en_multiple_tx_fifo_default;
+    for (i = 0; i < 15; i++)
+    {
+       core_if->core_params->dev_tx_fifo_size[i] = dwc_param_dev_tx_fifo_size_default;
+    }
+    core_if->core_params->otg_ver = 1;
+    return 0;
+}
+
+
+
+
+
+
+
diff --git a/boot/common/src/loader/drivers/dwc_otg_cil.h b/boot/common/src/loader/drivers/dwc_otg_cil.h
new file mode 100644
index 0000000..1408175
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_cil.h
@@ -0,0 +1,404 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
+ * $Revision: #123 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+#if !defined(__DWC_CIL_H__)
+#define __DWC_CIL_H__
+
+#include "type.h"
+#include "dwc_otg_regs.h"
+
+#include "dwc_otg_core_if.h"
+
+//ÊÕ·¢»Øµ÷º¯ÊýµÄÔ­ÐÍ
+typedef void (*F_USB_CB)(WORD32 dwPara, WORD32 dwResult, WORD32 dwLen, WORD32 dwWantLen);
+
+
+/** Macros defined for DWC OTG HW Release version */
+
+#define OTG_CORE_REV_2_60a	0x4F54260A
+#define OTG_CORE_REV_2_94a	0x4F54294A
+/**
+ * The <code>dwc_ep</code> structure represents the state of a single
+ * endpoint when acting in device mode. It contains the data items
+ * needed for an endpoint to be activated and transfer packets.
+ */
+#define DWC_OTG_EP_TYPE_ISOC	       1
+#define DWC_OTG_EP_TYPE_BULK	       2
+#define DWC_OTG_EP_TYPE_INTR	       3
+
+typedef struct dwc_ep
+{
+    /** EP number used for register address lookup */
+    uint8_t num;
+    /** EP direction 0 = OUT */
+    unsigned is_in;//:1;
+    /** EP active. */
+    unsigned active;//:1;
+    /**
+     * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic
+     * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
+    unsigned tx_fifo_num;//:4;
+    /** EP type: 0 - Control, 1 - ISOC,	 2 - BULK,	3 - INTR */
+    unsigned type;//:2;
+    /** DATA start PID for INTR and BULK EP */
+    unsigned data_pid_start;//:1;
+    /** Frame (even/odd) for ISOC EP */
+    unsigned even_odd_frame;//:1;
+    /** Max Packet bytes */
+    unsigned maxpacket;//:11;
+
+    /** Max Transfer size */
+    uint32_t maxxfer;
+
+    F_USB_CB fnUsbCb;
+
+    void  *pPara;
+
+    uint8_t *start_xfer_buff;
+    /** pointer to the transfer buffer */
+    uint8_t *xfer_buff;
+    /** Number of bytes to transfer */
+    unsigned xfer_len;//:19;
+    /** Number of bytes transferred. */
+    unsigned xfer_count;//:19;
+    /** Sent ZLP */
+    unsigned sent_zlp;//:1;
+    /** Total len for control transfer */
+    unsigned total_len;//:19;
+
+    /** stall clear flag */
+    unsigned stall_clear_flag;//:1;
+
+    /** SETUP pkt cnt rollover flag for EP0 out*/
+    unsigned stp_rollover;
+
+} dwc_ep_t;
+
+/**
+ * The following parameters may be specified when starting the module. These
+ * parameters define how the DWC_otg controller should be configured.
+ */
+typedef struct dwc_otg_core_params
+{
+    /**
+     * Specifies the OTG capabilities. The driver will automatically
+     * detect the value for this parameter if none is specified.
+     * 0 - HNP and SRP capable (default)
+     * 1 - SRP Only capable
+     * 2 - No HNP/SRP capable
+     */
+    int32_t otg_cap;
+
+
+    /**
+     * Specifies the maximum speed of operation in host and device mode.
+     * The actual speed depends on the speed of the attached device and
+     * the value of phy_type. The actual speed depends on the speed of the
+     * attached device.
+     * 0 - High Speed (default)
+     * 1 - Full Speed
+     */
+    int32_t speed;
+
+    /**
+     * Specifies the type of PHY interface to use. By default, the driver
+     * will automatically detect the phy_type.
+     *
+     * 0 - Full Speed PHY
+     * 1 - UTMI+ (default)
+     * 2 - ULPI
+     */
+    int32_t phy_type;
+
+    /**
+     * Specifies the UTMI+ Data Width. This parameter is
+     * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
+     * PHY_TYPE, this parameter indicates the data width between
+     * the MAC and the ULPI Wrapper.) Also, this parameter is
+     * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
+     * to "8 and 16 bits", meaning that the core has been
+     * configured to work at either data path width.
+     *
+     * 8 or 16 bits (default 16)
+     */
+    int32_t phy_utmi_width;
+
+    /**
+     * Specifies whether the ULPI operates at double or single
+     * data rate. This parameter is only applicable if PHY_TYPE is
+     * ULPI.
+     *
+     * 0 - single data rate ULPI interface with 8 bit wide data
+     * bus (default)
+     * 1 - double data rate ULPI interface with 4 bit wide data
+     * bus
+     */
+    int32_t phy_ulpi_ddr;
+
+    /**
+     * Specifies whether to use the internal or external supply to
+     * drive the vbus with a ULPI phy.
+     */
+    int32_t phy_ulpi_ext_vbus;
+
+    int32_t ulpi_fs_ls;
+
+    int32_t ts_dline;
+
+    /**
+     * Specifies whether dedicated transmit FIFOs are
+     * enabled for non periodic IN endpoints in device mode
+     * 0 - No
+     * 1 - Yes
+     */
+    int32_t en_multiple_tx_fifo;
+
+    /** Number of 4-byte words in each of the Tx FIFOs in device
+     * mode when dynamic FIFO sizing is enabled.
+     * 4 to 768 (default 256)
+     */
+    uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
+
+    /** Thresholding enable flag-
+     * bit 0 - enable non-ISO Tx thresholding
+     * bit 1 - enable ISO Tx thresholding
+     * bit 2 - enable Rx thresholding
+     */
+    //uint32_t thr_ctl;
+
+    /** Thresholding length for Tx
+     *	FIFOs in 32 bit DWORDs
+     */
+    //uint32_t tx_thr_length;
+
+    /** Thresholding length for Rx
+     *	FIFOs in 32 bit DWORDs
+     */
+    //uint32_t rx_thr_length;
+
+
+    /** Per Transfer Interrupt
+     *	mode enable flag
+     * 1 - Enabled
+     * 0 - Disabled
+     */
+    int32_t pti_enable;
+
+
+    /** HFIR Reload Control
+     * 0 - The HFIR cannot be reloaded dynamically.
+     * 1 - Allow dynamic reloading of the HFIR register during runtime.
+     */
+    //int32_t reload_ctl;
+    /** DCFG: Enable device Out NAK
+     * 0 - The core does not set NAK after Bulk Out transfer complete.
+     * 1 - The core sets NAK after Bulk OUT transfer complete.
+     */
+    int32_t dev_out_nak;
+
+
+    /** OTG revision supported
+     * 0 - OTG 1.3 revision
+     * 1 - OTG 2.0 revision
+     */
+    int32_t otg_ver;
+
+} dwc_otg_core_params_t;
+/**
+ * The <code>dwc_otg_core_if</code> structure contains information needed to manage
+ * the DWC_otg controller acting in either host or device mode. It
+ * represents the programming view of the controller as a whole.
+ */
+#define DWC_OTG_PCGCCTL_OFFSET 0xE00
+#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
+#define DWC_OTG_DATA_FIFO_SIZE 0x1000
+#define A_HOST		(1)
+#define A_SUSPEND	(2)
+#define A_PERIPHERAL	(3)
+#define B_PERIPHERAL	(4)
+#define B_HOST		(5)
+
+struct dwc_otg_core_if
+{
+    dwc_otg_core_params_t *core_params;
+
+    dwc_otg_core_global_regs_t *core_global_regs;
+
+    dwc_otg_dev_if_t *dev_if;
+    uint8_t phy_init_done;
+
+
+    volatile uint32_t *pcgcctl;
+
+    uint32_t *data_fifo[MAX_EPS_CHANNELS];
+
+    uint16_t total_fifo_size;
+    uint16_t rx_fifo_size;
+    uint16_t nperio_tx_fifo_size;
+
+    uint8_t pti_enh_enable;
+
+    uint8_t multiproc_int_enable;
+
+    uint8_t en_multiple_tx_fifo;
+
+    hwcfg1_data_t hwcfg1;
+    hwcfg2_data_t hwcfg2;
+    hwcfg3_data_t hwcfg3;
+    hwcfg4_data_t hwcfg4;
+    fifosize_data_t hptxfsiz;
+    dcfg_data_t dcfg;
+
+    uint32_t otg_ver;
+
+};
+
+extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
+
+extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
+                                          uint32_t * _dest);
+extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
+extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
+extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
+                                          dwc_ep_t * _ep);
+extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
+            dwc_ep_t * _ep);
+extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
+                                           dwc_ep_t * _ep);
+extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
+            dwc_ep_t * _ep);
+extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
+                                        dwc_ep_t * _ep, int _dma);
+extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
+extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
+                                       dwc_ep_t * _ep);
+extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
+
+void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
+
+
+extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
+                                    uint8_t * dest, uint16_t bytes);
+
+extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
+extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
+extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
+
+/**
+ * This function returns the Core Interrupt register.
+ */
+static uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
+{
+    return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
+            DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
+}
+
+
+/**
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the IN endpoint interrupt bits.
+ */
+static uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
+        core_if)
+{
+
+    uint32_t v;
+    {
+        v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
+            DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
+    }
+    return (v & 0xffff);
+}
+
+/**
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the OUT endpoint interrupt bits.
+ */
+static uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
+        core_if)
+{
+    uint32_t v;
+
+    {
+        v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
+            DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
+    }
+
+    return ((v & 0xffff0000) >> 16);
+}
+
+/**
+ * This function returns the Device IN EP Interrupt register
+ */
+static  uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
+        dwc_ep_t * ep)
+{
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    uint32_t v, msk, emp;
+
+    {
+        msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
+        emp = DWC_READ_REG32(&dev_if->dev_global_regs->dtknqr4_fifoemptymsk);
+        msk |= ((emp >> ep->num) & 0x1) << 7;
+        v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
+    }
+
+    return v;
+}
+
+/**
+ * This function returns the Device OUT EP Interrupt register
+ */
+static uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *_core_if, dwc_ep_t * _ep)
+{
+    dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
+    uint32_t v;
+    doepmsk_data_t msk;
+    msk.d32 = 0;
+    {
+        msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
+        if (_core_if->pti_enh_enable)
+        {
+            msk.b.pktdrpsts = 1;
+        }
+        v = DWC_READ_REG32(&dev_if->out_ep_regs[_ep->num]->doepint) & msk.d32;
+    }
+    return v;
+}
+
+static  uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
+{
+    return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);
+}
+
+#endif
diff --git a/boot/common/src/loader/drivers/dwc_otg_cil_intr.c b/boot/common/src/loader/drivers/dwc_otg_cil_intr.c
new file mode 100644
index 0000000..b52b083
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_cil_intr.c
@@ -0,0 +1,69 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
+ * $Revision: #32 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+/** @file
+ *
+ * The Core Interface Layer provides basic services for accessing and
+ * managing the DWC_otg hardware. These services are used by both the
+ * Host Controller Driver and the Peripheral Controller Driver.
+ *
+ * This file contains the Common Interrupt handlers.
+ */
+
+#include "dwc_otg_regs.h"
+#include "dwc_otg_cil.h"
+#include "dwc_otg_driver.h"
+#include "dwc_otg_pcd.h"
+/**
+ * This interrupt indicates that SUSPEND state has been detected on
+ * the USB.
+ *
+ * For HNP the USB Suspend interrupt signals the change from
+ * "a_peripheral" to "a_host".
+ *
+ * When power management is enabled the core will be put in low power
+ * mode.
+ */
+int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
+{
+    gintsts_data_t gintsts;
+    printf("S\n");
+  
+    /* Clear interrupt */
+    gintsts.d32 = 0;
+    gintsts.b.usbsuspend = 1;
+    DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
+
+    return 1;
+}
+
diff --git a/boot/common/src/loader/drivers/dwc_otg_core_if.h b/boot/common/src/loader/drivers/dwc_otg_core_if.h
new file mode 100644
index 0000000..4a17de0
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_core_if.h
@@ -0,0 +1,109 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
+ * $Revision: #13 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+#if !defined(__DWC_CORE_IF_H__)
+#define __DWC_CORE_IF_H__
+#include <common.h>
+struct dwc_otg_core_if;
+typedef struct dwc_otg_core_if dwc_otg_core_if_t;
+
+#define DWC_E_NOT_SUPPORTED	1004
+#define DWC_E_INVALID		    1001
+#define DWC_E_NO_MEMORY		1002
+#define DWC_E_NO_DEVICE		1003
+#define DWC_E_SHUTDOWN		    1010
+
+/** Maximum number of Periodic FIFOs */
+#define MAX_TX_FIFOS 15
+
+/** Maximum number of Endpoints/HostChannels */
+#define MAX_EPS_CHANNELS 3
+
+extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
+extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
+
+#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
+#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
+#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
+#define dwc_param_opt_default 1
+#define dwc_param_dma_enable_default 1
+#define dwc_param_dma_desc_enable_default 1
+#define dwc_param_dma_burst_size_default 32
+#define dwc_param_speed_default 0
+#define DWC_SPEED_PARAM_HIGH 0
+#define DWC_SPEED_PARAM_FULL 1
+#define dwc_param_host_support_fs_ls_low_power_default 0
+#define dwc_param_host_ls_low_power_phy_clk_default 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
+#define dwc_param_enable_dynamic_fifo_default 1
+#define dwc_param_data_fifo_size_default 8192
+#define dwc_param_dev_rx_fifo_size_default 1064
+#define dwc_param_dev_nperio_tx_fifo_size_default 1024
+#define dwc_param_dev_perio_tx_fifo_size_default 256
+#define dwc_param_host_rx_fifo_size_default 1024
+#define dwc_param_host_nperio_tx_fifo_size_default 1024
+#define dwc_param_host_perio_tx_fifo_size_default 1024
+#define dwc_param_max_transfer_size_default 65535
+#define dwc_param_max_packet_count_default 511
+#define dwc_param_host_channels_default 12
+#define dwc_param_dev_endpoints_default 6
+#define DWC_PHY_TYPE_PARAM_FS 0
+#define DWC_PHY_TYPE_PARAM_UTMI 1
+#define DWC_PHY_TYPE_PARAM_ULPI 2
+#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
+#define dwc_param_phy_utmi_width_default 16
+#define dwc_param_phy_ulpi_ddr_default 0
+#define DWC_PHY_ULPI_INTERNAL_VBUS 0
+#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
+#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
+#define dwc_param_i2c_enable_default 0
+#define dwc_param_ulpi_fs_ls_default 0
+#define dwc_param_ts_dline_default 0
+#define dwc_param_en_multiple_tx_fifo_default 1
+#define dwc_param_dev_tx_fifo_size_default 768
+#define dwc_param_thr_ctl_default 0
+#define dwc_param_tx_thr_length_default 64
+#define dwc_param_rx_thr_length_default 64
+#define dwc_param_lpm_enable_default 1
+#define dwc_param_pti_enable_default 0
+#define dwc_param_mpi_enable_default 0
+#define dwc_param_adp_enable_default 0
+#define dwc_param_ic_usb_cap_default 0
+#define dwc_param_ahb_thr_ratio_default 0
+#define dwc_param_power_down_default 0
+#define dwc_param_reload_ctl_default 0
+#define dwc_param_dev_out_nak_default 0
+#define dwc_param_cont_on_bna_default 0
+#define dwc_param_ahb_single_default 0
+
+#endif /* __DWC_CORE_IF_H__ */
diff --git a/boot/common/src/loader/drivers/dwc_otg_dev_test.c b/boot/common/src/loader/drivers/dwc_otg_dev_test.c
new file mode 100644
index 0000000..a9d4968
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_dev_test.c
@@ -0,0 +1,521 @@
+/******************************************************************/

+#include "global.h"

+#include "dwc_otg_driver.h"

+#include "config.h"

+

+

+void USB_isr(WORD32 dwIntNo,WORD32 dwPara)

+{

+    dwc_otg_pcd_handle_intr(global.g_dwc_otg_dev_t.pcd);

+

+}

+void USB_TstDev_InitEnv(void)

+{

+#if USE_ASIC

+    WORD32 i;

+    if(0 == global.g_USB_MODE)

+    {

+

+    //ÊÍ·ÅUSB¸ôÀë8bit for usb ctrl

+    	REG32(POWER_DOMAIN_ISO) |= (1<<8);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_RST) |= (1<<8);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_POWERON) &= ~(1<<8);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_POWERON) |= (1<<8);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_RST) &= ~(1<<8);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_ISO) &= ~(1<<8);

+		usdelay(10);

+

+          //usb  ahb clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<4);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<4);

+        //usb  phy clock enable

+        REG32(SOC_MOD_CLKEN1)&=~(1<<3);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN1)|=(1<<3);

+

+        // usb  ahb reset  ÏÈ×ÜÏߺó¹¤×÷

+        REG32(SOC_MOD_RSTEN)&=~(1<<5);

+        usdelay(100);

+        REG32(SOC_MOD_RSTEN)|=(1<<5);

+        usdelay(100);

+

+        // usb  work reset

+        REG32(SOC_MOD_RSTEN)&=~(1<<4);

+        usdelay(100);

+        REG32(SOC_MOD_RSTEN)|=(1<<4);

+		usdelay(100);

+

+        //release usb  phy reset 

+        REG32(SOC_MOD_RSTEN)&=~(1<<3);

+        usdelay(100);

+        REG32(SOC_MOD_RSTEN) |= 1<<3;

+        usdelay(100);

+		

+        i = 0;

+        while((REG32(SOC_MOD_USBSTATECTRL)&0x2) == 0)

+        {

+             i++;

+             usdelay(20);

+             if(i>50000) break;

+        }

+     }

+    else

+    {

+        //ÊÍ·ÅUSB_HSIC¸ôÀë9bit for hsic

+    	REG32(POWER_DOMAIN_ISO) |= (1<<9);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_RST) |= (1<<9);

+		usdelay(10);

+

+		REG32(POWER_DOMAIN_POWERON) &= ~(1<<9);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_POWERON) |= (1<<9);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_RST) &= ~(1<<9);

+		usdelay(10);

+		

+		REG32(POWER_DOMAIN_ISO) &= ~(1<<9);

+		usdelay(10);

+

+        //usb hsic ahb clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<2);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<2);

+        //usb hsic phy clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<1);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<1);

+

+        //usb hsic 480M clock enable

+        REG32(SOC_MOD_CLKEN0)&=~(1<<0);

+        usdelay(20);

+        REG32(SOC_MOD_CLKEN0)|=(1<<0);

+

+        // usb hsic ahb reset

+        REG32(SOC_MOD_RSTEN)&=~(1<<2);

+        usdelay(20);

+        REG32(SOC_MOD_RSTEN)|=(1<<2);

+        usdelay(10);

+

+        // usb hsic work reset

+        REG32(SOC_MOD_RSTEN)&=~(1<<1);

+        usdelay(20);

+        REG32(SOC_MOD_RSTEN)|=(1<<1);

+        //release usb hsic phy reset 

+        REG32(SOC_MOD_RSTEN)&=~(1<<0);

+        usdelay(20);

+        REG32(SOC_MOD_RSTEN)|=(1<<0);

+

+        usdelay(100);

+        i = 0;

+        while((REG32(SOC_MOD_USBSTATECTRL)&0x1) == 0)

+        {

+            i++;

+            usdelay(20);

+            if(i>50000) break;  

+        }

+

+#if SYNC_USB_HSIC

+        usdelay(20);

+		REG32(REG_GPIO_OUT)=1;

+        while(REG32(REG_GPIO_IN)!=0xFF);

+		usdelay(1);

+		REG32(REG_GPIO_OUT)=0;		

+#endif

+    }

+#endif  

+#if !USE_ASIC

+//usb power on

+    REG32(POWER_DOMAIN_POWERON) |= 0x22000;

+    usdelay(10);

+//usb disable reset 

+    REG32(POWER_DOMAIN_RST) &= 0xfffddfff;

+    usdelay(10);

+//usb disable iso 

+    REG32(POWER_DOMAIN_ISO) &= 0xfffddfff;

+    usdelay(10);

+

+//open usb0 and usb1

+    //usb ahb clock enable

+    REG32(SOC_MOD_CLKEN0)&=0xeffffffb;

+    usdelay(20);

+    REG32(SOC_MOD_CLKEN0)|=0x10000004;

+    //usb phy clock enable

+    REG32(SOC_MOD_CLKEN1)&=~(3<<16);

+    usdelay(20);

+    REG32(SOC_MOD_CLKEN1)|=(3<<16);

+

+

+    // usb ctr reset

+    REG32(SOC_MOD_RSTEN)&=0xeffffff7;

+    usdelay(20);

+    REG32(SOC_MOD_RSTEN)|=0x10000008;

+

+    // usb ahb reset

+    REG32(SOC_MOD_RSTEN)&=0xf7fffffb;

+    usdelay(20);

+    REG32(SOC_MOD_RSTEN)|=0x8000004;

+/*    

+  usb ctr and ahb reset release ,delay 60us, check usb reset state,

+  if the reset state is 0, reset ,if 1,reset release.

+*/

+#endif

+}

+

+void USB_TstDev_Isr(void)

+{

+        USB_isr(0,0);    //´¦ÀíÖжϷþÎñ

+}

+T_USB_ENUM USB_Need_Enum(WORD32 USB_ADDR)

+{

+	WORD32 temp = 0;

+	temp = DWC_READ_REG32(USB_ADDR+0x14);

+	if(((temp>>13)|1)==1)

+	{

+		return DONOT_NEED_ENUM;

+	}

+	return NEED_ENUM;

+}

+unsigned int g_testVal = 0;

+

+WORD32 USB_CDC_Enum(WORD32 USB_ADDR)

+{

+	WORD32 dwCount=0;

+	WORD32 dwCount1=0;

+	if(NEED_ENUM == global.g_enum)

+	{

+		global.g_Connet = 0;

+	}

+	else

+	{

+        	global.g_Connet = 1;

+	}

+

+	global.g_USB_TIMEOUT	= 10;

+

+	g_testVal = 20/5;

+	dwc_otg_driver_probe(USB_ADDR);

+	if(global.g_enum == NEED_ENUM)

+	{

+	while (1)

+	{

+	//poll mode or interrupt mode

+		USB_TstDev_Isr();

+#if SYNC_SETADDRESS

+	    if (global.g_dwc_otg_dev_t.pcd->request_config == 2)

+	    break;

+#else

+	    //µÈ´ý½øÈëÅäÖÃ̬

+		if (global.g_dwc_otg_dev_t.pcd->request_config == 1)

+			break;

+#endif

+/* µ±usb_mode =1ʱ£¬ÓÃÓÚHSIC,µ±usb_mode =0ʱ£¬ÓÃÓÚUSB */

+	    if(global.g_USB_MODE == 0)

+        {

+		    if(0==global.g_Connet)

+	        {

+			   dwCount++;

+#if SIM_EN

+			   //usdelay(5000);

+#else

+               usdelay(1);

+#endif

+			   if(dwCount>(400*global.g_USB_TIMEOUT))

+			   {

+				   //return 1;

+			   }

+		    }

+#if SYNC_SETADDRESS            

+	        else if(global.g_dwc_otg_dev_t.pcd->request_config == 2)

+#else

+            else if(global.g_dwc_otg_dev_t.pcd->request_config == 1)

+#endif

+	        {

+	        	break;

+	        }

+		    else

+		    {

+			    dwCount1++;

+#if SIM_EN

+			    //usdelay(5000);

+#else

+                usdelay(1);

+#endif

+			    if(dwCount1>(200*global.g_USB_TIMEOUT))

+			    {

+				    //return 1;  huhuahong

+			    }

+	        }

+        }

+     }

+		}

+     return 0;

+}

+

+void Out_callback( WORD32 dwPara, WORD32 dwCause, WORD32 dwDone, WORD32 dwLen)

+{

+         printf("Out_callback\n");

+	*((WORD32 *)dwPara) = dwDone;

+	global.dwRxQuit	= 1;

+#if SYNC_USB_CTRL

+    REG32(ARM_PORTA)=0x77;

+#endif

+

+}

+

+void In_callback( WORD32 dwPara, WORD32 dwCause, WORD32 dwDone, WORD32 dwLen)

+{

+	*((WORD32 *)dwPara) = dwDone;

+	global.dwTxQuit	= 1;

+#if SYNC_USB_CTRL

+        REG32(ARM_PORTA)=0x88;

+#endif

+}

+

+WORD32 USB_RecvOutData(WORD32 dwEPNo, BYTE *pchBuf, WORD32 dwLen, F_USB_CB fnUsbCb, void *pPara)

+{

+    dwc_otg_pcd_ep_t *ep = NULL;

+    ep = &(global.g_dwc_otg_dev_t.pcd->out_ep[dwEPNo-1]);

+    ep->dwc_ep.is_in = 0;

+    ep->dwc_ep.num = dwEPNo;

+    ep->dwc_ep.data_pid_start = 0;

+    ep->dwc_ep.tx_fifo_num = dwEPNo;

+    ep->dwc_ep.start_xfer_buff = pchBuf;

+    ep->dwc_ep.xfer_buff = pchBuf;

+    ep->dwc_ep.xfer_len = 0;

+    ep->dwc_ep.xfer_count = 0;

+    ep->dwc_ep.fnUsbCb = fnUsbCb;

+    ep->dwc_ep.pPara = pPara;

+    ep->dwc_ep.total_len = dwLen;

+    dwc_otg_ep_start_transfer(global.g_dwc_otg_dev_t.core_if,&ep->dwc_ep);

+    return 0;

+}

+

+WORD32 USB_SendInData(WORD32 dwEPNo, BYTE *pchBuf, WORD32 dwLen, F_USB_CB fnUsbCb, void *pPara)

+{

+    dwc_otg_pcd_ep_t *ep = NULL;

+    ep = &(global.g_dwc_otg_dev_t.pcd->in_ep[dwEPNo-1]);

+    ep->dwc_ep.is_in = 1;

+    ep->dwc_ep.num = dwEPNo;

+    ep->dwc_ep.data_pid_start = 0;

+    ep->dwc_ep.tx_fifo_num = dwEPNo;

+    ep->dwc_ep.start_xfer_buff = pchBuf;

+    ep->dwc_ep.xfer_buff = pchBuf;

+    ep->dwc_ep.fnUsbCb = fnUsbCb;

+    ep->dwc_ep.pPara = pPara;

+    ep->dwc_ep.xfer_len = 0;

+    ep->dwc_ep.xfer_count = 0;

+    ep->dwc_ep.total_len = dwLen;

+    dwc_otg_ep_start_transfer(global.g_dwc_otg_dev_t.core_if,&ep->dwc_ep);

+    return 0;

+}

+

+WORD32 usb_read(BYTE *pchBuf,WORD32 dwLen)

+{

+	WORD32 dwDone;

+

+	global.dwRxQuit=0;

+

+	USB_RecvOutData( 1,(BYTE *)pchBuf,dwLen,Out_callback,(void *)&dwDone);

+

+	while(!global.dwRxQuit)

+	{

+        USB_TstDev_Isr();

+	}

+

+	return dwDone;

+}

+

+WORD32 USB_Check_Sync(BYTE *pchBuf, WORD32 dwLen)

+{

+	WORD32 dwDone;

+	WORD32 dwCount = 0;

+

+	global.dwRxQuit=0;

+	USB_RecvOutData( 1,(BYTE *)pchBuf,dwLen,Out_callback,(void *)&dwDone);

+	dwCount=0;

+	while(1)

+	{

+        USB_TstDev_Isr();

+		if(0==global.dwRxQuit)

+		{

+			dwCount++;

+			if(dwCount>(200*global.g_USB_TIMEOUT))

+			{

+				//return 0;

+			}

+#if SIM_EN

+        	//usdelay(5000);

+#else

+            usdelay(1);

+#endif

+		}

+		else

+		{

+			break;

+		}

+	}

+

+	if(0x5A!=*pchBuf)

+	{

+		return 0;

+	}

+

+	return dwDone;

+}

+WORD32 usb_write(BYTE *pchBuf,WORD32 dwLen)

+{

+	WORD32 dwDone;

+

+	global.dwTxQuit=0;

+

+	USB_SendInData(1,pchBuf, dwLen, In_callback,(void *)&dwDone);

+

+	while(!global.dwTxQuit)

+	{

+    		USB_TstDev_Isr();

+	}

+

+	return dwDone;

+}

+

+int dwc_otg_driver_probe(WORD32 USB_ADDR)

+{

+    uint32_t udj = 0;

+    uint32_t *ptbase = (uint32_t *)USB_ADDR;

+    uint8_t* ptg_dwc_otg_dev_t = (uint8_t* )(&global.g_dwc_otg_dev_t);

+    for(udj= 0;udj<sizeof(global.g_dwc_otg_dev_t);udj++)

+    {

+       ptg_dwc_otg_dev_t[udj] = 0;

+    }

+

+    global.g_dwc_otg_dev_t.core_if = dwc_otg_cil_init(ptbase);

+

+    /*

+    * Initialize the DWC_otg core.

+    */

+	dwc_otg_core_init(global.g_dwc_otg_dev_t.core_if);

+ 

+#if SYNC_USB_CTRL

+    REG32(ARM_PORTA)=0x11;

+#endif

+    /*

+     * Initialize the PCD,½«pcd_initÕª³öÀ´

+     */

+    global.g_dwc_otg_dev_t.pcd = dwc_otg_pcd_init(global.g_dwc_otg_dev_t.core_if);

+

+#if SYNC_USB_CTRL

+    REG32(ARM_PORTA)=0x22; 

+#endif

+#if SYNC_USB_HSIC

+	//for hsic

+	REG32(REG_GPIO_OUT)=2;

+	while(REG32(REG_GPIO_IN)!=0xFF);

+	usdelay(1);

+	REG32(REG_GPIO_OUT)=0;

+#endif

+	global.g_dwc_otg_dev_t.pcd->otg_dev = (&global.g_dwc_otg_dev_t);

+	if(global.g_enum == NEED_ENUM)

+	{

+		DWC_MODIFY_REG32(&global.g_dwc_otg_dev_t.core_if->core_global_regs->gahbcfg, 0, 1);

+	}

+	return 0;

+}

+static inline void delay(unsigned long loops)

+{

+    /*

+	__asm__ volatile ("1:\n" "subs %0, %1, #1\n"

+			  "bne 1b":"=r" (loops):"0"(loops));

+	*/

+}

+static inline void udelay(unsigned long us)

+{

+	delay(us * 200); /* approximate */

+}

+

+#if 0

+void usdelay(unsigned us)

+{

+	udelay(us);

+}

+#endif

+extern  void ep0_out_start(dwc_otg_core_if_t * core_if,dwc_otg_pcd_t * pcd);

+extern void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep);

+extern void active_allep(dwc_otg_pcd_t * pcd);

+typedef struct usb_record

+{

+	WORD32 address;

+	WORD32 value;

+

+}T_usb_record;

+T_usb_record usb_record[1000];

+WORD32 index = 0;

+

+void usb_printf (WORD32 *address)

+{

+		usb_record[index].address = (WORD32)address;

+		usb_record[index].value = *address;

+		index = (index+1)%1000;

+		

+}

+

+static inline BYTE get_boot_mode(void)

+{

+	return (*(WORD32*)SYS_BOOTSEL_BASE &0x3);

+}

+

+int tsp_usb_init(void)

+{

+	WORD32 retVal = 0;

+	WORD32 usb_addr = 0;

+	BYTE boot_mode = get_boot_mode();

+	data_init();

+	/*add by sunyunchen*/

+	if(2 == boot_mode)

+	{

+		printf("hsic\n");

+		global.g_USB_MODE = 1;

+	    usb_addr = SYS_USB_HSIC_BASE;

+	}

+	else 

+	{

+		printf("usb\n");

+		global.g_USB_MODE = 0;

+        usb_addr = SYS_USB_BASE;

+	}

+	if((REG32(usb_addr+DWC_DEV_GLOBAL_REG_OFFSET)&0x7f0)!=0)//dcfg register

+	{

+		global.g_enum =DONOT_NEED_ENUM; 

+	}

+	if(NEED_ENUM == global.g_enum)

+	{

+	         USB_TstDev_InitEnv();

+	}

+	else

+	{

+		global.g_dwc_otg_pcd_tp.ep0state = EP0_IDLE;

+		global.dwRxQuit = 1;

+		global.dwTxQuit = 1;

+		global.g_dwc_otg_pcd_tp.request_config = 1;		

+	}

+

+	retVal = USB_CDC_Enum(usb_addr);

+	

+	return retVal;

+}

+

+

diff --git a/boot/common/src/loader/drivers/dwc_otg_driver.h b/boot/common/src/loader/drivers/dwc_otg_driver.h
new file mode 100644
index 0000000..c11e537
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_driver.h
@@ -0,0 +1,74 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
+ * $Revision: #19 $
+ * $Date: 2010/11/15 $
+ * $Change: 1627671 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+#ifndef __DWC_OTG_DRIVER_H__
+#define __DWC_OTG_DRIVER_H__
+
+
+
+
+#define   DWC_DEVICE_ONLY
+#define   DEV_FIRST
+/** @file
+ * This file contains the interface to the Linux driver.
+ */
+
+#include "usb.h"
+#include "dwc_otg_core_if.h"
+#include "dwc_otg_pcd.h"
+
+
+/* Type declarations */
+struct dwc_otg_pcd;
+/**
+ * This structure is a wrapper that encapsulates the driver components used to
+ * manage a single DWC_otg controller.
+ */
+typedef struct dwc_otg_device
+{
+
+    /** Pointer to the core interface structure. */
+    dwc_otg_core_if_t *core_if;
+
+    /** Pointer to the PCD structure. */
+    struct dwc_otg_pcd *pcd;
+
+} dwc_otg_device_t;
+
+
+
+
+int dwc_otg_driver_probe(WORD32 USB_ADDR);
+
+
+#endif
diff --git a/boot/common/src/loader/drivers/dwc_otg_pcd.c b/boot/common/src/loader/drivers/dwc_otg_pcd.c
new file mode 100644
index 0000000..74d6adb
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_pcd.c
@@ -0,0 +1,338 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
+ * $Revision: #101 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+#ifndef DWC_HOST_ONLY
+
+/** @file
+ * This file implements PCD Core. All code in this file is portable and doesn't
+ * use any OS specific functions.
+ * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
+ * header file, which can be used to implement OS specific PCD interface.
+ *
+ * An important function of the PCD is managing interrupts generated
+ * by the DWC_otg controller. The implementation of the DWC_otg device
+ * mode interrupt service routines is in dwc_otg_pcd_intr.c.
+ *
+ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
+ * @todo Does it work when the request size is greater than DEPTSIZ
+ * transfer size
+ *
+ */
+#include "global.h"
+#include "dwc_otg_pcd.h"
+
+__align(4) const dwc_device_descriptor_t  device_desc =
+{
+    sizeof(dwc_device_descriptor_t),
+    DEVICE_DESCRIPTOR,
+    0x0200, 			// usb 2.0   //usb 1.1
+    0x00,
+    0x00,
+    0x00,
+    CONTROL_64,			// ×î´ó°ü8×Ö½Ú
+    USB_VENDOR_ID,
+    USB_PRODUCT_ID,
+    PRODUCT_RELEASE_NUMBER,
+    0x01,               // manufacturer descriptionË÷ÒýºÅ
+    0x02,               // product descriptionË÷ÒýºÅ
+    0x03,               // serial number descriptionË÷ÒýºÅ
+    0x01                // ÅäÖÃÊý
+};
+
+__align(4) const dwc_dev_qual_descriptor_t  dev_qual_desc =
+{
+    sizeof(dwc_dev_qual_descriptor_t),
+    0x06,
+    0x0200,                      // usb 2.0
+    VERDOR_SPECIFIC,
+    0x00,
+    0x00,
+    64,
+    0x01,                      // ÅäÖÃÊý
+    0x0
+};
+
+
+
+__align(4) const dwc_langid_descriptor_t    tLanguage=
+{
+    STRING_DESCRIPTOR_SIZE(1),
+    STRING_DESCRIPTOR,
+    LANGID_US_ENGLISH
+};
+
+__align(4) const dwc_string_descriptor_t    tManufacture=
+{
+    STRING_DESCRIPTOR_SIZE(11),
+    STRING_DESCRIPTOR,
+    UNICODE('Z'), UNICODE('T'), UNICODE('E'), UNICODE(' '), UNICODE('C'),
+    UNICODE('o'), UNICODE(','), UNICODE('L'), UNICODE('t'), UNICODE('d'),
+    UNICODE('.'),
+};
+
+__align(4) const dwc_string_descriptor_t    tProduct=
+{
+	STRING_DESCRIPTOR_SIZE(14),
+	STRING_DESCRIPTOR,
+	UNICODE('Z'), UNICODE('T'), UNICODE('E'), UNICODE(' '), UNICODE('B'),
+	UNICODE('o'), UNICODE('o'), UNICODE('t'), UNICODE('L'), UNICODE('o'),
+	UNICODE('a'), UNICODE('d'), UNICODE('e'), UNICODE('r')
+};
+
+__align(4) const dwc_string_descriptor_t    tSN=
+{
+	STRING_DESCRIPTOR_SIZE(16),
+	STRING_DESCRIPTOR,
+	UNICODE('z'), UNICODE('t'), UNICODE('e'), UNICODE('&'), UNICODE('u'),
+	UNICODE('s'), UNICODE('b'), UNICODE('B'), UNICODE('o'), UNICODE('o'),
+	UNICODE('t'), UNICODE('l'), UNICODE('o'), UNICODE('d'), UNICODE('e'),
+	UNICODE('r')
+};
+
+__align(4) const dwc_string_descriptor_t	tIfc0Name=
+    {
+        STRING_DESCRIPTOR_SIZE(9),
+        STRING_DESCRIPTOR,
+        UNICODE('B'), UNICODE('o'), UNICODE('o'), UNICODE('t'), UNICODE('l'),
+        UNICODE('o'), UNICODE('d'), UNICODE('e'), UNICODE('r')
+    };
+
+__align(4) const dwc_string_descriptor_t	tIfc1Name=
+    {
+        STRING_DESCRIPTOR_SIZE(6),
+        STRING_DESCRIPTOR,
+        UNICODE('S'), UNICODE('e'), UNICODE('r'), UNICODE('i'), UNICODE('a'),
+        UNICODE('l')
+    };
+
+__align(4) const dwc_string_descriptor_t * const pStrDescIdx[]=
+{
+	(dwc_string_descriptor_t *)(&tLanguage),
+	(dwc_string_descriptor_t *)&tManufacture,
+	(dwc_string_descriptor_t *)&tProduct,
+	(dwc_string_descriptor_t *)&tSN,
+	(dwc_string_descriptor_t *)&tIfc0Name,
+	(dwc_string_descriptor_t *)&tIfc1Name,
+};
+
+
+static  void  do_get_descriptor(dwc_otg_pcd_t * pcd,uint32_t *buff,uint32_t len)
+{
+
+    dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+    pcd->ep0_pending = 1;
+    ep0->dwc_ep.start_xfer_buff =(uint8_t*) buff;
+    ep0->dwc_ep.xfer_buff =(uint8_t*)buff;
+    ep0->dwc_ep.xfer_len = len;
+    ep0->dwc_ep.xfer_count = 0;
+    ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
+    dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+
+}
+
+extern void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val);
+
+int  dwc_setup(dwc_otg_pcd_t * pcd,  usb_device_request_t * ctrl)
+{
+    uint8_t        byIdx;
+    uint32_t len = 0;
+    uint16_t value;
+    byIdx  = (uint8_t)(ctrl->wValue &0xff);
+    value = ctrl->wValue>>8;
+
+    if( USB_DT_DEVICE ==value )
+    	{
+	    len = MIN( sizeof(dwc_device_descriptor_t), ctrl->wLength);
+	    do_get_descriptor(pcd,(uint32_t*)&device_desc,len);
+    	}
+    else if( USB_DT_CONFIG==value )
+    	{
+	        len = MIN( sizeof(dwc_config_all_t), ctrl->wLength);
+	        do_get_descriptor(pcd,(uint32_t*)&g_config_desc,len);
+    	}
+
+    else if( USB_DT_STRING ==value)
+    	{
+	        len = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[byIdx]))->bLength, ctrl->wLength);
+	        do_get_descriptor(pcd,(uint32_t*)pStrDescIdx[byIdx],len);
+	 }
+  
+     else if(  USB_DT_INTERFACE == value)
+     	{
+	        len = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[byIdx]))->bLength, ctrl->wLength);
+	        do_get_descriptor(pcd,(uint32_t*)pStrDescIdx[byIdx],len);
+     	}
+     else if(   ENDPOINT_DESCRIPTOR == value)
+     	{
+	        len = MIN(((dwc_string_descriptor_t*)(pStrDescIdx[byIdx]))->bLength, ctrl->wLength);
+	        do_get_descriptor(pcd,(uint32_t*)pStrDescIdx[byIdx],len);
+     	}
+    else if( USB_DT_DEVICE_QUALIFIER ==value)
+    	{
+	        len = MIN(sizeof(dwc_dev_qual_descriptor_t),ctrl->wLength);
+	        do_get_descriptor(pcd,(uint32_t*)&dev_qual_desc,len);
+    	}
+    else 
+    	{
+	        ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+    	}
+    
+    return 0;
+}
+
+
+static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
+                                uint32_t is_in, uint32_t ep_num)
+{
+    /* Init EP structure */
+    pcd_ep->desc = 0;
+    pcd_ep->pcd = pcd;
+    pcd_ep->stopped = 1;
+    pcd_ep->queue_sof = 0;
+
+    /* Init DWC ep structure */
+    pcd_ep->dwc_ep.is_in = is_in;
+    pcd_ep->dwc_ep.num = ep_num;
+    pcd_ep->dwc_ep.active = 0;
+    pcd_ep->dwc_ep.tx_fifo_num = 0;
+    /* Control until ep is actvated */
+    pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_BULK;
+    pcd_ep->dwc_ep.maxpacket = 512;
+    pcd_ep->dwc_ep.maxxfer = 65536;
+
+    pcd_ep->dwc_ep.start_xfer_buff = 0;
+    pcd_ep->dwc_ep.xfer_buff = 0;
+    pcd_ep->dwc_ep.xfer_len = 0;
+    pcd_ep->dwc_ep.xfer_count = 0;
+    pcd_ep->dwc_ep.sent_zlp = 0;
+    pcd_ep->dwc_ep.total_len = 0;
+}
+
+/**
+ * Initialize ep's
+ */
+static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
+{
+    int i;
+    uint32_t hwcfg1;
+    dwc_otg_pcd_ep_t *ep;
+    int in_ep_cntr, out_ep_cntr;
+    uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
+    uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
+
+    /**
+     * Initialize the EP0 structure.
+     */
+    pcd->ep0.dwc_ep.pPara = (void*)(&global.g_in_pPara[1]);
+
+    ep = &pcd->ep0;
+    dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
+
+    in_ep_cntr = 0;
+    hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
+    for (i = 1; in_ep_cntr < num_in_eps; i++)
+    {
+        if ((hwcfg1 & 0x1) == 0)
+        {
+            pcd->in_ep[in_ep_cntr].dwc_ep.pPara = (void*)(&global.g_in_pPara[in_ep_cntr]);
+            ep = &pcd->in_ep[in_ep_cntr];
+            in_ep_cntr++;
+            /**
+             * @todo NGS: Add direction to EP, based on contents
+             * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
+             * sprintf(";r
+             */
+            dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
+        }
+        hwcfg1 >>= 2;
+    }
+
+    out_ep_cntr = 0;
+    hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
+    for (i = 1; out_ep_cntr < num_out_eps; i++)
+    {
+        if ((hwcfg1 & 0x1) == 0)
+        {
+            pcd->out_ep[out_ep_cntr].dwc_ep.pPara = (void*)(&global.g_out_pPara[out_ep_cntr]);
+            ep = &pcd->out_ep[out_ep_cntr];
+            out_ep_cntr++;
+            /**
+             * @todo NGS: Add direction to EP, based on contents
+             * of HWCFG1.  Need a copy of HWCFG1 in pcd structure?
+             * sprintf(";r
+             */
+            dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
+        }
+        hwcfg1 >>= 2;
+    }
+ if(NEED_ENUM == global.g_enum)
+ {
+        pcd->ep0state = EP0_DISCONNECT;
+ }
+ else
+ {
+	 pcd->ep0state = EP0_IDLE;
+
+ }
+    pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
+    pcd->ep0.dwc_ep.type = 0;
+}
+
+/**
+ * This function initialized the PCD portion of the driver.
+ *
+ */
+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
+{
+    dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *)&global.g_dwc_otg_pcd_tp;
+    int i;
+    uint8_t* pt_dwc_otg_pcd_t = (uint8_t*)&global.g_dwc_otg_pcd_tp;
+    for(i = 0;i<sizeof(dwc_otg_pcd_t);i++)
+    {
+       pt_dwc_otg_pcd_t[i] = 0;
+    }
+
+    pcd->core_if = core_if;
+
+    pcd->setup_pkt = global.g_u_setup_pkt;
+    pcd->status_buf = &global.g_status_buf;
+    dwc_otg_pcd_reinit(pcd);
+
+    return pcd;
+
+
+}
+
+
+/******************************************************************************/
+
+#endif /* DWC_HOST_ONLY */
diff --git a/boot/common/src/loader/drivers/dwc_otg_pcd.h b/boot/common/src/loader/drivers/dwc_otg_pcd.h
new file mode 100644
index 0000000..e96d8c7
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_pcd.h
@@ -0,0 +1,188 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
+ * $Revision: #48 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+#ifndef DWC_HOST_ONLY
+#if !defined(__DWC_PCD_H__)
+#define __DWC_PCD_H__
+#include "usb.h"
+#include "dwc_otg_cil.h"
+#include "dwc_otg_pcd_if.h"
+/**
+ * @file
+ *
+ * This file contains the structures, constants, and interfaces for
+ * the Perpherial Contoller Driver (PCD).
+ *
+ * The Peripheral Controller Driver (PCD) for Linux will implement the
+ * Gadget API, so that the existing Gadget drivers can be used. For
+ * the Mass Storage Function driver the File-backed USB Storage Gadget
+ * (FBS) driver will be used.  The FBS driver supports the
+ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
+ * transports.
+ *
+ */
+
+/**
+ * Get the pointer to the core_if from the pcd pointer.
+ */
+#define GET_CORE_IF( _pcd ) (_pcd->core_if)
+
+/**
+ * States of EP0.
+ */
+typedef enum ep0_state
+{
+    EP0_DISCONNECT,		/* no host */
+    EP0_IDLE,
+    EP0_IN_DATA_PHASE,
+    EP0_OUT_DATA_PHASE,
+    EP0_IN_STATUS_PHASE,
+    EP0_OUT_STATUS_PHASE,
+    EP0_STALL,
+} ep0state_e;
+
+/** Fordward declaration.*/
+struct dwc_otg_pcd;
+
+/** DWC_otg request structure.
+ * This structure is a list of requests.
+ */
+typedef struct dwc_otg_pcd_request
+{
+    void *priv;
+    void *buf;
+    uint32_t dma;
+    uint32_t length;
+    uint32_t actual;
+    unsigned sent_zlp:1;
+    /**
+     * Used instead of original buffer if
+     * it(physical address) is not dword-aligned.
+     **/
+    uint8_t *dw_align_buf;
+    uint32_t  dw_align_buf_dma;
+} dwc_otg_pcd_request_t;
+
+/**	  PCD EP structure.
+ * This structure describes an EP, there is an array of EPs in the PCD
+ * structure.
+ */
+typedef struct dwc_otg_pcd_ep
+{
+    /** USB EP Descriptor */
+    usb_endpoint_descriptor_t *desc;
+
+    /** queue of dwc_otg_pcd_requests. */
+    unsigned stopped:1;
+    unsigned disabling:1;
+    unsigned dma:1;
+    unsigned queue_sof:1;
+    dwc_ep_t dwc_ep;
+
+    /** Pointer to PCD */
+    struct dwc_otg_pcd *pcd;
+
+    void *priv;
+} dwc_otg_pcd_ep_t;
+
+/** DWC_otg PCD Structure.
+ * This structure encapsulates the data for the dwc_otg PCD.
+ */
+
+typedef union
+{
+    usb_device_request_t req;
+    uint32_t d32[2];
+}u_setup_pkt;
+
+struct dwc_otg_pcd
+{
+    /** The DWC otg device pointer */
+    struct dwc_otg_device *otg_dev;
+    /** Core Interface */
+    dwc_otg_core_if_t *core_if;
+    /** State of EP0 */
+    ep0state_e ep0state;
+    /** EP0 Request is pending */
+    unsigned ep0_pending;
+    /** Indicates when SET CONFIGURATION Request is in process */
+    unsigned request_config;
+    unsigned request_pending;
+
+    /** SETUP packet for EP0
+     * This structure is allocated as a DMA buffer on PCD initialization
+     * with enough space for up to 3 setup packets.
+     */
+    u_setup_pkt *setup_pkt;
+
+    uint32_t setup_pkt_dma_handle;
+    /* Additional buffer and flag for CTRL_WR premature case */
+    uint8_t *backup_buf;
+    unsigned data_terminated;
+
+    /** 2-byte dma buffer used to return status from GET_STATUS */
+    uint16_t *status_buf;
+    uint32_t  status_buf_dma_handle;
+    /** EP0 */
+    dwc_otg_pcd_ep_t ep0;
+
+    /** Array of IN EPs. */
+    dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
+    /** Array of OUT EPs. */
+    dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
+
+#ifdef DWC_UTE_CFI
+    cfiobject_t *cfi;
+#endif
+
+};
+
+#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
+do { \
+		doepint_data_t doepint ; \
+		doepint.d32 = 0;\
+		doepint.b.__intr = 1; \
+		DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
+		doepint.d32); \
+} while (0)
+
+#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
+do { \
+		diepint_data_t diepint; \
+		diepint.d32 = 0;\
+		diepint.b.__intr = 1; \
+		DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
+		diepint.d32); \
+} while (0)
+
+#endif
+#endif /* DWC_HOST_ONLY */
diff --git a/boot/common/src/loader/drivers/dwc_otg_pcd_if.h b/boot/common/src/loader/drivers/dwc_otg_pcd_if.h
new file mode 100644
index 0000000..63d2ddc
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_pcd_if.h
@@ -0,0 +1,60 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
+ * $Revision: #11 $
+ * $Date: 2011/10/26 $
+ * $Change: 1873028 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+#ifndef DWC_HOST_ONLY
+
+#if !defined(__DWC_PCD_IF_H__)
+#define __DWC_PCD_IF_H__
+#include "dwc_otg_core_if.h"
+#include "dwc_otg_pcd.h"
+
+/** @file
+ * This file defines DWC_OTG PCD Core API.
+ */
+
+typedef struct dwc_otg_pcd dwc_otg_pcd_t;
+
+/** Maxpacket size for EP0 */
+#define MAX_EP0_SIZE	64
+
+extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
+
+extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd);
+
+extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
+                                     const uint8_t * ep_desc, void *usb_ep);
+
+extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
+
+#endif				/* __DWC_PCD_IF_H__ */
+
+#endif				/* DWC_HOST_ONLY */
diff --git a/boot/common/src/loader/drivers/dwc_otg_pcd_intr.c b/boot/common/src/loader/drivers/dwc_otg_pcd_intr.c
new file mode 100644
index 0000000..e364597
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_pcd_intr.c
@@ -0,0 +1,1453 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
+ * $Revision: #116 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+#ifndef DWC_HOST_ONLY
+#include "dwc_otg_pcd.h"
+
+#ifdef DWC_UTE_CFI
+#include "dwc_otg_cfi.h"
+#endif
+
+#include "global.h"
+
+
+/**
+ * This function returns pointer to in ep struct with number ep_num
+ */
+static  dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
+{
+    int i;
+    int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
+    if (ep_num == 0)
+    {
+        return &pcd->ep0;
+    }
+    else
+    {
+        for (i = 0; i < num_in_eps; ++i)
+        {
+            if (pcd->in_ep[i].dwc_ep.num == ep_num)
+                return &pcd->in_ep[i];
+        }
+        return 0;
+    }
+}
+
+/**
+ * This function returns pointer to out ep struct with number ep_num
+ */
+static  dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
+{
+    int i;
+    int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
+    if (ep_num == 0)
+    {
+        return &pcd->ep0;
+    }
+    else
+    {
+        for (i = 0; i < num_out_eps; ++i)
+        {
+            if (pcd->out_ep[i].dwc_ep.num == ep_num)
+                return &pcd->out_ep[i];
+        }
+        return 0;
+    }
+}
+
+/**
+ * This functions gets a pointer to an EP from the wIndex address
+ * value of the control request.
+ */
+dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, uint16_t wIndex)
+{
+    dwc_otg_pcd_ep_t *ep;
+    uint32_t ep_num = UE_GET_ADDR(wIndex);
+
+	if (ep_num >= MAX_EPS_CHANNELS)
+		return 0;
+	
+    if (ep_num == 0)
+    {
+        ep = &pcd->ep0;
+    }
+    else if (UE_GET_DIR(wIndex) == UE_DIR_IN)
+    {	/* in ep */
+        ep = &pcd->in_ep[ep_num - 1];
+    }
+    else
+    {
+        ep = &pcd->out_ep[ep_num - 1];
+    }
+
+    return ep;
+}
+/**
+ * This function handles the Rx Status Queue Level Interrupt, which
+ * indicates that there is a least one packet in the Rx FIFO.  The
+ * packets are moved from the FIFO to memory, where they will be
+ * processed when the Endpoint Interrupt Register indicates Transfer
+ * Complete or SETUP Phase Done.
+ *
+ * Repeat the following until the Rx Status Queue is empty:
+ *	 -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
+ *		info
+ *	 -# If Receive FIFO is empty then skip to step Clear the interrupt
+ *		and exit
+ *	 -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
+ *		SETUP data to the buffer
+ *	 -# If OUT Data Packet call dwc_otg_read_packet to copy the data
+ *		to the destination buffer
+ */
+int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+    gintmsk_data_t gintmask;
+    device_grxsts_data_t status;
+    dwc_otg_pcd_ep_t *ep;
+    gintsts_data_t gintsts;
+    gintmask.d32 = 0;
+
+    /* Disable the Rx Status Queue Level interrupt */
+    gintmask.b.rxstsqlvl = 1;
+    DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
+
+    /* Get the Status from the top of the FIFO */
+    status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
+
+    /* Get pointer to EP structure */
+    ep = get_out_ep(pcd, status.b.epnum);
+	if(0==ep)
+		return -1;
+    switch (status.b.pktsts)
+    {
+    case DWC_DSTS_GOUT_NAK:
+        break;
+    case DWC_STS_DATA_UPDT:
+        if (status.b.bcnt && ep->dwc_ep.xfer_buff)
+        {
+            /** @todo NGS Check for buffer overflow? */
+            dwc_otg_read_packet(core_if, ep->dwc_ep.xfer_buff,status.b.bcnt);
+            ep->dwc_ep.xfer_count += status.b.bcnt;
+            ep->dwc_ep.xfer_buff += status.b.bcnt;
+        }
+        break;
+    case DWC_STS_XFER_COMP:
+        break;
+    case DWC_DSTS_SETUP_COMP:
+        break;
+    case DWC_DSTS_SETUP_UPDT:
+		 printf("complete_ep11\n");
+        dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
+        ep->dwc_ep.xfer_count += status.b.bcnt;
+
+        #if SYNC_USB_HSIC
+        if(pcd->setup_pkt->req.bRequest == 0x05)
+        {
+        
+		REG32(REG_GPIO_OUT)=0x9;
+        while(REG32(REG_GPIO_IN)!=0xFF);
+		usdelay(1);
+		REG32(REG_GPIO_OUT)=0;
+       }
+       #endif
+	   #if 0
+	  if(DONOT_NEED_ENUM == global.g_enum)
+	  {
+	  	printf("unmask endpoint\n");
+          	DWC_WRITE_REG32(&pcd->core_if->dev_if->dev_global_regs->daintmsk,0x3003);
+	  }
+	  #endif
+        break;
+    default:
+        break;
+    }
+
+    /* Enable the Rx Status Queue Level interrupt */
+    DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
+    /* Clear interrupt */
+    gintsts.d32 = 0;
+    gintsts.b.rxstsqlvl = 1;
+    DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
+
+    return 1;
+}
+
+/**
+ * This function examines the Device IN Token Learning Queue to
+ * determine the EP number of the last IN token received.  This
+ * implementation is for the Mass Storage device where there are only
+ * 2 IN EPs (Control-IN and BULK-IN).
+ *
+ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
+ * are 8 EP Numbers in each of the other possible DTKNQ Registers.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ *
+ */
+/**
+ * This function is called when dedicated Tx FIFO Empty interrupt occurs.
+ * The active request is checked for the next packet to be loaded into
+ * apropriate Tx FIFO.
+ */
+static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
+{
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    dtxfsts_data_t txstatus;
+    dwc_otg_pcd_ep_t *ep = 0;
+    uint32_t len = 0;
+    int dwords;
+    txstatus.d32 = 0;
+
+	if(epnum >= MAX_EPS_CHANNELS)
+		return -1;
+	
+    ep = get_in_ep(pcd, epnum);
+	if(0==ep)
+		return -1;
+    len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+
+    if (len > ep->dwc_ep.maxpacket)
+    {
+        len = ep->dwc_ep.maxpacket;
+    }
+
+    dwords = (len + 3) / 4;
+
+    /* While there is space in the queue and space in the FIFO and
+     * More data to tranfer, Write packets to the Tx FIFO */
+    txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
+    while (txstatus.b.txfspcavail > dwords &&
+            ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
+            ep->dwc_ep.xfer_len != 0)
+    {
+        /* Write the FIFO */
+        dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
+
+        len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+        if (len > ep->dwc_ep.maxpacket)
+        {
+            len = ep->dwc_ep.maxpacket;
+        }
+
+        dwords = (len + 3) / 4;
+        txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
+    }
+
+
+    return 1;
+}
+
+/**
+ * This function configures EPO to receive SETUP packets.
+ *
+ * @todo NGS: Update the comments from the HW FS.
+ *
+ *	-# Program the following fields in the endpoint specific registers
+ *	for Control OUT EP 0, in order to receive a setup packet
+ *	- DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
+ *	  setup packets)
+ *	- DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
+ *	  to back setup packets)
+ *		- In DMA mode, DOEPDMA0 Register with a memory address to
+ *		  store any setup packets received
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param pcd	  Programming view of the PCD.
+ */
+ void ep0_out_start(dwc_otg_core_if_t * core_if,
+                           dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    deptsiz0_data_t doeptsize0;
+    depctl_data_t doepctl;
+    doepctl.d32 = 0;
+    doeptsize0.d32 =0;
+
+
+    doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
+    if (doepctl.b.epena)
+    {
+        return;
+    }
+
+    doeptsize0.b.supcnt = 3;
+    doeptsize0.b.pktcnt = 1;
+    doeptsize0.b.xfersize = 8 * 3;
+
+    /** put here as for Hermes mode deptisz register should not be written */
+    DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,doeptsize0.d32);
+
+    /** DOEPCTL0 Register write cnak will be set after setup interrupt */
+    doepctl.d32 = 0;
+    doepctl.b.epena = 1;
+
+    DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
+
+}
+
+
+void USB_Recovercfg(dwc_otg_pcd_t *pcd)
+{
+    int i = 0;
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    depctl_data_t doepctl;
+    depctl_data_t diepctl;
+    doepctl.d32 = 0;
+    diepctl.d32 = 0;
+
+    for (i = 0; i < dev_if->num_out_eps; i++)
+    {
+        doepctl.d32= DWC_READ_REG32(&dev_if->out_ep_regs[i+1]->doepctl);
+        doepctl.b.eptype = pcd->out_ep[i].dwc_ep.type;
+        doepctl.b.mps = pcd->out_ep[i].dwc_ep.maxpacket;
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i+1]->doepctl, doepctl.d32);
+
+        diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i+1]->diepctl);
+        diepctl.b.eptype = pcd->in_ep[i].dwc_ep.type;
+        diepctl.b.mps = pcd->in_ep[i].dwc_ep.maxpacket;
+        DWC_WRITE_REG32(&dev_if->in_ep_regs[i+1]->diepctl, diepctl.d32);
+    }
+
+}
+int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    depctl_data_t doepctl;
+    daint_data_t daintmsk;
+    doepmsk_data_t doepmsk;
+    diepmsk_data_t diepmsk ;
+    dcfg_data_t dcfg ;
+    grstctl_t resetctl;
+    dctl_data_t dctl;
+    int i = 0;
+    gintsts_data_t gintsts;
+    pcgcctl_data_t power;
+    doepctl.d32 = 0;
+    daintmsk.d32 = 0;
+    doepmsk.d32 = 0;
+    diepmsk.d32 = 0;
+    dcfg.d32 = 0;
+    resetctl.d32 = 0;
+    dctl.d32 = 0;
+    power.d32 = 0;
+
+    power.d32 = DWC_READ_REG32(core_if->pcgcctl);
+    if (power.b.stoppclk)
+    {
+        power.d32 = 0;
+        power.b.stoppclk = 1;
+        DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
+
+        power.b.pwrclmp = 1;
+        DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
+
+        power.b.rstpdwnmodule = 1;
+        DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
+    }
+
+    printf("R\n");
+
+    /* Clear the Remote Wakeup Signalling */
+    dctl.b.rmtwkupsig = 1;
+    DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
+
+    /* Set NAK for all OUT EPs */
+    doepctl.b.snak = 1;
+    for (i = 0; i <= dev_if->num_out_eps; i++)
+    {
+        DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
+    }
+
+    /* Flush the NP Tx FIFO */
+    dwc_otg_flush_tx_fifo(core_if, 0x10);
+    /* Flush the Learning Queue */
+    resetctl.b.intknqflsh = 1;
+    DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
+    {
+        daintmsk.b.inep0 = 1;
+        daintmsk.b.outep0 = 1;
+        DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,daintmsk.d32);
+
+        doepmsk.b.setup = 1;
+        doepmsk.b.xfercompl = 1;
+        doepmsk.b.ahberr = 1;
+        doepmsk.b.epdisabled = 1;
+        DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
+
+        diepmsk.b.xfercompl = 1;
+        diepmsk.b.timeout = 1;
+        diepmsk.b.epdisabled = 1;
+        diepmsk.b.ahberr = 1;
+
+        DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
+    }
+
+    /* Reset Device Address */
+    dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
+    dcfg.b.devaddr = 0;
+    DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
+
+    /* Clear interrupt */
+    gintsts.d32 = 0;
+    gintsts.b.usbreset = 1;
+    DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
+
+    USB_Recovercfg(pcd);
+
+    return 1;
+}
+
+/**
+ * Get the device speed from the device status register and convert it
+ * to USB speed constant.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+static int get_device_speed(dwc_otg_core_if_t * core_if)
+{
+    dsts_data_t dsts;
+    int speed = 0;
+    dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
+
+    switch (dsts.b.enumspd)
+    {
+    case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
+        speed = USB_SPEED_HIGH;
+        break;
+    case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
+    case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
+        speed = USB_SPEED_FULL;
+        break;
+
+    case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
+        speed = USB_SPEED_LOW;
+        break;
+    }
+
+    return speed;
+}
+
+/**
+ * Read the device status register and set the device speed in the
+ * data structure.
+ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
+ */
+extern void init_devspd(dwc_otg_core_if_t * core_if,uint8_t speed);
+
+
+int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+    gintsts_data_t gintsts;
+    gusbcfg_data_t gusbcfg;
+    dwc_otg_core_global_regs_t *global_regs = GET_CORE_IF(pcd)->core_global_regs;
+    uint8_t utmi16b, utmi8b;
+    int speed;
+    printf("D\n");
+    
+    utmi16b = 6;	//vahrama old value was 6; data bookÉÏÊÇ5£¬add by lx 2012.10.13
+    utmi8b = 9;
+    dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
+    ep0_out_start(GET_CORE_IF(pcd), pcd);
+#if SYNC_USB_HSIC
+
+	REG32(REG_GPIO_OUT)=5;
+	while(REG32(REG_GPIO_IN)!=0xFF);
+	usdelay(1);
+	REG32(REG_GPIO_OUT)=0;
+
+	REG32(REG_GPIO_OUT)=6;
+	while(REG32(REG_GPIO_IN)!=0xFF);
+	usdelay(1);
+	REG32(REG_GPIO_OUT)=0;
+
+	REG32(REG_GPIO_OUT)=7;
+	while(REG32(REG_GPIO_IN)!=0xFF);
+	usdelay(1);
+	REG32(REG_GPIO_OUT)=0;
+
+	REG32(REG_GPIO_OUT)=8;
+	while(REG32(REG_GPIO_IN)!=0xFF);
+	usdelay(1);
+	REG32(REG_GPIO_OUT)=0;
+
+#endif
+    if (pcd->ep0state == EP0_DISCONNECT)
+    {
+        pcd->ep0state = EP0_IDLE;
+    }
+    else if (pcd->ep0state == EP0_STALL)
+    {
+        pcd->ep0state = EP0_IDLE;
+    }
+
+    ep0->stopped = 0;
+
+    speed = get_device_speed(GET_CORE_IF(pcd));
+    /* Set USB turnaround time based on device speed and PHY interface. */
+    gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+    if (speed == USB_SPEED_HIGH)
+    {
+    
+        if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI)
+        {
+            /* UTMI+  OR  ULPI interface */
+            if (gusbcfg.b.ulpi_utmi_sel == 1)
+            {
+                /* ULPI interface */
+                gusbcfg.b.usbtrdtim = 9;
+            }
+            else
+            {
+                /* UTMI+ interface */
+                if (GET_CORE_IF(pcd)->core_params->phy_utmi_width == 16)
+                {
+                    gusbcfg.b.usbtrdtim = utmi16b;
+                }
+                else
+                {
+                    gusbcfg.b.usbtrdtim = utmi8b;
+                }
+            }
+        }
+
+        printf("2\n");
+        
+    }
+    else
+    { 
+        printf("1\n");
+        pcd->out_ep[0].dwc_ep.maxpacket = 64;
+        pcd->in_ep[0].dwc_ep.maxpacket = 64;
+        pcd->out_ep[1].dwc_ep.maxpacket = 64;
+        pcd->in_ep[1].dwc_ep.maxpacket = 64;   
+        init_devspd(pcd->core_if,1);
+        g_config_desc.atTxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+        g_config_desc.atRxEP[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+        g_config_desc.atTxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+        g_config_desc.atRxEP1[0].wMaxPacketSize = USB_FULLSPEED_BULK_MAXSIZE;
+        /* Full or low speed */
+        gusbcfg.b.usbtrdtim = 9;
+    }
+    DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
+
+    /* Clear interrupt */
+    gintsts.d32 = 0;
+    gintsts.b.enumdone = 1;
+    DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,gintsts.d32);
+    return 1;
+}
+
+
+
+/**
+ * This funcion stalls EP0.
+ */
+void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
+{
+    dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+
+    ep0->dwc_ep.is_in = 1;
+    dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
+    pcd->ep0.stopped = 1;
+    pcd->ep0state = EP0_IDLE;
+    ep0_out_start(GET_CORE_IF(pcd), pcd);
+}
+
+static  void do_setup_in_out_status_phase(dwc_otg_pcd_t * pcd,s8 udir)
+{
+    dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+    if (pcd->ep0state == EP0_STALL)
+    {
+        return;
+    }
+
+    if(udir)
+    {
+     pcd->ep0state = EP0_IN_STATUS_PHASE;
+    }
+    else
+    {
+      pcd->ep0state = EP0_OUT_STATUS_PHASE;
+    }
+
+    /* Prepare for more SETUP Packets */
+    ep0->dwc_ep.xfer_len = 0;
+    ep0->dwc_ep.xfer_count = 0;
+    ep0->dwc_ep.is_in = udir;
+    dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+}
+
+
+/**
+ * Clear the EP halt (STALL) and if pending requests start the
+ * transfer.
+ */
+static  void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
+{
+    if (ep->dwc_ep.stall_clear_flag == 0)
+        dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
+
+    /* Reactive the EP */
+    dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
+    if (ep->stopped)
+    {
+        ep->stopped = 0;
+        /* If there is a request in the EP queue start it */
+
+        /** @todo FIXME: this causes an EP mismatch in DMA mode.
+         * epmismatch not yet implemented. */
+
+        /*
+         * Above fixme is solved by implmenting a tasklet to call the
+         * start_next_request(), outside of interrupt context at some
+         * time after the current time, after a clear-halt setup packet.
+         * Still need to implement ep mismatch in the future if a gadget
+         * ever uses more than one endpoint at once
+         */
+        ep->queue_sof = 1;
+    }
+    /* Start Control Status Phase */
+    do_setup_in_out_status_phase(pcd,1);
+}
+
+/**
+ * This function process the GET_STATUS Setup Commands.
+ */
+static  void do_get_status(dwc_otg_pcd_t * pcd)
+{
+    usb_device_request_t ctrl = pcd->setup_pkt->req;
+    dwc_otg_pcd_ep_t *ep;
+    dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+    uint16_t *status = pcd->status_buf;
+
+    switch (UT_GET_RECIPIENT(ctrl.bmRequestType))
+    {
+    case UT_INTERFACE:
+        *status = 0;
+        break;
+
+    case UT_ENDPOINT:
+        ep = get_ep_by_addr(pcd, ctrl.wIndex);
+        if (ep == 0 || ctrl.wLength > 2)
+        {
+            ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+            return;
+        }
+        /** @todo check for EP stall */
+        *status = ep->stopped;
+        break;
+    }
+    pcd->ep0_pending = 1;
+    ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
+    ep0->dwc_ep.xfer_buff = (uint8_t *) status;
+    ep0->dwc_ep.xfer_len = 2;
+    ep0->dwc_ep.xfer_count = 0;
+    ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
+    dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+}
+
+
+static  void do_clear_feature(dwc_otg_pcd_t * pcd)
+{
+    usb_device_request_t ctrl = pcd->setup_pkt->req;
+    dwc_otg_pcd_ep_t *ep = 0;
+    switch (UT_GET_RECIPIENT(ctrl.bmRequestType))
+    {
+    case UT_ENDPOINT:
+        ep = get_ep_by_addr(pcd, ctrl.wIndex);
+        if (ep == 0)
+        {
+            ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+            return;
+        }
+
+        pcd_clear_halt(pcd, ep);
+
+        break;
+
+    }
+}
+
+/**
+ * This function process the SET_ADDRESS Setup Commands.
+ */
+static  void do_set_address(dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
+    usb_device_request_t ctrl = pcd->setup_pkt->req;
+    dcfg_data_t dcfg;
+    dcfg.d32 = 0;
+
+    if (ctrl.bmRequestType == UT_DEVICE)
+    {
+
+        dcfg.b.devaddr = ctrl.wValue;
+        DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
+#if SYNC_USB_HSIC
+		REG32(REG_GPIO_OUT)=0xa;
+        while(REG32(REG_GPIO_IN)!=0xFF);
+		usdelay(1);
+		REG32(REG_GPIO_OUT)=0;
+
+		REG32(REG_GPIO_OUT)=0xb;
+        while(REG32(REG_GPIO_IN)!=0xFF);
+		usdelay(1);
+		REG32(REG_GPIO_OUT)=0;
+		
+#endif
+        do_setup_in_out_status_phase(pcd,1);
+#if SYNC_USB_HSIC
+       if(pcd->setup_pkt->req.bRequest == 0x05)
+       {
+        	REG32(REG_GPIO_OUT)=0x9;
+        	while(REG32(REG_GPIO_IN)!=0xFF);
+        	usdelay(10);
+        	REG32(REG_GPIO_OUT)=0;
+        }
+#endif
+    }
+}
+
+/**
+ *	This function processes SETUP commands. In Linux, the USB Command
+ *	processing is done in two places - the first being the PCD and the
+ *	second in the Gadget Driver (for example, the File-Backed Storage
+ *	Gadget Driver).
+ *
+ * <table>
+ * <tr><td>Command	</td><td>Driver </td><td>Description</td></tr>
+ *
+ * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
+ * defined in chapter 9 of the USB 2.0 Specification chapter 9
+ * </td></tr>
+ *
+ * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
+ * requests are the ENDPOINT_HALT feature is procesed, all others the
+ * interface requests are ignored.</td></tr>
+ *
+ * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
+ * requests are processed by the PCD.  Interface requests are passed
+ * to the Gadget Driver.</td></tr>
+ *
+ * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
+ * with device address received </td></tr>
+ *
+ * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
+ * requested descriptor</td></tr>
+ *
+ * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
+ * not implemented by any of the existing Gadget Drivers.</td></tr>
+ *
+ * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
+ * all EPs and enable EPs for new configuration.</td></tr>
+ *
+ * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
+ * the current configuration</td></tr>
+ *
+ * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
+ * EPs and enable EPs for new configuration.</td></tr>
+ *
+ * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
+ * current interface.</td></tr>
+ *
+ * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
+ * message.</td></tr>
+ * </table>
+ *
+ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
+ * processed by pcd_setup. Calling the Function Driver's setup function from
+ * pcd_setup processes the gadget SETUP commands.
+ */
+void active_allep(dwc_otg_pcd_t * pcd)
+{
+    int i = 0;
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    for (i = 0; i <dev_if->num_out_eps; i++)
+    {
+        dwc_otg_ep_activate(pcd->core_if,&pcd->out_ep[i].dwc_ep);
+        dwc_otg_ep_activate(pcd->core_if,&pcd->in_ep[i].dwc_ep);
+    }
+
+}
+
+extern int  dwc_setup(dwc_otg_pcd_t * pcd,  usb_device_request_t * ctrl);
+
+static  void pcd_setup(dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    usb_device_request_t ctrl = pcd->setup_pkt->req;
+    dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+
+    ep0->stopped = 0;
+
+    if (ctrl.bmRequestType & UE_DIR_IN)
+    {
+        ep0->dwc_ep.is_in = 1;
+        pcd->ep0state = EP0_IN_DATA_PHASE;
+    }
+    else
+    {
+        ep0->dwc_ep.is_in = 0;
+        pcd->ep0state = EP0_OUT_DATA_PHASE;
+    }
+
+    if (ctrl.wLength == 0)
+    {
+        printf("ctrl.wLength == 0\n");
+        ep0->dwc_ep.is_in = 1;
+        pcd->ep0state = EP0_IN_STATUS_PHASE;
+    }
+   if((ctrl.bmRequestType&0x60) == 0x40)
+   {
+	printf("vender request\n");
+	 ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+	 return;
+   }
+
+    if( UR_GET_STATUS == ctrl.bRequest)
+    {
+           do_get_status(pcd);
+    }
+
+    else if( UR_CLEAR_FEATURE ==  ctrl.bRequest)
+    	{
+        do_clear_feature(pcd);
+    	}
+
+    else if( UR_SET_FEATURE ==ctrl.bRequest) 
+    	{}
+
+    else if( UR_SET_ADDRESS == ctrl.bRequest)
+    	{
+	     #if SYNC_SETADDRESS
+	     pcd->request_config = 2;
+	     active_allep(pcd);
+	     #endif
+            do_set_address(pcd); 
+    	}
+
+    else if(  UR_GET_DESCRIPTOR== ctrl.bRequest)
+    	{
+            dwc_setup(pcd, &ctrl);
+    	}
+
+    else if( UR_SET_CONFIG== ctrl.bRequest)
+    	{
+        pcd->request_config = 1;
+        active_allep(pcd);
+        do_setup_in_out_status_phase(pcd,1);
+        ep0_out_start(core_if, pcd);
+    	}
+    else
+  	{
+        ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
+  	}
+    
+}
+
+/**
+ * This function completes the ep0 control transfer.
+ */
+static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
+{
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    dwc_otg_dev_in_ep_regs_t *in_ep_regs =
+    dev_if->in_ep_regs[ep->dwc_ep.num];
+    
+    deptsiz0_data_t deptsiz;
+    int is_last = 0;
+    dwc_otg_pcd_t *pcd = ep->pcd;
+
+    if (pcd->ep0_pending)
+    {
+        if (ep->dwc_ep.is_in)
+        {
+
+            do_setup_in_out_status_phase(pcd,0);
+        }
+        else
+        {
+            do_setup_in_out_status_phase(pcd,1);
+        }
+        pcd->ep0_pending = 0;
+        return 1;
+    }
+
+    if (pcd->ep0state == EP0_OUT_STATUS_PHASE
+            || pcd->ep0state == EP0_IN_STATUS_PHASE)
+    {
+        is_last = 1;
+    }
+    else if (ep->dwc_ep.is_in)
+    {
+        deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
+
+       if (deptsiz.b.xfersize == 0)
+        {
+            do_setup_in_out_status_phase(pcd,0);
+        }
+    }
+    else
+    {
+
+        ep0_out_start(core_if, pcd);
+
+    }
+
+    /* Complete the request */
+    if (is_last)
+    {
+        ep->dwc_ep.start_xfer_buff = 0;
+        ep->dwc_ep.xfer_buff = 0;
+        ep->dwc_ep.xfer_len = 0;
+        return 1;
+    }
+    return 0;
+}
+
+/**
+ * This function completes the request for the EP. If there are
+ * additional requests for the EP in the queue they will be started.
+ */
+static void complete_ep(dwc_otg_pcd_ep_t * ep)
+{
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    dwc_otg_dev_in_ep_regs_t *in_ep_regs = dev_if->in_ep_regs[ep->dwc_ep.num];
+    deptsiz_data_t deptsiz;
+
+    if (ep->dwc_ep.is_in)
+    {
+        deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
+        {
+            if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0)
+            {
+                /*      Check if the whole transfer was completed,
+                 *      if no, setup transfer for next portion of data
+                 */
+                if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len)
+                {
+                    dwc_otg_ep_start_transfer(core_if,&ep->dwc_ep);
+                }
+                else if (ep->dwc_ep.sent_zlp)
+                {
+                    /*
+                     * This fragment of code should initiate 0
+                     * length trasfer in case if it is queued
+                     * a trasfer with size divisible to EPs max
+                     * packet size and with usb_request zero field
+                     * is set, which means that after data is transfered,
+                     * it is also should be transfered
+                     * a 0 length packet at the end. For Slave and
+                     * Buffer DMA modes in this case SW has
+                     * to initiate 2 transfers one with transfer size,
+                     * and the second with 0 size. For Desriptor
+                     * DMA mode SW is able to initiate a transfer,
+                     * which will handle all the packets including
+                     * the last  0 legth.
+                     */
+                    ep->dwc_ep.sent_zlp = 0;
+                    dwc_otg_ep_start_zl_transfer(core_if,
+                                                 &ep->dwc_ep);
+                }
+                else
+                {
+
+                    if (ep->dwc_ep.fnUsbCb)
+                        ep->dwc_ep.fnUsbCb( (WORD32)(ep->dwc_ep.pPara), 0, ep->dwc_ep.xfer_count, ep->dwc_ep.total_len);
+
+                }
+            }
+        }
+    }
+    // OUT EP
+    else
+    {
+       
+        dwc_otg_dev_out_ep_regs_t *out_ep_regs = dev_if->out_ep_regs[ep->dwc_ep.num];
+        {
+            deptsiz.d32 = 0;
+            deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
+            if (deptsiz.b.xfersize>0)
+            {
+
+                if (ep->dwc_ep.fnUsbCb)
+                    ep->dwc_ep.fnUsbCb( (WORD32)(ep->dwc_ep.pPara), 0, ep->dwc_ep.xfer_count, ep->dwc_ep.total_len);
+
+            }
+            else
+            {
+                dwc_otg_ep_start_transfer(core_if,&ep->dwc_ep);
+            }
+        }
+
+
+    }
+
+}
+
+/**
+ * This function handles EP0 Control transfers.
+ *
+ * The state of the control transfers are tracked in
+ * <code>ep0state</code>.
+ */
+static void handle_ep0(dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
+
+    if(EP0_DISCONNECT == pcd->ep0state )
+    	{
+		return;
+	}
+   else if(EP0_IDLE == pcd->ep0state ) 
+   	{
+	        pcd->request_config = 0;
+
+	        pcd_setup(pcd);
+               #if SYNC_USB_CTRL
+		 REG32(ARM_PORTA)=0x55;
+                #endif
+   	}
+	else if(EP0_IN_DATA_PHASE == pcd->ep0state)
+	{
+	        if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)
+	        {
+	            dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),&ep0->dwc_ep);
+	        }
+	        else if (ep0->dwc_ep.sent_zlp)
+	        {
+	            dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),&ep0->dwc_ep);
+	            ep0->dwc_ep.sent_zlp = 0;
+	        }
+	        else
+	        {
+	            ep0_complete_request(ep0);
+	        }
+	}
+    else if( EP0_OUT_DATA_PHASE == pcd->ep0state)
+    	{
+        if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)
+        {
+            dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
+                                          &ep0->dwc_ep);
+        }
+        else if (ep0->dwc_ep.sent_zlp)
+        {
+            dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+            ep0->dwc_ep.sent_zlp = 0;
+        }
+        else
+        {
+            ep0_complete_request(ep0);
+        }
+    	}
+	else if(EP0_IN_STATUS_PHASE == pcd->ep0state ||EP0_OUT_STATUS_PHASE == pcd->ep0state )
+	{
+	        ep0_complete_request(ep0);
+	        pcd->ep0state = EP0_IDLE;
+	        ep0->stopped = 1;
+	        ep0->dwc_ep.is_in = 0;	/* OUT for next SETUP */
+	}
+      else if(EP0_STALL == pcd->ep0state )
+      	{
+
+	 }
+	 else
+	  {}
+
+   
+
+}
+
+/**
+ * Handler for the IN EP NAK interrupt.
+ */
+
+/**
+ * Handler for the OUT EP NAK interrupt.
+ */
+static  int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
+                                       const uint32_t epnum)
+{
+    /** @todo implement ISR */
+    dwc_otg_core_if_t *core_if;
+    doepmsk_data_t intr_mask;
+    intr_mask.d32 = 0;
+
+    core_if = GET_CORE_IF(pcd);
+    intr_mask.b.nak = 1;
+    {
+        DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,intr_mask.d32, 0);
+    }
+
+    return 1;
+}
+
+/**
+ * Handler for the OUT EP NYET interrupt.
+ */
+static  int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
+                                        const uint32_t epnum)
+{
+    /** @todo implement ISR */
+    dwc_otg_core_if_t *core_if;
+    doepmsk_data_t intr_mask;
+    intr_mask.d32 = 0 ;
+
+    core_if = GET_CORE_IF(pcd);
+    intr_mask.b.nyet = 1;
+    {
+        DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, intr_mask.d32, 0);
+    }
+
+    return 1;
+}
+
+/**
+ * This interrupt indicates that an IN EP has a pending Interrupt.
+ * The sequence for handling the IN EP interrupt is shown below:
+ * -#	Read the Device All Endpoint Interrupt register
+ * -#	Repeat the following for each IN EP interrupt bit set (from
+ *		LSB to MSB).
+ * -#	Read the Device Endpoint Interrupt (DIEPINTn) register
+ * -#	If "Transfer Complete" call the request complete function
+ * -#	If "Endpoint Disabled" complete the EP disable procedure.
+ * -#	If "AHB Error Interrupt" log error
+ * -#	If "Time-out Handshake" log error
+ * -#	If "IN Token Received when TxFIFO Empty" write packet to Tx
+ *		FIFO.
+ * -#	If "IN Token EP Mismatch" (disable, this is handled by EP
+ *		Mismatch Interrupt)
+ */
+static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
+{
+
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+    diepint_data_t diepint;
+    depctl_data_t depctl;
+    uint32_t ep_intr;
+    uint32_t epnum = 0;
+    dwc_otg_pcd_ep_t *ep;
+    dwc_ep_t *dwc_ep;
+    diepmsk_data_t diepmsk;
+    uint32_t fifoemptymsk;
+    diepint.d32 = 0;
+    depctl.d32 = 0;
+    diepmsk.d32 = 0;
+
+    ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
+    /* Service the Device IN interrupts for each endpoint */
+    while ((ep_intr)&&(epnum<MAX_EPS_CHANNELS))
+    {
+        if (ep_intr & 0x1)
+        {
+
+            /* Get EP pointer */
+            ep = get_in_ep(pcd, epnum);
+            dwc_ep = &ep->dwc_ep;
+            depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
+            diepint.d32 = dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
+            /* Transfer complete */
+            if (diepint.b.xfercompl)
+            {
+                {
+                   /* Disable the Tx FIFO Empty Interrupt for this EP */
+                    fifoemptymsk = 0x1 << dwc_ep->num;
+                    DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,fifoemptymsk, 0);
+                }
+                /* Clear the bit in DIEPINTn for this interrupt */
+                CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
+
+                /* Complete the transfer */
+                if (epnum == 0)
+                {
+                    handle_ep0(pcd);
+
+                }
+                else
+                {
+
+                    complete_ep(ep);
+                    if (diepint.b.nak)
+                        CLEAR_IN_EP_INTR(core_if, epnum, nak);
+                }
+            }
+            /* Endpoint disable      */
+            if (diepint.b.epdisabled)
+            {
+
+                CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
+            }
+
+            /* TimeOUT Handshake (non-ISOC IN EPs) */
+            if (diepint.b.timeout)
+            {
+                CLEAR_IN_EP_INTR(core_if, epnum, timeout);
+            }
+            /** IN Token received with TxF Empty */
+            if (diepint.b.intktxfemp)
+            {
+                if (!ep->stopped && epnum != 0)
+                {
+                    diepmsk.b.intktxfemp = 1;
+                    {
+                        DWC_MODIFY_REG32
+                        (&dev_if->dev_global_regs->diepmsk,
+                         diepmsk.d32, 0);
+                    }
+                }
+                CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
+            }
+
+            /** IN Endpoint NAK Effective */
+            if (diepint.b.inepnakeff)
+            {
+                /* Periodic EP */
+                if (ep->disabling)
+                {
+                    depctl.d32 = 0;
+                    depctl.b.snak = 1;
+                    depctl.b.epdis = 1;
+                    DWC_MODIFY_REG32(&dev_if->in_ep_regs
+                                     [epnum]->diepctl,
+                                     depctl.d32,
+                                     depctl.d32);
+                }
+                CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
+
+            }
+
+            /** IN EP Tx FIFO Empty Intr */
+            if (diepint.b.emptyintr)
+            {
+               printf("diepint.b.emptyintr\n");
+                write_empty_tx_fifo(pcd, epnum);
+                
+                CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
+ 
+            }
+            /* NAK Interrutp */
+            if (diepint.b.nak)
+            {
+                CLEAR_IN_EP_INTR(core_if, epnum, nak);
+            }
+        }
+        epnum++;
+        ep_intr >>= 1;
+    }
+
+    return 1;
+#undef CLEAR_IN_EP_INTR
+}
+
+/**
+ * This interrupt indicates that an OUT EP has a pending Interrupt.
+ * The sequence for handling the OUT EP interrupt is shown below:
+ * -#	Read the Device All Endpoint Interrupt register
+ * -#	Repeat the following for each OUT EP interrupt bit set (from
+ *		LSB to MSB).
+ * -#	Read the Device Endpoint Interrupt (DOEPINTn) register
+ * -#	If "Transfer Complete" call the request complete function
+ * -#	If "Endpoint Disabled" complete the EP disable procedure.
+ * -#	If "AHB Error Interrupt" log error
+ * -#	If "Setup Phase Done" process Setup Packet (See Standard USB
+ *		Command Processing)
+ */
+static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
+{
+
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+    uint32_t ep_intr;
+    doepint_data_t doepint;
+    doepint_data_t doepint1;
+    uint32_t epnum = 0;
+    dwc_otg_pcd_ep_t *ep;
+    dwc_ep_t *dwc_ep;
+
+    doepint.d32 = 0;
+    doepint1.d32 = 0;
+
+    printf("dwc_otg_pcd_handle_out_ep_int\nr");
+    ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
+    while ((ep_intr)&&(epnum<MAX_EPS_CHANNELS))
+    {
+        if (ep_intr & 0x1)
+        {
+            /* Get EP pointer */
+            ep = get_out_ep(pcd, epnum);
+            dwc_ep = &ep->dwc_ep;
+            doepint.d32 = dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
+            /* Transfer complete */
+            if (doepint.b.xfercompl)
+            {
+                if (epnum == 0)
+                {
+                    /* Clear the bit in DOEPINTn for this interrupt */
+                    CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
+                    doepint1.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint);
+                    if (pcd->ep0state == EP0_IDLE && doepint1.b.sr)
+                    {
+                        CLEAR_OUT_EP_INTR(core_if, epnum, sr);
+                    }
+                    else if(pcd->ep0state != EP0_IDLE)
+                    {
+                        handle_ep0(pcd);
+                    }
+                }
+                else
+                {
+                    /* Clear the bit in DOEPINTn for this interrupt */
+                    CLEAR_OUT_EP_INTR(core_if, epnum,xfercompl);
+                    complete_ep(ep);
+                }
+
+            }
+
+            /* Endpoint disable      */
+            if (doepint.b.epdisabled)
+            {
+                /* Clear the bit in DOEPINTn for this interrupt */
+                CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
+            }
+            if (doepint.b.setup)
+            {
+                CLEAR_OUT_EP_INTR(core_if, epnum, setup);
+
+                handle_ep0(pcd);
+
+            }
+            if (doepint.b.outtknepdis)
+            {
+                CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
+            }
+
+            /* NAK Interrutp */
+            if (doepint.b.nak)
+            {
+                handle_out_ep_nak_intr(pcd, epnum);
+
+                CLEAR_OUT_EP_INTR(core_if, epnum, nak);
+            }
+
+            /* NYET Interrutp */
+            if (doepint.b.nyet)
+            {
+                handle_out_ep_nyet_intr(pcd, epnum);
+
+                CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
+            }
+        }
+
+        epnum++;
+        ep_intr >>= 1;
+    }
+
+    return 1;
+
+#undef CLEAR_OUT_EP_INTR
+}
+
+/**
+ * PCD interrupt handler.
+ *
+ * The PCD handles the device interrupts.  Many conditions can cause a
+ * device interrupt. When an interrupt occurs, the device interrupt
+ * service routine determines the cause of the interrupt and
+ * dispatches handling to the appropriate function. These interrupt
+ * handling functions are described below.
+ *
+ * All interrupt registers are processed from LSB to MSB.
+ *
+ */
+
+extern int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if);
+
+int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
+{
+    dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
+
+    gintsts_data_t gintr_status;
+    int32_t retval = 0;
+        gintr_status.d32 = dwc_otg_read_core_intr(core_if);
+
+        if (gintr_status.b.rxstsqlvl)
+        {
+            retval |=
+                dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
+        }
+      //½«Á½¸öÖжϺϳÉÒ»¸ö
+        if (gintr_status.b.usbsuspend)
+        {
+            retval |= dwc_otg_handle_usb_suspend_intr(pcd->core_if);
+        }
+        if (gintr_status.b.usbreset)
+        {
+            retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
+	       global.g_Connet =1;
+        }
+        if (gintr_status.b.enumdone)
+        {
+            retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
+#if SYNC_USB_CTRL
+            REG32(ARM_PORTA)=0x33;
+            usdelay(1);
+            REG32(ARM_PORTA)=0x66;
+#endif
+        }
+        if (gintr_status.b.inepint)
+        {
+            if (!core_if->multiproc_int_enable)
+            {
+                retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
+            }
+        }
+        if (gintr_status.b.outepintr)
+        {
+            if (!core_if->multiproc_int_enable)
+            {
+                retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
+            }
+        }
+    return retval;
+}
+
+#endif /* DWC_HOST_ONLY */
diff --git a/boot/common/src/loader/drivers/dwc_otg_regs.h b/boot/common/src/loader/drivers/dwc_otg_regs.h
new file mode 100644
index 0000000..5f1c0e5
--- /dev/null
+++ b/boot/common/src/loader/drivers/dwc_otg_regs.h
@@ -0,0 +1,1593 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
+ * $Revision: #98 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+#ifndef __DWC_OTG_REGS_H__
+#define __DWC_OTG_REGS_H__
+#include "dwc_otg_core_if.h"
+
+/**
+ * @file
+ *
+ * This file contains the data structures for accessing the DWC_otg core registers.
+ *
+ * The application interfaces with the HS OTG core by reading from and
+ * writing to the Control and Status Register (CSR) space through the
+ * AHB Slave interface. These registers are 32 bits wide, and the
+ * addresses are 32-bit-block aligned.
+ * CSRs are classified as follows:
+ * - Core Global Registers
+ * - Device Mode Registers
+ * - Device Global Registers
+ * - Device Endpoint Specific Registers
+ * - Host Mode Registers
+ * - Host Global Registers
+ * - Host Port CSRs
+ * - Host Channel Specific Registers
+ *
+ * Only the Core Global registers can be accessed in both Device and
+ * Host modes. When the HS OTG core is operating in one mode, either
+ * Device or Host, the application must not access registers from the
+ * other mode. When the core switches from one mode to another, the
+ * registers in the new mode of operation must be reprogrammed as they
+ * would be after a power-on reset.
+ */
+
+/****************************************************************************/
+/** DWC_otg Core registers .
+ * The dwc_otg_core_global_regs structure defines the size
+ * and relative field offsets for the Core Global registers.
+ */
+typedef struct dwc_otg_core_global_regs
+{
+    /** OTG Control and Status Register.  <i>Offset: 000h</i> */
+    volatile uint32_t gotgctl;
+    /** OTG Interrupt Register.	 <i>Offset: 004h</i> */
+    volatile uint32_t gotgint;
+    /**Core AHB Configuration Register.	 <i>Offset: 008h</i> */
+    volatile uint32_t gahbcfg;
+    /**Core USB Configuration Register.	 <i>Offset: 00Ch</i> */
+    volatile uint32_t gusbcfg;
+    /**Core Reset Register.	 <i>Offset: 010h</i> */
+    volatile uint32_t grstctl;
+    /**Core Interrupt Register.	 <i>Offset: 014h</i> */
+    volatile uint32_t gintsts;
+    /**Core Interrupt Mask Register.  <i>Offset: 018h</i> */
+    volatile uint32_t gintmsk;
+    /**Receive Status Queue Read Register (Read Only).	<i>Offset: 01Ch</i> */
+    volatile uint32_t grxstsr;
+    /**Receive Status Queue Read & POP Register (Read Only).  <i>Offset: 020h</i>*/
+    volatile uint32_t grxstsp;
+    /**Receive FIFO Size Register.	<i>Offset: 024h</i> */
+    volatile uint32_t grxfsiz;
+    /**Non Periodic Transmit FIFO Size Register.  <i>Offset: 028h</i> */
+    volatile uint32_t gnptxfsiz;
+    /**Non Periodic Transmit FIFO/Queue Status Register (Read
+     * Only). <i>Offset: 02Ch</i> */
+    volatile uint32_t gnptxsts;
+    /**I2C Access Register.	 <i>Offset: 030h</i> */
+    volatile uint32_t gi2cctl;
+    /**PHY Vendor Control Register.	 <i>Offset: 034h</i> */
+    volatile uint32_t gpvndctl;
+    /**General Purpose Input/Output Register.  <i>Offset: 038h</i> */
+    volatile uint32_t ggpio;
+    /**User ID Register.  <i>Offset: 03Ch</i> */
+    volatile uint32_t guid;
+    /**Synopsys ID Register (Read Only).  <i>Offset: 040h</i> */
+    volatile uint32_t gsnpsid;
+    /**User HW Config1 Register (Read Only).  <i>Offset: 044h</i> */
+    volatile uint32_t ghwcfg1;
+    /**User HW Config2 Register (Read Only).  <i>Offset: 048h</i> */
+    volatile uint32_t ghwcfg2;
+    /**User HW Config3 Register (Read Only).  <i>Offset: 04Ch</i> */
+    volatile uint32_t ghwcfg3;
+    /**User HW Config4 Register (Read Only).  <i>Offset: 050h</i>*/
+    volatile uint32_t ghwcfg4;
+    /** Core LPM Configuration register <i>Offset: 054h</i>*/
+    volatile uint32_t glpmcfg;
+    /** Global PowerDn Register <i>Offset: 058h</i> */
+    volatile uint32_t gpwrdn;
+    /** Global DFIFO SW Config Register  <i>Offset: 05Ch</i> */
+    volatile uint32_t gdfifocfg;
+    /** ADP Control Register  <i>Offset: 060h</i> */
+    volatile uint32_t adpctl;
+} dwc_otg_core_global_regs_t;
+
+/**
+ * This union represents the bit fields of the Core OTG Control
+ * and Status Register (GOTGCTL).  Set the bits using the bit
+ * fields then write the <i>d32</i> value to the register.
+ */
+typedef union gotgctl_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned sesreqscs:1;
+        unsigned sesreq:1;
+        unsigned vbvalidoven:1;
+        unsigned vbvalidovval:1;
+        unsigned avalidoven:1;
+        unsigned avalidovval:1;
+        unsigned bvalidoven:1;
+        unsigned bvalidovval:1;
+        unsigned hstnegscs:1;
+        unsigned hnpreq:1;
+        unsigned hstsethnpen:1;
+        unsigned devhnpen:1;
+        unsigned reserved12_15:4;
+        unsigned conidsts:1;
+        unsigned dbnctime:1;
+        unsigned asesvld:1;
+        unsigned bsesvld:1;
+        unsigned otgver:1;
+        unsigned reserved1:1;
+        unsigned multvalidbc:5;
+        unsigned chirpen:1;
+        unsigned reserved28_31:4;
+    } b;
+} gotgctl_data_t;
+/**
+ * This union represents the bit fields of the Core AHB Configuration
+ * Register (GAHBCFG). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY		1
+#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY	0
+typedef union gahbcfg_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned glblintrmsk:1;
+        unsigned hburstlen:4;
+        unsigned dmaenable:1;
+        unsigned reserved:1;
+        unsigned nptxfemplvl_txfemplvl:1;
+        unsigned ptxfemplvl:1;
+        unsigned reserved9_20:12;
+        unsigned remmemsupp:1;
+        unsigned notialldmawrit:1;
+        unsigned ahbsingle:1;
+        unsigned reserved24_31:8;
+    } b;
+} gahbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core USB Configuration
+ * Register (GUSBCFG). Set the bits using the bit fields then write
+ * the <i>d32</i> value to the register.
+ */
+typedef union gusbcfg_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned toutcal:3;
+        unsigned phyif:1;
+        unsigned ulpi_utmi_sel:1;
+        unsigned fsintf:1;
+        unsigned physel:1;
+        unsigned ddrsel:1;
+        unsigned srpcap:1;
+        unsigned hnpcap:1;
+        unsigned usbtrdtim:4;
+        unsigned reserved1:1;
+        unsigned phylpwrclksel:1;
+        unsigned otgutmifssel:1;
+        unsigned ulpi_fsls:1;
+        unsigned ulpi_auto_res:1;
+        unsigned ulpi_clk_sus_m:1;
+        unsigned ulpi_ext_vbus_drv:1;
+        unsigned ulpi_int_vbus_indicator:1;
+        unsigned term_sel_dl_pulse:1;
+        unsigned indicator_complement:1;
+        unsigned indicator_pass_through:1;
+        unsigned ulpi_int_prot_dis:1;
+        unsigned ic_usb_cap:1;
+        unsigned ic_traffic_pull_remove:1;
+        unsigned tx_end_delay:1;
+        unsigned force_host_mode:1;
+        unsigned force_dev_mode:1;
+        unsigned reserved31:1;
+    } b;
+} gusbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core Reset Register
+ * (GRSTCTL).  Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+typedef union grstctl_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Core Soft Reset (CSftRst) (Device and Host)
+         *
+         * The application can flush the control logic in the
+         * entire core using this bit. This bit resets the
+         * pipelines in the AHB Clock domain as well as the
+         * PHY Clock domain.
+         *
+         * The state machines are reset to an IDLE state, the
+         * control bits in the CSRs are cleared, all the
+         * transmit FIFOs and the receive FIFO are flushed.
+         *
+         * The status mask bits that control the generation of
+         * the interrupt, are cleared, to clear the
+         * interrupt. The interrupt status bits are not
+         * cleared, so the application can get the status of
+         * any events that occurred in the core after it has
+         * set this bit.
+         *
+         * Any transactions on the AHB are terminated as soon
+         * as possible following the protocol. Any
+         * transactions on the USB are terminated immediately.
+         *
+         * The configuration settings in the CSRs are
+         * unchanged, so the software doesn't have to
+         * reprogram these registers (Device
+         * Configuration/Host Configuration/Core System
+         * Configuration/Core PHY Configuration).
+         *
+         * The application can write to this bit, any time it
+         * wants to reset the core. This is a self clearing
+         * bit and the core clears this bit after all the
+         * necessary logic is reset in the core, which may
+         * take several clocks, depending on the current state
+         * of the core.
+         */
+        unsigned csftrst:1;
+        /** Hclk Soft Reset
+         *
+         * The application uses this bit to reset the control logic in
+         * the AHB clock domain. Only AHB clock domain pipelines are
+         * reset.
+         */
+        unsigned hsftrst:1;
+        /** Host Frame Counter Reset (Host Only)<br>
+         *
+         * The application can reset the (micro)frame number
+         * counter inside the core, using this bit. When the
+         * (micro)frame counter is reset, the subsequent SOF
+         * sent out by the core, will have a (micro)frame
+         * number of 0.
+         */
+        unsigned hstfrm:1;
+        /** In Token Sequence Learning Queue Flush
+         * (INTknQFlsh) (Device Only)
+         */
+        unsigned intknqflsh:1;
+        /** RxFIFO Flush (RxFFlsh) (Device and Host)
+         *
+         * The application can flush the entire Receive FIFO
+         * using this bit. The application must first
+         * ensure that the core is not in the middle of a
+         * transaction. The application should write into
+         * this bit, only after making sure that neither the
+         * DMA engine is reading from the RxFIFO nor the MAC
+         * is writing the data in to the FIFO. The
+         * application should wait until the bit is cleared
+         * before performing any other operations. This bit
+         * will takes 8 clocks (slowest of PHY or AHB clock)
+         * to clear.
+         */
+        unsigned rxfflsh:1;
+        /** TxFIFO Flush (TxFFlsh) (Device and Host).
+         *
+         * This bit is used to selectively flush a single or
+         * all transmit FIFOs. The application must first
+         * ensure that the core is not in the middle of a
+         * transaction. The application should write into
+         * this bit, only after making sure that neither the
+         * DMA engine is writing into the TxFIFO nor the MAC
+         * is reading the data out of the FIFO. The
+         * application should wait until the core clears this
+         * bit, before performing any operations. This bit
+         * will takes 8 clocks (slowest of PHY or AHB clock)
+         * to clear.
+         */
+        unsigned txfflsh:1;
+
+        /** TxFIFO Number (TxFNum) (Device and Host).
+         *
+         * This is the FIFO number which needs to be flushed,
+         * using the TxFIFO Flush bit. This field should not
+         * be changed until the TxFIFO Flush bit is cleared by
+         * the core.
+         *	 - 0x0 : Non Periodic TxFIFO Flush
+         *	 - 0x1 : Periodic TxFIFO #1 Flush in device mode
+         *	   or Periodic TxFIFO in host mode
+         *	 - 0x2 : Periodic TxFIFO #2 Flush in device mode.
+         *	 - ...
+         *	 - 0xF : Periodic TxFIFO #15 Flush in device mode
+         *	 - 0x10: Flush all the Transmit NonPeriodic and
+         *	   Transmit Periodic FIFOs in the core
+         */
+        unsigned txfnum:5;
+        /** Reserved */
+        unsigned reserved11_29:19;
+        /** DMA Request Signal.	 Indicated DMA request is in
+         * probress. Used for debug purpose. */
+        unsigned dmareq:1;
+        /** AHB Master Idle.  Indicates the AHB Master State
+         * Machine is in IDLE condition. */
+        unsigned ahbidle:1;
+    } b;
+} grstctl_t;
+
+/**
+ * This union represents the bit fields of the Core Interrupt Mask
+ * Register (GINTMSK). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+typedef union gintmsk_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned reserved0:1;
+        unsigned modemismatch:1;
+        unsigned otgintr:1;
+        unsigned sofintr:1;
+        unsigned rxstsqlvl:1;
+        unsigned nptxfempty:1;
+        unsigned ginnakeff:1;
+        unsigned goutnakeff:1;
+        unsigned ulpickint:1;
+        unsigned i2cintr:1;
+        unsigned erlysuspend:1;
+        unsigned usbsuspend:1;
+        unsigned usbreset:1;
+        unsigned enumdone:1;
+        unsigned isooutdrop:1;
+        unsigned eopframe:1;
+        unsigned restoredone:1;
+        unsigned epmismatch:1;
+        unsigned inepintr:1;
+        unsigned outepintr:1;
+        unsigned incomplisoin:1;
+        unsigned incomplisoout:1;
+        unsigned fetsusp:1;
+        unsigned resetdet:1;
+        unsigned portintr:1;
+        unsigned hcintr:1;
+        unsigned ptxfempty:1;
+        unsigned lpmtranrcvd:1;
+        unsigned conidstschng:1;
+        unsigned disconnect:1;
+        unsigned sessreqintr:1;
+        unsigned wkupintr:1;
+    } b;
+} gintmsk_data_t;
+/**
+ * This union represents the bit fields of the Core Interrupt Register
+ * (GINTSTS).  Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+#define DWC_SOF_INTR_MASK 0x0008
+#define DWC_HOST_MODE 1
+
+typedef union gintsts_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned curmode:1;
+        unsigned modemismatch:1;
+        unsigned otgintr:1;
+        unsigned sofintr:1;
+        unsigned rxstsqlvl:1;
+        unsigned nptxfempty:1;
+        unsigned ginnakeff:1;
+        unsigned goutnakeff:1;
+        unsigned ulpickint:1;
+        unsigned i2cintr:1;
+        unsigned erlysuspend:1;
+        unsigned usbsuspend:1;
+        unsigned usbreset:1;
+        unsigned enumdone:1;
+        unsigned isooutdrop:1;
+        unsigned eopframe:1;
+        unsigned restoredone:1;
+        unsigned epmismatch:1;
+        unsigned inepint:1;
+        unsigned outepintr:1;
+        unsigned incomplisoin:1;
+        unsigned incomplisoout:1;
+        unsigned fetsusp:1;
+        unsigned resetdet:1;
+        unsigned portintr:1;
+        unsigned hcintr:1;
+        unsigned ptxfempty:1;
+        unsigned lpmtranrcvd:1;
+        unsigned conidstschng:1;
+        unsigned disconnect:1;
+        unsigned sessreqintr:1;
+        unsigned wkupintr:1;
+    } b;
+} gintsts_data_t;
+
+/**
+ * This union represents the bit fields in the Device Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
+ * element then read out the bits using the <i>b</i>it elements.
+ */
+
+#define DWC_STS_DATA_UPDT		0x2	// OUT Data Packet
+#define DWC_STS_XFER_COMP		0x3	// OUT Data Transfer Complete
+#define DWC_DSTS_GOUT_NAK		0x1	// Global OUT NAK
+#define DWC_DSTS_SETUP_COMP	0x4	// Setup Phase Complete
+#define DWC_DSTS_SETUP_UPDT   0x6	// SETUP Packet
+
+typedef union device_grxsts_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned epnum:4;
+        unsigned bcnt:11;
+        unsigned dpid:2;
+        unsigned pktsts:4;
+        unsigned fn:4;
+        unsigned reserved25_31:7;
+    } b;
+} device_grxsts_data_t;
+/**
+ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element
+ * then read out the bits using the <i>b</i>it elements.
+ */
+typedef union fifosize_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned startaddr:16;
+        unsigned depth:16;
+    } b;
+} fifosize_data_t;
+
+/**
+ * This union represents the bit fields in the Non-Periodic Transmit
+ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union gnptxsts_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned nptxfspcavail:16;
+        unsigned nptxqspcavail:8;
+        /** Top of the Non-Periodic Transmit Request Queue
+         *	- bit 24 - Terminate (Last entry for the selected
+         *	  channel/EP)
+         *	- bits 26:25 - Token Type
+         *	  - 2'b00 - IN/OUT
+         *	  - 2'b01 - Zero Length OUT
+         *	  - 2'b10 - PING/Complete Split
+         *	  - 2'b11 - Channel Halt
+         *	- bits 30:27 - Channel/EP Number
+         */
+        unsigned nptxqtop_terminate:1;
+        unsigned nptxqtop_token:2;
+        unsigned nptxqtop_chnep:4;
+        unsigned reserved:1;
+    } b;
+} gnptxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Transmit
+ * FIFO Status Register (DTXFSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union dtxfsts_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned txfspcavail:16;
+        unsigned reserved:16;
+    } b;
+} dtxfsts_data_t;
+/**
+ * This union represents the bit fields in the User HW Config1
+ * Register.  Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg1_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned ep_dir0:2;
+        unsigned ep_dir1:2;
+        unsigned ep_dir2:2;
+        unsigned ep_dir3:2;
+        unsigned ep_dir4:2;
+        unsigned ep_dir5:2;
+        unsigned ep_dir6:2;
+        unsigned ep_dir7:2;
+        unsigned ep_dir8:2;
+        unsigned ep_dir9:2;
+        unsigned ep_dir10:2;
+        unsigned ep_dir11:2;
+        unsigned ep_dir12:2;
+        unsigned ep_dir13:2;
+        unsigned ep_dir14:2;
+        unsigned ep_dir15:2;
+    } b;
+} hwcfg1_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config2
+ * Register.  Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
+#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
+
+typedef union hwcfg2_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /* GHWCFG2 */
+        unsigned op_mode:3;
+        unsigned architecture:2; //00 salve-only;01 external dma;10 internal dma;
+        unsigned point2point:1;
+        unsigned hs_phy_type:2;
+        unsigned fs_phy_type:2;
+        unsigned num_dev_ep:4;
+        unsigned num_host_chan:4;
+        unsigned perio_ep_supported:1;
+        unsigned dynamic_fifo:1;
+        unsigned multi_proc_int:1;
+        unsigned reserved21:1;
+        unsigned nonperio_tx_q_depth:2;
+        unsigned host_perio_tx_q_depth:2;
+        unsigned dev_token_q_depth:5;
+        unsigned otg_enable_ic_usb:1;
+    } b;
+} hwcfg2_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config3
+ * Register.  Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg3_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /* GHWCFG3 */
+        unsigned xfer_size_cntr_width:4;
+        unsigned packet_size_cntr_width:3;
+        unsigned otg_func:1;
+        unsigned i2c:1;
+        unsigned vendor_ctrl_if:1;
+        unsigned optional_features:1;
+        unsigned synch_reset_type:1;
+        unsigned adp_supp:1;
+        unsigned otg_enable_hsic:1;
+        unsigned bc_support:1;
+        unsigned otg_lpm_en:1;
+        unsigned dfifo_depth:16;
+    } b;
+} hwcfg3_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config4
+ * Register.  Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg4_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        unsigned num_dev_perio_in_ep:4;
+        unsigned power_optimiz:1;
+        unsigned min_ahb_freq:1;
+        unsigned hiber:1;
+        unsigned xhiber:1;
+        unsigned reserved:6;
+        unsigned utmi_phy_data_width:2;
+        unsigned num_dev_mode_ctrl_ep:4;
+        unsigned iddig_filt_en:1;
+        unsigned vbus_valid_filt_en:1;
+        unsigned a_valid_filt_en:1;
+        unsigned b_valid_filt_en:1;
+        unsigned session_end_filt_en:1;
+        unsigned ded_fifo_en:1;
+        unsigned num_in_eps:4;
+        unsigned desc_dma:1;
+        unsigned desc_dma_dyn:1;
+    } b;
+} hwcfg4_data_t;
+
+/**
+ * This union represents the bit fields of the Core LPM Configuration
+ * Register (GLPMCFG). Set the bits using bit fields then write
+ * the <i>d32</i> value to the register.
+ */
+typedef union glpmctl_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** LPM-Capable (LPMCap) (Device and Host)
+         * The application uses this bit to control
+         * the DWC_otg core LPM capabilities.
+         */
+        unsigned lpm_cap_en:1;
+        /** LPM response programmed by application (AppL1Res) (Device)
+         * Handshake response to LPM token pre-programmed
+         * by device application software.
+         */
+        unsigned appl_resp:1;
+        /** Host Initiated Resume Duration (HIRD) (Device and Host)
+         * In Host mode this field indicates the value of HIRD
+         * to be sent in an LPM transaction.
+         * In Device mode this field is updated with the
+         * Received LPM Token HIRD bmAttribute
+         * when an ACK/NYET/STALL response is sent
+         * to an LPM transaction.
+         */
+        unsigned hird:4;
+        /** RemoteWakeEnable (bRemoteWake) (Device and Host)
+         * In Host mode this bit indicates the value of remote
+         * wake up to be sent in wIndex field of LPM transaction.
+         * In Device mode this field is updated with the
+         * Received LPM Token bRemoteWake bmAttribute
+         * when an ACK/NYET/STALL response is sent
+         * to an LPM transaction.
+         */
+        unsigned rem_wkup_en:1;
+        /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
+         * The application uses this bit to control
+         * the utmi_sleep_n assertion to the PHY when in L1 state.
+         */
+        unsigned en_utmi_sleep:1;
+        /** HIRD Threshold (HIRD_Thres) (Device and Host)
+         */
+        unsigned hird_thres:5;
+        /** LPM Response (CoreL1Res) (Device and Host)
+         * In Host mode this bit contains handsake response to
+         * LPM transaction.
+         * In Device mode the response of the core to
+         * LPM transaction received is reflected in these two bits.
+         	- 0x0 : ERROR (No handshake response)
+        	- 0x1 : STALL
+        	- 0x2 : NYET
+        	- 0x3 : ACK
+         */
+        unsigned lpm_resp:2;
+        /** Port Sleep Status (SlpSts) (Device and Host)
+         * This bit is set as long as a Sleep condition
+         * is present on the USB bus.
+         */
+        unsigned prt_sleep_sts:1;
+        /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
+         * Indicates that the application or host
+         * can start resume from Sleep state.
+         */
+        unsigned sleep_state_resumeok:1;
+        /** LPM channel Index (LPM_Chnl_Indx) (Host)
+         * The channel number on which the LPM transaction
+         * has to be applied while sending
+         * an LPM transaction to the local device.
+         */
+        unsigned lpm_chan_index:4;
+        /** LPM Retry Count (LPM_Retry_Cnt) (Host)
+         * Number host retries that would be performed
+         * if the device response was not valid response.
+         */
+        unsigned retry_count:3;
+        /** Send LPM Transaction (SndLPM) (Host)
+         * When set by application software,
+         * an LPM transaction containing two tokens
+         * is sent.
+         */
+        unsigned send_lpm:1;
+        /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
+         * Number of LPM Host Retries still remaining
+         * to be transmitted for the current LPM sequence
+         */
+        unsigned retry_count_sts:3;
+        unsigned reserved28_29:2;
+        /** In host mode once this bit is set, the host
+         * configures to drive the HSIC Idle state on the bus.
+         * It then waits for the  device to initiate the Connect sequence.
+         * In device mode once this bit is set, the device waits for
+         * the HSIC Idle line state on the bus. Upon receving the Idle
+         * line state, it initiates the HSIC Connect sequence.
+         */
+        unsigned hsic_connect:1;
+        /** This bit overrides and functionally inverts
+         * the if_select_hsic input port signal.
+         */
+        unsigned inv_sel_hsic:1;
+    } b;
+} glpmcfg_data_t;
+// Device Registers
+/**
+ * Device Global Registers. <i>Offsets 800h-BFFh</i>
+ *
+ * The following structures define the size and relative field offsets
+ * for the Device Mode Registers.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_global_regs
+{
+    /** Device Configuration Register. <i>Offset 800h</i> */
+    volatile uint32_t dcfg;
+    /** Device Control Register. <i>Offset: 804h</i> */
+    volatile uint32_t dctl;
+    /** Device Status Register (Read Only). <i>Offset: 808h</i> */
+    volatile uint32_t dsts;
+    /** Reserved. <i>Offset: 80Ch</i> */
+    uint32_t unused;
+    /** Device IN Endpoint Common Interrupt Mask
+     * Register. <i>Offset: 810h</i> */
+    volatile uint32_t diepmsk;
+    /** Device OUT Endpoint Common Interrupt Mask
+     * Register. <i>Offset: 814h</i> */
+    volatile uint32_t doepmsk;
+    /** Device All Endpoints Interrupt Register.  <i>Offset: 818h</i> */
+    volatile uint32_t daint;
+    /** Device All Endpoints Interrupt Mask Register.  <i>Offset:
+     * 81Ch</i> */
+    volatile uint32_t daintmsk;
+    /** Device IN Token Queue Read Register-1 (Read Only).
+     * <i>Offset: 820h</i> */
+    volatile uint32_t dtknqr1;
+    /** Device IN Token Queue Read Register-2 (Read Only).
+     * <i>Offset: 824h</i> */
+    volatile uint32_t dtknqr2;
+    /** Device VBUS	 discharge Register.  <i>Offset: 828h</i> */
+    volatile uint32_t dvbusdis;
+    /** Device VBUS Pulse Register.	 <i>Offset: 82Ch</i> */
+    volatile uint32_t dvbuspulse;
+    /** Device IN Token Queue Read Register-3 (Read Only). /
+     *	Device Thresholding control register (Read/Write)
+     * <i>Offset: 830h</i> */
+    volatile uint32_t dtknqr3_dthrctl;
+    /** Device IN Token Queue Read Register-4 (Read Only). /
+     *	Device IN EPs empty Inr. Mask Register (Read/Write)
+     * <i>Offset: 834h</i> */
+    volatile uint32_t dtknqr4_fifoemptymsk;
+    /** Device Each Endpoint Interrupt Register (Read Only). /
+     * <i>Offset: 838h</i> */
+    volatile uint32_t deachint;
+    /** Device Each Endpoint Interrupt mask Register (Read/Write). /
+     * <i>Offset: 83Ch</i> */
+    volatile uint32_t deachintmsk;
+    /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
+     * <i>Offset: 840h</i> */
+    volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
+    /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
+     * <i>Offset: 880h</i> */
+    volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
+} dwc_otg_device_global_regs_t;
+
+/**
+ * This union represents the bit fields in the Device Configuration
+ * Register.  Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.  Write the
+ * <i>d32</i> member to the dcfg register.
+ */
+#define DWC_DCFG_SEND_STALL 1
+#define DWC_DCFG_FRAME_INTERVAL_80 0
+#define DWC_DCFG_FRAME_INTERVAL_85 1
+#define DWC_DCFG_FRAME_INTERVAL_90 2
+#define DWC_DCFG_FRAME_INTERVAL_95 3
+
+typedef union dcfg_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Device Speed */
+        unsigned devspd:2;
+        /** Non Zero Length Status OUT Handshake */
+        unsigned nzstsouthshk:1;
+        unsigned ena32khzs:1;
+        /** Device Addresses */
+        unsigned devaddr:7;
+        /** Periodic Frame Interval */
+        unsigned perfrint:2;
+        /** Enable Device OUT NAK for bulk in DDMA mode */
+        unsigned endevoutnak:1;
+        unsigned reserved14_17:4;
+        /** In Endpoint Mis-match count */
+        unsigned epmscnt:5;
+        /** Enable Descriptor DMA in Device mode */
+        unsigned descdma:1;
+        unsigned perschintvl:2;
+        unsigned resvalid:6;
+    } b;
+} dcfg_data_t;
+
+/**
+ * This union represents the bit fields in the Device Control
+ * Register.  Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union dctl_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Remote Wakeup */
+        unsigned rmtwkupsig:1;
+        /** Soft Disconnect */
+        unsigned sftdiscon:1;
+        /** Global Non-Periodic IN NAK Status */
+        unsigned gnpinnaksts:1;
+        /** Global OUT NAK Status */
+        unsigned goutnaksts:1;
+        /** Test Control */
+        unsigned tstctl:3;
+        /** Set Global Non-Periodic IN NAK */
+        unsigned sgnpinnak:1;
+        /** Clear Global Non-Periodic IN NAK */
+        unsigned cgnpinnak:1;
+        /** Set Global OUT NAK */
+        unsigned sgoutnak:1;
+        /** Clear Global OUT NAK */
+        unsigned cgoutnak:1;
+        /** Power-On Programming Done */
+        unsigned pwronprgdone:1;
+        /** Reserved */
+        unsigned reserved:1;
+        /** Global Multi Count */
+        unsigned gmc:2;
+        /** Ignore Frame Number for ISOC EPs */
+        unsigned ifrmnum:1;
+        /** NAK on Babble */
+        unsigned nakonbble:1;
+        /** Enable Continue on BNA */
+        unsigned encontonbna:1;
+
+        unsigned reserved18_31:14;
+    } b;
+} dctl_data_t;
+
+/**
+ * This union represents the bit fields in the Device Status
+ * Register.  Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
+#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
+#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ		   2
+#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ		   3
+typedef union dsts_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Suspend Status */
+        unsigned suspsts:1;
+        /** Enumerated Speed */
+        unsigned enumspd:2;
+        /** Erratic Error */
+        unsigned errticerr:1;
+        unsigned reserved4_7:4;
+        /** Frame or Microframe Number of the received SOF */
+        unsigned soffn:14;
+        unsigned reserved22_31:10;
+    } b;
+} dsts_data_t;
+
+/**
+ * This union represents the bit fields in the Device IN EP Interrupt
+ * Register and the Device IN EP Common Mask Register.
+ *
+ * - Read the register into the <i>d32</i> member then set/clear the
+ *	 bits using the <i>b</i>it elements.
+ */
+typedef union diepint_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Transfer complete mask */
+        unsigned xfercompl:1;
+        /** Endpoint disable mask */
+        unsigned epdisabled:1;
+        /** AHB Error mask */
+        unsigned ahberr:1;
+        /** TimeOUT Handshake mask (non-ISOC EPs) */
+        unsigned timeout:1;
+        /** IN Token received with TxF Empty mask */
+        unsigned intktxfemp:1;
+        /** IN Token Received with EP mismatch mask */
+        unsigned intknepmis:1;
+        /** IN Endpoint NAK Effective mask */
+        unsigned inepnakeff:1;
+        /** Reserved */
+        unsigned emptyintr:1;
+
+        unsigned txfifoundrn:1;
+
+        /** BNA Interrupt mask */
+        unsigned bna:1;
+
+        unsigned reserved10_12:3;
+        /** BNA Interrupt mask */
+        unsigned nak:1;
+
+        unsigned reserved14_31:18;
+    } b;
+} diepint_data_t;
+
+/**
+ * This union represents the bit fields in the Device IN EP
+ * Common/Dedicated Interrupt Mask Register.
+ */
+typedef union diepint_data diepmsk_data_t;
+
+/**
+ * This union represents the bit fields in the Device OUT EP Interrupt
+ * Registerand Device OUT EP Common Interrupt Mask Register.
+ *
+ * - Read the register into the <i>d32</i> member then set/clear the
+ *	 bits using the <i>b</i>it elements.
+ */
+typedef union doepint_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Transfer complete */
+        unsigned xfercompl:1;
+        /** Endpoint disable  */
+        unsigned epdisabled:1;
+        /** AHB Error */
+        unsigned ahberr:1;
+        /** Setup Phase Done (contorl EPs) */
+        unsigned setup:1;
+        /** OUT Token Received when Endpoint Disabled */
+        unsigned outtknepdis:1;
+
+        unsigned stsphsercvd:1;
+        /** Back-to-Back SETUP Packets Received */
+        unsigned back2backsetup:1;
+
+        unsigned reserved7:1;
+        /** OUT packet Error */
+        unsigned outpkterr:1;
+        /** BNA Interrupt */
+        unsigned bna:1;
+
+        unsigned reserved10:1;
+        /** Packet Drop Status */
+        unsigned pktdrpsts:1;
+        /** Babble Interrupt */
+        unsigned babble:1;
+        /** NAK Interrupt */
+        unsigned nak:1;
+        /** NYET Interrupt */
+        unsigned nyet:1;
+        /** Bit indicating setup packet received */
+        unsigned sr:1;
+
+        unsigned reserved16_31:16;
+    } b;
+} doepint_data_t;
+
+/**
+ * This union represents the bit fields in the Device OUT EP
+ * Common/Dedicated Interrupt Mask Register.
+ */
+typedef union doepint_data doepmsk_data_t;
+
+/**
+ * This union represents the bit fields in the Device All EP Interrupt
+ * and Mask Registers.
+ * - Read the register into the <i>d32</i> member then set/clear the
+ *	 bits using the <i>b</i>it elements.
+ */
+typedef union daint_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** IN Endpoint bits */
+        unsigned in:16;
+        /** OUT Endpoint bits */
+        unsigned out:16;
+    } ep;
+    struct
+    {
+        /** IN Endpoint bits */
+        unsigned inep0:1;
+        unsigned inep1:1;
+        unsigned inep2:1;
+        unsigned inep3:1;
+        unsigned inep4:1;
+        unsigned inep5:1;
+        unsigned inep6:1;
+        unsigned inep7:1;
+        unsigned inep8:1;
+        unsigned inep9:1;
+        unsigned inep10:1;
+        unsigned inep11:1;
+        unsigned inep12:1;
+        unsigned inep13:1;
+        unsigned inep14:1;
+        unsigned inep15:1;
+        /** OUT Endpoint bits */
+        unsigned outep0:1;
+        unsigned outep1:1;
+        unsigned outep2:1;
+        unsigned outep3:1;
+        unsigned outep4:1;
+        unsigned outep5:1;
+        unsigned outep6:1;
+        unsigned outep7:1;
+        unsigned outep8:1;
+        unsigned outep9:1;
+        unsigned outep10:1;
+        unsigned outep11:1;
+        unsigned outep12:1;
+        unsigned outep13:1;
+        unsigned outep14:1;
+        unsigned outep15:1;
+    } b;
+} daint_data_t;
+
+/**
+ * This union represents the bit fields in the Device IN Token Queue
+ * Read Registers.
+ * - Read the register into the <i>d32</i> member.
+ * - READ-ONLY Register
+ */
+typedef union dtknq1_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** In Token Queue Write Pointer */
+        unsigned intknwptr:5;
+        /** Reserved */
+        unsigned reserved05_06:2;
+        /** write pointer has wrapped. */
+        unsigned wrap_bit:1;
+        /** EP Numbers of IN Tokens 0 ... 4 */
+        unsigned epnums0_5:24;
+    } b;
+} dtknq1_data_t;
+
+
+/**
+ * Device Logical IN Endpoint-Specific Registers. <i>Offsets
+ * 900h-AFCh</i>
+ *
+ * There will be one set of endpoint registers per logical endpoint
+ * implemented.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_in_ep_regs
+{
+    /** Device IN Endpoint Control Register. <i>Offset:900h +
+     * (ep_num * 20h) + 00h</i> */
+    volatile uint32_t diepctl;
+    /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
+    uint32_t reserved04;
+    /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
+     * (ep_num * 20h) + 08h</i> */
+    volatile uint32_t diepint;
+    /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
+    uint32_t reserved0C;
+    /** Device IN Endpoint Transfer Size
+     * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
+    volatile uint32_t dieptsiz;
+    /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
+     * (ep_num * 20h) + 14h</i> */
+    volatile uint32_t diepdma;
+    /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
+     * (ep_num * 20h) + 18h</i> */
+    volatile uint32_t dtxfsts;
+    /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
+     * (ep_num * 20h) + 1Ch</i> */
+    volatile uint32_t diepdmab;
+} dwc_otg_dev_in_ep_regs_t;
+
+/**
+ * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
+ * B00h-CFCh</i>
+ *
+ * There will be one set of endpoint registers per logical endpoint
+ * implemented.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_out_ep_regs
+{
+    /** Device OUT Endpoint Control Register. <i>Offset:B00h +
+     * (ep_num * 20h) + 00h</i> */
+    volatile uint32_t doepctl;
+    /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
+    uint32_t reserved04;
+    /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
+     * (ep_num * 20h) + 08h</i> */
+    volatile uint32_t doepint;
+    /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
+    uint32_t reserved0C;
+    /** Device OUT Endpoint Transfer Size Register. <i>Offset:
+     * B00h + (ep_num * 20h) + 10h</i> */
+    volatile uint32_t doeptsiz;
+    /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
+     * + (ep_num * 20h) + 14h</i> */
+    volatile uint32_t doepdma;
+    /** Reserved. <i>Offset:B00h + 	 * (ep_num * 20h) + 18h</i> */
+    uint32_t unused;
+    /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
+     * + (ep_num * 20h) + 1Ch</i> */
+    uint32_t doepdmab;
+} dwc_otg_dev_out_ep_regs_t;
+
+/**
+ * This union represents the bit fields in the Device EP Control
+ * Register.  Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+#define DWC_DEP0CTL_MPS_64	 0
+#define DWC_DEP0CTL_MPS_32	 1
+#define DWC_DEP0CTL_MPS_16	 2
+#define DWC_DEP0CTL_MPS_8	     3
+
+typedef union depctl_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Maximum Packet Size
+         * IN/OUT EPn
+         * IN/OUT EP0 - 2 bits
+         *	 2'b00: 64 Bytes
+         *	 2'b01: 32
+         *	 2'b10: 16
+         *	 2'b11: 8 */
+        unsigned mps:11;
+        /** Next Endpoint
+         * IN EPn/IN EP0
+         * OUT EPn/OUT EP0 - reserved */
+        unsigned nextep:4;
+
+        /** USB Active Endpoint */
+        unsigned usbactep:1;
+
+        /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
+         * This field contains the PID of the packet going to
+         * be received or transmitted on this endpoint. The
+         * application should program the PID of the first
+         * packet going to be received or transmitted on this
+         * endpoint , after the endpoint is
+         * activated. Application use the SetD1PID and
+         * SetD0PID fields of this register to program either
+         * D0 or D1 PID.
+         *
+         * The encoding for this field is
+         *	 - 0: D0
+         *	 - 1: D1
+         */
+        unsigned dpid:1;
+
+        /** NAK Status */
+        unsigned naksts:1;
+
+        /** Endpoint Type
+         *	2'b00: Control
+         *	2'b01: Isochronous
+         *	2'b10: Bulk
+         *	2'b11: Interrupt */
+        unsigned eptype:2;
+
+        /** Snoop Mode
+         * OUT EPn/OUT EP0
+         * IN EPn/IN EP0 - reserved */
+        unsigned snp:1;
+
+        /** Stall Handshake */
+        unsigned stall:1;
+
+        /** Tx Fifo Number
+         * IN EPn/IN EP0
+         * OUT EPn/OUT EP0 - reserved */
+        unsigned txfnum:4;
+
+        /** Clear NAK */
+        unsigned cnak:1;
+        /** Set NAK */
+        unsigned snak:1;
+        /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
+         * Writing to this field sets the Endpoint DPID (DPID)
+         * field in this register to DATA0. Set Even
+         * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
+         * Writing to this field sets the Even/Odd
+         * (micro)frame (EO_FrNum) field to even (micro)
+         * frame.
+         */
+        unsigned setd0pid:1;
+        /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
+         * Writing to this field sets the Endpoint DPID (DPID)
+         * field in this register to DATA1 Set Odd
+         * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
+         * Writing to this field sets the Even/Odd
+         * (micro)frame (EO_FrNum) field to odd (micro) frame.
+         */
+        unsigned setd1pid:1;
+
+        /** Endpoint Disable */
+        unsigned epdis:1;
+        /** Endpoint Enable */
+        unsigned epena:1;
+    } b;
+} depctl_data_t;
+
+/**
+ * This union represents the bit fields in the Device EP Transfer
+ * Size Register.  Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+
+/** Max packet count for EP (pow(2,10)-1) */
+#define MAX_PKT_CNT 1023
+typedef union deptsiz_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Transfer size */
+        unsigned xfersize:19;
+        /** Packet Count */
+        unsigned pktcnt:10;
+        /** Multi Count - Periodic IN endpoints */
+        unsigned mc:2;
+        unsigned reserved:1;
+    } b;
+} deptsiz_data_t;
+
+/**
+ * This union represents the bit fields in the Device EP 0 Transfer
+ * Size Register.  Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union deptsiz0_data
+{
+    /** raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** Transfer size */
+        unsigned xfersize:7;
+        /** Reserved */
+        unsigned reserved7_18:12;
+        /** Packet Count */
+        unsigned pktcnt:2;
+        /** Reserved */
+        unsigned reserved21_28:8;
+        /**Setup Packet Count (DOEPTSIZ0 Only) */
+        unsigned supcnt:2;
+        unsigned reserved31;
+    } b;
+} deptsiz0_data_t;
+
+/////////////////////////////////////////////////
+// DMA Descriptor Specific Structures
+//
+
+/** Buffer status definitions */
+
+#define BS_HOST_READY	0x0
+#define BS_DMA_BUSY		0x1
+#define BS_DMA_DONE		0x2
+#define BS_HOST_BUSY	0x3
+
+/** Receive/Transmit status definitions */
+
+#define RTS_SUCCESS		0x0
+#define RTS_BUFFLUSH	0x1
+#define RTS_RESERVED	0x2
+#define RTS_BUFERR		0x3
+
+
+/**
+ * The dwc_otg_dev_if structure contains information needed to manage
+ * the DWC_otg controller acting in device mode. It represents the
+ * programming view of the device-specific aspects of the controller.
+ */
+#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
+#define DWC_DEV_IN_EP_REG_OFFSET 0x900
+#define DWC_EP_REG_OFFSET 0x20
+#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
+
+typedef struct  dwc_otg_dev_if
+{
+    /** Pointer to device Global registers.
+     * Device Global Registers starting at offset 800h
+     */
+    dwc_otg_device_global_regs_t *dev_global_regs;
+    /**
+     * Device Logical IN Endpoint-Specific Registers 900h-AFCh
+     */
+    dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
+
+    /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
+    dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
+    /* Device configuration information */
+    uint8_t speed;				 /**< Device Speed	0: Unknown, 1: LS, 2:FS, 3: HS */
+    uint8_t num_in_eps;		 /**< Number # of Tx EP range: 0-15 exept ep0 */
+    uint8_t num_out_eps;		 /**< Number # of Rx EP range: 0-15 exept ep 0*/
+
+    /** Thresholding enable flags and length varaiables **/
+    uint16_t rx_thr_en;
+    //uint16_t iso_tx_thr_en;
+    uint16_t non_iso_tx_thr_en;
+
+    uint16_t rx_thr_length;
+    uint16_t tx_thr_length;
+
+    /**
+     * Pointers to the DMA Descriptors for EP0 Control
+     * transfers (virtual and physical)
+     */
+
+    /** Setup Packet Detected - if set clear NAK when queueing */
+    uint32_t spd;
+
+} dwc_otg_dev_if_t;
+
+/////////////////////////////////////////////////
+// Host Mode Register Structures
+//
+
+/**
+ * This union represents the bit fields in the Host Configuration Register.
+ * Read the register into the <i>d32</i> member then set/clear the bits using
+ * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
+ */
+#define DWC_HCFG_30_60_MHZ 0
+#define DWC_HCFG_48_MHZ	   1
+#define DWC_HCFG_6_MHZ	   2
+/**
+ * This union represents the bit fields in the Power and Clock Gating Control
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union pcgcctl_data
+{
+    /** raw register data */
+    uint32_t d32;
+
+    /** register bits */
+    struct
+    {
+        /** Stop Pclk */
+        unsigned stoppclk:1;
+        /** Gate Hclk */
+        unsigned gatehclk:1;
+        /** Power Clamp */
+        unsigned pwrclmp:1;
+        /** Reset Power Down Modules */
+        unsigned rstpdwnmodule:1;
+        /** Reserved */
+        unsigned reserved:1;
+        /** Enable Sleep Clock Gating (Enbl_L1Gating) */
+        unsigned enbl_sleep_gating:1;
+        /** PHY In Sleep (PhySleep) */
+        unsigned phy_in_sleep:1;
+        /** Deep Sleep*/
+        unsigned deep_sleep:1;
+        unsigned resetaftsusp:1;
+        unsigned restoremode:1;
+        unsigned enbl_extnd_hiber:1;
+        unsigned extnd_hiber_pwrclmp:1;
+        unsigned extnd_hiber_switch:1;
+        unsigned ess_reg_restored:1;
+        unsigned prt_clk_sel:2;
+        unsigned port_power:1;
+        unsigned max_xcvrselect:2;
+        unsigned max_termsel:1;
+        unsigned mac_dev_addr:7;
+        unsigned p2hd_dev_enum_spd:2;
+        unsigned p2hd_prt_spd:2;
+        unsigned if_dev_mode:1;
+    } b;
+} pcgcctl_data_t;
+
+/**
+ * This union represents the bit fields in the Global Data FIFO Software
+ * Configuration Register. Read the register into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union gdfifocfg_data
+{
+    /* raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** OTG Data FIFO depth */
+        unsigned gdfifocfg:16;
+        /** Start address of EP info controller */
+        unsigned epinfobase:16;
+    } b;
+} gdfifocfg_data_t;
+
+/**
+ * This union represents the bit fields in the Global Power Down Register
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+#define disconn_det disconn_det
+
+#define lnstschng   lnstschng
+
+#define rst_det rst_det
+
+#define srp_det srp_det
+
+#define sts_chngint sts_chngint
+
+typedef union gpwrdn_data
+{
+    /* raw register data */
+    uint32_t d32;
+    /** register bits */
+    struct
+    {
+        /** PMU Interrupt Select */
+        unsigned pmuintsel:1;
+        /** PMU Active */
+        unsigned pmuactv:1;
+        /** Restore */
+        unsigned restore:1;
+        /** Power Down Clamp */
+        unsigned pwrdnclmp:1;
+        /** Power Down Reset */
+        unsigned pwrdnrstn:1;
+        /** Power Down Switch */
+        unsigned pwrdnswtch:1;
+        /** Disable VBUS */
+        unsigned dis_vbus:1;
+        /** Line State Change */
+        unsigned lnstschng:1;
+        /** Line state change mask */
+        unsigned lnstchng_msk:1;
+        /** Reset Detected */
+        unsigned rst_det:1;
+        /** Reset Detect mask */
+        unsigned rst_det_msk:1;
+        /** Disconnect Detected */
+        unsigned disconn_det:1;
+        /** Disconnect Detect mask */
+        unsigned disconn_det_msk:1;
+        /** Connect Detected*/
+        unsigned connect_det:1;
+        /** Connect Detected Mask*/
+        unsigned connect_det_msk:1;
+        /** SRP Detected */
+        unsigned srp_det:1;
+        /** SRP Detect mask */
+        unsigned srp_det_msk:1;
+        /** Status Change Interrupt */
+        unsigned sts_chngint:1;
+        /** Status Change Interrupt Mask */
+        unsigned sts_chngint_msk:1;
+        /** Line State */
+        unsigned linestate:2;
+        /** Indicates current mode(status of IDDIG signal) */
+        unsigned idsts:1;
+        /** B Session Valid signal status*/
+        unsigned bsessvld:1;
+        /** ADP Event Detected */
+        unsigned adp_int:1;
+        /** Multi Valued ID pin */
+        unsigned mult_val_id_bc:5;
+        /** Reserved 24_31 */
+        unsigned reserved29_31:3;
+    } b;
+} gpwrdn_data_t;
+
+#endif
diff --git a/boot/common/src/loader/drivers/efuse.c b/boot/common/src/loader/drivers/efuse.c
new file mode 100644
index 0000000..0aa6bf8
--- /dev/null
+++ b/boot/common/src/loader/drivers/efuse.c
@@ -0,0 +1,100 @@
+/*
+ ***********************************************************	
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <sdio.h>
+
+#include "efuse.h"
+
+
+
+void efuse_init(void)
+{
+	//start read efuse all 256bit
+	while((REG32(SYS_EFUSE_BASE + 0x4) & 1) == 1);// bit0=1 ctl is busy
+	REG32(SYS_EFUSE_BASE + 0x4) = 1;
+	while((REG32(SYS_EFUSE_BASE + 0x14) & 2) == 0);//bit1=0 read not over
+}
+
+int get_ddr_flag(void)
+{
+	efuse_struct *psEfuseInfo = NULL;
+	int ddr_flag = 0;
+
+
+	psEfuseInfo = (efuse_struct*)EFUSE_RAM_BASE;
+
+	/* get chip flag */
+	if(((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_GW_WINBD_256M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_ZW_WINBD_256M_DDR)		
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_GW_UNILC_256M_DDR)		
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_ZW_UNILC_256M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_GW_APM_256M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_ZW_APM_256M_DDR))
+	{
+		ddr_flag = CHIP_DDR_32M;
+	}	
+	else if(((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_GW_UNILC_512M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_GW_APM_512M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_GW_ESMT_512M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_ZW_UNILC_512M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_AZW_UNILC_512M_DDR)		
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_ZW_APM_512M_DDR)
+		||((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECO_ZW_ESMT_512M_DDR))
+	{
+		ddr_flag = CHIP_DDR_64M;
+	}
+	else if((psEfuseInfo->secure_flag >> 8) == ZX297520V3ECOSC_GW_NYC_2G_DDR)
+	{
+		ddr_flag = CHIP_DDR_256M;
+	}
+	else
+	{
+		ddr_flag = CHIP_DDR_128M;
+	}
+
+	return ddr_flag;
+}
+
+int get_secure_verify_status(void)
+{
+	u32 uiLen;
+	efuse_struct *psEfuseInfo = NULL;
+
+	if((REG32(EFUSE_BYPASS) & 1) == 1)   //Secure Verify. 1->Disable, 0->Enable.
+	{
+		return SECURE_VERIFY_DISABLE;
+	}
+	
+	/*
+	 * 0. Èç¹ûsecure flag²»µÈÓÚ0xFF£¬Í˳ö°²È«boot¡£
+	 */
+	psEfuseInfo = (efuse_struct*)EFUSE_RAM_BASE;
+	if((psEfuseInfo->secure_flag & 0xFF) != 0xFF)
+	{
+		return SECURE_VERIFY_DISABLE;
+	}	
+	
+	/*
+	 * 1.´ÓefuseÖжÁ³öpuk_hash[127:0], ÅжÏÈç¹ûÈ«²¿Îª0Í˳ö°²È«boot¡£
+	 */
+	for(uiLen = 0; uiLen < 4; uiLen++)
+	{
+		if(psEfuseInfo->puk_hash[uiLen] != 0)
+		{
+			break;
+		}
+		if(uiLen == 3)
+		{
+			return SECURE_VERIFY_DISABLE;
+		}
+	}
+	printf("SecureVerify->enable.\n");
+	
+	return SECURE_VERIFY_ENABLE;
+}
+
+
+
diff --git a/boot/common/src/loader/drivers/efuse.h b/boot/common/src/loader/drivers/efuse.h
new file mode 100644
index 0000000..7a891a1
--- /dev/null
+++ b/boot/common/src/loader/drivers/efuse.h
@@ -0,0 +1,72 @@
+/*
+ ***********************************************************	
+ */
+
+#ifndef __EFUSE_H__
+#define __EFUSE_H__
+
+
+/* -------- efuse ¼Ä´æÆ÷-------------*/
+#define SYS_EFUSE_BASE					0x0121b000
+#define EFUSE_RAM_BASE		(SYS_EFUSE_BASE+0x40)
+
+#define SYS_CTRL_BASE          0x00140000
+#define EFUSE_BYPASS      (SYS_CTRL_BASE+0x140)
+
+
+#define CHIP_DDR_32M	0
+#define CHIP_DDR_64M	1
+#define CHIP_DDR_128M	2
+#define CHIP_DDR_256M	3
+
+
+#define SECURE_VERIFY_ENABLE	0
+#define SECURE_VERIFY_DISABLE	1
+
+#define ZX297520V3_GW_NYB_1G_DDR			0xF86302
+#define ZX297520V3_GW_NYC_1G_DDR			0xF86303
+#define ZX297520V3ECO_GW_UNILC_512M_DDR		0xF86304
+#define ZX297520V3ECO_GW_APM_512M_DDR		0xF86305
+#define ZX297520V3ECO_GW_NYB_1G_DDR			0xF86306
+#define ZX297520V3ECO_GW_NYC_1G_DDR			0xF86307
+#define ZX297520V3ECO_GW_WINBD_256M_DDR	0xF86308
+#define ZX297520V3ECO_GW_UNILC_256M_DDR		0xF86309
+#define ZX297520V3ECO_GW_APM_256M_DDR		0xF8630a
+#define ZX297520V3ECO_GW_ESMT_512M_DDR		0xF8630b
+#define ZX297520V3SC_GW_NYC_1G_DDR			0xF8630c
+#define ZX297520V3ECOSCC_GW_UNILC_1G_DDR	0xF8630d
+#define ZX297520V3ECOSCC_GW_NYC_1G_DDR		0xF8630e
+#define ZX297520V3ECOSC_GW_NYC_1G_DDR		0xF8630f
+#define ZX297520V3ECOSC_GW_UNILC_1G_DDR		0xF86310
+#define ZX297520V3ECOSC_GW_NYC_2G_DDR		0xF86311
+
+#define ZX297520V3_ZW_NYB_1G_DDR			0x1E871E
+#define ZX297520V3_ZW_NYC_1G_DDR			0x1E871F
+#define ZX297520V3ECO_ZW_UNILC_512M_DDR		0x1E8720
+#define ZX297520V3ECO_ZW_APM_512M_DDR		0x1E8721
+#define ZX297520V3ECO_ZW_NYB_1G_DDR			0x1E8722
+#define ZX297520V3ECO_ZW_NYC_1G_DDR			0x1E8723
+#define ZX297520V3ECO_ZW_WINBD_256M_DDR	0x1E8724
+#define ZX297520V3ECO_ZW_UNILC_256M_DDR		0x1E8725
+#define ZX297520V3ECO_ZW_APM_256M_DDR		0x1E8726
+#define ZX297520V3ECO_ZW_ESMT_512M_DDR		0x1E8727
+
+#define ZX297520V3ECO_AZW_UNILC_512M_DDR	0x1F9801
+
+
+/*ΪÁË¿´ÆðÀ´·½±ã, hashºÍkeyÔÚbufferµÄ´æ·Å˳ÐòΪµÍµØÖ··Å¸ßλÊý¾Ý*/
+// ¶¨Òå½á¹¹
+typedef volatile struct
+{
+	u32		secure_flag;
+	u32		puk_hash[4];
+} efuse_struct;
+
+
+
+void efuse_init(void);
+int get_ddr_flag(void);
+int get_secure_verify_status(void);
+
+
+#endif /* __EFUSE_H__ */
diff --git a/boot/common/src/loader/drivers/flash.c b/boot/common/src/loader/drivers/flash.c
new file mode 100755
index 0000000..75d5dd7
--- /dev/null
+++ b/boot/common/src/loader/drivers/flash.c
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2016 ZXIC Inc.
+ */
+#include <asm/io.h>
+#include <asm/arch/top_clock.h>
+ 
+#include "flash.h"
+
+struct flash_type flash;
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+char get_boot_mode(void)
+{
+	char boot_info = 0;
+
+	boot_info = readl(BOOTSEL_INFO);
+
+	if(((boot_info >> 4)&0x3) == 0x3)
+	{
+		return NOR_BOOT;
+	}
+	else
+	{
+		if(((boot_info & 0x7) == 0x0) || ((boot_info & 0x7) == 0x1))
+		{
+			return NAND_BOOT;
+		}
+		else if(((boot_info & 0x7) == 0x4) || ((boot_info & 0x7) == 0x5))
+		{
+			return SPI_NAND_BOOT;
+		}
+		else
+		{
+			return OTHER_BOOT;
+		}
+	}
+}
+
+
+
diff --git a/boot/common/src/loader/drivers/flash.h b/boot/common/src/loader/drivers/flash.h
new file mode 100755
index 0000000..2fe2ddb
--- /dev/null
+++ b/boot/common/src/loader/drivers/flash.h
@@ -0,0 +1,53 @@
+/*******************************************************************************

+ * Copyright (C) 2016, ZXIC Corporation.

+ *

+ * File Name:    

+ * File Mark:    

+ * Description:  

+ * Others:        

+ * Version:       v1.0

+ * Author:        zhouqi

+ * Date:          2013-8-21

+ * History 1:      

+ *     Date: 

+ *     Version:

+ *     Author: 

+ *     Modification:  

+ * History 2: 

+  ********************************************************************************/

+

+#ifndef _FLASH_H_

+#define _FLASH_H_

+

+#include <linux/types.h>

+

+#define 	NOR_BOOT		0x0

+#define 	NAND_BOOT		0x1

+#define 	SPI_NAND_BOOT	0x2

+#define 	OTHER_BOOT		0xff

+

+struct flash_type{

+	uint8_t flash_type;

+    uint8_t manuf_id;             

+    uint8_t device_id;            

+	uint16_t page_size;

+    uint16_t page_size_shift;      

+    uint16_t oob_size;                    

+    uint16_t block_size_shift;

+    uint16_t block_num;          

+	uint32_t block_size;

+	int32_t	(*read_page_raw)(uint32_t buf, uint32_t offset);

+	int32_t	(*read)(uint32_t from, uint32_t len, uint32_t to);

+	void (*read_oob)(uint8_t *buf, uint32_t offset, uint32_t len);

+};

+

+

+extern struct flash_type flash;

+

+char get_boot_mode(void);

+int board_flash_init(void);

+

+

+#endif/*_FLASH_H_*/

+

+

diff --git a/boot/common/src/loader/drivers/global.c b/boot/common/src/loader/drivers/global.c
new file mode 100644
index 0000000..ab05703
--- /dev/null
+++ b/boot/common/src/loader/drivers/global.c
@@ -0,0 +1,96 @@
+#include "global.h"

+

+__align(4) const dwc_config_all_t  desc =

+{

+//T_CONFIG_DESCRIPTOR

+{

+	sizeof(dwc_config_descriptor_t),				//bLength

+	CONFIG_DESCRIPTOR,							//bDescriptorType

+	sizeof(dwc_config_all_t),

+	2,											//bNumInterfaces

+	1,											//bConfigurationValue

+	0,											//iConfiguration×Ö·û´®ÃèÊöµÄË÷Òý

+	ATTR_D7 |ATTR_SELF_POWERED ,	//bmAttributes

+	POWER_MA(500),											//

+},

+

+

+//T_INTERFACE_DESCRIPTOR

+{

+	sizeof(dwc_interface_descriptor_t),		//bLength

+	INTERFACE_DESCRIPTOR,				//bDescriptorType

+	0,									//bInterfaceNumber

+	0,									//bAlternateSetting

+	0x02,						//bNumEndpoints

+	VERDOR_SPECIFIC,					//bInterfaceClass

+	0xff,								//bInterfaceSubClass

+	0xff,								//bInterfaceProtocol

+	0x04,									//iInterface×Ö·û´®ÃèÊöµÄË÷Òý

+},

+

+{

+	sizeof(dwc_ep_descriptor_t), 		//bLength

+	ENDPOINT_DESCRIPTOR, 			//bDescriptorType

+	EP_ADDRESS_DIRECTION_IN	|0x1, 	//bEndpointAddress

+	EP_ATTR_TRANSFER_TYPE_BULK, 	//bmAttributes

+	USB_HIGHSPEED_BULK_MAXSIZE, 		   //wMaxPacketSize

+	0,								//bInterval

+},

+{

+	sizeof(dwc_ep_descriptor_t), 		//bLength

+	ENDPOINT_DESCRIPTOR, 			//bDescriptorType

+	0x1, 							//bEndpointAddress

+	EP_ATTR_TRANSFER_TYPE_BULK, 	//bmAttributes

+	USB_HIGHSPEED_BULK_MAXSIZE, 		 //wMaxPacketSize

+	0,							//bInterval

+},

+//T_INTERFACE_DESCRIPTOR

+{

+    sizeof(dwc_interface_descriptor_t),		//bLength

+    INTERFACE_DESCRIPTOR,				//bDescriptorType

+    1,									//bInterfaceNumber

+    0,									//bAlternateSetting

+    0x02,						//bNumEndpoints

+    VERDOR_SPECIFIC,					//bInterfaceClass

+    0xff,								//bInterfaceSubClass

+    0xff,								//bInterfaceProtocol

+    0x05,									//iInterface×Ö·û´®ÃèÊöµÄË÷Òý

+},

+

+{

+	sizeof(dwc_ep_descriptor_t), 		//bLength

+	ENDPOINT_DESCRIPTOR, 			//bDescriptorType

+	EP_ADDRESS_DIRECTION_IN	|0x2, 	//bEndpointAddress

+	EP_ATTR_TRANSFER_TYPE_BULK, 	//bmAttributes

+	USB_HIGHSPEED_BULK_MAXSIZE, 	      //wMaxPacketSize

+	0,								//bInterval

+},

+

+{

+	sizeof(dwc_ep_descriptor_t), 		//bLength

+	ENDPOINT_DESCRIPTOR, 			//bDescriptorType

+	0x2, 							//bEndpointAddress

+	EP_ATTR_TRANSFER_TYPE_BULK, 	//bmAttributes

+	USB_HIGHSPEED_BULK_MAXSIZE, 	     //wMaxPacketSize

+	0,							//bInterval

+},

+};

+

+

+struct g_data	  					global;

+

+__align(4) dwc_config_all_t g_config_desc;

+

+void data_init(void)

+{

+	int i;

+	char *src 	= (char*)&desc;

+	char *dst	= (char*)&g_config_desc;

+

+	for(i = 0; i < sizeof(dwc_config_all_t); i++)

+	{

+		*dst++	= *src++;

+	}

+}

+

+

diff --git a/boot/common/src/loader/drivers/global.h b/boot/common/src/loader/drivers/global.h
new file mode 100644
index 0000000..8d14d73
--- /dev/null
+++ b/boot/common/src/loader/drivers/global.h
@@ -0,0 +1,51 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+*

+* ÎļþÃû³Æ£º global.c

+* Îļþ±êʶ£º

+* ÄÚÈÝÕªÒª£º È«¾Ö±äÁ¿¼°³õʼ»¯

+* ÆäËü˵Ã÷£º

+* µ±Ç°°æ±¾£º 1.0

+* ×÷¡¡¡¡Õߣº ÎÌÔÆ·å

+* Íê³ÉÈÕÆÚ£º

+*******************************************************************************/

+#ifndef __GLOBAL_H_

+#define __GLOBAL_H_

+#include "common.h"

+

+#include "dwc_otg_driver.h"

+

+

+struct g_data

+{

+	dwc_otg_device_t 		g_dwc_otg_dev_t;

+	u32						dwRxQuit;

+	u32						dwTxQuit;

+	u32						g_Connet;

+	u32						g_USB_MODE;

+	u32						g_USB_TIMEOUT;

+	u16						g_status_buf;

+	int						g_State;

+	int 					g_bootfinish;

+	int						g_bootaddr;

+	int						g_bootsize;

+    int                     g_boot_save_size;

+    int                     g_boot_save_addr;

+

+	dwc_otg_core_if_t 		core_if_t;

+	dwc_otg_dev_if_t 		dev_if_t;

+	dwc_otg_core_params_t 	g_core_params;

+

+	u32						g_in_pPara[3];

+	u32						g_out_pPara[3];

+	u_setup_pkt 			g_u_setup_pkt[sizeof(u_setup_pkt)*5];

+	dwc_otg_pcd_t 			g_dwc_otg_pcd_tp;

+    u32                     g_pll_cfg;

+	int                     g_enum;

+};

+

+extern struct 				g_data global;

+//extern dwc_config_all_t		desc;

+extern dwc_config_all_t g_config_desc;

+#endif

+

diff --git a/boot/common/src/loader/drivers/image.c b/boot/common/src/loader/drivers/image.c
new file mode 100755
index 0000000..8b9c89e
--- /dev/null
+++ b/boot/common/src/loader/drivers/image.c
@@ -0,0 +1,350 @@
+/*
+ * (C) Copyright 2016 ZXIC Inc.
+ */
+#include <common.h>   
+#include <asm/io.h>
+#include <asm/string.h>
+
+#include <image.h>
+#include <linux/byteorder/generic.h>
+#include <secure_verify.h>
+
+#include "flash.h"
+#include <bbt.h>
+
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+uint32_t page_align(uint32_t offset)
+{
+    uint32_t page_size = flash.page_size;
+    if(offset & (page_size - 1))
+    {
+        offset &= (~(page_size - 1));
+        offset += page_size;
+    }
+    return offset;
+}
+
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+uint32_t find_partition_para(partition_entry_t *entry, 
+ 									   uint32_t entrys, 
+ 									   uint8_t *name)
+{
+    partition_entry_t *p_entry = entry;
+    uint32_t entry_nums = entrys;
+    while(entry_nums--)
+    {
+        if(memcmp( p_entry->part_name, name, strlen(name)) == 0)
+            return p_entry->part_offset;
+        p_entry++;
+    }
+    return -1;
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int read_image_part_offset(uint8_t *name, uint32_t *offset)
+{
+	int ret = 0;
+	uint32_t part_size = 0;
+
+	if(flash.flash_type == NOR_BOOT)
+	{
+		part_size = 8*flash.page_size;
+	}
+	else
+	{
+		part_size = flash.page_size;	
+	}
+
+	ret = flash.read(0x2000, part_size, CFG_TEMP_ADDR);
+	if(ret != 0)
+	{
+		return -1;
+	}
+            
+	partition_table_t *part = (partition_table_t  *)CFG_TEMP_ADDR;   
+	partition_entry_t *entry = &part->table[0];
+	uint32_t entrys = part->entrys;
+
+	if(part->magic != CFG_PARTITION_MAGIC)
+	{
+		return -1;
+	}
+
+	*offset = find_partition_para(entry, entrys, name);
+	if(*offset == -1 )
+	{
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_ZX297520V3E_MDL_AB
+int read_flags_image(uint8_t *name)
+{
+    T_BOOT_FOTA_FLAG *fotaFlag;
+	uint32_t uiPageSize = 0;
+    uint32_t flags_offset = 0;
+	uint32_t off = 0;
+	uint32_t flags_size = 0x4E0000;/*flags·ÖÇø*/
+	uint32_t blockNum = 0;
+	int32_t flag_one = 0;
+	uint32_t work_area_offset = 0;
+	uint32_t backup_area_offset = 0;
+	int32_t ret = 0;
+	int32_t fota_size = sizeof(T_BOOT_FOTA_FLAG);
+	int32_t block_size = flash.block_size;
+
+	fota_size = page_align(fota_size);
+
+	ret = read_image_part_offset(name, &flags_offset);
+	if(ret != 0)
+	{
+		printf("flags partition offset fail.\n");
+		return -1;
+	}
+
+	/*È·¶¨¹¤×÷ÇøºÍ±¸·ÝÇøÆ«ÒÆµØÖ·*/
+	for (off = flags_offset; off < flags_offset+flags_size; off += flash.block_size)
+	{
+		if (!(nand_block_isbad(off)))
+		{
+            blockNum += 1;
+		}   
+		
+		if((blockNum == 1) && (flag_one == 0))
+		{
+            work_area_offset = off;
+			flag_one = 1;
+		}
+	
+		else if(blockNum == 2)
+		{
+             backup_area_offset = off;
+			 break;
+		}		
+	}
+
+	if(blockNum < 2)
+	{
+        printf("flags partition have not enough space!\n");
+			
+		return -1;
+	}
+	
+	ret = flash.read(work_area_offset, fota_size, CFG_TEMP_ADDR);
+	if(ret != 0)
+	{
+		printf("read flags work partition err.\n");
+		
+		return -1;
+	}
+
+	fotaFlag = (T_BOOT_FOTA_FLAG *)(CFG_TEMP_ADDR);
+	
+	if(fotaFlag->magic != FLAGS_MAGIC)
+	{
+        ret = flash.read(backup_area_offset, fota_size, CFG_TEMP_ADDR);
+		if(ret != 0)
+		{
+			printf("read flags backup partition err.\n");
+			
+			return -1;
+		}
+		fotaFlag = (T_BOOT_FOTA_FLAG *)(CFG_TEMP_ADDR);
+		if(fotaFlag->magic != FLAGS_MAGIC)
+		{
+            printf("flags magic err.\n");
+		    return -1;
+		}	
+	}
+	
+	return 0;
+    
+}
+#endif
+/*
+ ****************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *****************************************************************************
+ */
+int read_uboot_image(uint8_t *name, uint32_t *uboot_entry_point)
+{
+	/*
+	 * +----------------------------------------------------------------+
+	 * |  sImageHeader  |  image_header_t  |    u-boot.bin     |                
+	 * +----------------------------------------------------------------+
+	 * |    384 Bytes      |     64 Bytes         |    xxx Bytes       |
+	 *                                 
+	 */
+
+	image_header_t *psImgHdrOld = NULL;
+
+	uint32_t uiPageSize = 0;
+
+	uint32_t uiImgHdrSizeOld = sizeof(image_header_t);
+	uint32_t uiImgHdrSizeNew = sizeof(sImageHeader);
+
+	uint32_t uiUBootSize = 0;
+	uint32_t uiUBootLoadAddr = 0;
+	uint32_t uiUBootIsReadSize = 0;
+
+	int32_t ret = 0;
+	uint32_t uboot_offset = 0;
+
+
+		
+	if(flash.flash_type == NOR_BOOT)
+	{
+		uiPageSize = 8*flash.page_size;
+	}
+	else 
+	{
+		uiPageSize = flash.page_size;	
+	}
+
+	ret = read_image_part_offset(name, &uboot_offset);
+	if(ret != 0)
+	{
+		printf("offset fail.\n");
+		return -1;
+	}
+	
+	ret = flash.read(uboot_offset, uiPageSize, CFG_TEMP_ADDR);
+	if(ret != 0)
+	{
+		printf("image header err.\n");
+		return -1;
+	}
+
+	psImgHdrOld = (image_header_t *)(CFG_TEMP_ADDR + uiImgHdrSizeNew);
+	uiUBootSize = ___htonl(psImgHdrOld->ih_size);   
+	uiUBootLoadAddr = ___htonl(psImgHdrOld->ih_load);
+	*uboot_entry_point = ___htonl(psImgHdrOld->ih_ep);
+
+	if(___htonl(psImgHdrOld->ih_magic) != IH_MAGIC)
+	{
+		printf("magic err.\n");
+		return -1;
+	}
+
+	uiUBootIsReadSize = uiPageSize - uiImgHdrSizeOld - uiImgHdrSizeNew;
+	uiUBootSize -= uiUBootIsReadSize;			
+	uiUBootSize = page_align(uiUBootSize);   
+
+	memcpy(uiUBootLoadAddr - uiImgHdrSizeOld, 
+			CFG_TEMP_ADDR + uiImgHdrSizeNew, 
+		   	uiUBootIsReadSize + uiImgHdrSizeOld);
+
+	ret = flash.read(uboot_offset + uiPageSize, 
+						uiUBootSize, 
+						uiUBootLoadAddr + uiUBootIsReadSize);
+	if(ret != 0)
+	{
+		printf("image err.\n");
+		return -1;
+	}
+	
+	ret = SecureVerify(CFG_TEMP_ADDR);
+	if(ret != 0)
+	{
+		printf("Secure verify fail!\n");
+		return -1;
+	}
+	
+	return 0;
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+ int nand_read_m0(uint32_t *m0_entry_point)
+{
+	int remap = 0;
+	image_header_t *header = NULL;
+	uint32_t image_header_size = sizeof(image_header_t);
+	uint32_t m0_size = 0;
+	uint32_t m0_load_addr = 0;
+	/*
+	 * +---------------------------------------------------------+
+	 * |  image_header_t    |          m0                        |                
+	 * +---------------------------------------------------------+
+                            m0.bin
+	 */
+
+	/*1¡¢µÈ´ýBOOT°áÔËM0°æ±¾µ½CONFIG_SYS_SDRAM_TEMP_BASEÖÐ*/
+	writel(0, M0_IMAGE_READY_FLAG_ADDR);
+	while(!readl(M0_IMAGE_READY_FLAG_ADDR));
+
+	/*2¡¢M0µÄ0µØÖ·ÖØÓ³Éä*/
+	remap = readl(0x140000);
+	remap |= 0x800000;
+	writel(remap,0x140000);
+
+	/*3¡¢½âÎöM0µÄ°æ±¾Í·£¬»ñÈ¡ÔËÐеØÖ·ÒÔ¼°´óС*/
+	header = (image_header_t *)CONFIG_SYS_SDRAM_TEMP_BASE;
+	m0_size = ___htonl(header->ih_size);    /* m0.bin */
+	m0_load_addr = ___htonl(header->ih_load);
+	*m0_entry_point = ___htonl(header->ih_ep);   
+
+	if(___htonl(header->ih_magic) != IH_MAGIC)
+	{
+		return -1;
+	}
+
+	/*4¡¢½«M0µÄ°æ±¾´ÓIRAM0¿½±´µ½load_addr*/
+	memcpy(m0_load_addr, CONFIG_SYS_SDRAM_TEMP_BASE + image_header_size, m0_size); 
+
+	/*5¡¢ÐÞ¸ÄIRAM±ê¼Ç£¬Ê¹BOOT¼ÌÐøÍùÏÂÖ´ÐÐ*/
+	writel(0, M0_IMAGE_READY_FLAG_ADDR);
+
+	return 0;
+}
+
+
diff --git a/boot/common/src/loader/drivers/nor.c b/boot/common/src/loader/drivers/nor.c
new file mode 100755
index 0000000..afccaf9
--- /dev/null
+++ b/boot/common/src/loader/drivers/nor.c
@@ -0,0 +1,417 @@
+/*
+ * Freescale QuadSPI driver.
+ *
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <sdio.h>
+#include <common.h>
+#include <asm/io.h>
+#include "nor.h"
+#include <image.h>
+#include <linux/byteorder/generic.h>
+#include <secure_verify.h>
+#include "config.h"
+#include "flash.h"
+
+
+/* Used when the "_ext_id" is two bytes at most */
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
+		.id = {							\
+			((_jedec_id) >> 16) & 0xff,			\
+			((_jedec_id) >> 8) & 0xff,			\
+			(_jedec_id) & 0xff,				\
+			((_ext_id) >> 8) & 0xff,			\
+			(_ext_id) & 0xff,				\
+			},						\
+		.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),	\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = 256,					\
+		.flags = (_flags),
+
+
+spinor_cmd_t nor_cmd_table[]=
+{	
+	{CMD_RDFT, TX_DMA_DIS, RX_DMA_DIS, ADDR_TX_EN, ADDR_WIDTH_24, DATA_TX_DIS, DATA_RX_EN, DUMY_TX_EN, 1, 0, ADDR_MULTI_LINE_DIS, DATA_MULTI_LINE_DIS, TRANS_MOD_SINGLE, "read fast"},
+	{CMD_RDID, TX_DMA_DIS, RX_DMA_DIS, ADDR_TX_DIS, ADDR_WIDTH_24, DATA_TX_DIS, DATA_RX_EN, DUMY_TX_DIS, 0, 0, ADDR_MULTI_LINE_DIS, DATA_MULTI_LINE_DIS, TRANS_MOD_SINGLE, "read identification"},
+	{NULL}
+};
+
+#ifdef CONFIG_ZX297520V3_UFI_MINI_32K_NOR
+static const struct nor_info spi_nor_ids[] = {
+	/* GigaDevice */
+	{ "gd25q128", INFO(0xc86018, 0, 32 * 1024, 512, 0) },
+	/* winbond */	
+	{ "w25q128fw", INFO(0xef6018, 0, 32 * 1024, 512, 0) },
+	/* dosilicon */
+	{ "fm25m4aa", INFO(0xf84218, 0, 32 * 1024, 512, 0) },
+	/* fudanwei */
+	{ "fm25w128", INFO(0xA12818, 0, 32 * 1024, 512, 0) },
+	/* XMC */
+	{ "XM25QU64C", INFO(0x204117, 0, 32 * 1024, 256, 0) },
+	{ "XM25QU128", INFO(0x205018, 0, 32 * 1024, 512, 0) },
+	{ "XM25QU128C", INFO(0x204118, 0, 32 * 1024, 512, 0) },
+	/* DQ25Q128AL */
+	{ "DQ25Q128AL", INFO(0x546018, 0, 32 * 1024, 512, 0) },
+	/* dosilicon */
+	{ "DS25M4AB", INFO(0xE54218, 0, 32 * 1024, 512, 0) },
+	/* esmt(eon) */
+	{ "EN25SX128A", INFO(0x1C7818, 0, 32 * 1024, 512, 0) },
+	/* dosilicon */
+	{ "FM25M4AA", INFO(0xF84218, 0, 32 * 1024, 512, 0) },
+	{ },
+};
+#else
+static const struct nor_info spi_nor_ids[] = {
+	/* GigaDevice */
+	{ "gd25q128", INFO(0xc86018, 0, 64 * 1024, 256, 0) },
+	/* winbond */	
+	{ "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, 0) },
+	/* dosilicon */
+	{ "fm25m4aa", INFO(0xf84218, 0, 64 * 1024, 256, 0) },
+	/* fudanwei */
+	{ "fm25w128", INFO(0xA12818, 0, 64 * 1024, 256, 0) },
+	/* xmc */
+	{ "XM25QU128", INFO(0x205018, 0, 64 * 1024, 256, 0) },
+	{ "XM25QU128C", INFO(0x204118, 0, 64 * 1024, 256, 0) },
+	/* DQ25Q128AL */
+	{ "DQ25Q128AL", INFO(0x546018, 0, 64 * 1024, 256, 0) },
+	/* dosilicon */
+	{ "DS25M4AB", INFO(0xE54218, 0, 64 * 1024, 256, 0) },
+	/* esmt(eon) */
+	{ "EN25SX128A", INFO(0x1C7818, 0, 64 * 1024, 256, 0) },
+	/* dosilicon */
+	{ "FM25M4AA", INFO(0xF84218, 0, 64 * 1024, 256, 0) },
+	{ },
+};
+#endif
+
+
+struct nor_info *spi_nor_flash = NULL;
+
+
+ void spifc_enable(void)
+{
+   volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    
+    if(spifc->SFC_EN & FC_EN_BACK)
+    {
+		printf("spifc en err.\n");
+		return;
+	}   
+    spifc->SFC_EN |= (1 << FC_EN);  
+    spifc->SFC_CTRL0 |= (1 << FC_SCLK_PAUSE_EN);
+}
+
+ void spifc_disable(void)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    
+    if(!(spifc->SFC_EN & FC_EN_BACK))
+    {
+		printf("spifc dis err.\n");
+		return;
+	}     
+    spifc->SFC_EN &= (~(1 <<FC_EN));    
+}
+
+ void spifc_setup_cmd(spinor_cmd_t *cmd, uint32_t addr, uint32_t len)
+{   
+	volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+
+	/* clear dma config */
+	spifc->SFC_CTRL0 &= ~((1 << FC_RX_DMA_EN)|(1 << FC_TX_DMA_EN));
+	/* clear fifo */
+	spifc->SFC_CTRL0 |= (1 << FC_RXFIFO_CLR)|(1 << FC_TXFIFO_CLR);
+
+	/* clear interrupt register */
+	spifc->SFC_INT_SW_CLR = 0xFF;  
+	
+	/* dma + fifo config */
+	spifc->SFC_CTRL0 |= ((cmd->tx_dma_en << FC_TX_DMA_EN) 
+						  | (cmd->rx_dma_en << FC_RX_DMA_EN)
+						  | (1 << FC_RXFIFO_THRES)
+						  | (1 << FC_TXFIFO_THRES));
+
+	/* addr dumy data code config */
+    spifc->SFC_CTRL1 = 0;
+    spifc->SFC_CTRL1 = ((cmd->addr_tx_en << FC_ADDR_TX_EN) 
+						| (cmd->dumy_tx_en << FC_DUMMY_TX_EN) 
+                        | (cmd->data_rx_en << FC_READ_DAT_EN) 
+                        | (cmd->data_tx_en << FC_WRITE_DAT_EN));
+
+    spifc->SFC_CTRL2 = 0;
+    spifc->SFC_CTRL2 = ((cmd->dumy_byte_num << FC_DUMMY_BYTE_NUM) 
+            			| (cmd->dumy_bit_num << FC_DUMMY_BIT_NUM) 
+	            		| (cmd->addr_byte_num << FC_ADDR_BYTE_NUM)
+	            		| (cmd->addr_multi_line_en << FC_ADDR_MULTI_LINE_EN)
+	            		| (cmd->data_multi_line_en << FC_DAT_MULTI_LINE_EN)
+	            		| (cmd->trans_mod << FC_TRANS_MOD));
+
+    if(len)
+        spifc->SFC_BYTE_NUM = len - 1;
+    else
+        spifc->SFC_BYTE_NUM = 0; 
+	
+	spifc->SFC_ADDR = addr; 
+    spifc->SFC_INS = cmd->cmd;          
+}
+
+ int spifc_wait_cmd_end(void)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    uint32_t intr_status = 0;
+
+    while(!(spifc->SFC_INT_RAW & FC_INT_RAW_MASK));
+    
+    intr_status = spifc->SFC_INT_RAW;
+    spifc->SFC_INT_SW_CLR = intr_status;           /* ??? */   
+
+	if(intr_status & FC_INT_RAW_CMD_END)
+    {   
+        return 0;
+    }
+    else
+    {
+		printf("intr status err.\n");
+        return -1;
+    }   
+}
+
+uint32_t spifc_read_fifo(uint8_t *buf, uint32_t len)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    uint32_t *p = (uint32_t *)buf;
+    uint32_t cnt = 0;
+
+	int remainder_cnt = len % 4;
+
+	if(remainder_cnt != 0)
+	{
+		len = len + (4 - remainder_cnt);
+	}
+	else
+	{
+		remainder_cnt = 4;
+	}
+   
+    while(cnt < (len>>2))  
+    {
+        if(spifc->SFC_SW & (FC_RX_FIFO_CNT_MASK<<FC_RX_FIFO_CNT))//rx fifo not empty
+        {           
+            p[cnt++]= spifc->SFC_DATA;
+        }
+    }
+
+    return ((cnt<<2) - (4 - remainder_cnt));
+}
+
+ void spifc_start(void)
+{
+    volatile struct spifc_nor_reg_t* spifc = (struct spifc_nor_reg_t*)SYS_SPI_NAND_BASE;
+    
+    spifc->SFC_START |= FC_START;
+}
+
+spinor_cmd_t *cmd_seek(u8 opcode)
+{
+	int i;
+
+	for(i = 0; (&nor_cmd_table[i]) != NULL; i++)
+	{
+		if(opcode == nor_cmd_table[i].cmd)
+		{
+			return (&nor_cmd_table[i]);
+		}
+	}
+
+	return NULL;	
+}
+
+int nor_read_reg(u8 opcode, int len, u8 *buf)
+{
+	int ret = 0;
+	spinor_cmd_t *cmd = NULL;
+	
+	cmd = cmd_seek(opcode);
+	if(cmd == NULL)
+	{
+		printf("cmd_seek unkown cmd error.\n");
+		return -1;
+	}
+	
+	spifc_setup_cmd(cmd, 0x0, len);            
+    spifc_start();                          
+    ret = spifc_wait_cmd_end();             
+    if(ret != 0)
+    {
+		printf("spifc_wait_cmd_end error.\n");
+	   	return ret;
+    }
+
+	ret = spifc_read_fifo(buf, len);
+	if(ret < 0)
+	{
+		printf("spifc_read_fifo error.\n");
+	    return ret;
+	}
+
+	return 0;	
+}
+
+int nor_read_id(void)
+{
+	int	tmp;
+	u8	id[SPI_NOR_MAX_ID_LEN];
+	const struct nor_info	*info;
+
+	tmp = nor_read_reg(CMD_RDID, SPI_NOR_MAX_ID_LEN, id);
+	if(tmp < 0) 
+	{
+		printf("error reading JEDEC ID\n");
+		return tmp;
+	}
+
+	for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) 
+	{
+		info = &spi_nor_ids[tmp];
+		if(info->id_len) 
+		{
+			if(!memcmp(info->id, id, info->id_len))
+			{
+				spi_nor_flash = info;
+				return 0;
+			}
+		}
+	}
+	printf("unrecognized JEDEC id\n");
+	return -1;
+	
+}
+ 
+int spi_nor_read(uint32_t from, size_t len, u_char *buf)
+{
+	int ret;
+	spinor_cmd_t *cmd = NULL;
+
+	cmd = cmd_seek(CMD_RDFT);
+	if(cmd == NULL)
+	{
+		printf("cmd_seek unkown error.\n");
+		return -1;
+	}
+
+	spifc_setup_cmd(cmd, from, len);	            
+	spifc_start();
+	ret = spifc_read_fifo(buf, len);
+	if(ret < 0)
+	{
+		printf("spifc_read_fifo error.\n");
+		return ret;
+	}
+
+	ret = spifc_wait_cmd_end();             
+    if(ret != 0)
+    {
+		printf("spifc_wait_cmd_end error.\n");
+	   	return ret;
+    }
+	
+	return 0;
+}
+
+int nor_read(uint32_t from, uint32_t len, uint32_t to)
+{
+	int ret;
+	u32 page_offset, page_size, i;
+	struct nor_info *info = spi_nor_flash;
+	
+	page_offset = from & (info->page_size - 1);
+
+	/* do all the bytes fit onto one page? */
+	if (page_offset + len <= info->page_size) {
+		ret = spi_nor_read(from, len, (uint8_t *)to);
+	} else {
+		/* the size of data remaining on the first page */
+		page_size = info->page_size - page_offset;
+		ret = spi_nor_read(from, page_size, (uint8_t *)to);
+
+		/* read everything in nor->page_size chunks */
+		for (i = page_size; i < len; i += page_size) {
+			page_size = len - i;
+			if (page_size > info->page_size)
+				page_size = info->page_size;
+
+			ret = spi_nor_read(from + i, page_size, ((uint8_t *)to + i));
+		}
+	}
+
+	return ret;
+}
+
+
+
+int nor_init(void)
+{
+	int ret = 0;
+
+	spifc_disable(); //hsy ?
+	
+	spifc_enable();
+
+	ret = nor_read_id();
+	if(ret != 0)
+	{
+		return -1;
+	}
+	
+	flash.flash_type = NOR_BOOT;
+	flash.page_size = spi_nor_flash->page_size;
+	flash.read = nor_read;		
+	
+	return 0;
+}
+
+/*
+ **********************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ **********************************************************************
+ */
+int board_flash_init(void)
+{
+	int ret = 0;
+	char boot_mode = 0;
+	
+	boot_mode = get_boot_mode();
+	if(boot_mode != NOR_BOOT)
+	{
+		printf("not nor flash.\n");
+		return -1; 
+	}
+	
+	writel(CFG_START_MODE_NOR, CFG_BOOT_MODE_START_MODE_FOR_UBOOT); 
+	ret = nor_init();
+	if(ret != 0)
+	{
+		printf("nor init err.\n");
+		return -1;
+	}
+
+	printf("nor init ok.\n");
+
+	return 0;
+}
+
+
+
diff --git a/boot/common/src/loader/drivers/nor.h b/boot/common/src/loader/drivers/nor.h
new file mode 100644
index 0000000..c3e81db
--- /dev/null
+++ b/boot/common/src/loader/drivers/nor.h
@@ -0,0 +1,204 @@
+
+#ifndef _SPIFC_H_
+#define _SPIFC_H_
+
+#define SYS_SPI_NAND_BASE           0x01407000
+
+struct spifc_nor_reg_t
+{
+    uint32_t     VER_REG;					//0x00
+    uint32_t     SFC_START;                 //0x04
+    uint32_t     SFC_EN;                    //0x08
+	uint32_t	 SFC_CTRL0;					//0x0c 
+	uint32_t	 SFC_CTRL1;					//0x10
+	uint32_t	 SFC_CTRL2;					//0x14 
+	uint32_t	 SFC_BYTE_NUM;				//0x18
+	uint32_t	 SFC_ADDR;					//0x1c
+	uint32_t	 SFC_INS;					//0x20
+	uint32_t	 SFC_TIMING;				//0x24
+	uint32_t	 SFC_INT_EN;				//0x28
+    uint32_t     SFC_INT_RAW;               //0x2c
+    uint32_t     SFC_INT_SW_CLR;            //0x30
+    uint32_t     SFC_SW;                    //0x34
+    uint32_t     SFC_DATA;                  //0x38
+};
+
+/*spifc start 0x4*/
+#define     FC_START      (1<<0)
+#define     FC_BUSY       (1<<0)
+
+/*spifc enable 0x8*/
+#define     FC_EN_BACK          (1)
+#define     FC_EN               (0)
+
+/*spifc main ctr0 0xc*/
+#define     FC_SCLK_PAUSE_CLR_ALLOW     (17)
+#define     FC_SCLK_PAUSE_EN            (16)
+#define     FC_TXFIFO_CLR               (15)
+#define     FC_RXFIFO_CLR               (14)
+#define     FC_TXFIFO_THRES             (10)
+#define     FC_RXFIFO_THRES             (6)
+#define     FC_TX_DMA_EN                (5)
+#define     FC_RX_DMA_EN                (4)
+#define     FC_WDOG_EN                  (3)
+#define     FC_SPI_MODE                 (1)
+#define     FC_WR_PROTECT               (0)
+
+/*spifc ctrl1 0x10  in the condition : SFC_EN = 1 SFC_BUSY = 0*/
+#define     FC_ADDR_TX_EN           (4)
+#define     FC_DUMMY_TX_EN          (2)
+#define     FC_READ_DAT_EN          (1)
+#define     FC_WRITE_DAT_EN         (0)
+
+/*spifc ctrl2 0x14*/
+#define     FC_DUMMY_BYTE_NUM           (12)  /* [12:15} */
+#define     FC_DUMMY_BIT_NUM            (8)   /* [8:10] */
+#define     FC_ADDR_BYTE_NUM            (5)   /* [5:6] */ 
+#define     FC_ADDR_MULTI_LINE_EN       (4)
+#define     FC_DAT_MULTI_LINE_EN        (2)
+#define     FC_TRANS_MOD                (0)
+
+#define     FC_ADDR_BYTE_NUM_8             (0) 
+#define     FC_ADDR_BYTE_NUM_16            (1) 
+#define     FC_ADDR_BYTE_NUM_24            (2)  
+#define     FC_ADDR_BYTE_NUM_32            (3)  
+
+
+/*spifc timing 0x24*/
+#define     FC_READ_DELAY           (1<<16)   /* [17:16} */
+#define     FC_T_CS_SETUP           (1<<11)   /* [11:13} */
+#define     FC_T_CS_HOLD            (1<<6)    /* [8:6} */
+#define     FC_T_CS_DESEL           (1<<0)    /* [0:3} */
+
+
+/*spifc int enable 0x28*/
+#define     FC_INT_EN_TX_BYD_THES           (1<<7)
+#define     FC_INT_EN_RX_BYD_THES           (1<<6)
+#define     FC_INT_EN_TX_UNDERRUN           (1<<5)
+#define     FC_INT_EN_RX_OVERRUN            (1<<4)
+#define     FC_INT_EN_WDOG_OVERRUN          (1<<2)
+#define     FC_INT_EN_FMT_ERR               (1<<1)
+#define     FC_INT_EN_CMD_END               (1<<0)
+
+/*spifc raw interrupt 0x2c*/
+#define     FC_INT_RAW_TX_BYD_THES           (1<<7)
+#define     FC_INT_RAW_RX_BYD_THES           (1<<6)
+#define     FC_INT_RAW_TX_UNDERRUN           (1<<5)
+#define     FC_INT_RAW_RX_OVERRUN            (1<<4)
+#define     FC_INT_RAW_WDOG_OVERRUN          (1<<2)
+#define     FC_INT_RAW_FMT_ERR               (1<<1)
+#define     FC_INT_RAW_CMD_END               (1<<0)
+#define     FC_INT_RAW_MASK              	 (FC_INT_RAW_TX_UNDERRUN|	\
+                                              FC_INT_RAW_RX_OVERRUN|	\
+                                              FC_INT_RAW_WDOG_OVERRUN|	\
+                                              FC_INT_RAW_FMT_ERR|		\
+                                              FC_INT_RAW_CMD_END)
+
+
+/*spifc int startus and clr 0x30*/
+#define     FC_INT_CLR_TX_BYD_THES           (1<<7)
+#define     FC_INT_CLR_RX_BYD_THES           (1<<6)
+#define     FC_INT_CLR_TX_UNDERRUN           (1<<5)
+#define     FC_INT_CLR_RX_OVERRUN            (1<<4)
+#define     FC_INT_CLR_WDOG_OVERRUN          (1<<2)
+#define     FC_INT_CLR_FMT_ERR               (1<<1)
+#define     FC_INT_CLR_CMD_END               (1<<0)
+
+/*spifc sw 0x34*/
+#define     FC_TX_FIFO_CNT              (16)         /* [16:20} */
+#define     FC_TX_FIFO_CNT_MASK         (0x1F)      /* [8:12} */
+#define     FC_RX_FIFO_CNT              (8)             /* [8:12} */
+#define     FC_RX_FIFO_CNT_MASK         (0x1F)      /* [8:12} */
+#define     FC_TX_BYD_THRES             (1<<5)  
+#define     FC_RX_BYD_THRES             (1<<4)  
+#define     FC_SCLK_PAUSE_FLAG          (1<<3)  
+#define     FC_WAIT_FLAG                (1<<2) 
+#define     FC_FORMAT_ERR               (1<<1)  
+
+
+#define     FC_DMA_NONE           		0
+#define     FC_DMA_TX             		1
+#define     FC_DMA_RX             		2
+
+
+#define TX_DMA_EN		1 
+#define TX_DMA_DIS      0 
+#define RX_DMA_EN		1 
+#define RX_DMA_DIS      0
+#define ADDR_TX_EN      1   
+#define ADDR_TX_DIS     0
+#define DATA_TX_EN      1
+#define DATA_TX_DIS     0
+#define DATA_RX_EN      1
+#define DATA_RX_DIS     0
+#define DUMY_TX_EN      1
+#define DUMY_TX_DIS     0
+#define ADDR_MULTI_LINE_EN		1 
+#define ADDR_MULTI_LINE_DIS      0
+#define DATA_MULTI_LINE_EN		1 
+#define DATA_MULTI_LINE_DIS      0
+#define TRANS_MOD_QUAD		1 
+#define TRANS_MOD_DUAL      0
+#define TRANS_MOD_SINGLE	2
+
+
+#define ADDR_WIDTH_8    0
+#define ADDR_WIDTH_16   1
+#define ADDR_WIDTH_24   2
+#define ADDR_WIDTH_32   3
+
+
+
+typedef struct spinor_cmd
+{
+    u8 cmd;
+	u8 tx_dma_en;
+	u8 rx_dma_en;
+    u8 addr_tx_en;
+    u8 addr_byte_num;
+    u8 data_tx_en;
+    u8 data_rx_en;
+    u8 dumy_tx_en;
+    u8 dumy_byte_num;
+	u8 dumy_bit_num;
+	u8 addr_multi_line_en;
+	u8 data_multi_line_en;
+	u8 trans_mod;
+	u8 reserved[3];
+    u8 *info;
+}spinor_cmd_t;
+
+#define CMD_RDFT                   		0x0B
+#define CMD_RDID                    	0x9F
+
+
+#define SPI_NOR_MAX_ID_LEN	8
+
+struct nor_info {
+	char		*name;
+
+	u8		id[SPI_NOR_MAX_ID_LEN];
+	u8		id_len;
+
+	unsigned	sector_size;
+	u16		n_sectors;
+
+	u16		page_size;
+	u16		addr_width;
+
+	u16		flags;
+#define	SECT_4K				0x01
+#define	SPI_NOR_NO_ERASE	0x02
+#define	SST_WRITE			0x04
+#define	SPI_NOR_NO_FR		0x08
+#define	SECT_4K_PMC			0x10
+#define	SPI_NOR_DUAL_READ	0x20
+#define	SPI_NOR_QUAD_READ	0x40
+#define	USE_FSR				0x80
+};
+
+extern struct nor_info *spi_nor_flash;
+
+
+#endif /* _SPIFC_H_ */
+
diff --git a/boot/common/src/loader/drivers/sdio.c b/boot/common/src/loader/drivers/sdio.c
new file mode 100644
index 0000000..03b4acc
--- /dev/null
+++ b/boot/common/src/loader/drivers/sdio.c
@@ -0,0 +1,544 @@
+/*******************************************************************************
+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ£º sdio.c
+* ÄÚÈÝÕªÒª£º
+* ÆäËü˵Ã÷£º
+* µ±Ç°°æ±¾£º 1.0
+* ×÷¡¡¡¡Õߣºcaidaofang
+* Íê³ÉÈÕÆÚ£º 
+*
+*
+*******************************************************************************/
+#include <common.h>
+#include <linux/byteorder/generic.h>
+#include <asm/io.h>
+#include <sdio.h>
+#include <image.h>
+
+
+#define SYS_STD_CRM_BASE                   0x1307000
+#define DMA_BUFFER_SIZE_16K               (0x2<<1) 
+
+#define DMA_BUFFER_SIZE_32K               (0x3<<1) 
+#define DMA_BUFFER_SIZE_64K               (0x4<<1) 
+
+#define DMA_BUFFER_SIZE_256K              (0x6<<1)  
+#define DMA_BUFFER_SIZE_512K              (0x7<<1)    
+#define SDIO_ERR                           -1
+#define SDIO_INPROGRESS                    -2
+
+uint32_t uboot_entry_point = 0;
+
+static void sdio_clk_reset(void)
+{
+// enable sdio clk  16,17 hclk  
+   REG32(SYS_STD_CRM_BASE+0x44) |= (0x3<<16);
+   usdelay(80);
+// release reset sdio clk 16 ahb clk
+   REG32(SYS_STD_CRM_BASE+0x48) |= (0x1<<16);
+   usdelay(80);
+}
+
+/*²ÉÓÃCPU¶ÁÈ¡FIFO£¬½ûÖ¹ÖжÏ*/
+static void sdio_initial_setup(void)
+{
+    u32 val = 0;
+    REG32(SDIO_SLAVE_IOREADY)          |= 0x3e;//ÅäÖÃ1-5bit 
+
+    REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0;  //mask sdio int
+    REG32(SDIO_SLAVE_INTSTATUS)         = 0xffffffff;//clear int
+    
+    REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0xffffffff; //enable status int
+
+    //REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0x33C0181B; //enable status int
+    REG32(SDIO_SLAVE_INTSIGNAL_EN)      = 0; //maskedÖжÏÐźÅ1£¬²»Éϱ¨¸øÖжϿØÖÆÆ÷
+    REG32(SDIO_SLAVE_INT_SIGNAL_EN2)    = 0; //maskedÖжÏÐźÅ2£¬²»Éϱ¨¸øÖжϿØÖÆÆ÷
+    val = REG32(SDIO_SLAVE_SDIO_CCCR_CTRL);
+    REG32(SDIO_SLAVE_SDIO_CCCR_CTRL)    = val;//0x3FF3E343; 
+
+    REG32(0x1307080)= 0x7ffe0;
+
+    memset((u8*)0x20000000,0,1024*180);
+
+    val = REG32(SDIO_SLAVE_CARD_OCR);
+
+    REG32(SDIO_SLAVE_CARD_OCR) = val|0x01000000; 
+    
+/*dma*/    
+    /*dma1 address register config*/
+  //  REG32(SDIO_SLAVE_DMA1ADDR)          = CFG_SDIO_LOAD_BASE; //set dma address
+    /*adma/dma1 address register and buffer size is 0:not valid 1:valid,buffer size is 4K(default)*/
+   // REG32(SDIO_SLAVE_DMA1CTRL)         |=0x1|DMA_BUFFER_SIZE_256K;  //enable dma address
+    /*disable adma£¬enable dma ,sel one*/
+    REG32(SDIO_SLAVE_CTRL2)            &=(~0x4); 
+   
+/*sdio slave config ready operate*/
+    REG32(SDIO_SLAVE_CTRL)             |=0x4; //ÅäÖõÚ2bit£¬±íʾ׼±¸²Ù×÷
+
+
+    
+}
+
+int Sdio_Slave_Read_4K(const u32 load_addr,u32 len)
+{
+    u32 status =0 ;
+    int ret = 0;
+
+    u32 dma_addr = (u32)CFG_SDIO_LOAD_BASE;
+    
+    REG32(SDIO_SLAVE_DMA1ADDR)  = CFG_SDIO_LOAD_BASE;  //CFG_SDIO_LOAD_BASE; 
+    REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1;    //|DMA_BUFFER_SIZE_512K;    //256K
+    
+    while(1)
+    {
+        status = REG32(SDIO_SLAVE_INTSTATUS);
+
+        if((status &SDIO_STS_DMA1)!=0)
+        {
+
+            dma_addr += 0x1000;
+            /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_DMA1);
+            /*2,clear*/
+            
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_DMA1;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_DMA1;
+
+            REG32(SDIO_SLAVE_DMA1ADDR)  = dma_addr ;//CFG_SDIO_LOAD_BASE; 
+            REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1;
+                     
+        }
+        
+
+        if((status &SDIO_STS_TC)!=0)
+        {
+           // printf("SDIO xfer OK!\n");
+            break;
+        }
+        
+        if((status &SDIO_STS_F_CRC_E)!=0)
+           {
+            printf("SDIO CRC Error!\n");  
+
+           /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_CRC_E);
+            /*2,clear*/
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_CRC_E;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_CRC_E;
+      
+            ret = SDIO_ERR;
+        }
+
+        if((status &SDIO_STS_F_A)!=0)
+           {
+
+            /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_A);
+            /*2,clear*/
+            //status = REG32(SDIO_SLAVE_INTSTATUS);
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_A;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_A;
+
+            
+            printf("SDIO ABORT Xfer!\n");
+
+        }
+           
+        
+    }
+/*thansfer complete,write program done*/
+    REG32(SDIO_SLAVE_CTRL)     |= 0x1;
+/*clear int status*/
+    /*1,mask*/
+   // REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~(SDIO_STS_TC|SDIO_STS_WS|SDIO_STS_DMA1|SDIO_STS_F_A|SDIO_STS_F_CRC_E));
+
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0;
+    /*2,clear*/
+    status = REG32(SDIO_SLAVE_INTSTATUS);
+    REG32(SDIO_SLAVE_INTSTATUS) = status;
+    /*3,enalbe*/
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0xffffffff;
+
+     /*thansfer complete,write program done*/
+   // REG32(SDIO_SLAVE_CTRL)     |= 0x1;
+       
+   // REG32(SDIO_SLAVE_INTSTATUS_EN)      = 0x33C0181B; //enable status int;
+    memcpy(load_addr,(u32)CFG_SDIO_LOAD_BASE,len);
+
+
+    return ret;
+}
+
+
+int Sdio_Slave_Write_Ack(void)
+{
+
+
+    u32 status = 0;
+    int ret = 0;
+
+    //u32 ack[2] = {0x11223344,0xAABBCCDD};
+    char *ack = "rxok";
+
+    memcpy((u32)CFG_SDIO_LOAD_BASE,ack,4);
+
+    printf("SDIO write ack\n");
+     
+    REG32(SDIO_SLAVE_DMA1ADDR)  = CFG_SDIO_LOAD_BASE;  
+    REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1;    
+    
+    while(1)
+    {
+        status = REG32(SDIO_SLAVE_INTSTATUS);
+
+      
+        if((status &SDIO_STS_TC)!=0)
+        {
+           // printf("SDIO xfer OK!\n");
+            break;
+        }
+        
+        if((status &SDIO_STS_F_CRC_E)!=0)
+           {
+            printf("SDIO CRC Error!\n");  
+
+           /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_CRC_E);
+            /*2,clear*/
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_CRC_E;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_CRC_E;
+      
+            ret = SDIO_ERR;
+        }
+
+        if((status &SDIO_STS_F_A)!=0)
+           {
+
+            /*1,mask*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_A);
+            /*2,clear*/
+            //status = REG32(SDIO_SLAVE_INTSTATUS);
+            REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_A;
+            /*3,enalbe*/
+            REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_A;
+
+            
+            printf("SDIO ABORT Xfer!\n");
+
+        }
+           
+        
+    }
+/*thansfer complete,write program done*/
+   // REG32(SDIO_SLAVE_CTRL)     |= 0x1;
+/*clear int status*/
+    /*1,mask*/
+
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0;
+    /*2,clear*/
+    status = REG32(SDIO_SLAVE_INTSTATUS);
+    REG32(SDIO_SLAVE_INTSTATUS) = status;
+    /*3,enalbe*/
+    REG32(SDIO_SLAVE_INTSTATUS_EN) = 0xffffffff;
+
+    return ret;
+    
+}
+
+
+static int sdio_slave_init(void)
+{
+
+    // SDIOÉèÖÃCPRMÄ£¿éµÄ´úÂë
+    //sdio_clk_reset();
+
+	// Initialize controller
+	sdio_initial_setup();
+
+
+    
+}
+
+static int slave_size = 0; 
+
+/**************   success :return boot size  ***********/
+int sdio_slave_read(const u32 load_addr)
+{
+    u32 dwInt_status = 0;
+    u32 dwCurrent_Cmd = 0;
+    u32 cmdreg =0;
+    u32 argreg = 0;
+    u32 cmd = 0;
+    u32 blksize = 0;
+    u32 blkcnt = 0;
+    u32 boot_size = 0;
+    
+    int ret = SDIO_INPROGRESS;
+
+    while(1)
+    {
+        // dwCurrent_CmdΪ53ʱ£¬½øÐÐÊý¾Ýдor¶Á²Ù×÷
+
+        dwCurrent_Cmd = ((REG32(SDIO_SLAVE_CMD)>>13) & 0x3F);
+
+        switch(dwCurrent_Cmd)
+        {
+            case SDIO_CMD53:
+            {
+
+            dwInt_status = REG32(SDIO_SLAVE_INTSTATUS);
+
+            
+            if((dwInt_status & SDIO_STS_WS) == SDIO_STS_WS)
+            {
+                cmdreg = REG32(SDIO_SLAVE_CMD); 
+                argreg = REG32(SDIO_SLAVE_ARGU);
+
+                blksize = (cmdreg >>1) &0xFFF;
+                
+                blkcnt = argreg & 0x1FF;
+
+                if(!(argreg & 0x08000000))
+                {
+                
+                   boot_size =blksize;  
+                }
+                else
+                {
+                   boot_size =blkcnt * blksize;  
+                }
+
+                slave_size = boot_size;
+
+                    
+               ret = Sdio_Slave_Read_4K(load_addr,boot_size);
+
+             if(!ret)
+                 return boot_size;
+             else if(ret == SDIO_ERR)
+                return SDIO_ERR;
+               
+            }
+            
+             break;
+           }
+            default:
+                break;
+        } 
+
+    }
+
+    return boot_size;
+}
+
+int sdio_slave_write(void)
+{
+
+
+   u32 dwInt_status = 0;
+   u32 dwCurrent_Cmd = 0;
+   u32 cmdreg =0;
+   u32 argreg = 0;
+   u32 cmd = 0;
+   u32 blksize = 0;
+   u32 blkcnt = 0;
+   u32 boot_size = 0;
+
+   int ret = SDIO_INPROGRESS;
+
+     printf("SDIO slave write \n");
+ 
+    REG32(SDIO_SLAVE_FUN1CTRL) |= (0x4 & 0xFFFF);
+  
+     while(1)
+    {
+        dwCurrent_Cmd = ((REG32(SDIO_SLAVE_CMD)>>13) & 0x3F);
+
+        switch(dwCurrent_Cmd)
+        {
+            case SDIO_CMD53:
+            {
+
+            dwInt_status = REG32(SDIO_SLAVE_INTSTATUS);
+
+            
+            if((dwInt_status & SDIO_STS_RS) == SDIO_STS_RS)
+            {
+                cmdreg = REG32(SDIO_SLAVE_CMD); 
+                argreg = REG32(SDIO_SLAVE_ARGU);
+
+                blksize = (cmdreg >>1) &0xFFF;
+                
+                blkcnt = argreg & 0x1FF;
+
+                if(!(argreg & 0x08000000))
+                {
+                
+                   boot_size =blksize;  
+                }
+                else
+                {
+                   boot_size =blkcnt * blksize;  
+                }
+
+                    
+               ret = Sdio_Slave_Write_Ack();
+
+             if(!ret)
+                 return boot_size;
+             else if(ret == SDIO_ERR)
+                return SDIO_ERR;
+               
+            }
+            
+             break;
+           }
+            default:
+                break;
+        } 
+
+    
+   }
+
+   return boot_size;
+    
+}
+
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int sdio_slave_read_bin()
+{
+    int32_t len = 0;
+    uint32_t i =0;
+    
+  /*1.µÚÒ»´Î½ÓÊÕ */
+    len = sdio_slave_read((u32)CFG_TEMP_ADDR);
+    if( len < 0 )
+    {
+        printf("sdio_slave: read first error\n");
+        goto sdio_error1;
+    }
+
+  /*2.»ñÈ¡°æ±¾ÐÅÏ¢ */
+    image_header_t *header = NULL;
+    header = (image_header_t *)CFG_TEMP_ADDR;
+    uint32_t header_size = sizeof(image_header_t);
+    uint32_t size = ___htonl(header->ih_size); 
+    uint32_t load_addr = ___htonl(header->ih_load);
+    uboot_entry_point = ___htonl(header->ih_ep);
+
+  /*3.¿½±´µÚÒ»´ÎÊý¾Ý */
+    memcpy(load_addr, CFG_TEMP_ADDR+sizeof(image_header_t), len);
+    load_addr = load_addr + len - header_size;
+    
+  /*4.¼ÆËã´«Êä´ÎÊý */
+    /* Èç¹ûµÚÒ»´Î´«ÊäµÄ×Ö½Ú´óÓÚ»òµÈÓÚ°æ±¾µÄ´óС£¬Ôò´«ÊäÍê³ÉÖ±½Ó·µ»Ø */
+    if( (len > size) || (len == size) )
+    {   
+        printf("sdio_slave: first finsh and return\n");
+        return 0;
+    }
+
+    uint32_t left_times = size/CFG_SDIO_SLAVE_PACKAGE_LEN;
+    uint32_t mod = size%CFG_SDIO_SLAVE_PACKAGE_LEN;
+    if( mod == 0 )
+    {
+        left_times--;
+    }
+
+    
+    /* debug */
+    printf("sdio_slave: display the transfer times\n");
+    for( i=0; i<left_times+1; i++ )
+        printf(" + ");
+    printf("\n");
+
+  /*5.½ÓÊÕÆäÓàµÄÊý¾Ý */ 
+    for( i=0; i<left_times; i++ )
+    {
+        len = sdio_slave_read(load_addr);
+        if( len < 0 )
+        {
+            printf("sdio_slave: read others error\n");
+            goto sdio_error1;        
+        }
+        load_addr += len;
+    }
+
+    return 0;
+ sdio_error1:
+    return -1;
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+void sdio_slave_process(void)
+{
+    int ret = 0;
+
+    //sdio_slave_init();
+    printf("run into sdio_slave_process\n");
+/* 1. ½ÓÊÕuboot  */
+    ret = sdio_slave_read_bin();
+    if( ret != 0 )
+    {
+       printf("sdio_slave: read uboot error\n");
+       goto wait_error;
+    }
+    printf("sdio_slave: read uboot OK\n");
+
+
+    
+   ret = sdio_slave_write();
+   if(ret > 0)
+   {
+
+      printf("sdio_slave: write ack success\n"); 
+   }
+
+    
+
+    /*  r7 Ìø×ªÆô¶¯´úÂë */ 
+    writel(0xE59ff000, 0x100000);             
+    writel(uboot_entry_point, 0x100000 + 8);   
+
+    printf("Start the uboot....\n");
+
+    
+    writel(0xf, 0x130702c); 
+      
+    while(1);
+    
+wait_error:
+    printf("sdio_slave: error wait\n");
+    while(1);
+}
+
diff --git a/boot/common/src/loader/drivers/secure_verify.c b/boot/common/src/loader/drivers/secure_verify.c
new file mode 100644
index 0000000..98eea5c
--- /dev/null
+++ b/boot/common/src/loader/drivers/secure_verify.c
@@ -0,0 +1,189 @@
+/*
+ ***********************************************************	
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/string.h>
+#include <sdio.h>
+#include <image.h>
+#include <key.h>
+
+
+#include "efuse.h"
+#include "drv_rsa.h"
+#include "drv_hash.h"
+
+
+#define E_N_LEN 256
+#define HASH_LEN 128
+
+
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+static u8 data_cmp_word(u32* src, u32* dst, u32 cnt)
+{
+	u32 i;
+	for(i = 0; i < cnt; i++)
+	{
+		if(src[i] != dst[i])
+		{
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int SecureVerify(u32 puiSdrmStartAddr)
+{
+	u32 uiLen = 0;
+	u32 uiRet = -1;
+	image_header_t *puiLegacyImgAddr = NULL;
+	sImageHeader *psImageHeader = NULL;
+	efuse_struct *psEfuseInfo = NULL;
+
+	u32 *puiDataLoadAddr = NULL;
+	u32 *puiArrPubKeyEN = NULL;
+	u32 *puiArrHASH = NULL;
+	u32 uiHashResArr[4] = {0};
+	u32 uiHashResLen = 0;
+	u32 uiHashVerifySize = 0;
+	u32 uiRsaResArr[32] = {0};
+	int guiEfuseStatus = 1;
+
+	u32 sRamKey[5] = {SECURE_EN,SECURE_PUK_HASH0,SECURE_PUK_HASH1,
+					  SECURE_PUK_HASH2,SECURE_PUK_HASH3};
+	
+	T_Rsa_Paramter sRSAInput;
+	u32 *puiRsaResAddr = NULL;
+
+	if(0 == puiSdrmStartAddr)
+	{
+		return -1;
+	}
+
+	psImageHeader = (sImageHeader *)puiSdrmStartAddr;
+	puiLegacyImgAddr = (image_header_t *)(puiSdrmStartAddr + sizeof(sImageHeader));
+	uiHashVerifySize = ___htonl(puiLegacyImgAddr->ih_size) + sizeof(image_header_t);
+
+	guiEfuseStatus = get_secure_verify_status();
+	if(guiEfuseStatus == 0)    //efuse secure verify.
+		psEfuseInfo = (efuse_struct*)EFUSE_RAM_BASE;
+	else
+		psEfuseInfo = (efuse_struct*)sRamKey;
+
+	/*
+	 * 0. ¼ì²éPubKeyÊÇ·ñ±»´Û¸Ä¡£
+	 *  - ¶ÔPubKeyÃ÷ÎĽøÐÐHASH_MD5ÔËË㣬
+	 *  ²¢ÇÒÓëefuseÖб£´æµÄpuk_hash±È½Ï¡£
+	 *    - ±È½ÏÊý¾ÝÏàͬ£¬·µ»Ø0£»
+	 *    - ²»Í¬£¬·µ»Ø1¡£
+	 */
+	uiLen = E_N_LEN;  //¹«Ô¿EºÍN£¬¹²256byte³¤¶È¡£
+	puiArrPubKeyEN = psImageHeader->uiPubKeyRsaE;
+
+	uiRet = Hash_Calculate(HASH_MODE_MD5, 
+						   HASH_SMALL_ENDIAN, 
+						   puiArrPubKeyEN, 
+						   uiLen, 
+						   NULL, 
+						   0, 
+						   uiHashResArr, 
+						   &uiHashResLen);
+	if(uiRet != 0)
+	{
+		return -1;
+	}
+	
+	if(data_cmp_word((u32 *)psEfuseInfo->puk_hash, 
+						uiHashResArr, uiHashResLen))
+	{
+		printf("Puk hash verify fail!\n");
+		return -1;
+	}
+
+	puiArrHASH = psImageHeader->uiHashY;
+	uiLen = HASH_LEN;
+
+	/*
+	 * 1. ÀûÓù«Ô¿¶ÔuiHashY'½øÐнâÃÜ£¬µÃµ½1024bit½á¹û¡£
+	 */
+	sRSAInput.udCalMode = RSA_MOD_EXPO_WITH_INIT;
+	sRSAInput.udNbitLen = 1024;
+	sRSAInput.udEbitLen = 1024;
+	sRSAInput.pudInputM = puiArrHASH;
+	sRSAInput.pudInputE = puiArrPubKeyEN;
+	sRSAInput.pudInputN = (puiArrPubKeyEN + 32);
+	sRSAInput.pudOutputP = uiRsaResArr;
+	
+	uiRet = Rsa_Calculate(sRSAInput);
+	if(uiRet != 0)
+	{
+		printf("Rsa_Calculate fail!\n");
+		return -1;
+	}
+
+	//È¡×îºó4×Ö½Ú×÷ΪPubKey½âÃܺóµÄHASH_MD5Öµ¡£
+	puiRsaResAddr = sRSAInput.pudOutputP + (32 - uiHashResLen);    
+
+	/*
+	 * 2. ¼ÆËãÏÂÒ»¼¶¾µÏñµÄHASH_MD5Öµ¡£
+	 *  - ¶ÔLegacyImage(64 BytesµÄÍ·ÐÅÏ¢+°æ±¾Çø)½øÐÐhash¼ÆË㣬
+	 * ²¢ÇÒÓëPubKeyÑéÇ©µÄ½á¹û½øÐбȽϡ£
+	 */
+	uiLen = uiHashVerifySize;
+	puiDataLoadAddr = (u32 *)(___htonl(puiLegacyImgAddr->ih_load)
+								- sizeof(image_header_t));
+
+	/* Cleanup Output Buffer. */
+	uiHashResLen = 0;
+	memset(uiHashResArr, 0, 4*sizeof(uiHashResArr[0]));
+	
+	uiRet = Hash_Calculate(HASH_MODE_MD5, 
+						   HASH_SMALL_ENDIAN, 
+						   puiDataLoadAddr, 
+						   uiLen, 
+						   NULL, 
+						   0, 
+						   uiHashResArr, 
+						   &uiHashResLen);
+	if(uiRet != 0)
+	{
+		printf("Hash_Calculate Fail!\n");
+		return -1;
+	}
+
+	if(data_cmp_word(puiRsaResAddr, uiHashResArr, uiHashResLen))
+	{
+		printf("SignImage Verify Fail!\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+
+
diff --git a/boot/common/src/loader/drivers/spifc.c b/boot/common/src/loader/drivers/spifc.c
new file mode 100755
index 0000000..7703efd
--- /dev/null
+++ b/boot/common/src/loader/drivers/spifc.c
@@ -0,0 +1,867 @@
+/*********************************************************************
+ Copyright 2016 by  ZXIC Corporation.
+*
+* FileName::    spifc.c
+* File Mark:
+* Description:  
+* Others:
+* Version:  
+* Author:  
+* Date:   
+
+* History 1:
+*     Date: 
+*     Version:
+*     Author: 
+*     Modification:
+* History 2:
+**********************************************************************/
+#include <common.h>
+#include <asm/arch/spifc.h>
+#include <asm/io.h>
+#include <bbt.h>
+
+#include "flash.h"
+
+
+static const struct spi_flash_device_para *spi_flash_info = NULL;
+/* spi flash parameter config */
+static const struct spi_flash_device_para spi_flash_para[] = {
+	/* GIGADEVICE GD5F1GQ4R 128MB 1.8V SPI-NAND */
+	{0xC8, 0xC1, 0x77, 2048, 11, 128, 17, 1024, 0x20000, 1},
+	/* GIGADEVICE GD5F1GQ5RExxG  128MB 1.8V SPI-NAND */
+	{0xC8, 0x41, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/* GIGADEVICE GD5F2GQ4R 256MB SPI-NAND */	
+	{0xC8, 0xC2, 0x77, 2048, 11, 128, 17, 2048, 0x20000, 1}, 
+	/* GIGADEVICE GD5F4GQ4U 512MB SPI-NAND */
+	{0xC8, 0xC4, 0x77, 4096, 12, 256, 18, 2048, 0x40000, 1},
+
+	/* PARAGON PN26Q01AWSIUG 128MB SPI-NAND */	
+	{0xA1, 0xC1, 0x77, 2048, 11, 128, 17, 1024, 0x20000, 1},
+	/* PN26Q02AWSIUG 1.8V 2G-BIT SPI NAND  */	
+	{0xA1, 0xC2, 0x77, 2048, 11, 128, 17, 2048, 0x20000, 1},
+
+	/* HYF1GQ4IAACAE SPI-NAND  */	
+	{0xC9, 0x51, 0x77, 2048, 11, 128, 17, 1024, 0x20000, 1},
+	/* HYF2GQ4IAACAE SPI-NAND  */	
+	{0xC9, 0x52, 0x77, 2048, 11, 128, 17, 2048, 0x20000, 1},
+	/*winbond W25N01G*/
+	{0xEF, 0xBA, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/*winbond W25N02G*/
+	{0xEF, 0xBB, 0x77, 2048, 11, 64, 17, 2048, 0x20000, 1},		
+	/* TOSHIBA TC58CYG0S3HRAIG 128MB SPI-NAND*/
+	{0x98, 0xB2, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/* TOSHIBA TC58CYG1S3HRAIG 256MB SPI-NAND*/
+	{0x98, 0xBB, 0x77, 2048, 11, 64, 17, 2048, 0x20000, 1},
+	/* ZETTA ZD35X1GAXXX 128MB SPI-NAND*/
+	{0xBA, 0x21, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/* DOSILICON DS35X1GAXXX 128MB SPI-NAND*/
+	{0xE5, 0x21, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/* DOSILICON DS35X12BXXX 64MB SPI-NAND*/
+	{0xE5, 0xA5, 0x77, 2048, 11, 128, 17, 512, 0x20000, 1},
+	/* FUDANWEI FM25LS01 128MB SPI-NAND*/
+	{0xA1, 0xA5, 0x77, 2048, 11, 128, 17, 1024, 0x20000, 1},
+	/* hosin  HG-SPIXGb-1XAIA 128MB SPI-NAND*/
+	{0xD6, 0x21, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/* EMST F50D1G41LB (2M) 128MB SPI-NAND */
+	{0xC8, 0x11, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/* FORESEE F35UQA001G 128MB SPI-NAND */
+	{0xCD, 0x61, 0x77, 2048, 11, 64, 17, 1024, 0x20000, 1},
+	/* FORESEE F35UQA512M 64MB SPI-NAND */
+	{0xCD, 0x60, 0x77, 2048, 11, 64, 17, 512, 0x20000, 1},
+	/* micron-MT29F2G01ABAGDWB-ITG 256MB SPI-NAND */
+	{0x2C, 0x25, 0x77, 2048, 11, 128, 17, 2048, 0x20000, 2},
+	/* ESMT F50D44G41XB (2X)  512MB SPI-NAND*/
+	{0x2C, 0x35, 0x77, 4096, 12, 256, 18, 2048, 0x40000, 1},
+	{0}
+};
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_enable
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+static void spifc_enable(void)
+{
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+    
+    if( spi->SFC_EN & FC_EN_BACK )
+        return;
+    
+    spi->SFC_EN |= FC_EN;  
+    spi->SFC_CTRL0 |= FC_SCLK_PAUSE_EN;
+}
+
+/*
+ ******************************************************************************
+ * Function:    spifc_clear_fifo
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+void spifc_clear_fifo( void )
+{
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+    
+    spi->SFC_CTRL0 |= (FC_RXFIFO_THRES | FC_TXFIFO_THRES | 
+                       FC_RXFIFO_CLR | FC_TXFIFO_CLR);
+}
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_setup_cmd
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+static void spifc_setup_cmd( struct spiflash_cmd_t *cmd, 
+                                  uint32_t addr, uint32_t len )
+{   
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+    uint32_t wrap = 0;	
+    uint32_t tmp = 0;
+	
+    /* ÃüÁîÂë */  
+    spi->SFC_INS = cmd->cmd;
+
+	/* Êý¾Ý³¤¶È */
+    if( len )
+        spi->SFC_BYTE_NUM = len - 1;
+    else
+        spi->SFC_BYTE_NUM = 0;  
+
+    switch( len )
+    {
+        case 2048:
+            wrap = WRAP_SIZE_MAIN;
+            break;
+        case 2112:
+             wrap = WRAP_SIZE_MAIN_OOB;;
+            break;
+        case 64:
+             wrap = WRAP_SIZE_OOB;;
+            break;
+        default:
+            wrap = 0;
+            break;
+    }
+
+    /* µØÖ·Âë */
+    switch( spi->SFC_INS )
+    {
+        case CMD_READ_FROM_CACHE:
+        //  case CMD_READ_FROM_CACHE_X2:
+        case CMD_READ_FROM_CACHE_X4:
+        case CMD_READ_FROM_CACHE_QIO:
+        case CMD_PROGRAM_LOAD:
+        case CMD_PROGRAM_LOAD_X4:
+            // case CMD_PROGRAM_LOAD_RANDOM:
+            //  case CMD_PROGRAM_LOAD_RANDOM_X4:
+            //case CMD_PROGRAM_LOAD_RANDOM_QIO:
+            addr |= wrap;
+            break;
+            
+        default:
+            addr = addr;
+            break;
+    }
+    spi->SFC_ADDR = addr;  
+
+    /* µØÖ·Âë¡¢¿ÕÖÜÆÚ¡¢¶Á/д ʹÄÜÉèÖà */
+    spi->SFC_CTRL1 = 0;
+    spi->SFC_CTRL1 = ((cmd->addr_tx_en << FC_ADDR_TX_EN) |  
+                      (cmd->dumy_tx_en << FC_DUMMY_TX_EN) | 
+                      (cmd->data_rx_en << FC_READ_DAT_EN) | 
+                      (cmd->data_tx_en << FC_WRITE_DAT_EN)); 
+                    
+
+	/* ¿ÕÖÜÆÚÊý¡¢µØÖ·¿í¶È(1£¬2£¬3£¬4×Ö½Ú)¡¢
+	 * µØÖ·/Êý¾ÝÏß¶È¡¢´«Êäģʽ 
+	 */
+#if 0
+    tmp = spi->SFC_CTRL2;
+    tmp &= 0x1f;
+    tmp |= ((cmd->dumy_bytes << FC_DUMMY_BYTE_NUM) |
+            (cmd->dumy_bits << FC_DUMMY_BIT_NUM) |
+            (cmd->addr_width << FC_ADDR_BYTE_NUM));
+    spi->SFC_CTRL2 = tmp;
+#else
+	spi->SFC_CTRL2 = 0;
+	tmp |= ((cmd->dumy_bytes << FC_DUMMY_BYTE_NUM) |
+			(cmd->dumy_bits << FC_DUMMY_BIT_NUM) |
+			(cmd->addr_width << FC_ADDR_BYTE_NUM));
+	tmp &= ~0x700;
+	spi->SFC_CTRL2 = tmp;
+#endif
+       
+}
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_clear_int
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+ void spifc_clear_int( void )
+{
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+    
+    if(spi->SFC_INT_RAW & 0x2)
+        printf("\n");
+
+    spi->SFC_INT_SW_CLR = 0xFF; //clear int ?
+}
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_wait_cmd_end
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+static int spifc_wait_cmd_end( void )
+{
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+    uint32_t int_status = 0;
+    
+    while(!(spi->SFC_INT_RAW & FC_INT_RAW_MASK));
+    
+    int_status = spi->SFC_INT_RAW;
+    spi->SFC_INT_SW_CLR = int_status;	/* clear intrrupt */
+
+	if(int_status & FC_INT_RAW_CMD_END)
+    {   
+        return 0;
+    }
+    else
+    {
+		printf("intr err.\n");
+        return -1;
+    } 
+
+}
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_read_fifo_one_byte
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ *
+ * Others:  only for:
+                [Instruction]                 |--addr width is 8 bit
+                [addr]                        |--get feature
+                [data_rx]   
+ *******************************************************************************
+ */
+static int spifc_read_fifo_one_byte( uint8_t *value )
+{
+    uint32_t sw = 0;
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+
+    sw = spi->SFC_SW;
+    
+    if( ((sw >> FC_RX_FIFO_CNT) & FC_RX_FIFO_CNT_MASK) != 1 )
+    {
+        return -1;
+    }
+
+    *value = (uint8_t)spi->SFC_DATA;   
+    
+    return 0;
+}
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_read_fifo
+ * Description:
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+static uint32_t spifc_read_fifo( uint32_t len, uint8_t *buf )
+{
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+    uint32_t *p = (uint32_t *)buf;
+    uint32_t cnt = 0;
+
+    while(cnt < ((len+3)>>2))  
+    {
+        if(spi->SFC_SW & (FC_RX_FIFO_CNT_MASK<<FC_RX_FIFO_CNT))//rx fifo not empty
+        {           
+            p[cnt++]= spi->SFC_DATA;
+        }
+    }
+
+    return (cnt<<2);
+}
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_start
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+static void spifc_start( void )
+{
+    volatile struct spi_t* spi	= (struct spi_t*)SYS_SPI_NAND_BASE;
+    
+    spi->SFC_START |= FC_START;
+}
+
+/*
+ ******************************************************************************
+ * Function:    spifc_get_feature
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ *
+ * Others:   [Instruction]                 |--addr width is 8 bit
+             [addr]                        |--get feature
+             [data_rx]                     |--read id
+            
+ *******************************************************************************
+ */
+ static int spifc_get_feature( uint32_t reg_addr, uint8_t *value)
+ {   
+    int ret = 0;
+    
+    struct spiflash_cmd_t cmd = {CMD_GET_FEATURE,		
+                                 1,                     
+                                 FC_ADDR_BYTE_NUM_8,    
+                                 0,                     
+                                 1,                     
+                                 0,                     
+                                 0,                     
+                                 0                      
+                                };
+
+    spifc_clear_fifo();
+    spifc_clear_int();
+     
+    spifc_setup_cmd(&cmd, reg_addr, 1);
+    spifc_start();             
+    ret = spifc_wait_cmd_end();
+    if(ret != 0)
+    {
+        return ret;
+    }
+
+    ret = spifc_read_fifo_one_byte(value);
+    if(ret != 0) 
+    {
+        return ret;
+    }
+     
+    return 0;
+}
+
+/*
+ ******************************************************************************
+ * Function:    spifc_read_id
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ *
+ * Others:  [Instruction]                 |--addr width is 8 bit
+            [addr]                        |--get feature
+            [data_rx]                     |--read id
+ *******************************************************************************
+ */
+static int spifc_read_id(uint32_t reg_addr, uint8_t *value, uint8_t len)
+{   
+    int ret = 0;
+    
+    struct spiflash_cmd_t cmd = {   CMD_READ_ID,            
+	                                1,                      
+	                                FC_ADDR_BYTE_NUM_8,     
+	                                0,                     
+	                                1,                     
+	                                0,                     
+	                                0,                     
+	                                0                      
+                                };
+
+    spifc_clear_fifo();
+    spifc_clear_int();
+    spifc_setup_cmd(&cmd, reg_addr, len);       
+    spifc_start();                             
+	ret = spifc_wait_cmd_end();            
+    if(ret != 0)
+    {
+        return ret;
+    }
+
+    ret = spifc_read_fifo(len, value);    
+    if(ret != 0) 
+    {
+        return ret;
+    }   
+
+    return 0;
+}
+
+
+/*
+ ******************************************************************************
+ * Function:    spifc_read_page_to_cache
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:  [Instruction]       |--addr width is 24 bit(page/block addr!!!!)
+            [addr]              |--page read
+                                |--block erase
+                                |--program execute
+ *******************************************************************************
+ */
+static int spifc_read_page_to_cache(uint32_t page_addr)
+{     
+    int ret = 0;
+    uint8_t status = 0;
+    
+    struct spiflash_cmd_t cmd = {   CMD_READ_PAGE_TO_CACHE, 
+                                    1,                      
+                                    FC_ADDR_BYTE_NUM_24,    
+                                    0,                      
+                                    0,                      
+                                    0,                      
+                                    0,                      
+                                    0                       
+                                };
+	
+    spifc_clear_fifo();
+    spifc_clear_int();
+    spifc_setup_cmd(&cmd, page_addr, 0);   
+    spifc_start();                         
+    ret = spifc_wait_cmd_end();            
+    if(ret != 0)
+    {
+        return ret;
+    }
+	
+    do
+    {
+        spifc_get_feature(REG_STATUS, &status);
+    }while( status & OIP);
+     
+    return 0;
+}
+
+/*
+ ******************************************************************************
+ * Function:    spifc_read_from_cache
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:  [Instruction]                 |--addr width is 16 bit
+            [addr]                        |--dummy cycel 8/4/2
+            [dummy]                       |--read form cache(X1,X2,X4)
+            [data_rx]                     |--read form cache(dual,quad)IO
+ *******************************************************************************
+ */
+static int spifc_read_from_cache(uint32_t column_addr, uint32_t len, uint8_t *buf)
+{      
+    int ret = 0;
+
+    uint32_t len_tmp = 0;
+    struct spiflash_cmd_t cmd;
+    
+    cmd.cmd = CMD_READ_FROM_CACHE;          
+    cmd.dumy_bytes = 1;                     
+    cmd.dumy_bits = 0;                      
+    cmd.addr_tx_en = 1;                     
+    cmd.addr_width = FC_ADDR_BYTE_NUM_16;   
+    cmd.data_tx_en = 0;                     
+    cmd.data_rx_en = 1;                     
+    cmd.dumy_tx_en = 1;                     
+ 
+    spifc_clear_fifo();
+    spifc_clear_int();
+    spifc_setup_cmd(&cmd, column_addr, len);
+    spifc_start();                          
+    
+    len_tmp = spifc_read_fifo(len, buf);           
+    if( len_tmp != len ) 
+    {
+        ret = -2;
+        return ret;
+    }
+
+    ret = spifc_wait_cmd_end();
+    if( ret != 0 )
+    {
+        return ret;
+    }
+     
+    return 0;
+}
+
+
+/*
+ ******************************************************************************
+ * Function:     nand_read_oob
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+void spifc_read_oob(uint8_t *buf, uint32_t offset, uint32_t len)
+{  
+	uint32_t column_offset = spi_flash_info->page_size;
+	uint32_t page = offset >> (spi_flash_info->page_size_shift);
+	uint32_t blocks = offset >> (spi_flash_info->block_size_shift);
+	
+	spifc_read_page_to_cache(page);
+
+	if((spi_flash_info->planes == 2) && ((blocks%2) != 0))
+	{
+		column_offset |= (0x1 << 12);
+	}
+	spifc_read_from_cache(column_offset, spi_flash_info->oob_size, buf);
+}
+
+
+/*
+ ******************************************************************************
+ * Function:     read_page
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int32_t spifc_read_page(uint32_t buf, uint32_t offset)
+{
+	int ret = 0;
+	uint8_t feature = 0x0;
+
+	uint32_t page = offset >> (spi_flash_info->page_size_shift);
+	uint32_t blocks = offset >> (spi_flash_info->block_size_shift);
+	uint32_t column_offset = 0;
+
+	if( (buf & 0x3) != 0 )		/* DMAµØÖ·ÒªÇó4×Ö½Ú¶ÔÆë */
+	{
+		printf("addr err.\n"); 
+		return -1;      
+	}
+
+	ret = spifc_read_page_to_cache(page);
+	if( ret != 0 )
+		return ret;
+
+	ret = spifc_get_feature(REG_STATUS, &feature);
+	if(ret != 0)
+		return ret;
+
+	if((feature>>ECC_ERR_BIT & 0x3) == 0x2)
+	{
+		printf("ecc err.\n");
+		return -1;
+	}
+	if((spi_flash_info->planes == 2) && ((blocks%2) != 0))
+	{
+		column_offset |= (0x1 << 12);
+	}
+	ret = spifc_read_from_cache(column_offset, spi_flash_info->page_size, (uint8_t *)buf);
+	if(ret != 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ ******************************************************************************
+ * Function:     read_page
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int32_t spifc_read_page_raw(uint32_t buf, uint32_t offset)
+{
+    int ret = 0;
+    uint8_t feature = 0x0;
+
+    uint32_t page = offset >> (spi_flash_info->page_size_shift);
+
+    if( (buf & 0x3) != 0 )		/* DMAµØÖ·ÒªÇó4×Ö½Ú¶ÔÆë */
+    {
+        printf("addr err.\n"); 
+        return -1;      
+    }
+    
+    ret = spifc_read_page_to_cache(page);
+    if( ret != 0 )
+        return ret;
+
+    ret = spifc_read_from_cache(0, spi_flash_info->page_size, (uint8_t *)buf);
+	if(ret != 0)
+        return ret;
+
+    return 0;
+}
+
+
+/*
+ ******************************************************************************
+ * Function:     nand_read
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others: from: must page align len:  must page align
+ *******************************************************************************
+ */
+int32_t spifc_read(uint32_t from, uint32_t len, uint32_t to)
+{
+    uint32_t offset = from;
+    uint32_t left_to_read = len;
+    uint32_t p_to = to;
+    int32_t ret = 0;
+    int32_t page_size = (spi_flash_info->page_size);
+
+    if((offset & (page_size - 1)) || (len & (page_size - 1)) )
+    {
+        return -1;       
+    }
+
+    while( left_to_read > 0 )
+    {       
+        ret = spifc_read_page(p_to, offset);
+		if(ret != 0)
+		{
+			return -1;
+		}
+        
+        left_to_read -= page_size;
+        offset += page_size;
+        p_to += page_size;          
+    }
+    return 0;
+}
+
+
+/*******************************************************************************
+ * Function:     nand_read_id
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+ int32_t read_id (void)
+{
+    uint8_t id[4];
+    const struct spi_flash_device_para *spi_flash = &spi_flash_para[0];
+
+    spifc_read_id(0x0, id, 2);
+	
+    while( spi_flash->manuf_id != 0 )
+    {   
+        if( ((uint8_t)id[0] == spi_flash->manuf_id) && 
+                ((uint8_t)id[1] == spi_flash->device_id) )
+        {
+            spi_flash_info = spi_flash;
+            return 0;
+        };
+        spi_flash++;
+    }
+    
+    return -1;   
+}
+
+/*******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t read_data(uint32_t from, uint32_t len, uint32_t to)
+{
+    uint32_t offset = from;
+    uint32_t left_to_read = len;
+    uint32_t p_to = to;
+    int32_t ret = 0;
+    int32_t block_size = (spi_flash_info->block_size);
+            
+    while(left_to_read > 0)
+    {
+        uint32_t block_offset = offset & (block_size - 1);
+		uint32_t read_length;
+
+        if( nand_block_isbad(offset) )
+        {
+            offset += block_size;
+            continue;
+        }
+            
+        if (left_to_read < (block_size - block_offset))
+			read_length = left_to_read;
+		else
+			read_length = block_size - block_offset;
+      
+        ret = spifc_read(offset, read_length, p_to);
+		if(ret != 0)
+		{
+			return -1;
+		}
+
+        left_to_read -= read_length;
+        offset += read_length;
+        p_to += read_length;         
+    }
+    
+    return 0;
+}
+
+/*******************************************************************************
+ * Function:     nand_init
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t spifc_init (void)
+{
+    int32_t ret = 0;
+    spifc_enable();
+    ret = read_id();
+    if(ret != 0)
+    {
+		printf("id err!\n");
+		return -1;
+    }
+        
+	flash.flash_type = SPI_NAND_BOOT;
+	flash.manuf_id = spi_flash_info->manuf_id;
+	flash.device_id = spi_flash_info->device_id;
+	flash.page_size = spi_flash_info->page_size;
+	flash.page_size_shift = spi_flash_info->page_size_shift;
+	flash.oob_size = spi_flash_info->oob_size;
+	flash.block_size = spi_flash_info->block_size;
+	flash.block_size_shift = spi_flash_info->block_size_shift;
+	flash.block_num = spi_flash_info->block_num;
+	flash.read_page_raw = spifc_read_page_raw;
+	flash.read_oob = spifc_read_oob;
+	flash.read = read_data;
+	
+    return 0;
+	
+}
+
+/*
+ ******************************************************************************
+ * Function:     
+ * Description: 
+ * Parameters:
+ *	 Input:
+ *	 Output:
+ * Returns:
+ * Others:
+ *******************************************************************************
+ */
+int board_flash_init(void)
+{
+	int ret = 0;
+	char boot_mode = 0;
+
+	printf("spi-nand:");
+	
+	boot_mode = get_boot_mode();
+	if(boot_mode != SPI_NAND_BOOT)
+	{
+		printf("mode err.\n");
+		return -1; 
+	}
+
+	writel(CFG_START_MODE_SPI_NAND, CFG_BOOT_MODE_START_MODE_FOR_UBOOT); 
+	ret = spifc_init();
+	if(ret != 0)
+	{
+		printf("init err.\n");
+		return -1;
+	}
+	printf("init ok.\n");
+
+//	nand_creat_bbt();
+nand_creat_ram_bbt();
+	
+	return 0;
+}
+
+
diff --git a/boot/common/src/loader/drivers/type.h b/boot/common/src/loader/drivers/type.h
new file mode 100755
index 0000000..13fbe4b
--- /dev/null
+++ b/boot/common/src/loader/drivers/type.h
@@ -0,0 +1,58 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£

+*

+* ÎļþÃû³Æ£º types.h

+* ÄÚÈÝÕªÒª£º Êý¾ÝÀàÐͶ¨Òå

+* ÆäËü˵Ã÷£º

+* µ±Ç°°æ±¾£º 1.0

+* ×÷¡¡¡¡Õߣº 177792

+* Íê³ÉÈÕÆÚ£º 2010-9-30

+*

+*

+*******************************************************************************/

+

+#ifndef __INCLUDE_TYPES_H

+#define __INCLUDE_TYPES_H

+#include <linux/types.h>

+#if 0

+typedef signed char 			s8;

+typedef unsigned char 			u8;

+

+typedef signed short 			s16;

+typedef unsigned short 			u16;

+

+typedef signed int 				s32;

+typedef unsigned int 			u32;

+typedef unsigned long long 		u64;

+#endif

+

+typedef u8						BYTE;

+typedef	u32						WORD32;

+typedef	u16						WORD16;

+

+#if 0

+typedef int						int32_t;

+typedef u32						uint32_t;

+typedef u16						uint16_t;

+typedef u8						uint8_t;

+#endif

+

+

+#define MIN(x,y)		  		((x) < (y) ? (x) : (y))

+#define MAX(x,y)      			((x) > (y) ? (x) : (y))

+#define ARRAY_SIZE(x) 			(sizeof(x) / sizeof((x)[0]))

+#define REG(x)				    (*(volatile u32*)(x))

+#define REG8(x)				    (*(volatile u8*)(x))

+#define REG16(x)			    (*(volatile u16*)(x))

+#define REG32(x)			    (*(volatile u32*)(x))

+#define DWC_READ_REG32(a)     	(*(volatile u32 *)(a))

+#define DWC_WRITE_REG32(a,v)    ((*(volatile u32 *)(a)) = v)

+

+// ÏÂÃæÊÇGCC±àÒëÑ¡ÏÒå

+#define __weak__				__attribute__((weak))

+#define __aligned(x)			__attribute__((aligned(x)))

+#define __align(x)				__attribute__((aligned(x)))

+

+

+#endif

+

diff --git a/boot/common/src/loader/drivers/uart.c b/boot/common/src/loader/drivers/uart.c
new file mode 100644
index 0000000..420b8e0
--- /dev/null
+++ b/boot/common/src/loader/drivers/uart.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2016 ZXIC Inc.
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/uart.h>
+#include <asm/io.h>
+#include <asm/arch/top_clock.h>
+#include <asm/arch/gpio.h>
+
+#define CONFIG_BAUDRATE 921600
+
+/*******************************************************************************
+ * Function:    serial_gpio_config
+ * Description: 
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+static void serial_gpio_config(void)
+{
+#ifdef CONFIG_ZX297520V3E_CPE
+	unsigned int tmp = 0;
+	/*uart0_cts----->uart1_txd*/
+	__REG(PAD_TOP_FUNC_BASE+0x20) |= (1<<2);
+	tmp = __REG(PAD_PD_FUNC_BASE+0x4);
+	tmp &= ~(0x3<<2);
+	__REG(PAD_PD_FUNC_BASE+0x4) = tmp | (0x1<<2);
+
+	/*uart0_rts----->uart1_rxd*/
+    __REG(PAD_TOP_FUNC_BASE+0x20) |= (1<<3);
+	tmp = __REG(PAD_PD_FUNC_BASE+0x4);
+	tmp &= ~(0x3<<4);
+	__REG(PAD_PD_FUNC_BASE+0x4) = tmp | (0x1<<4);
+
+#endif
+}
+
+/*******************************************************************************
+ * Function: 
+ * Description: ÉèÖô®¿ÚµÄ²¨ÌØÂÊ
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+static void serial_setbrg(void)
+{
+    u32 uartClk = 26000000;
+    u32 ibrd = uartClk / (CONFIG_BAUDRATE << 4);
+    u32 fbrd = (((uartClk-((ibrd*CONFIG_BAUDRATE)<<4))<<6)+(CONFIG_BAUDRATE<<3))/(CONFIG_BAUDRATE<<4);
+    __REG(UART_IBRD) = ibrd;
+    __REG(UART_FBRD) = fbrd;  
+    #if 0
+    if( __REG(PLL_624_208_CFG0_REG) & PLL_624_208_CFG0_LOCK )  
+    {
+        __REG(UART_IBRD) = 0x38;
+        __REG(UART_FBRD) = 0x1b;
+    }            
+    else
+    {
+        __REG(UART_IBRD) = 0x2;     /* midify !!! */
+        __REG(UART_FBRD) = 0x16;
+    }    
+    #endif
+}
+
+
+/*******************************************************************************
+ * Function: 
+ * Description: ³õʼ»¯´®¿Ú²ÎÊý  115200
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+void uart_init(void)
+{
+	int count = 3000;
+
+	while(__REG(UART_FR) & UART_FR_TXBUSY){
+
+		if(--count == 0)
+		{
+			break;
+		}
+	}
+	
+	/* Òý½Å¸´ÓÃÉèÖà */
+	serial_gpio_config();
+
+	/*  ½ûÓÃUART */
+	__REG(UART_ICR) = 0xffff;
+	__REG(UART_CR) &= (~(UART_EN | UART_TXE)); 
+
+	
+
+	/*  ²¨ÌØÂÊÉèÖà */
+	serial_setbrg();    
+
+	/*  ÉèÖô«Êä¸ñʽΪ: ÎÞУÑé/1λֹͣλ/8λÊý¾Ýλ/ʹÄÜ FIFO £»¼Ä´æÆ÷³õʼ»¯Îª 0x0 */
+	__REG(UART_LCR_H) &= (~(UART_BREAK | UART_PEN | UART_STP2 ));
+	__REG(UART_LCR_H) |= (UART_WLEN_8 | UART_FEN );
+
+	/*  ÆÁ±ÎËùÓеÄuartÄ£¿é·¢³öµÄÖÐ¶Ï */
+	__REG(UART_IMSC) &= (~UART_INT_MASK);
+
+	/*  ʹÄÜUART */
+	__REG(UART_CR) |= (UART_TXE | UART_EN ); 
+
+}
+
+
+
+/*******************************************************************************
+ * Function:    uart_putc
+ * Description: 
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+ void uart_putc(const char c)
+{
+	/* µÈ´ý·¢ËÍ FIFO ²»Âú£¬¿ÉÒÔдÊý¾Ý */
+	while ((__REG(UART_FR) & UART_TXFF) != 0 );
+    __REG(UART_DR) = c;
+    
+	/* If \n, also do \r */
+	if (c == '\n')
+		uart_putc('\r');
+}
+
+
+/*******************************************************************************
+ * Function:    uart_puts
+ * Description: 
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+void uart_puts (const char *s)
+{
+	while (*s) {
+		uart_putc (*s++);
+	}
+}
+
+/*******************************************************************************
+ * Function:    uart_getc
+ * Description: 
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+char uart_getc(void)
+{
+	while ((__REG(UART_FR) & UART_RXFE) != 0 );
+	return (__REG(UART_DR) & 0xff);
+}
+
+/*******************************************************************************
+ * Function:    uart_tstc
+ * Description: 
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+int uart_tstc(void)
+{
+    if( __REG(UART_FR) & UART_RXFE )
+        return 0;       //µÈÓÚ1ʱ£¬½ÓÊÕFIFOΪ¿Õ£¬Ã»ÓÐÊý¾Ý
+    else
+        return 1;       //µÈÓÚ0ʱ£¬½ÓÊÕFIFO²»Îª¿Õ£¬ÓÐÊý¾Ý;
+}
+
+/*******************************************************************************
+ * Function: 
+ * Description: 
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+
+int UART_Read(char *pchBuf, int dwLen)
+{
+    int i = 0;
+	for(i=0;i<dwLen;i++)
+	{
+	    pchBuf[i] = (char)uart_getc();
+	}
+
+	return dwLen;
+}
+
+/*******************************************************************************
+ * Function: 
+ * Description: 
+ * Parameters: 
+ *   Input:
+ *
+ *   Output:
+ *
+ * Returns: 
+ *
+ *
+ * Others: 
+ ********************************************************************************/
+
+int UART_Write(char *pchBuf, int dwLen)
+
+{
+	int i = 0;
+	for(i=0;i<dwLen;i++)
+	{
+	    uart_putc(pchBuf[i]);
+	}
+
+	return dwLen;
+}
+
+int UART_Check_Sync(char *pchBuf, int dwLen)
+{
+    int ret = 0;
+	ret = UART_Read(pchBuf,1);
+    
+	if(0x5A!=*pchBuf)
+	{
+		return 0;
+	}
+
+	return ret;
+}
+
+
+
diff --git a/boot/common/src/loader/drivers/usb.h b/boot/common/src/loader/drivers/usb.h
new file mode 100644
index 0000000..6f46be4
--- /dev/null
+++ b/boot/common/src/loader/drivers/usb.h
@@ -0,0 +1,628 @@
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Modified by Synopsys, Inc, 12/12/2007 */
+
+
+#ifndef _USB_H_
+#define _USB_H_
+
+#include <common.h>
+#include "type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// T_LANGID_DESCRIPTOR
+#define LANGID_US_ENGLISH					0x0409
+
+// T_STRING_DESCRIPTOR
+#define MAX_STRING_LENGTH					(0x20)//(0x100)
+
+typedef enum
+{
+
+ NEED_ENUM = 0,
+ DONOT_NEED_ENUM
+ 
+}T_USB_ENUM;
+
+/*usb´«ÊäÀàÐÍ*/
+typedef enum
+{
+    TRA_CTRL = 0,
+    TRA_BULK,
+    TRA_INTR,
+    TRA_ISO
+}T_USB_TRAN;
+
+/* USB¿ØÖÆ´«ÊäÃüÁî*/
+typedef struct
+{
+    BYTE     bmRequestType;
+    BYTE     bRequest;
+    WORD16     wValue;
+    WORD16     wIndex;
+    WORD16     wLength;
+}T_CTRL_COMMAND;
+
+
+// ¶ËµãÊý¾Ý°ü´óС
+typedef enum
+{
+	CONTROL_8		=8,
+	CONTROL_16		=16,
+	CONTROL_32		=32,
+	CONTROL_64		=64,
+
+	BULK_8			=8,
+	BULK_16			=16,
+	BULK_32			=32,
+	BULKL_64		=64	
+}T_EP_PKT_SIZE;
+
+
+// CLEAR_FEATURE, SET_FEATURE
+#define FEATURE_DEVICE_REMOTE_WAKEUP		(0x1)
+#define FEATURE_ENDPOINT_HALT				(0x0)
+#define FEATURE_TEST_MODE					(0x2)
+
+// ¸ù¾Ýʵ¼ÊÇé¿öÐÞ¸Ä
+#define	USB_VENDOR_ID			                      (0x19D2)	// 2×Ö½Ú
+#define USB_PRODUCT_ID			                      (0x0256)	// 2×Ö½Ú
+#define PRODUCT_RELEASE_NUMBER	               (0x7510)	// 2×Ö½Ú
+
+#define VERDOR_SPECIFIC			(0xff)
+
+#define EP0_PACKET_SIZE CONTROL_64
+#define EP1_PACKET_SIZE 64
+#define EPX_PACKET_SIZE 64
+
+#define EP_FOR_IN 2
+#define EP_FOR_OUT 3
+
+
+/*usbÉ豸µÄÆß¸ö״̬*/
+typedef enum
+{
+    eUSB_ATTACHED = 0,
+    eUSB_POWERED,
+    eUSB_DEFAULT,
+    eUSB_SUSPEND,
+    eUSB_RUSUME,
+    eUSB_ADDRESS,    
+    eUSB_CONFIG
+}E_USB_STATE;
+
+
+// ±ê×¼ÇëÇóÃüÁî
+typedef enum
+{
+	GET_STATUS          =0x0,
+	CLEAR_FEATURE       =0x1,
+	SET_FEATURE         =0x3,
+	SET_ADDRESS         =0x5,
+	GET_DESCRIPTOR      =0x6,
+	SET_DESCRIPTOR      =0x7,
+	GET_CONFIGURATION   =0x8,
+	SET_CONFIGURATION   =0x9,
+	GET_INTERFACE       =0xa,
+	SET_INTERFACE       =0xb,
+	SYNCH_FRAME         =0xc
+}T_STANDARD_REQUST;
+
+
+// ÃèÊö·ûÀàÐÍ
+typedef enum
+{
+    DEVICE_DESCRIPTOR   = 0x01,
+    CONFIG_DESCRIPTOR   = 0x02,
+    STRING_DESCRIPTOR   = 0x03,
+    INTERFACE_DESCRIPTOR= 0x04,
+    ENDPOINT_DESCRIPTOR = 0x05
+} T_DESCRIPTORS_TYPE;
+
+// USBÖ§³ÖµÄÌØÕ÷¶¨Òå
+typedef enum
+{
+	DEVICE_REMOTE_WAKEUP	=1,		// Device 
+	ENDPOINT_HALT 			=0, 	// Endpoint 
+	TEST_MODE 				=2		//Device 
+}T_FEATURE;
+
+
+// bmAttributes
+#define ATTR_D7						       (0x01 <<7)		// ±ØÐëΪ1
+#define ATTR_SELF_POWERED			       (0x01 <<6)		// ×Ô¹©µç
+#define ATTR_SUPPORT_REMOTE_WAKEUP	(0x01 <<5)		// Ô¶³Ì»½ÐÑ
+
+// bMaxPower
+#define POWER_MA(power)				        (power>>1)		// µ¥Î»: 2mA
+
+#define EP_ADDRESS_DIRECTION_MASK	        (0x01 <<7)	//Direction, ignored for control endpoints
+#define EP_ADDRESS_DIRECTION_IN		 (0x01 <<7)
+#define EP_ADDRESS_DIRECTION_OUT	         (0x0   <<7)
+
+
+//bmAttributes
+#define EP_ATTR_TRANSFER_TYPE_MASK		 (0x03 <<0)
+#define EP_ATTR_TRANSFER_TYPE_CONTROL	        (0     <<0)
+#define EP_ATTR_TRANSFER_TYPE_ISO		        (1     <<0)
+#define EP_ATTR_TRANSFER_TYPE_BULK		 (2     <<0)
+#define EP_ATTR_TRANSFER_TYPE_INTERRUPT	 (3     <<0)
+
+//ͬ²½´«Êä¶Ëµã, ×î´ó1023×Ö½Ú, ÂÖѯ¼ä¸ô---2^(bInterval -1)Ö¡
+#define MAX_ISO_PKT			(256)	//×î´ó1023×Ö½Ú
+#define MAX_ISO_R_INTERVAL	(1)		//ÂÖѯ¼ä¸ô---2^(bInterval -1)Ö¡
+#define MAX_ISO_T_INTERVAL	(1)		//ÂÖѯ¼ä¸ô---2^(bInterval -1)Ö¡
+
+//T_STRING_DESCRIPTOR, ascii to unicode---*2, length,type--+2
+#define STRING_DESCRIPTOR_SIZE(size)    	((size*2)+2)
+//ת»»ascii×Ö·ûΪunicode×Ö·û
+#define UNICODE(ascii)							ascii,0x00
+
+/**************************************************************************/
+typedef uint8_t uByte;
+typedef uint8_t uWord[2];
+typedef uint8_t uDWord[4];
+
+
+#define UT_GET_TYPE(a) ((a) & 0x60)
+#define UT_STANDARD		0x00
+#define UT_CLASS		0x20
+#define UT_VENDOR		0x40
+
+#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
+#define UT_DEVICE		0x00
+#define UT_INTERFACE		0x01
+#define UT_ENDPOINT		0x02
+#define UT_OTHER		0x03
+/* Requests */
+#define  UR_GET_STATUS		0x00
+#define  USTAT_STANDARD_STATUS  0x00
+#define  UR_CLEAR_FEATURE	0x01
+#define  UR_SET_FEATURE		0x03
+#define  UR_SET_ADDRESS		0x05
+#define  UR_GET_DESCRIPTOR	0x06
+#define UR_SET_CONFIG		0x09
+/* Feature numbers */
+#define UF_ENDPOINT_HALT	0
+
+
+
+
+
+#define UE_GET_DIR(a)	((a) & 0x80)
+#define UE_SET_DIR(a,d)	((a) | (((d)&1) << 7))
+#define UE_DIR_IN	0x80
+#define UE_DIR_OUT	0x00
+#define UE_ADDR		0x0f
+#define UE_GET_ADDR(a)	((a) & UE_ADDR)
+
+
+#define USB_MAX_STRING_LEN 128
+#define USB_LANGUAGE_TABLE 0	/* # of the string language id table */
+
+/* Hub specific request */
+#define UR_GET_BUS_STATE	0x02
+#define UR_CLEAR_TT_BUFFER	0x08
+#define UR_RESET_TT		0x09
+#define UR_GET_TT_STATE		0x0a
+#define UR_STOP_TT		0x0b
+
+/* Hub features */
+#define UHF_C_HUB_LOCAL_POWER	0
+#define UHF_C_HUB_OVER_CURRENT	1
+#define UHF_PORT_CONNECTION	0
+#define UHF_PORT_ENABLE		1
+#define UHF_PORT_SUSPEND	2
+#define UHF_PORT_OVER_CURRENT	3
+#define UHF_PORT_RESET		4
+#define UHF_PORT_L1		5
+#define UHF_PORT_POWER		8
+#define UHF_PORT_LOW_SPEED	9
+#define UHF_PORT_HIGH_SPEED	10
+#define UHF_C_PORT_CONNECTION	16
+#define UHF_C_PORT_ENABLE	17
+#define UHF_C_PORT_SUSPEND	18
+#define UHF_C_PORT_OVER_CURRENT	19
+#define UHF_C_PORT_RESET	20
+#define UHF_C_PORT_L1		23
+#define UHF_PORT_TEST		21
+#define UHF_PORT_INDICATOR	22
+
+#define UHD_PWR			0x0003
+#define  UHD_PWR_GANGED		0x0000
+#define  UHD_PWR_INDIVIDUAL	0x0001
+#define  UHD_PWR_NO_SWITCH	0x0002
+#define UHD_COMPOUND		0x0004
+#define UHD_OC			0x0018
+#define  UHD_OC_GLOBAL		0x0000
+#define  UHD_OC_INDIVIDUAL	0x0008
+#define  UHD_OC_NONE		0x0010
+#define UHD_TT_THINK		0x0060
+#define  UHD_TT_THINK_8		0x0000
+#define  UHD_TT_THINK_16	0x0020
+#define  UHD_TT_THINK_24	0x0040
+#define  UHD_TT_THINK_32	0x0060
+#define UHD_PORT_IND		0x0080
+#define UHD_PWRON_FACTOR 2
+#define UHD_NOT_REMOV(desc, i)  (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
+    
+#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
+
+
+/* OTG feature selectors */
+#define UOTG_B_HNP_ENABLE	3
+#define UOTG_A_HNP_SUPPORT	4
+#define UOTG_A_ALT_HNP_SUPPORT	5
+
+/* Device status flags */
+#define UDS_SELF_POWERED		0x0001
+#define UDS_REMOTE_WAKEUP		0x0002
+/* Endpoint status flags */
+#define UES_HALT			0x0001
+
+
+
+#define UHS_LOCAL_POWER	    0x0001
+#define UHS_OVER_CURRENT		0x0002
+
+
+
+#define UPS_CURRENT_CONNECT_STATUS	0x0001
+#define UPS_PORT_ENABLED		0x0002
+#define UPS_SUSPEND			0x0004
+#define UPS_OVERCURRENT_INDICATOR	0x0008
+#define UPS_RESET			0x0010
+#define UPS_PORT_POWER			0x0100
+#define UPS_LOW_SPEED			0x0200
+#define UPS_HIGH_SPEED			0x0400
+#define UPS_PORT_TEST			0x0800
+#define UPS_PORT_INDICATOR		0x1000
+#define UPS_C_CONNECT_STATUS		0x0001
+#define UPS_C_PORT_ENABLED		0x0002
+#define UPS_C_SUSPEND			0x0004
+#define UPS_C_OVERCURRENT_INDICATOR	0x0008
+#define UPS_C_PORT_RESET		0x0010
+
+
+/* Device class codes */
+#define UDCLASS_IN_INTERFACE	0x00
+#define UDCLASS_COMM		0x02
+#define UDCLASS_HUB		0x09
+#define  UDSUBCLASS_HUB		0x00
+#define  UDPROTO_FSHUB		0x00
+#define  UDPROTO_HSHUBSTT	0x01
+#define  UDPROTO_HSHUBMTT	0x02
+#define UDCLASS_DIAGNOSTIC	0xdc
+#define UDCLASS_WIRELESS	0xe0
+#define  UDSUBCLASS_RF		0x01
+#define   UDPROTO_BLUETOOTH	0x01
+#define UDCLASS_VENDOR		0xff
+
+/* Interface class codes */
+#define UICLASS_UNSPEC		0x00
+
+#define UICLASS_AUDIO		0x01
+#define  UISUBCLASS_AUDIOCONTROL	1
+#define  UISUBCLASS_AUDIOSTREAM		2
+#define  UISUBCLASS_MIDISTREAM		3
+
+#define UICLASS_CDC		0x02 /* communication */
+#define  UISUBCLASS_DIRECT_LINE_CONTROL_MODEL	1
+#define  UISUBCLASS_ABSTRACT_CONTROL_MODEL	2
+#define  UISUBCLASS_TELEPHONE_CONTROL_MODEL	3
+#define  UISUBCLASS_MULTICHANNEL_CONTROL_MODEL	4
+#define  UISUBCLASS_CAPI_CONTROLMODEL		5
+#define  UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
+#define  UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
+#define   UIPROTO_CDC_AT			1
+
+#define UICLASS_HID		0x03
+#define  UISUBCLASS_BOOT	1
+#define  UIPROTO_BOOT_KEYBOARD	1
+
+#define UICLASS_PHYSICAL	0x05
+
+#define UICLASS_IMAGE		0x06
+
+#define UICLASS_PRINTER		0x07
+#define  UISUBCLASS_PRINTER	1
+#define  UIPROTO_PRINTER_UNI	1
+#define  UIPROTO_PRINTER_BI	2
+#define  UIPROTO_PRINTER_1284	3
+
+#define UICLASS_MASS		0x08
+#define  UISUBCLASS_RBC		1
+#define  UISUBCLASS_SFF8020I	2
+#define  UISUBCLASS_QIC157	3
+#define  UISUBCLASS_UFI		4
+#define  UISUBCLASS_SFF8070I	5
+#define  UISUBCLASS_SCSI	6
+#define  UIPROTO_MASS_CBI_I	0
+#define  UIPROTO_MASS_CBI	1
+#define  UIPROTO_MASS_BBB_OLD	2	/* Not in the spec anymore */
+#define  UIPROTO_MASS_BBB	80	/* 'P' for the Iomega Zip drive */
+
+#define UICLASS_HUB		0x09
+#define  UISUBCLASS_HUB		0
+#define  UIPROTO_FSHUB		0
+#define  UIPROTO_HSHUBSTT	0 /* Yes, same as previous */
+#define  UIPROTO_HSHUBMTT	1
+
+#define UICLASS_CDC_DATA	0x0a
+#define  UISUBCLASS_DATA		0
+#define   UIPROTO_DATA_ISDNBRI		0x30    /* Physical iface */
+#define   UIPROTO_DATA_HDLC		0x31    /* HDLC */
+#define   UIPROTO_DATA_TRANSPARENT	0x32    /* Transparent */
+#define   UIPROTO_DATA_Q921M		0x50    /* Management for Q921 */
+#define   UIPROTO_DATA_Q921		0x51    /* Data for Q921 */
+#define   UIPROTO_DATA_Q921TM		0x52    /* TEI multiplexer for Q921 */
+#define   UIPROTO_DATA_V42BIS		0x90    /* Data compression */
+#define   UIPROTO_DATA_Q931		0x91    /* Euro-ISDN */
+#define   UIPROTO_DATA_V120		0x92    /* V.24 rate adaption */
+#define   UIPROTO_DATA_CAPI		0x93    /* CAPI 2.0 commands */
+#define   UIPROTO_DATA_HOST_BASED	0xfd    /* Host based driver */
+#define   UIPROTO_DATA_PUF		0xfe    /* see Prot. Unit Func. Desc.*/
+#define   UIPROTO_DATA_VENDOR		0xff    /* Vendor specific */
+
+#define UICLASS_SMARTCARD	0x0b
+
+/*#define UICLASS_FIRM_UPD	0x0c*/
+
+#define UICLASS_SECURITY	0x0d
+
+#define UICLASS_DIAGNOSTIC	0xdc
+
+#define UICLASS_WIRELESS	0xe0
+#define  UISUBCLASS_RF			0x01
+#define   UIPROTO_BLUETOOTH		0x01
+
+#define UICLASS_APPL_SPEC	0xfe
+#define  UISUBCLASS_FIRMWARE_DOWNLOAD	1
+#define  UISUBCLASS_IRDA		2
+#define  UIPROTO_IRDA			0
+
+#define UICLASS_VENDOR		0xff
+
+#define USB_HUB_MAX_DEPTH 5
+
+/*
+ * Minimum time a device needs to be powered down to go through
+ * a power cycle.  XXX Are these time in the spec?
+ */
+#define USB_POWER_DOWN_TIME	200 /* ms */
+#define USB_PORT_POWER_DOWN_TIME	100 /* ms */
+
+
+/* Allow for marginal (i.e. non-conforming) devices. */
+#define USB_PORT_RESET_DELAY	50  /* ms */
+#define USB_PORT_ROOT_RESET_DELAY 250  /* ms */
+#define USB_PORT_RESET_RECOVERY	250  /* ms */
+#define USB_PORT_POWERUP_DELAY	300 /* ms */
+#define USB_SET_ADDRESS_SETTLE	10  /* ms */
+#define USB_RESUME_DELAY	(50*5)  /* ms */
+#define USB_RESUME_WAIT		50  /* ms */
+#define USB_RESUME_RECOVERY	50  /* ms */
+#define USB_EXTRA_POWER_UP_TIME	20  /* ms */
+
+
+#define USB_MIN_POWER		100 /* mA */
+#define USB_MAX_POWER		500 /* mA */
+
+#define USB_BUS_RESET_DELAY	100 /* ms XXX?*/
+
+#define USB_UNCONFIG_NO 0
+#define USB_UNCONFIG_INDEX (-1)
+
+typedef struct usb_device_request_t
+{
+	uint8_t		bmRequestType;
+	uint8_t		bRequest;
+	uint16_t		wValue;
+	uint16_t		wIndex;
+	uint16_t		wLength;
+} __attribute__ ((__packed__)) usb_device_request_t;
+
+/*** ioctl() related stuff ***/
+
+#define USBD_SHORT_XFER_OK	0x04	/* allow short reads */
+#define USB_CURRENT_CONFIG_INDEX (-1)
+#define USB_CURRENT_ALT_INDEX (-1)
+
+
+
+typedef struct usb_endpoint_descriptor_t
+{
+	        uint8_t		bLength;
+	        uint8_t		bDescriptorType;
+	        uint8_t		bEndpointAddress;
+            uint8_t		bmAttributes;
+			uint16_t	wMaxPacketSize;
+	        uint8_t		bInterval;
+} __attribute__ ((__packed__)) usb_endpoint_descriptor_t;
+
+#define USB_MAX_DEVNAMES 4
+#define USB_MAX_DEVNAMELEN 16
+#define USB_SPEED_UNKNOWN	0
+#define USB_SPEED_LOW		1
+#define USB_SPEED_FULL		2
+#define USB_SPEED_HIGH		3
+/*
+ * USB directions
+ *
+ * This bit flag is used in endpoint descriptors' bEndpointAddress field.
+ * It's also one of three fields in control requests bRequestType.
+ */
+#define USB_DIR_OUT			0		/* to device */
+#define USB_DIR_IN			0x80		/* to host */
+
+#define USB_DT_DEVICE			0x01
+#define USB_DT_CONFIG			0x02
+#define USB_DT_STRING			0x03
+#define USB_DT_INTERFACE		0x04
+#define USB_DT_ENDPOINT			0x05
+#define USB_DT_DEVICE_QUALIFIER		0x06
+#define USB_DT_OTHER_SPEED_CONFIG	0x07
+#define USB_DT_INTERFACE_POWER		0x08
+
+/***************************************************/
+// ±ê×¼½Ó¿ÚÃèÊö·û
+typedef struct dwc_interface_descriptor_t
+{
+	BYTE 	bLength;
+	BYTE 	bDescriptorType;
+	BYTE 	bInterfaceNumber;
+	BYTE 	bAlternateSetting;
+	BYTE 	bNumEndpoints;
+	BYTE 	bInterfaceClass;
+	BYTE 	bInterfaceSubClass;
+	BYTE 	bInterfaceProtocol;
+	BYTE 	iInterface;
+}__attribute__ ((__packed__)) dwc_interface_descriptor_t;
+
+
+// ±ê×¼¶ËµãÃèÊö·û
+typedef struct dwc_ep_descriptor_t
+{
+	BYTE 	bLength;
+	BYTE 	bDescriptorType;
+	BYTE 	bEndpointAddress;
+	BYTE 	bmAttributes;
+	WORD16	wMaxPacketSize;
+	BYTE 	bInterval;
+}__attribute__ ((__packed__)) dwc_ep_descriptor_t;
+
+
+// ×Ö·û´®ÃèÊö·û
+typedef struct dwc_langid_descriptor_t
+{
+	BYTE	bLength;
+	BYTE 	bDescriptorType;
+	WORD16	wLANGID0;
+
+}__attribute__ ((__packed__)) dwc_langid_descriptor_t;
+
+typedef struct dwc_string_descriptor_t
+{
+	BYTE	bLength;
+	BYTE 	bDescriptorType;
+	BYTE	bString[MAX_STRING_LENGTH];
+
+}__attribute__ ((__packed__)) dwc_string_descriptor_t;
+
+// É豸ÃèÊö·û
+typedef struct dwc_device_descriptor_t
+{
+    BYTE    bLength;
+    BYTE    bDescriptorType;
+    WORD16	bcdUSB;
+    BYTE    bDeviceClass;
+    BYTE    bDeviceSubClass;
+    BYTE    bDeviceProtocol;
+    BYTE    bMaxPacketSize0;
+    WORD16 	idVendor;
+    WORD16 	idProduct;
+    WORD16 	bcdDevice;
+    BYTE 	iManufacturer;
+    BYTE    iProduct;
+    BYTE    iSerialNumber;
+    BYTE    bNumConfigurations;
+}__attribute__ ((__packed__)) dwc_device_descriptor_t;
+
+//device qualifierÃèÊö·û
+typedef struct dwc_dev_qual_descriptor_t
+{
+    BYTE    bLength;
+    BYTE    bDescriptorType;
+    WORD16	bcdUSB;
+    BYTE    bDeviceClass;
+    BYTE    bDeviceSubClass;
+    BYTE    bDeviceProtocol;
+    BYTE    bMaxPacketSize0;
+    BYTE    bNumConfigurations;
+    BYTE    Reserved;
+}__attribute__ ((__packed__)) dwc_dev_qual_descriptor_t;
+
+
+// ±ê×¼ÅäÖÃÃèÊö·û
+typedef struct dwc_config_descriptor_t
+{
+	BYTE 	bLength;
+	BYTE 	bDescriptorType;
+	WORD16 	wTotalLength;
+	BYTE 	bNumInterfaces;
+	BYTE 	bConfigurationValue;
+	BYTE 	iConfiguration;
+	BYTE 	bmAttributes;
+	BYTE 	bMaxPower;
+}__attribute__ ((__packed__)) dwc_config_descriptor_t;
+
+typedef struct dwc_product_descriptor_t
+{
+	BYTE 	bLength;
+	BYTE 	bDescriptorType;
+    char    Prod_Desc[98];
+} __attribute__ ((__packed__)) dwc_product_descriptor_t;
+
+//#define	MAX_EPS				(0x8)
+#define	MAX_EPS				(0x2)
+typedef enum
+{
+    USB_MAX_PACKET_SIZE_NOT_SET      = 0,
+    USB_FULLSPEED_BULK_MAXSIZE         = 64,
+    USB_HIGHSPEED_BULK_MAXSIZE        = 512,
+}T_USB_MAX_PACKET_SIZE;
+
+typedef struct dwc_config_all_t
+{
+  dwc_config_descriptor_t		tConfig;
+  dwc_interface_descriptor_t	tInterface;
+  dwc_ep_descriptor_t			atTxEP[1];	//·¢ËͶ˵ã(²»°üÀ¨ep0)
+  dwc_ep_descriptor_t			atRxEP[1];	//½ÓÊն˵ã(²»°üÀ¨ep0)
+  dwc_interface_descriptor_t	tInterface1;
+  dwc_ep_descriptor_t			atTxEP1[1];	//·¢ËͶ˵ã(²»°üÀ¨ep0)
+  dwc_ep_descriptor_t			atRxEP1[1];	//½ÓÊն˵ã(²»°üÀ¨ep0)
+}__attribute__ ((__packed__)) dwc_config_all_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _USB_H_ */
diff --git a/boot/common/src/loader/drivers/zx_mmc.c b/boot/common/src/loader/drivers/zx_mmc.c
new file mode 100644
index 0000000..057b6e9
--- /dev/null
+++ b/boot/common/src/loader/drivers/zx_mmc.c
@@ -0,0 +1,256 @@
+/*
+ * (C) Copyright 2003
+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
+ *
+ * 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 "zx_mmc.h"
+#include "type.h"
+#include <asm/io.h>
+#include <image.h>
+#include <linux/byteorder/generic.h>
+
+
+u32 mmc_rca;
+static u32 ocr_avail = 0;
+static u32 block_addr = 0;
+
+#define MMC_BLOCK_SIZE 512
+
+static u32 emmc_cmd(u32 cmd, u32 arg,
+	void *resp, u32 flags)
+{
+	u32 *response = resp;
+	u32 i,response_words = 0;
+	u32 status,err_status = ZXMCI_STS_RE | ZXMCI_STS_RCRC | ZXMCI_STS_RTO;
+	u32 cmdreg;
+
+	/*Clear all raw interrupt status*/
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_RINTSTS) = 0xffffffff;
+
+	cmdreg = cmd & ZXMCI_CMD_INDEX_MASK;
+	cmdreg |= flags | ZXMCI_CMD_START;
+
+	cmdreg |= (0x1 << 29);
+	
+	if(flags & ZXMCI_CMD_RSPLEN)
+	{
+		response_words = 4;
+	}
+	else if(flags & ZXMCI_CMD_RSPEXP)
+	{
+		response_words = 1;
+	}
+
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_CMDARG) = arg;
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_CMD)    = cmdreg;
+
+/*check command done*/	
+	do {
+		status = REG32(SYS_EMMC_REGS_BASE+ZXMCI_RINTSTS);
+        
+	} while (!(status & ZXMCI_STS_CD)); 
+/*check error*/
+    if(status & err_status)
+    {
+        printf("send cmd error\n");
+        return 1;
+    }
+
+	for(i = 0;i < response_words;i++)
+	{
+		response[i] = REG32(SYS_EMMC_REGS_BASE+ZXMCI_RESP0 + i*4);
+	}
+	
+	return 0;
+}
+
+s32 zx_mmc_read(u32 src, u8 * dst, u32 size)
+{
+	u32 ret, i = 0,j = 0;
+	u32 resp;
+	u32 data;
+	u32 wordcount;
+	u32 *p = (u32 *)dst;
+	u32 status;
+	u32 start_addr;
+	u32 fifo_cnt;
+
+	if (size == 0)
+		return -1;
+
+	while((REG32(SYS_EMMC_REGS_BASE+ZXMCI_STATUS) & ZXMCI_STA_DATBUSY) != 0)
+	{
+		i++;
+        mmcdelay((80));
+		if(i>200)
+			break;
+	}
+
+
+	start_addr = src;
+
+
+	data = REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL);
+	data |=(1<<1) ;
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL) = data;
+
+    i = 0;
+    do
+    {
+		i++;
+        mmcdelay((80));
+        if(i>100)
+        {
+            printf("fifo reset failure");
+            break;
+        }
+	}while(REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL) & 2);
+
+
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_BYTCNT) = size;
+	REG32(SYS_EMMC_REGS_BASE+ZXMCI_BLKSIZ) = MMC_DEFAULT_BLKLEN;
+	
+	if (size > MMC_DEFAULT_BLKLEN)
+	{
+		ret = emmc_cmd(MMC_CMD_READ_MULTIPLE_BLOCK,start_addr, &resp,(R1 | CF_DATA));
+		if (ret)
+		{
+			return -MMC_CMD_READ_MULTIPLE_BLOCK;
+		}
+	}
+	else
+	{
+		ret = emmc_cmd(MMC_CMD_READ_SINGLE_BLOCK,start_addr, &resp,(R1 | CF_DATA));
+		if (ret)
+		{
+			return -MMC_CMD_READ_SINGLE_BLOCK;
+		}
+	}
+
+	wordcount = 0;
+	do {
+		
+		status = REG32(SYS_EMMC_REGS_BASE+ZXMCI_STATUS);	
+		fifo_cnt =(status >> 17) & 0x1fff;
+		for(j = 0;j < fifo_cnt;j++)
+		{
+			data = REG32(SYS_EMMC_REGS_BASE+ZXMCI_FIFO);
+			*p++ = data;
+			wordcount++;
+		}
+			
+	} while(wordcount < (size/4));
+		
+	return 0;
+    
+}
+
+static u32 mmc_bread(u32 dev_num, u32 blknr, u32 blkcnt, void *dst)
+{
+	u32 src = 0;
+	s32 ret;
+
+	if (block_addr == 0)
+	{
+		src = blknr * MMC_BLOCK_SIZE;
+	}
+	else
+	{
+		src = blknr;
+	}
+	
+	ret = zx_mmc_read(src, (u8 *) dst, blkcnt * MMC_BLOCK_SIZE);
+	if (ret < 0)
+	{
+		printf("mmc read error\n");
+		return 1;
+	}
+		
+	return blkcnt;
+}
+
+
+ void mmcdelay(unsigned long us)
+ {
+	volatile int i = 0; /* approximate */
+	for(i=0;i<5000;i++)
+	{
+        ;
+	}
+ }
+
+int mmc_read( u32 src, u32 length, void *dst)
+{
+    u32 blkcnt = 0;
+	u32 start_blk = 0;
+	int ret = 0;
+    
+    if(length%MMC_DEFAULT_BLKLEN)
+	    blkcnt = (length/MMC_DEFAULT_BLKLEN)+1;
+	else
+		blkcnt = (length/MMC_DEFAULT_BLKLEN);
+
+	start_blk = src/MMC_DEFAULT_BLKLEN;
+    block_addr = 1;
+
+	printf("entry mmc_bread\n");
+	ret = mmc_bread(0, start_blk, blkcnt, (void *)dst);
+
+	if(ret == blkcnt )
+		return 0;
+	else
+		return -1;
+
+}
+
+uint32_t page_align(uint32_t offset)
+{
+    uint32_t page_size = 2048;
+    if( offset & (page_size - 1) )
+    {
+        offset &= (~(page_size - 1));
+        offset += page_size;
+    }
+    return offset;
+}
+
+/*******************************************************************************
+ * Function:     nand_init
+ * Description: mmc init
+ * Parameters:
+ *	 Input:
+ *
+ *	 Output:
+ *
+ * Returns:
+ *
+ *
+ * Others:
+ ********************************************************************************/
+int32_t mmc_init (void)
+{
+    return 0;
+    
+}
+
+
diff --git a/boot/common/src/loader/drivers/zx_mmc.h b/boot/common/src/loader/drivers/zx_mmc.h
new file mode 100644
index 0000000..bee530d
--- /dev/null
+++ b/boot/common/src/loader/drivers/zx_mmc.h
@@ -0,0 +1,307 @@
+/*
+ *  linux/drivers/mmc/mmc_pxa.h
+ *
+ *  Author: Vladimir Shebordaev, Igor Oblakov
+ *  Copyright:  MontaVista Software Inc.
+ *
+ *  $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#ifndef __MMC_ZX_P_H__
+#define __MMC_ZX_P_H__
+
+#define SD_VERSION_SD	0x20000
+#define SD_VERSION_2	(SD_VERSION_SD | 0x20)
+#define SD_VERSION_1_0	(SD_VERSION_SD | 0x10)
+#define SD_VERSION_1_10	(SD_VERSION_SD | 0x1a)
+#define MMC_VERSION_MMC		0x10000
+#define MMC_VERSION_UNKNOWN	(MMC_VERSION_MMC)
+#define MMC_VERSION_1_2		(MMC_VERSION_MMC | 0x12)
+#define MMC_VERSION_1_4		(MMC_VERSION_MMC | 0x14)
+#define MMC_VERSION_2_2		(MMC_VERSION_MMC | 0x22)
+#define MMC_VERSION_3		(MMC_VERSION_MMC | 0x30)
+#define MMC_VERSION_4		(MMC_VERSION_MMC | 0x40)
+
+#define MMC_MODE_HS		0x001
+#define MMC_MODE_HS_52MHz	0x010
+#define MMC_MODE_4BIT		0x100
+#define MMC_MODE_8BIT		0x200
+
+#define SD_DATA_4BIT	0x00040000
+
+#define IS_SD(x) (x->version & SD_VERSION_SD)
+
+#define MMC_DATA_READ		1
+#define MMC_DATA_WRITE		2
+
+#define NO_CARD_ERR		-16 /* No SD/MMC card inserted */
+#define UNUSABLE_ERR		-17 /* Unusable Card */
+#define COMM_ERR		-18 /* Communications Error */
+#define TIMEOUT			-19
+
+#define MMC_CMD_GO_IDLE_STATE		0
+#define MMC_CMD_SEND_OP_COND		1
+#define MMC_CMD_ALL_SEND_CID		2
+#define MMC_CMD_SET_RELATIVE_ADDR	3
+#define MMC_CMD_SET_DSR			4
+#define MMC_CMD_SWITCH			6
+#define MMC_CMD_SELECT_CARD		7
+#define MMC_CMD_SEND_EXT_CSD		8
+#define MMC_CMD_SEND_CSD		9
+#define MMC_CMD_SEND_CID		10
+#define MMC_CMD_STOP_TRANSMISSION	12
+#define MMC_CMD_SEND_STATUS		13
+#define MMC_CMD_SET_BLOCKLEN		16
+#define MMC_CMD_READ_SINGLE_BLOCK	17
+#define MMC_CMD_READ_MULTIPLE_BLOCK	18
+#define MMC_CMD_WRITE_SINGLE_BLOCK	24
+#define MMC_CMD_WRITE_MULTIPLE_BLOCK	25
+
+#define MMC_CMD_ERASE_GROUP_START	35
+#define MMC_CMD_ERASE_GROUP_END	    36
+#define MMC_CMD_ERASE           	38
+
+#define MMC_CMD_APP_CMD			55
+
+#define SD_CMD_SEND_RELATIVE_ADDR	3
+#define SD_CMD_SWITCH_FUNC		6
+#define SD_CMD_SEND_IF_COND		8
+
+#define SD_CMD_APP_SET_BUS_WIDTH	6
+#define SD_CMD_APP_SEND_OP_COND		41
+#define SD_CMD_APP_SEND_SCR		51
+
+/* SCR definitions in different words */
+#define SD_HIGHSPEED_BUSY	0x00020000
+#define SD_HIGHSPEED_SUPPORTED	0x00020000
+
+#define MMC_HS_TIMING		0x00000100
+#define MMC_HS_52MHZ		0x2
+
+#define OCR_BUSY	0x80000000
+#define OCR_HCS		0x40000000
+
+#define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
+#define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22		0x00000200	/* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23		0x00000400	/* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24		0x00000800	/* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25		0x00001000	/* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26		0x00002000	/* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27		0x00004000	/* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28		0x00008000	/* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29		0x00010000	/* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30		0x00020000	/* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31		0x00040000	/* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32		0x00080000	/* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33		0x00100000	/* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34		0x00200000	/* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35		0x00400000	/* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36		0x00800000	/* VDD voltage 3.5 ~ 3.6 */
+
+#define MMC_SWITCH_MODE_CMD_SET		0x00 /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS	0x01 /* Set bits in EXT_CSD byte
+						addressed by index which are
+						1 in value field */
+#define MMC_SWITCH_MODE_CLEAR_BITS	0x02 /* Clear bits in EXT_CSD byte
+						addressed by index, which are
+						1 in value field */
+#define MMC_SWITCH_MODE_WRITE_BYTE	0x03 /* Set target byte to value */
+
+#define SD_SWITCH_CHECK		0
+#define SD_SWITCH_SWITCH	1
+
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH	183	/* R/W */
+#define EXT_CSD_HS_TIMING	185	/* R/W */
+#define EXT_CSD_CARD_TYPE	196	/* RO */
+#define EXT_CSD_REV		192	/* RO */
+#define EXT_CSD_SEC_CNT		212	/* RO, 4 bytes */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+#define EXT_CSD_CMD_SET_NORMAL		(1<<0)
+#define EXT_CSD_CMD_SET_SECURE		(1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
+
+#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
+
+#define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
+
+#define R1_ILLEGAL_COMMAND		(1 << 22)
+#define R1_APP_CMD			(1 << 5)
+
+#define MMC_RSP_PRESENT (1 << 0)
+#define MMC_RSP_136     (1 << 1)                /* 136 bit response */
+#define MMC_RSP_CRC     (1 << 2)                /* expect valid crc */
+#define MMC_RSP_BUSY    (1 << 3)                /* card may send busy */
+#define MMC_RSP_OPCODE  (1 << 4)                /* response contains opcode */
+
+#define MMC_RSP_NONE    (0)
+#define MMC_RSP_R1      (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R1b	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE| \
+			MMC_RSP_BUSY)
+#define MMC_RSP_R2      (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+#define MMC_RSP_R3      (MMC_RSP_PRESENT)
+#define MMC_RSP_R4      (MMC_RSP_PRESENT)
+#define MMC_RSP_R5      (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R6      (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7      (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+
+
+struct mmc_cid {
+	unsigned long psn;
+	unsigned short oid;
+	unsigned char mid;
+	unsigned char prv;
+	unsigned char mdt;
+	char pnm[7];
+};
+
+
+#define MMC_DEFAULT_BLKLEN	512
+#define MMC_DEFAULT_RCA		1
+
+/*¼Ä´æÆ÷Æ«ÒÆ*/
+#define  ZXMCI_CTRL    	                (0x00)
+#define  ZXMCI_PWREN   	                (0x04)
+#define  ZXMCI_CLKDIV  	                (0x08)
+#define  ZXMCI_CLKSRC  	                (0x0C)
+#define  ZXMCI_CLKENA  	                (0x10)
+#define  ZXMCI_TMOUT  	                (0x14)
+#define  ZXMCI_CTYPE   	                (0x18)
+#define  ZXMCI_BLKSIZ  	                (0x1C)
+#define  ZXMCI_BYTCNT  	                (0x20)
+#define  ZXMCI_INTMSK  	                (0x24)
+#define  ZXMCI_CMDARG  	                (0x28)
+#define  ZXMCI_CMD     	                (0x2C)
+#define  ZXMCI_RESP0   	                (0x30)
+#define  ZXMCI_RESP1   	                (0x34)
+#define  ZXMCI_RESP2   	                (0x38)
+#define  ZXMCI_RESP3   	                (0x3C)
+#define  ZXMCI_MINTSTS 	                (0x40)
+#define  ZXMCI_RINTSTS 	                (0x44)
+#define  ZXMCI_STATUS  	                (0x48)
+#define  ZXMCI_FIFOTH  	                (0x4C)
+
+#define  ZXMCI_CDETECT 	                (0x50)
+#define  ZXMCI_CDETECT_MASK             (0x3fffffff)
+
+#define  ZXMCI_WRTPRT  	                (0x54)
+#define  ZXMCI_GPIO    	                (0x58)
+#define  ZXMCI_TCBCNT  	                (0x5C)
+#define  ZXMCI_TBBCNT  	                (0x60)
+#define  ZXMCI_DEBNCE  	                (0x64)
+#define  ZXMCI_USRID   	                (0x68)
+#define  ZXMCI_VERID   	                (0x6C)
+#define  ZXMCI_HCON    	                (0x70)
+#define  ZXMCI_BMOD		                (0x80)
+#define  ZXMCI_PLDMND	                (0x84)
+#define	 ZXMCI_DBADDR	                (0x88)
+#define  ZXMCI_IDSTS	                (0x8C)
+#define	 ZXMCI_IDINTEN	                (0x90)
+#define  ZXMCI_DSCADDR	                (0x94)
+#define  ZXMCI_BUFADDR	                (0x98)
+#define  ZXMCI_CARDRDTHRCTRL	        (0x100)
+
+#define  ZXMCI_FIFO		                (0x200)
+
+#define ZXMCI_FIFO_DEPTH		        128
+
+/*CTRL Register BIT*/
+#define ZXMCI_CTRL_OD_PULLUP            (1 << 24)
+
+
+/*rintstsÖжÏ״̬¼Ä´æÆ÷*/
+#define ZXMCI_STS_CRC		            (1<<15)	//End-bit error (read)/write no CRC
+#define ZXMCI_STS_ACD		            (1<<14)	//auto command done
+#define ZXMCI_STS_SBE		            (1<<13)	//Start-bit error
+#define ZXMCI_STS_HLE		            (1<<12)	//Hardware locked write error
+#define ZXMCI_STS_FRUN		            (1<<11)	//FIFO underrun/overrun error
+#define ZXMCI_STS_HTO		            (1<<10)	//Data starvation-by-host timeout
+#define ZXMCI_STS_DRTO		            (1<<9)	//Data read timeout
+#define ZXMCI_STS_RTO		            (1<<8)	//Response timeout 
+#define ZXMCI_STS_DCRC		(1<<7)	//Data CRC error 
+#define ZXMCI_STS_RCRC		(1<<6)	//Response CRC error
+#define ZXMCI_STS_RXDR		(1<<5)	//Receive FIFO data request
+#define ZXMCI_STS_TXDR		(1<<4)	//Transmit FIFO data request 
+#define ZXMCI_STS_DTO		(1<<3)	//Data transfer over Êý¾Ý´«ÊäÍê±Ï
+#define ZXMCI_STS_CD		(1<<2)	//Command done
+#define ZXMCI_STS_RE		(1<<1)	//Response error
+#define ZXMCI_STS_CDT		(1<<0)	//Card detect 
+
+/*ÃüÁî¼Ä´æÆ÷*/
+#define ZXMCI_CMD_START	(1U<<31)	//Start command,Once command is taken by CIU, bit is cleared
+#define ZXMCI_CMD_CCS		(1<<23)	// 1= Interrupts are enabled in CE-ATA device
+#define ZXMCI_CMD_RCEATA	(1<<22)	// 1= Host is performing read access (RW_REG or RW_BLK)towards CE-ATA 
+#define ZXMCI_CMD_UCREG	(1<<21)	//0= Normal command sequencregisters_only,1= Do not send commands
+#define ZXMCI_CMD_CNUM		(1<<16) //Card number in use
+#define ZXMCI_CMD_SINIT	(1<<15)	// 1= Send initialization sequence before sending this comman
+#define ZXMCI_CMD_STOP		(1<<14)	// 1= Stop or abort command intended to stop current data transferin progress.
+#define ZXMCI_CMD_WAITC	(1<<13)	// 1= Wait for previous data transfer completion before sending command
+#define ZXMCI_CMD_SSTOP	(1<<12)	// 1= Send stop command at end of data transfe
+#define ZXMCI_CMD_TMODE	(1<<11)	//0= Block data transfer command,1= Stream
+#define ZXMCI_CMD_WRITE	(1<<10)	//0= Read from card,1= Write 
+#define ZXMCI_CMD_DEXP		(1<<9)	//0= No data transfer expected (read/write)
+#define ZXMCI_CMD_CRSP		(1<<8)	// 1= Check response CRC
+#define ZXMCI_CMD_RSPLEN	(1<<7)	// 1= Long response expected from car,0=Short 
+#define ZXMCI_CMD_RSPEXP	(1<<6)	//  1= Response expected from car
+#define ZXMCI_CMD_INDEX	(1<<0)	//Command index
+#define ZXMCI_CMD_INDEX_MASK  0x3f  
+
+/*״̬¼Ä´æÆ÷*/
+#define ZXMCI_STA_DMAREQ	(1<<31)	//DMA request signal state
+#define ZXMCI_STA_DMAACK	(1<<30)	//DMA acknowledge signal state
+#define ZXMCI_STA_FIFOCNT	(1<<17)	//FIFO count= Number of filled locations in FIFO
+#define ZXMCI_STA_PRERSP	(1<<11)	//Index of previous response, including any auto-stop sent by core
+#define ZXMCI_STA_TMTBUSY	(1<<10)	//Data transmit or receive state-machine is busy
+#define ZXMCI_STA_DATBUSY	(1<<9)	//Inverted version of raw selected card_data[0],1=BUSY
+#define ZXMCI_STA_D3STA	(1<<8)	//Raw selected card_data[3];1=card present
+#define ZXMCI_STA_FSMSTA	(1<<4)	//Command FSM states
+#define ZXMCI_STA_FIFOFULL	(1<<3)	//FIFO is full status
+#define ZXMCI_STA_FIFOEMPTY	(1<<2)	//FIFO is empty status
+#define ZXMCI_STA_TXWMARK	(1<<1)	//µ½´ï·§ÖµÁËFIFO reached Transmit watermark level; not qualified with data transfer
+#define ZXMCI_STA_RXWMARK	(1<<0)	//FIFO reached Receive watermark level
+
+#define ZXMCI_STA_FSM_MASK  (0xF0)
+#define ZXMCI_STA_FSM_POS   (0x04)
+#define ZXMCI_STA_FSM_IDLE  (0x00)
+
+
+//#define R1				(ZXMCI_CMD_RSPEXP /*| ZXMCI_CMD_CRSP*/)
+#define R1				(ZXMCI_CMD_RSPEXP | ZXMCI_CMD_CRSP)
+#define R1B				(ZXMCI_CMD_RSPEXP | ZXMCI_CMD_CRSP)
+//#define R2				(ZXMCI_CMD_RSPEXP | /*ZXMCI_CMD_CRSP |*/ZXMCI_CMD_RSPLEN)
+#define R2				(ZXMCI_CMD_RSPEXP | ZXMCI_CMD_CRSP |ZXMCI_CMD_RSPLEN)
+#define R3				(ZXMCI_CMD_RSPEXP)
+#define R4				(ZXMCI_CMD_RSPEXP)
+#define R5				(ZXMCI_CMD_RSPEXP | ZXMCI_CMD_CRSP)
+#define R6				(ZXMCI_CMD_RSPEXP | ZXMCI_CMD_CRSP)
+#define R7				(ZXMCI_CMD_RSPEXP | ZXMCI_CMD_CRSP)
+#define CF_DATA			(ZXMCI_CMD_DEXP | ZXMCI_CMD_WAITC | ZXMCI_CMD_SSTOP)
+#define CF_WR			ZXMCI_CMD_WRITE
+
+#define ERR_STS			(ZXMCI_STS_CRC | ZXMCI_STS_DCRC | ZXMCI_STS_RCRC)	
+
+/*SD/MMC ²ÎÊý*/
+#define SYS_EMMC_REGS_BASE                 0x01210000  //SD0
+#define CFG_EMMC_CLK_REF	               26000000
+#define	CFG_EMMC_CLK_ENUM		           400000
+#define CFG_EMMC_CLK_WORK		           26000000 
+
+#define SYS_STD_CRM_BASE                   0x1307000
+
+
+
+#endif /* __MMC_PXA_P_H__ */