diff -urN u-boot-1.1.6/board/100ask24x0/100ask24x0.c u-boot-1.1.6_jz2440/board/100ask24x0/100ask24x0.c
--- u-boot-1.1.6/board/100ask24x0/100ask24x0.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/100ask24x0.c	2010-11-26 12:54:37.034090906 +0800
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
+ *
+ * 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 <s3c2410.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Miscellaneous platform dependent initialisations
+ */
+
+int board_init (void)
+{
+    S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+    S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+
+    /* set up the I/O ports */
+    gpio->GPACON = 0x007FFFFF;
+    gpio->GPBCON = 0x00044555;
+    gpio->GPBUP = 0x000007FF;
+    gpio->GPCCON = 0xAAAAAAAA;
+    gpio->GPCUP = 0x0000FFFF;
+    gpio->GPDCON = 0xAAAAAAAA;
+    gpio->GPDUP = 0x0000FFFF;
+    gpio->GPECON = 0xAAAAAAAA;
+    gpio->GPEUP = 0x0000FFFF;
+    gpio->GPFCON = 0x000055AA;
+    gpio->GPFUP = 0x000000FF;
+    gpio->GPGCON = 0xFF95FFBA;
+    gpio->GPGUP = 0x0000FFFF;
+    gpio->GPHCON = 0x002AFAAA;
+    gpio->GPHUP = 0x000007FF;
+
+    /* support both of S3C2410 and S3C2440, by www.100ask.net */
+    if (isS3C2410)
+    {
+        /* arch number of SMDK2410-Board */
+        gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
+    }
+    else
+    {
+        /* arch number of SMDK2440-Board */
+        gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
+    }
+
+    /* adress of boot parameters */
+    gd->bd->bi_boot_params = 0x30000100;
+#if 0
+    icache_enable();
+    dcache_enable();
+#endif
+    return 0;
+}
+
+int dram_init (void)
+{
+    gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+    gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+    return 0;
+}
+
+ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
+{	
+	info->portwidth = CFG_FLASH_CFI_WIDTH;
+	info->chipwidth = CFG_FLASH_CFI_WIDTH;
+	info->interface = FLASH_CFI_X16;
+	return 1;
+}
+
+
diff -urN u-boot-1.1.6/board/100ask24x0/boot_init.c u-boot-1.1.6_jz2440/board/100ask24x0/boot_init.c
--- u-boot-1.1.6/board/100ask24x0/boot_init.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/boot_init.c	2010-11-26 12:54:37.042080086 +0800
@@ -0,0 +1,566 @@
+#include <common.h>
+#include <s3c2410.h>
+
+#define BUSY            1
+
+#define NAND_SECTOR_SIZE    512
+#define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)
+
+#define NAND_SECTOR_SIZE_LP    2048
+#define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)
+
+/* 供外部调用的函数 */
+void nand_init_ll(void);
+void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
+
+/* NAND Flash操作的总入口, 它们将调用S3C2410或S3C2440的相应函数 */
+static void nand_reset(void);
+static void wait_idle(void);
+static void nand_select_chip(void);
+static void nand_deselect_chip(void);
+static void write_cmd(int cmd);
+static void write_addr(unsigned int addr);
+static unsigned char read_data(void);
+
+/* S3C2410的NAND Flash处理函数 */
+static void s3c2410_nand_reset(void);
+static void s3c2410_wait_idle(void);
+static void s3c2410_nand_select_chip(void);
+static void s3c2410_nand_deselect_chip(void);
+static void s3c2410_write_cmd(int cmd);
+static void s3c2410_write_addr(unsigned int addr);
+static unsigned char s3c2410_read_data(void);
+
+/* S3C2440的NAND Flash处理函数 */
+static void s3c2440_nand_reset(void);
+static void s3c2440_wait_idle(void);
+static void s3c2440_nand_select_chip(void);
+static void s3c2440_nand_deselect_chip(void);
+static void s3c2440_write_cmd(int cmd);
+static void s3c2440_write_addr(unsigned int addr);
+static unsigned char s3c2440_read_data(void);
+
+/* S3C2410的NAND Flash操作函数 */
+
+/* 复位 */
+static void s3c2410_nand_reset(void)
+{
+    s3c2410_nand_select_chip();
+    s3c2410_write_cmd(0xff);  // 复位命令
+    s3c2410_wait_idle();
+    s3c2410_nand_deselect_chip();
+}
+
+/* 等待NAND Flash就绪 */
+static void s3c2410_wait_idle(void)
+{
+    int i;
+	S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
+	
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;
+    while(!(*p & BUSY))
+        for(i=0; i<10; i++);
+}
+
+/* 发出片选信号 */
+static void s3c2410_nand_select_chip(void)
+{
+    int i;
+	S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
+
+    s3c2410nand->NFCONF &= ~(1<<11);
+    for(i=0; i<10; i++);    
+}
+
+/* 取消片选信号 */
+static void s3c2410_nand_deselect_chip(void)
+{
+	S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
+
+    s3c2410nand->NFCONF |= (1<<11);
+}
+
+/* 发出命令 */
+static void s3c2410_write_cmd(int cmd)
+{
+	S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
+
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;
+    *p = cmd;
+}
+
+/* 发出地址 */
+static void s3c2410_write_addr(unsigned int addr)
+{
+    int i;
+	S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFADDR;
+    
+    *p = addr & 0xff;
+    for(i=0; i<10; i++);
+    *p = (addr >> 9) & 0xff;
+    for(i=0; i<10; i++);
+    *p = (addr >> 17) & 0xff;
+    for(i=0; i<10; i++);
+    *p = (addr >> 25) & 0xff;
+    for(i=0; i<10; i++);
+}
+
+/* 读取数据 */
+static unsigned char s3c2410_read_data(void)
+{
+	S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
+
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;
+    return *p;
+}
+
+/* S3C2440的NAND Flash操作函数 */
+
+/* 复位 */
+static void s3c2440_nand_reset(void)
+{
+    s3c2440_nand_select_chip();
+    s3c2440_write_cmd(0xff);  // 复位命令
+    s3c2440_wait_idle();
+    s3c2440_nand_deselect_chip();
+}
+
+/* 等待NAND Flash就绪 */
+static void s3c2440_wait_idle(void)
+{
+    int i;
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
+
+    while(!(*p & BUSY))
+        for(i=0; i<10; i++);
+}
+
+/* 发出片选信号 */
+static void s3c2440_nand_select_chip(void)
+{
+    int i;
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+
+    s3c2440nand->NFCONT &= ~(1<<1);
+    for(i=0; i<10; i++);    
+}
+
+/* 取消片选信号 */
+static void s3c2440_nand_deselect_chip(void)
+{
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+
+    s3c2440nand->NFCONT |= (1<<1);
+}
+
+/* 发出命令 */
+static void s3c2440_write_cmd(int cmd)
+{
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
+    *p = cmd;
+}
+
+/* 发出地址 */
+static void s3c2440_write_addr(unsigned int addr)
+{
+    int i;
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
+    
+    *p = addr & 0xff;
+    for(i=0; i<10; i++);
+    *p = (addr >> 9) & 0xff;
+    for(i=0; i<10; i++);
+    *p = (addr >> 17) & 0xff;
+    for(i=0; i<10; i++);
+    *p = (addr >> 25) & 0xff;
+    for(i=0; i<10; i++);
+}
+
+
+/* 发出地址 */
+static void s3c2440_write_addr_lp(unsigned int addr)
+{
+    int i;
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
+	int col, page;
+
+	col = addr & NAND_BLOCK_MASK_LP;
+	page = addr / NAND_SECTOR_SIZE_LP;
+	
+    *p = col & 0xff;			/* Column Address A0~A7 */
+    for(i=0; i<10; i++);		
+    *p = (col >> 8) & 0x0f;		/* Column Address A8~A11 */
+    for(i=0; i<10; i++);
+    *p = page & 0xff;			/* Row Address A12~A19 */
+    for(i=0; i<10; i++);
+    *p = (page >> 8) & 0xff;	/* Row Address A20~A27 */
+    for(i=0; i<10; i++);
+    *p = (page >> 16) & 0x03;	/* Row Address A28~A29 */
+    for(i=0; i<10; i++);
+}
+
+/* 读取数据 */
+static unsigned char s3c2440_read_data(void)
+{
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
+    return *p;
+}
+
+
+/* 在第一次使用NAND Flash前，复位一下NAND Flash */
+static void nand_reset(void)
+{
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    s3c2410_nand_reset();
+	}
+	else
+	{
+	    s3c2440_nand_reset();
+	}
+}
+
+static void wait_idle(void)
+{
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    s3c2410_wait_idle();
+	}
+	else
+	{
+	    s3c2440_wait_idle();
+	}
+}
+
+static void nand_select_chip(void)
+{
+    int i;
+	
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    s3c2410_nand_select_chip();
+	}
+	else
+	{
+	    s3c2440_nand_select_chip();
+	}
+	
+    for(i=0; i<10; i++);
+}
+
+static void nand_deselect_chip(void)
+{
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    s3c2410_nand_deselect_chip();
+	}
+	else
+	{
+	    s3c2440_nand_deselect_chip();
+	}	
+}
+
+static void write_cmd(int cmd)
+{
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    s3c2410_write_cmd(cmd);
+	}
+	else
+	{
+	    s3c2440_write_cmd(cmd);
+	}	
+}
+static void write_addr(unsigned int addr)
+{
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    s3c2410_write_addr(addr);
+	}
+	else
+	{
+	    s3c2440_write_addr(addr);
+	}	
+}
+
+static void write_addr_lp(unsigned int addr)
+{
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    s3c2410_write_addr(addr);
+	}
+	else
+	{
+	    s3c2440_write_addr_lp(addr);
+	}	
+}
+
+static unsigned char read_data(void)
+{
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+	{
+	    return s3c2410_read_data();
+	}
+	else
+	{
+	    return s3c2440_read_data();
+	}	
+}
+
+/* 初始化NAND Flash */
+void nand_init_ll(void)
+{
+	S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
+	S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
+
+#define TACLS   0
+#define TWRPH0  3
+#define TWRPH1  0
+
+    /* 判断是S3C2410还是S3C2440 */
+    if (isS3C2410)
+    {
+		/* 使能NAND Flash控制器, 初始化ECC, 禁止片选, 设置时序 */
+        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
+    }
+    else
+    {
+		/* 设置时序 */
+        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
+        /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
+        s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
+    }
+
+	/* 复位NAND Flash */
+	nand_reset();
+}
+
+
+/* 读函数 */
+void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
+{
+    int i, j;
+    
+    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
+        return ;    /* 地址或长度不对齐 */
+    }
+
+    /* 选中芯片 */
+    nand_select_chip();
+
+    for(i=start_addr; i < (start_addr + size);) {
+      /* 发出READ0命令 */
+      write_cmd(0);
+
+      /* Write Address */
+      write_addr(i);
+      wait_idle();
+
+      for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
+          *buf = read_data();
+          buf++;
+      }
+    }
+
+    /* 取消片选信号 */
+    nand_deselect_chip();
+    
+    return ;
+}
+
+
+/* 读函数 
+  * Large Page
+  */
+void nand_read_ll_lp(unsigned char *buf, unsigned long start_addr, int size)
+{
+    int i, j;
+    
+    if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {
+        return ;    /* 地址或长度不对齐 */
+    }
+
+    /* 选中芯片 */
+    nand_select_chip();
+
+    for(i=start_addr; i < (start_addr + size);) {
+      /* 发出READ0命令 */
+      write_cmd(0);
+
+      /* Write Address */
+      write_addr_lp(i);
+	  write_cmd(0x30);
+      wait_idle();
+
+      for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {
+          *buf = read_data();
+          buf++;
+      }
+    }
+
+    /* 取消片选信号 */
+    nand_deselect_chip();
+    
+    return ;
+}
+
+int bBootFrmNORFlash(void)
+{
+    volatile unsigned int *pdw = (volatile unsigned int *)0;
+    unsigned int dwVal;
+    
+    /*
+     * 无论是从NOR Flash还是从NAND Flash启动，
+     * 地址0处为指令"b	Reset", 机器码为0xEA00000B，
+     * 对于从NAND Flash启动的情况，其开始4KB的代码会复制到CPU内部4K内存中，
+     * 对于从NOR Flash启动的情况，NOR Flash的开始地址即为0。
+     * 对于NOR Flash，必须通过一定的命令序列才能写数据，
+     * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:
+     * 向地址0写入一个数据，然后读出来，如果没有改变的话就是NOR Flash
+     */
+
+    dwVal = *pdw;       
+    *pdw = 0x12345678;
+    if (*pdw != 0x12345678)
+    {
+        return 1;
+    }
+    else
+    {
+        *pdw = dwVal;
+        return 0;
+    }
+}
+
+int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
+{
+    unsigned int *pdwDest;
+    unsigned int *pdwSrc;
+    int i;
+
+    if (bBootFrmNORFlash())
+    {
+        pdwDest = (unsigned int *)buf;
+        pdwSrc  = (unsigned int *)start_addr;
+        /* 从 NOR Flash启动 */
+        for (i = 0; i < size / 4; i++)
+        {
+            pdwDest[i] = pdwSrc[i];
+        }
+        return 0;
+    }
+    else
+    {
+        /* 初始化NAND Flash */
+		nand_init_ll();
+        /* 从 NAND Flash启动 */
+        nand_read_ll_lp(buf, start_addr, (size + NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP));
+		return 0;
+    }
+}
+
+static inline void delay (unsigned long loops)
+{
+    __asm__ volatile ("1:\n"
+      "subs %0, %1, #1\n"
+      "bne 1b":"=r" (loops):"0" (loops));
+}
+
+/* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s)
+ * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
+ */
+#define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
+#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))
+#define S3C2440_MPLL_100MHZ     ((0x5c<<12)|(0x01<<4)|(0x03))
+#define S3C2440_UPLL_96MHZ      ((0x38<<12)|(0x02<<4)|(0x01))
+#define S3C2440_UPLL_48MHZ      ((0x38<<12)|(0x02<<4)|(0x02))
+#define S3C2440_CLKDIV          (0x05) // | (1<<3))    /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */
+#define S3C2440_CLKDIV188       0x04    /* FCLK:HCLK:PCLK = 1:8:8 */
+#define S3C2440_CAMDIVN188      ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */
+
+/* Fin = 16.9344MHz */
+#define S3C2440_MPLL_399MHz_Fin16MHz	((0x6e<<12)|(0x03<<4)|(0x01))
+#define S3C2440_UPLL_48MHZ_Fin16MHz     ((60<<12)|(4<<4)|(2))
+
+/* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)
+ * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
+ */
+#define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))
+#define S3C2410_UPLL_48MHZ      ((0x28<<12)|(0x01<<4)|(0x02))
+#define S3C2410_CLKDIV          0x03    /* FCLK:HCLK:PCLK = 1:2:4 */
+void clock_init(void)
+{
+	S3C24X0_CLOCK_POWER *clk_power = (S3C24X0_CLOCK_POWER *)0x4C000000;
+
+    /* support both of S3C2410 and S3C2440, by www.100ask.net */
+    if (isS3C2410)
+    {
+        /* FCLK:HCLK:PCLK = 1:2:4 */
+        clk_power->CLKDIVN = S3C2410_CLKDIV;
+
+        /* change to asynchronous bus mod */
+        __asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    /* read ctrl register   */  
+                    "orr    r1, r1, #0xc0000000\n"      /* Asynchronous         */  
+                    "mcr    p15, 0, r1, c1, c0, 0\n"    /* write ctrl register  */  
+                    :::"r1"
+                    );
+        
+        /* to reduce PLL lock time, adjust the LOCKTIME register */
+        clk_power->LOCKTIME = 0xFFFFFFFF;
+
+        /* configure UPLL */
+        clk_power->UPLLCON = S3C2410_UPLL_48MHZ;
+
+        /* some delay between MPLL and UPLL */
+        delay (4000);
+
+        /* configure MPLL */
+        clk_power->MPLLCON = S3C2410_MPLL_200MHZ;
+
+        /* some delay between MPLL and UPLL */
+        delay (8000);
+    }
+    else
+    {
+        /* FCLK:HCLK:PCLK = 1:4:8 */
+        clk_power->CLKDIVN = S3C2440_CLKDIV;
+
+        /* change to asynchronous bus mod */
+        __asm__(    "mrc    p15, 0, r1, c1, c0, 0\n"    /* read ctrl register   */  
+                    "orr    r1, r1, #0xc0000000\n"      /* Asynchronous         */  
+                    "mcr    p15, 0, r1, c1, c0, 0\n"    /* write ctrl register  */  
+                    :::"r1"
+                    );
+
+        /* to reduce PLL lock time, adjust the LOCKTIME register */
+        clk_power->LOCKTIME = 0xFFFFFFFF;
+
+        /* configure UPLL */
+        clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
+
+        /* some delay between MPLL and UPLL */
+        delay (4000);
+
+        /* configure MPLL */
+        clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
+
+        /* some delay between MPLL and UPLL */
+        delay (8000);
+    }
+}
+
diff -urN u-boot-1.1.6/board/100ask24x0/config.mk u-boot-1.1.6_jz2440/board/100ask24x0/config.mk
--- u-boot-1.1.6/board/100ask24x0/config.mk	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/config.mk	2010-11-26 12:54:37.022042833 +0800
@@ -0,0 +1,25 @@
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
+#
+# SAMSUNG SMDK2410 board with S3C2410X (ARM920T) cpu
+#
+# see http://www.samsung.com/ for more information on SAMSUNG
+#
+
+#
+# SMDK2410 has 1 bank of 64 MB DRAM
+#
+# 3000'0000 to 3400'0000
+#
+# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
+# optionally with a ramdisk at 3080'0000
+#
+# we load ourself to 33F8'0000
+#
+# download area is 3300'0000
+#
+
+
+TEXT_BASE = 0x33F80000
diff -urN u-boot-1.1.6/board/100ask24x0/flash.c u-boot-1.1.6_jz2440/board/100ask24x0/flash.c
--- u-boot-1.1.6/board/100ask24x0/flash.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/flash.c	2010-11-26 12:54:37.022042833 +0800
@@ -0,0 +1,433 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+ulong myflush (void);
+
+
+#define FLASH_BANK_SIZE	PHYS_FLASH_SIZE
+#define MAIN_SECT_SIZE  0x10000	/* 64 KB */
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+#define CMD_READ_ARRAY		0x000000F0
+#define CMD_UNLOCK1		0x000000AA
+#define CMD_UNLOCK2		0x00000055
+#define CMD_ERASE_SETUP		0x00000080
+#define CMD_ERASE_CONFIRM	0x00000030
+#define CMD_PROGRAM		0x000000A0
+#define CMD_UNLOCK_BYPASS	0x00000020
+
+#define MEM_FLASH_ADDR1		(*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
+#define MEM_FLASH_ADDR2		(*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))
+
+#define BIT_ERASE_DONE		0x00000080
+#define BIT_RDY_MASK		0x00000080
+#define BIT_PROGRAM_ERROR	0x00000020
+#define BIT_TIMEOUT		0x80000000	/* our flag */
+
+#define READY 1
+#define ERR   2
+#define TMO   4
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init (void)
+{
+	int i, j;
+	ulong size = 0;
+
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+		ulong flashbase = 0;
+
+		flash_info[i].flash_id =
+#if defined(CONFIG_AMD_LV400)
+			(AMD_MANUFACT & FLASH_VENDMASK) |
+			(AMD_ID_LV400B & FLASH_TYPEMASK);
+#elif defined(CONFIG_AMD_LV800)
+			(AMD_MANUFACT & FLASH_VENDMASK) |
+			(AMD_ID_LV800B & FLASH_TYPEMASK);
+#else
+#error "Unknown flash configured"
+#endif
+			flash_info[i].size = FLASH_BANK_SIZE;
+		flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
+		memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
+		if (i == 0)
+			flashbase = PHYS_FLASH_1;
+		else
+			panic ("configured too many flash banks!\n");
+		for (j = 0; j < flash_info[i].sector_count; j++) {
+			if (j <= 3) {
+				/* 1st one is 16 KB */
+				if (j == 0) {
+					flash_info[i].start[j] =
+						flashbase + 0;
+				}
+
+				/* 2nd and 3rd are both 8 KB */
+				if ((j == 1) || (j == 2)) {
+					flash_info[i].start[j] =
+						flashbase + 0x4000 + (j -
+								      1) *
+						0x2000;
+				}
+
+				/* 4th 32 KB */
+				if (j == 3) {
+					flash_info[i].start[j] =
+						flashbase + 0x8000;
+				}
+			} else {
+				flash_info[i].start[j] =
+					flashbase + (j - 3) * MAIN_SECT_SIZE;
+			}
+		}
+		size += flash_info[i].size;
+	}
+
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_FLASH_BASE,
+		       CFG_FLASH_BASE + monitor_flash_len - 1,
+		       &flash_info[0]);
+
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_ENV_ADDR,
+		       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
+
+	return size;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+	int i;
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case (AMD_MANUFACT & FLASH_VENDMASK):
+		printf ("AMD: ");
+		break;
+	default:
+		printf ("Unknown Vendor ");
+		break;
+	}
+
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case (AMD_ID_LV400B & FLASH_TYPEMASK):
+		printf ("1x Amd29LV400BB (4Mbit)\n");
+		break;
+	case (AMD_ID_LV800B & FLASH_TYPEMASK):
+		printf ("1x Amd29LV800BB (8Mbit)\n");
+		break;
+	default:
+		printf ("Unknown Chip Type\n");
+		goto Done;
+		break;
+	}
+
+	printf ("  Size: %ld MB in %d Sectors\n",
+		info->size >> 20, info->sector_count);
+
+	printf ("  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; i++) {
+		if ((i % 5) == 0) {
+			printf ("\n   ");
+		}
+		printf (" %08lX%s", info->start[i],
+			info->protect[i] ? " (RO)" : "     ");
+	}
+	printf ("\n");
+
+      Done:;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+	ushort result;
+	int iflag, cflag, prot, sect;
+	int rc = ERR_OK;
+	int chip;
+
+	/* first look for protection bits */
+
+	if (info->flash_id == FLASH_UNKNOWN)
+		return ERR_UNKNOWN_FLASH_TYPE;
+
+	if ((s_first < 0) || (s_first > s_last)) {
+		return ERR_INVAL;
+	}
+
+	if ((info->flash_id & FLASH_VENDMASK) !=
+	    (AMD_MANUFACT & FLASH_VENDMASK)) {
+		return ERR_UNKNOWN_FLASH_VENDOR;
+	}
+
+	prot = 0;
+	for (sect = s_first; sect <= s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+	if (prot)
+		return ERR_PROTECTED;
+
+	/*
+	 * Disable interrupts which might cause a timeout
+	 * here. Remember that our exception vectors are
+	 * at address 0 in the flash, and we don't want a
+	 * (ticker) exception to happen while the flash
+	 * chip is in programming mode.
+	 */
+	cflag = icache_status ();
+	icache_disable ();
+	iflag = disable_interrupts ();
+
+	/* Start erase on unprotected sectors */
+	for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
+		printf ("Erasing sector %2d ... ", sect);
+
+		/* arm simple, non interrupt dependent timer */
+		reset_timer_masked ();
+
+		if (info->protect[sect] == 0) {	/* not protected */
+			vu_short *addr = (vu_short *) (info->start[sect]);
+
+			MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+			MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+			MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
+
+			MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+			MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+			*addr = CMD_ERASE_CONFIRM;
+
+			/* wait until flash is ready */
+			chip = 0;
+
+			do {
+				result = *addr;
+
+				/* check timeout */
+				if (get_timer_masked () >
+				    CFG_FLASH_ERASE_TOUT) {
+					MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+					chip = TMO;
+					break;
+				}
+
+				if (!chip
+				    && (result & 0xFFFF) & BIT_ERASE_DONE)
+					chip = READY;
+
+				if (!chip
+				    && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
+					chip = ERR;
+
+			} while (!chip);
+
+			MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
+
+			if (chip == ERR) {
+				rc = ERR_PROG_ERROR;
+				goto outahere;
+			}
+			if (chip == TMO) {
+				rc = ERR_TIMOUT;
+				goto outahere;
+			}
+
+			printf ("ok.\n");
+		} else {	/* it was protected */
+
+			printf ("protected!\n");
+		}
+	}
+
+	if (ctrlc ())
+		printf ("User Interrupt!\n");
+
+      outahere:
+	/* allow flash to settle - wait 10 ms */
+	udelay_masked (10000);
+
+	if (iflag)
+		enable_interrupts ();
+
+	if (cflag)
+		icache_enable ();
+
+	return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash
+ */
+
+volatile static int write_hword (flash_info_t * info, ulong dest, ushort data)
+{
+	vu_short *addr = (vu_short *) dest;
+	ushort result;
+	int rc = ERR_OK;
+	int cflag, iflag;
+	int chip;
+
+	/*
+	 * Check if Flash is (sufficiently) erased
+	 */
+	result = *addr;
+	if ((result & data) != data)
+		return ERR_NOT_ERASED;
+
+
+	/*
+	 * Disable interrupts which might cause a timeout
+	 * here. Remember that our exception vectors are
+	 * at address 0 in the flash, and we don't want a
+	 * (ticker) exception to happen while the flash
+	 * chip is in programming mode.
+	 */
+	cflag = icache_status ();
+	icache_disable ();
+	iflag = disable_interrupts ();
+
+	MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+	MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+	MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
+	*addr = CMD_PROGRAM;
+	*addr = data;
+
+	/* arm simple, non interrupt dependent timer */
+	reset_timer_masked ();
+
+	/* wait until flash is ready */
+	chip = 0;
+	do {
+		result = *addr;
+
+		/* check timeout */
+		if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
+			chip = ERR | TMO;
+			break;
+		}
+		if (!chip && ((result & 0x80) == (data & 0x80)))
+			chip = READY;
+
+		if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
+			result = *addr;
+
+			if ((result & 0x80) == (data & 0x80))
+				chip = READY;
+			else
+				chip = ERR;
+		}
+
+	} while (!chip);
+
+	*addr = CMD_READ_ARRAY;
+
+	if (chip == ERR || *addr != data)
+		rc = ERR_PROG_ERROR;
+
+	if (iflag)
+		enable_interrupts ();
+
+	if (cflag)
+		icache_enable ();
+
+	return rc;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ */
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+	ulong cp, wp;
+	int l;
+	int i, rc;
+	ushort data;
+
+	wp = (addr & ~1);	/* get lower word aligned address */
+
+	/*
+	 * handle unaligned start bytes
+	 */
+	if ((l = addr - wp) != 0) {
+		data = 0;
+		for (i = 0, cp = wp; i < l; ++i, ++cp) {
+			data = (data >> 8) | (*(uchar *) cp << 8);
+		}
+		for (; i < 2 && cnt > 0; ++i) {
+			data = (data >> 8) | (*src++ << 8);
+			--cnt;
+			++cp;
+		}
+		for (; cnt == 0 && i < 2; ++i, ++cp) {
+			data = (data >> 8) | (*(uchar *) cp << 8);
+		}
+
+		if ((rc = write_hword (info, wp, data)) != 0) {
+			return (rc);
+		}
+		wp += 2;
+	}
+
+	/*
+	 * handle word aligned part
+	 */
+	while (cnt >= 2) {
+		data = *((vu_short *) src);
+		if ((rc = write_hword (info, wp, data)) != 0) {
+			return (rc);
+		}
+		src += 2;
+		wp += 2;
+		cnt -= 2;
+	}
+
+	if (cnt == 0) {
+		return ERR_OK;
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	data = 0;
+	for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
+		data = (data >> 8) | (*src++ << 8);
+		--cnt;
+	}
+	for (; i < 2; ++i, ++cp) {
+		data = (data >> 8) | (*(uchar *) cp << 8);
+	}
+
+	return write_hword (info, wp, data);
+}
diff -urN u-boot-1.1.6/board/100ask24x0/lowlevel_init.S u-boot-1.1.6_jz2440/board/100ask24x0/lowlevel_init.S
--- u-boot-1.1.6/board/100ask24x0/lowlevel_init.S	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/lowlevel_init.S	2010-11-26 12:54:37.042080086 +0800
@@ -0,0 +1,168 @@
+/*
+ * Memory Setup stuff - taken from blob memsetup.S
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
+ *                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ *
+ * Modified for the Samsung SMDK2410 by
+ * (C) Copyright 2002
+ * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <config.h>
+#include <version.h>
+
+
+/* some parameters for the board */
+
+/*
+ *
+ * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
+ *
+ * Copyright (C) 2002 Samsung Electronics SW.LEE  <hitchcar@sec.samsung.com>
+ *
+ */
+
+#define BWSCON	0x48000000
+
+/* BWSCON */
+#define DW8		 	(0x0)
+#define DW16		 	(0x1)
+#define DW32		 	(0x2)
+#define WAIT		 	(0x1<<2)
+#define UBLB		 	(0x1<<3)
+
+#define B1_BWSCON	  	(DW16)
+#define B2_BWSCON	  	(DW16)
+//#define B3_BWSCON	  	(DW16 + WAIT + UBLB)
+#define B3_BWSCON	  	(DW16 + UBLB)
+#define B4_BWSCON	  	(DW16 + WAIT + UBLB)
+#define B5_BWSCON	  	(DW8)
+#define B6_BWSCON	  	(DW32)
+#define B7_BWSCON	  	(DW32)
+
+/* BANK0CON */
+#define B0_Tacs		 	0x0	/*  0clk */
+#define B0_Tcos		 	0x0	/*  0clk */
+#define B0_Tacc		 	0x7	/* 14clk */
+#define B0_Tcoh		 	0x0	/*  0clk */
+#define B0_Tah		 	0x0	/*  0clk */
+#define B0_Tacp		 	0x0
+#define B0_PMC		 	0x0	/* normal */
+
+/* BANK1CON */
+#define B1_Tacs		 	0x0	/*  0clk */
+#define B1_Tcos		 	0x0	/*  0clk */
+#define B1_Tacc		 	0x7	/* 14clk */
+#define B1_Tcoh		 	0x0	/*  0clk */
+#define B1_Tah		 	0x0	/*  0clk */
+#define B1_Tacp		 	0x0
+#define B1_PMC		 	0x0
+
+#define B2_Tacs		 	0x0
+#define B2_Tcos		 	0x0
+#define B2_Tacc		 	0x7
+#define B2_Tcoh		 	0x0
+#define B2_Tah		 	0x0
+#define B2_Tacp		 	0x0
+#define B2_PMC		 	0x0
+
+#define B3_Tacs		 	0x0	/*  0clk */
+#define B3_Tcos		 	0x3	/*  4clk */
+#define B3_Tacc		 	0x7	/* 14clk */
+#define B3_Tcoh		 	0x1	/*  1clk */
+#define B3_Tah		 	0x0	/*  0clk */
+#define B3_Tacp		 	0x3     /*  6clk */
+#define B3_PMC		 	0x0	/* normal */
+
+#define B4_Tacs		 	0x0	/*  0clk */
+#define B4_Tcos		 	0x3	/*  4clk */
+#define B4_Tacc		 	0x7	/* 14clk */
+#define B4_Tcoh		 	0x1	/*  1clk */
+#define B4_Tah		 	0x3	/*  4clk */
+#define B4_Tacp		 	0x6 /*  6clk */
+#define B4_PMC		 	0x0	/* normal */
+
+#define B5_Tacs		 	0x0	/*  0clk */
+#define B5_Tcos		 	0x0	/*  0clk */
+#define B5_Tacc		 	0x7	/* 14clk */
+#define B5_Tcoh		 	0x0	/*  0clk */
+#define B5_Tah		 	0x0	/*  0clk */
+#define B5_Tacp		 	0x0
+#define B5_PMC		 	0x0	/* normal */
+
+#define B6_MT		 	0x3	/* SDRAM */
+#define B6_Trcd	 	 	0x1
+#define B6_SCAN		 	0x1	/* 9bit */
+
+#define B7_MT		 	0x3	/* SDRAM */
+#define B7_Trcd		 	0x1	/* 3clk */
+#define B7_SCAN		 	0x1	/* 9bit */
+
+/* REFRESH parameter */
+#define REFEN		 	0x1	/* Refresh enable */
+#define TREFMD		 	0x0	/* CBR(CAS before RAS)/Auto refresh */
+#define Trp		 	    0x0	/* 2clk */
+#define Trc		    	0x3	/* 7clk */
+#define Tchr		 	0x2	/* 3clk */
+#define REFCNT		 	0x4f4	/* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */
+/**************************************/
+
+_TEXT_BASE:
+	.word	TEXT_BASE
+
+.globl lowlevel_init
+lowlevel_init:
+	/* memory control configuration */
+	/* make r0 relative the current location so that it */
+	/* reads SMRDATA out of FLASH rather than memory ! */
+	ldr     r0, =SMRDATA
+	ldr	r1, _TEXT_BASE
+	sub	r0, r0, r1
+	ldr	r1, =BWSCON	/* Bus Width Status Controller */
+	add     r2, r0, #13*4
+0:
+	ldr     r3, [r0], #4
+	str     r3, [r1], #4
+	cmp     r2, r0
+	bne     0b
+
+	/* everything is fine now */
+	mov	pc, lr
+
+	.ltorg
+/* the literal pools origin */
+
+SMRDATA:
+    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) 
+    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
+    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
+    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
+    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
+    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
+    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
+    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
+    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
+    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
+    .word 0xb1
+    .word 0x30
+    .word 0x30
diff -urN u-boot-1.1.6/board/100ask24x0/Makefile u-boot-1.1.6_jz2440/board/100ask24x0/Makefile
--- u-boot-1.1.6/board/100ask24x0/Makefile	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/Makefile	2010-11-26 12:54:37.030096240 +0800
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2000-2006
+# 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
+
+LIB	= $(obj)lib$(BOARD).a
+
+COBJS	:= 100ask24x0.o boot_init.o
+SOBJS	:= lowlevel_init.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff -urN u-boot-1.1.6/board/100ask24x0/u-boot.lds u-boot-1.1.6_jz2440/board/100ask24x0/u-boot.lds
--- u-boot-1.1.6/board/100ask24x0/u-boot.lds	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/board/100ask24x0/u-boot.lds	2010-11-26 12:54:37.042080086 +0800
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+	. = 0x00000000;
+
+	. = ALIGN(4);
+	.text      :
+	{
+	  cpu/arm920t/start.o	(.text)
+          board/100ask24x0/boot_init.o (.text)
+	  *(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data : { *(.data) }
+
+	. = ALIGN(4);
+	.got : { *(.got) }
+
+	. = .;
+	__u_boot_cmd_start = .;
+	.u_boot_cmd : { *(.u_boot_cmd) }
+	__u_boot_cmd_end = .;
+
+	. = ALIGN(4);
+	__bss_start = .;
+	.bss : { *(.bss) }
+	_end = .;
+}
diff -urN u-boot-1.1.6/board/MAI/bios_emulator/scitech/src/v86bios/lex.l u-boot-1.1.6_jz2440/board/MAI/bios_emulator/scitech/src/v86bios/lex.l
--- u-boot-1.1.6/board/MAI/bios_emulator/scitech/src/v86bios/lex.l	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/board/MAI/bios_emulator/scitech/src/v86bios/lex.l	1970-01-01 07:00:00.000000000 +0700
@@ -1,79 +0,0 @@
-%{
-#include "parser.h"
-
-#include <string.h>
-#include <stdio.h>
-
- void getline(char *buf,int *num,int max_num);
-    
-#define YY_INPUT(buf,result,max_size) {\
-      getline(buf,&result,max_size);\
-      }
-
- void
- yyerror (char *s)  
- {
-     printf ("%s\n", s);
- }
-
-%}
-
-DIGIT [0-9a-fA-F]
-
-%%
-
-"0x"?{DIGIT}+ { yylval = strtol(yytext,NULL,0); return TOK_NUM; }
-"ax"          { return TOK_REG_AX; }
-"bx"          { return TOK_REG_BX; }
-"cx"          { return TOK_REG_CX; }
-"dx"          { return TOK_REG_DX; }
-"di"          { return TOK_REG_SI; }
-"si"          { return TOK_REG_DI; }
-"ds"          { return TOK_SEG_DS; }
-"es"          { return TOK_SEG_ES; }
-":"           { return TOK_SEP;}
-"$"{DIGIT}{1,2} { yylval = strtol(yytext+1,NULL,0); return TOK_VAR; }
-"$mem"        { return TOK_VAR_MEM; }
-[ \t]+
-"#".*[\n]   { return TOK_END; }
-"boot"        { return TOK_COMMAND_BOOT; }
-"do"          { return TOK_COMMAND_EXEC; }
-"\"".*"\""    { yylval = (unsigned long) yytext; return TOK_STRING; }
-"byte"        { return TOK_BYTE; }
-"word"        { return TOK_WORD; }
-"long"        { return TOK_LONG; }
-"setmem"      { return TOK_COMMAND_MEMSET; }
-"dumpmem"     { return TOK_COMMAND_MEMDUMP; }
-"quit"        { return TOK_COMMAND_QUIT; }
-"\n"          { return TOK_END; }
-"select"      { return TOK_SELECT; }
-"isa"         { return TOK_ISA; }
-"pci"         { return TOK_PCI; }
-"pport"       { return TOK_PRINT_PORT; }
-"iostat"      { return TOK_IOSTAT; }
-"pirq"        { return TOK_PRINT_IRQ; }
-"ppci"        { return TOK_PPCI; }
-"pip"         { return TOK_PIP; }
-"trace"       { return TOK_TRACE; }
-"on"          { return TOK_ON; }
-"off"         { return TOK_OFF; }
-"verbose"     { return TOK_VERBOSE; }
-"log"         { return TOK_LOG; }
-"print"       { return TOK_STDOUT; }
-"clstat"      { return TOK_CLSTAT; }
-"hlt"         { return TOK_HLT; }
-"del"         { return TOK_DEL; }
-"ioperm"      { return TOK_IOPERM; }
-"lpci"        { return TOK_DUMP_PCI; }
-"bootbios"    { return TOK_BOOT_BIOS; }
-"?"           { return '?'; }
-.             { return TOK_ERROR; }
-    
-%%
-
-
-
-
-
-
-
diff -urN u-boot-1.1.6/common/cmd_bootm.c u-boot-1.1.6_jz2440/common/cmd_bootm.c
--- u-boot-1.1.6/common/cmd_bootm.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/common/cmd_bootm.c	2010-11-26 12:54:38.150155640 +0800
@@ -305,12 +305,12 @@
 
 	iflag = disable_interrupts();
 
-#ifdef CONFIG_AMIGAONEG3SE
+#ifdef CONFIG_AMIGAONEG3SE 
 	/*
 	 * We've possible left the caches enabled during
 	 * bios emulation, so turn them off again
 	 */
-	icache_disable();
+	icache_disable();  
 	invalidate_l1_instruction_cache();
 	flush_data_cache();
 	dcache_disable();
@@ -318,7 +318,7 @@
 
 	switch (hdr->ih_comp) {
 	case IH_COMP_NONE:
-		if(ntohl(hdr->ih_load) == addr) {
+		if(ntohl(hdr->ih_load) == data) {
 			printf ("   XIP %s ... ", name);
 		} else {
 #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
diff -urN u-boot-1.1.6/common/cmd_load.c u-boot-1.1.6_jz2440/common/cmd_load.c
--- u-boot-1.1.6/common/cmd_load.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/common/cmd_load.c	2010-11-26 12:54:38.142063808 +0800
@@ -34,6 +34,8 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 #if (CONFIG_COMMANDS & CFG_CMD_LOADB)
+/* support xmodem, www.100ask.net */
+static ulong load_serial_xmodem (ulong offset);
 static ulong load_serial_ymodem (ulong offset);
 #endif
 
@@ -53,355 +55,355 @@
 #if (CONFIG_COMMANDS & CFG_CMD_LOADS)
 int do_load_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong offset = 0;
-	ulong addr;
-	int i;
-	char *env_echo;
-	int rcode = 0;
-#ifdef	CFG_LOADS_BAUD_CHANGE
-	int load_baudrate, current_baudrate;
+    ulong offset = 0;
+    ulong addr;
+    int i;
+    char *env_echo;
+    int rcode = 0;
+#ifdef  CFG_LOADS_BAUD_CHANGE
+    int load_baudrate, current_baudrate;
 
-	load_baudrate = current_baudrate = gd->baudrate;
+    load_baudrate = current_baudrate = gd->baudrate;
 #endif
 
-	if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) {
-		do_echo = 1;
-	} else {
-		do_echo = 0;
-	}
-
-#ifdef	CFG_LOADS_BAUD_CHANGE
-	if (argc >= 2) {
-		offset = simple_strtoul(argv[1], NULL, 16);
-	}
-	if (argc == 3) {
-		load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
-
-		/* default to current baudrate */
-		if (load_baudrate == 0)
-			load_baudrate = current_baudrate;
-	}
-	if (load_baudrate != current_baudrate) {
-		printf ("## Switch baudrate to %d bps and press ENTER ...\n",
-			load_baudrate);
-		udelay(50000);
-		gd->baudrate = load_baudrate;
-		serial_setbrg ();
-		udelay(50000);
-		for (;;) {
-			if (getc() == '\r')
-				break;
-		}
-	}
-#else	/* ! CFG_LOADS_BAUD_CHANGE */
-	if (argc == 2) {
-		offset = simple_strtoul(argv[1], NULL, 16);
-	}
-#endif	/* CFG_LOADS_BAUD_CHANGE */
-
-	printf ("## Ready for S-Record download ...\n");
-
-	addr = load_serial (offset);
-
-	/*
-	 * Gather any trailing characters (for instance, the ^D which
-	 * is sent by 'cu' after sending a file), and give the
-	 * box some time (100 * 1 ms)
-	 */
-	for (i=0; i<100; ++i) {
-		if (tstc()) {
-			(void) getc();
-		}
-		udelay(1000);
-	}
-
-	if (addr == ~0) {
-		printf ("## S-Record download aborted\n");
-		rcode = 1;
-	} else {
-		printf ("## Start Addr      = 0x%08lX\n", addr);
-		load_addr = addr;
-	}
-
-#ifdef	CFG_LOADS_BAUD_CHANGE
-	if (load_baudrate != current_baudrate) {
-		printf ("## Switch baudrate to %d bps and press ESC ...\n",
-			current_baudrate);
-		udelay (50000);
-		gd->baudrate = current_baudrate;
-		serial_setbrg ();
-		udelay (50000);
-		for (;;) {
-			if (getc() == 0x1B) /* ESC */
-				break;
-		}
-	}
+    if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) {
+        do_echo = 1;
+    } else {
+        do_echo = 0;
+    }
+
+#ifdef  CFG_LOADS_BAUD_CHANGE
+    if (argc >= 2) {
+        offset = simple_strtoul(argv[1], NULL, 16);
+    }
+    if (argc == 3) {
+        load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+
+        /* default to current baudrate */
+        if (load_baudrate == 0)
+            load_baudrate = current_baudrate;
+    }
+    if (load_baudrate != current_baudrate) {
+        printf ("## Switch baudrate to %d bps and press ENTER ...\n",
+            load_baudrate);
+        udelay(50000);
+        gd->baudrate = load_baudrate;
+        serial_setbrg ();
+        udelay(50000);
+        for (;;) {
+            if (getc() == '\r')
+                break;
+        }
+    }
+#else   /* ! CFG_LOADS_BAUD_CHANGE */
+    if (argc == 2) {
+        offset = simple_strtoul(argv[1], NULL, 16);
+    }
+#endif  /* CFG_LOADS_BAUD_CHANGE */
+
+    printf ("## Ready for S-Record download ...\n");
+
+    addr = load_serial (offset);
+
+    /*
+     * Gather any trailing characters (for instance, the ^D which
+     * is sent by 'cu' after sending a file), and give the
+     * box some time (100 * 1 ms)
+     */
+    for (i=0; i<100; ++i) {
+        if (tstc()) {
+            (void) getc();
+        }
+        udelay(1000);
+    }
+
+    if (addr == ~0) {
+        printf ("## S-Record download aborted\n");
+        rcode = 1;
+    } else {
+        printf ("## Start Addr      = 0x%08lX\n", addr);
+        load_addr = addr;
+    }
+
+#ifdef  CFG_LOADS_BAUD_CHANGE
+    if (load_baudrate != current_baudrate) {
+        printf ("## Switch baudrate to %d bps and press ESC ...\n",
+            current_baudrate);
+        udelay (50000);
+        gd->baudrate = current_baudrate;
+        serial_setbrg ();
+        udelay (50000);
+        for (;;) {
+            if (getc() == 0x1B) /* ESC */
+                break;
+        }
+    }
 #endif
-	return rcode;
+    return rcode;
 }
 
 static ulong
 load_serial (ulong offset)
 {
-	char	record[SREC_MAXRECLEN + 1];	/* buffer for one S-Record	*/
-	char	binbuf[SREC_MAXBINLEN];		/* buffer for binary data	*/
-	int	binlen;				/* no. of data bytes in S-Rec.	*/
-	int	type;				/* return code for record type	*/
-	ulong	addr;				/* load address from S-Record	*/
-	ulong	size;				/* number of bytes transferred	*/
-	char	buf[32];
-	ulong	store_addr;
-	ulong	start_addr = ~0;
-	ulong	end_addr   =  0;
-	int	line_count =  0;
-
-	while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
-		type = srec_decode (record, &binlen, &addr, binbuf);
-
-		if (type < 0) {
-			return (~0);		/* Invalid S-Record		*/
-		}
-
-		switch (type) {
-		case SREC_DATA2:
-		case SREC_DATA3:
-		case SREC_DATA4:
-		    store_addr = addr + offset;
+    char    record[SREC_MAXRECLEN + 1]; /* buffer for one S-Record  */
+    char    binbuf[SREC_MAXBINLEN];     /* buffer for binary data   */
+    int binlen;             /* no. of data bytes in S-Rec.  */
+    int type;               /* return code for record type  */
+    ulong   addr;               /* load address from S-Record   */
+    ulong   size;               /* number of bytes transferred  */
+    char    buf[32];
+    ulong   store_addr;
+    ulong   start_addr = ~0;
+    ulong   end_addr   =  0;
+    int line_count =  0;
+
+    while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {
+        type = srec_decode (record, &binlen, &addr, binbuf);
+
+        if (type < 0) {
+            return (~0);        /* Invalid S-Record     */
+        }
+
+        switch (type) {
+        case SREC_DATA2:
+        case SREC_DATA3:
+        case SREC_DATA4:
+            store_addr = addr + offset;
 #ifndef CFG_NO_FLASH
-		    if (addr2info(store_addr)) {
-			int rc;
+            if (addr2info(store_addr)) {
+            int rc;
 
-			rc = flash_write((char *)binbuf,store_addr,binlen);
-			if (rc != 0) {
-				flash_perror (rc);
-				return (~0);
-			}
-		    } else
+            rc = flash_write((char *)binbuf,store_addr,binlen);
+            if (rc != 0) {
+                flash_perror (rc);
+                return (~0);
+            }
+            } else
 #endif
-		    {
-			memcpy ((char *)(store_addr), binbuf, binlen);
-		    }
-		    if ((store_addr) < start_addr)
-			start_addr = store_addr;
-		    if ((store_addr + binlen - 1) > end_addr)
-			end_addr = store_addr + binlen - 1;
-		    break;
-		case SREC_END2:
-		case SREC_END3:
-		case SREC_END4:
-		    udelay (10000);
-		    size = end_addr - start_addr + 1;
-		    printf ("\n"
-			    "## First Load Addr = 0x%08lX\n"
-			    "## Last  Load Addr = 0x%08lX\n"
-			    "## Total Size      = 0x%08lX = %ld Bytes\n",
-			    start_addr, end_addr, size, size
-		    );
-		    flush_cache (start_addr, size);
-		    sprintf(buf, "%lX", size);
-		    setenv("filesize", buf);
-		    return (addr);
-		case SREC_START:
-		    break;
-		default:
-		    break;
-		}
-		if (!do_echo) {	/* print a '.' every 100 lines */
-			if ((++line_count % 100) == 0)
-				putc ('.');
-		}
-	}
+            {
+            memcpy ((char *)(store_addr), binbuf, binlen);
+            }
+            if ((store_addr) < start_addr)
+            start_addr = store_addr;
+            if ((store_addr + binlen - 1) > end_addr)
+            end_addr = store_addr + binlen - 1;
+            break;
+        case SREC_END2:
+        case SREC_END3:
+        case SREC_END4:
+            udelay (10000);
+            size = end_addr - start_addr + 1;
+            printf ("\n"
+                "## First Load Addr = 0x%08lX\n"
+                "## Last  Load Addr = 0x%08lX\n"
+                "## Total Size      = 0x%08lX = %ld Bytes\n",
+                start_addr, end_addr, size, size
+            );
+            flush_cache (start_addr, size);
+            sprintf(buf, "%lX", size);
+            setenv("filesize", buf);
+            return (addr);
+        case SREC_START:
+            break;
+        default:
+            break;
+        }
+        if (!do_echo) { /* print a '.' every 100 lines */
+            if ((++line_count % 100) == 0)
+                putc ('.');
+        }
+    }
 
-	return (~0);			/* Download aborted		*/
+    return (~0);            /* Download aborted     */
 }
 
 static int
 read_record (char *buf, ulong len)
 {
-	char *p;
-	char c;
+    char *p;
+    char c;
 
-	--len;	/* always leave room for terminating '\0' byte */
+    --len;  /* always leave room for terminating '\0' byte */
 
-	for (p=buf; p < buf+len; ++p) {
-		c = getc();		/* read character		*/
-		if (do_echo)
-			putc (c);	/* ... and echo it		*/
-
-		switch (c) {
-		case '\r':
-		case '\n':
-			*p = '\0';
-			return (p - buf);
-		case '\0':
-		case 0x03:			/* ^C - Control C		*/
-			return (-1);
-		default:
-			*p = c;
-		}
-
-	    /* Check for the console hangup (if any different from serial) */
-	    if (gd->jt[XF_getc] != getc) {
-		if (ctrlc()) {
-		    return (-1);
-		}
-	    }
-	}
-
-	/* line too long - truncate */
-	*p = '\0';
-	return (p - buf);
+    for (p=buf; p < buf+len; ++p) {
+        c = getc();     /* read character       */
+        if (do_echo)
+            putc (c);   /* ... and echo it      */
+
+        switch (c) {
+        case '\r':
+        case '\n':
+            *p = '\0';
+            return (p - buf);
+        case '\0':
+        case 0x03:          /* ^C - Control C       */
+            return (-1);
+        default:
+            *p = c;
+        }
+
+        /* Check for the console hangup (if any different from serial) */
+        if (gd->jt[XF_getc] != getc) {
+        if (ctrlc()) {
+            return (-1);
+        }
+        }
+    }
+
+    /* line too long - truncate */
+    *p = '\0';
+    return (p - buf);
 }
 
 #if (CONFIG_COMMANDS & CFG_CMD_SAVES)
 
 int do_save_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong offset = 0;
-	ulong size   = 0;
-#ifdef	CFG_LOADS_BAUD_CHANGE
-	int save_baudrate, current_baudrate;
+    ulong offset = 0;
+    ulong size   = 0;
+#ifdef  CFG_LOADS_BAUD_CHANGE
+    int save_baudrate, current_baudrate;
 
-	save_baudrate = current_baudrate = gd->baudrate;
+    save_baudrate = current_baudrate = gd->baudrate;
 #endif
 
-	if (argc >= 2) {
-		offset = simple_strtoul(argv[1], NULL, 16);
-	}
-#ifdef	CFG_LOADS_BAUD_CHANGE
-	if (argc >= 3) {
-		size = simple_strtoul(argv[2], NULL, 16);
-	}
-	if (argc == 4) {
-		save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);
-
-		/* default to current baudrate */
-		if (save_baudrate == 0)
-			save_baudrate = current_baudrate;
-	}
-	if (save_baudrate != current_baudrate) {
-		printf ("## Switch baudrate to %d bps and press ENTER ...\n",
-			save_baudrate);
-		udelay(50000);
-		gd->baudrate = save_baudrate;
-		serial_setbrg ();
-		udelay(50000);
-		for (;;) {
-			if (getc() == '\r')
-				break;
-		}
-	}
-#else	/* ! CFG_LOADS_BAUD_CHANGE */
-	if (argc == 3) {
-		size = simple_strtoul(argv[2], NULL, 16);
-	}
-#endif	/* CFG_LOADS_BAUD_CHANGE */
-
-	printf ("## Ready for S-Record upload, press ENTER to proceed ...\n");
-	for (;;) {
-		if (getc() == '\r')
-			break;
-	}
-	if(save_serial (offset, size)) {
-		printf ("## S-Record upload aborted\n");
-	} else {
-		printf ("## S-Record upload complete\n");
-	}
-#ifdef	CFG_LOADS_BAUD_CHANGE
-	if (save_baudrate != current_baudrate) {
-		printf ("## Switch baudrate to %d bps and press ESC ...\n",
-			(int)current_baudrate);
-		udelay (50000);
-		gd->baudrate = current_baudrate;
-		serial_setbrg ();
-		udelay (50000);
-		for (;;) {
-			if (getc() == 0x1B) /* ESC */
-				break;
-		}
-	}
+    if (argc >= 2) {
+        offset = simple_strtoul(argv[1], NULL, 16);
+    }
+#ifdef  CFG_LOADS_BAUD_CHANGE
+    if (argc >= 3) {
+        size = simple_strtoul(argv[2], NULL, 16);
+    }
+    if (argc == 4) {
+        save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);
+
+        /* default to current baudrate */
+        if (save_baudrate == 0)
+            save_baudrate = current_baudrate;
+    }
+    if (save_baudrate != current_baudrate) {
+        printf ("## Switch baudrate to %d bps and press ENTER ...\n",
+            save_baudrate);
+        udelay(50000);
+        gd->baudrate = save_baudrate;
+        serial_setbrg ();
+        udelay(50000);
+        for (;;) {
+            if (getc() == '\r')
+                break;
+        }
+    }
+#else   /* ! CFG_LOADS_BAUD_CHANGE */
+    if (argc == 3) {
+        size = simple_strtoul(argv[2], NULL, 16);
+    }
+#endif  /* CFG_LOADS_BAUD_CHANGE */
+
+    printf ("## Ready for S-Record upload, press ENTER to proceed ...\n");
+    for (;;) {
+        if (getc() == '\r')
+            break;
+    }
+    if(save_serial (offset, size)) {
+        printf ("## S-Record upload aborted\n");
+    } else {
+        printf ("## S-Record upload complete\n");
+    }
+#ifdef  CFG_LOADS_BAUD_CHANGE
+    if (save_baudrate != current_baudrate) {
+        printf ("## Switch baudrate to %d bps and press ESC ...\n",
+            (int)current_baudrate);
+        udelay (50000);
+        gd->baudrate = current_baudrate;
+        serial_setbrg ();
+        udelay (50000);
+        for (;;) {
+            if (getc() == 0x1B) /* ESC */
+                break;
+        }
+    }
 #endif
-	return 0;
+    return 0;
 }
 
-#define SREC3_START				"S0030000FC\n"
-#define SREC3_FORMAT			"S3%02X%08lX%s%02X\n"
-#define SREC3_END				"S70500000000FA\n"
-#define SREC_BYTES_PER_RECORD	16
+#define SREC3_START             "S0030000FC\n"
+#define SREC3_FORMAT            "S3%02X%08lX%s%02X\n"
+#define SREC3_END               "S70500000000FA\n"
+#define SREC_BYTES_PER_RECORD   16
 
 static int save_serial (ulong address, ulong count)
 {
-	int i, c, reclen, checksum, length;
-	char *hex = "0123456789ABCDEF";
-	char	record[2*SREC_BYTES_PER_RECORD+16];	/* buffer for one S-Record	*/
-	char	data[2*SREC_BYTES_PER_RECORD+1];	/* buffer for hex data	*/
-
-	reclen = 0;
-	checksum  = 0;
-
-	if(write_record(SREC3_START))			/* write the header */
-		return (-1);
-	do {
-		if(count) {						/* collect hex data in the buffer  */
-			c = *(volatile uchar*)(address + reclen);	/* get one byte    */
-			checksum += c;							/* accumulate checksum */
-			data[2*reclen]   = hex[(c>>4)&0x0f];
-			data[2*reclen+1] = hex[c & 0x0f];
-			data[2*reclen+2] = '\0';
-			++reclen;
-			--count;
-		}
-		if(reclen == SREC_BYTES_PER_RECORD || count == 0) {
-			/* enough data collected for one record: dump it */
-			if(reclen) {	/* build & write a data record: */
-				/* address + data + checksum */
-				length = 4 + reclen + 1;
-
-				/* accumulate length bytes into checksum */
-				for(i = 0; i < 2; i++)
-					checksum += (length >> (8*i)) & 0xff;
-
-				/* accumulate address bytes into checksum: */
-				for(i = 0; i < 4; i++)
-					checksum += (address >> (8*i)) & 0xff;
-
-				/* make proper checksum byte: */
-				checksum = ~checksum & 0xff;
-
-				/* output one record: */
-				sprintf(record, SREC3_FORMAT, length, address, data, checksum);
-				if(write_record(record))
-					return (-1);
-			}
-			address  += reclen;  /* increment address */
-			checksum  = 0;
-			reclen    = 0;
-		}
-	}
-	while(count);
-	if(write_record(SREC3_END))	/* write the final record */
-		return (-1);
-	return(0);
+    int i, c, reclen, checksum, length;
+    char *hex = "0123456789ABCDEF";
+    char    record[2*SREC_BYTES_PER_RECORD+16]; /* buffer for one S-Record  */
+    char    data[2*SREC_BYTES_PER_RECORD+1];    /* buffer for hex data  */
+
+    reclen = 0;
+    checksum  = 0;
+
+    if(write_record(SREC3_START))           /* write the header */
+        return (-1);
+    do {
+        if(count) {                     /* collect hex data in the buffer  */
+            c = *(volatile uchar*)(address + reclen);   /* get one byte    */
+            checksum += c;                          /* accumulate checksum */
+            data[2*reclen]   = hex[(c>>4)&0x0f];
+            data[2*reclen+1] = hex[c & 0x0f];
+            data[2*reclen+2] = '\0';
+            ++reclen;
+            --count;
+        }
+        if(reclen == SREC_BYTES_PER_RECORD || count == 0) {
+            /* enough data collected for one record: dump it */
+            if(reclen) {    /* build & write a data record: */
+                /* address + data + checksum */
+                length = 4 + reclen + 1;
+
+                /* accumulate length bytes into checksum */
+                for(i = 0; i < 2; i++)
+                    checksum += (length >> (8*i)) & 0xff;
+
+                /* accumulate address bytes into checksum: */
+                for(i = 0; i < 4; i++)
+                    checksum += (address >> (8*i)) & 0xff;
+
+                /* make proper checksum byte: */
+                checksum = ~checksum & 0xff;
+
+                /* output one record: */
+                sprintf(record, SREC3_FORMAT, length, address, data, checksum);
+                if(write_record(record))
+                    return (-1);
+            }
+            address  += reclen;  /* increment address */
+            checksum  = 0;
+            reclen    = 0;
+        }
+    }
+    while(count);
+    if(write_record(SREC3_END)) /* write the final record */
+        return (-1);
+    return(0);
 }
 
 static int
 write_record (char *buf)
 {
-	char c;
+    char c;
 
-	while((c = *buf++))
-		putc(c);
+    while((c = *buf++))
+        putc(c);
 
-	/* Check for the console hangup (if any different from serial) */
+    /* Check for the console hangup (if any different from serial) */
 
-	if (ctrlc()) {
-	    return (-1);
-	}
-	return (0);
+    if (ctrlc()) {
+        return (-1);
+    }
+    return (0);
 }
 # endif /* CFG_CMD_SAVES */
 
-#endif	/* CFG_CMD_LOADS */
+#endif  /* CFG_CMD_LOADS */
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_LOADB)  /* loadb command (load binary) included */
@@ -409,7 +411,7 @@
 #define XON_CHAR        17
 #define XOFF_CHAR       19
 #define START_CHAR      0x01
-#define ETX_CHAR	0x03
+#define ETX_CHAR    0x03
 #define END_CHAR        0x0D
 #define SPACE           0x20
 #define K_ESCAPE        0x23
@@ -436,189 +438,198 @@
 
 int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	ulong offset = 0;
-	ulong addr;
-	int load_baudrate, current_baudrate;
-	int rcode = 0;
-	char *s;
-
-	/* pre-set offset from CFG_LOAD_ADDR */
-	offset = CFG_LOAD_ADDR;
-
-	/* pre-set offset from $loadaddr */
-	if ((s = getenv("loadaddr")) != NULL) {
-		offset = simple_strtoul(s, NULL, 16);
-	}
-
-	load_baudrate = current_baudrate = gd->baudrate;
-
-	if (argc >= 2) {
-		offset = simple_strtoul(argv[1], NULL, 16);
-	}
-	if (argc == 3) {
-		load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
-
-		/* default to current baudrate */
-		if (load_baudrate == 0)
-			load_baudrate = current_baudrate;
-	}
-
-	if (load_baudrate != current_baudrate) {
-		printf ("## Switch baudrate to %d bps and press ENTER ...\n",
-			load_baudrate);
-		udelay(50000);
-		gd->baudrate = load_baudrate;
-		serial_setbrg ();
-		udelay(50000);
-		for (;;) {
-			if (getc() == '\r')
-				break;
-		}
-	}
-
-	if (strcmp(argv[0],"loady")==0) {
-		printf ("## Ready for binary (ymodem) download "
-			"to 0x%08lX at %d bps...\n",
-			offset,
-			load_baudrate);
-
-		addr = load_serial_ymodem (offset);
-
-	} else {
-
-		printf ("## Ready for binary (kermit) download "
-			"to 0x%08lX at %d bps...\n",
-			offset,
-			load_baudrate);
-		addr = load_serial_bin (offset);
-
-		if (addr == ~0) {
-			load_addr = 0;
-			printf ("## Binary (kermit) download aborted\n");
-			rcode = 1;
-		} else {
-			printf ("## Start Addr      = 0x%08lX\n", addr);
-			load_addr = addr;
-		}
-	}
-	if (load_baudrate != current_baudrate) {
-		printf ("## Switch baudrate to %d bps and press ESC ...\n",
-			current_baudrate);
-		udelay (50000);
-		gd->baudrate = current_baudrate;
-		serial_setbrg ();
-		udelay (50000);
-		for (;;) {
-			if (getc() == 0x1B) /* ESC */
-				break;
-		}
-	}
+    ulong offset = 0;
+    ulong addr;
+    int load_baudrate, current_baudrate;
+    int rcode = 0;
+    char *s;
+
+    /* pre-set offset from CFG_LOAD_ADDR */
+    offset = CFG_LOAD_ADDR;
+
+    /* pre-set offset from $loadaddr */
+    if ((s = getenv("loadaddr")) != NULL) {
+        offset = simple_strtoul(s, NULL, 16);
+    }
+
+    load_baudrate = current_baudrate = gd->baudrate;
+
+    if (argc >= 2) {
+        offset = simple_strtoul(argv[1], NULL, 16);
+    }
+    if (argc == 3) {
+        load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+
+        /* default to current baudrate */
+        if (load_baudrate == 0)
+            load_baudrate = current_baudrate;
+    }
+
+    if (load_baudrate != current_baudrate) {
+        printf ("## Switch baudrate to %d bps and press ENTER ...\n",
+            load_baudrate);
+        udelay(50000);
+        gd->baudrate = load_baudrate;
+        serial_setbrg ();
+        udelay(50000);
+        for (;;) {
+            if (getc() == '\r')
+                break;
+        }
+    }
+
+    /* support xmodem, www.100ask.net */
+    if (strcmp(argv[0],"loadx")==0) {
+        printf ("## Ready for binary (xmodem) download "
+            "to 0x%08lX at %d bps...\n",
+            offset,
+            load_baudrate);
+
+        addr = load_serial_xmodem (offset);
+
+    } else if (strcmp(argv[0],"loady")==0) {
+        printf ("## Ready for binary (ymodem) download "
+            "to 0x%08lX at %d bps...\n",
+            offset,
+            load_baudrate);
+
+        addr = load_serial_ymodem (offset);
+
+    } else {
+
+        printf ("## Ready for binary (kermit) download "
+            "to 0x%08lX at %d bps...\n",
+            offset,
+            load_baudrate);
+        addr = load_serial_bin (offset);
+
+        if (addr == ~0) {
+            load_addr = 0;
+            printf ("## Binary (kermit) download aborted\n");
+            rcode = 1;
+        } else {
+            printf ("## Start Addr      = 0x%08lX\n", addr);
+            load_addr = addr;
+        }
+    }
+    if (load_baudrate != current_baudrate) {
+        printf ("## Switch baudrate to %d bps and press ESC ...\n",
+            current_baudrate);
+        udelay (50000);
+        gd->baudrate = current_baudrate;
+        serial_setbrg ();
+        udelay (50000);
+        for (;;) {
+            if (getc() == 0x1B) /* ESC */
+                break;
+        }
+    }
 
 #ifdef CONFIG_AUTOSCRIPT
-	if (load_addr) {
-		char *s;
+    if (load_addr) {
+        char *s;
 
-		if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
-			printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
-			rcode = autoscript (load_addr);
-		}
-	}
+        if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
+            printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
+            rcode = autoscript (load_addr);
+        }
+    }
 #endif
-	return rcode;
+    return rcode;
 }
 
 
 static ulong load_serial_bin (ulong offset)
 {
-	int size, i;
-	char buf[32];
+    int size, i;
+    char buf[32];
 
-	set_kerm_bin_mode ((ulong *) offset);
-	size = k_recv ();
+    set_kerm_bin_mode ((ulong *) offset);
+    size = k_recv ();
 
-	/*
-	 * Gather any trailing characters (for instance, the ^D which
-	 * is sent by 'cu' after sending a file), and give the
-	 * box some time (100 * 1 ms)
-	 */
-	for (i=0; i<100; ++i) {
-		if (tstc()) {
-			(void) getc();
-		}
-		udelay(1000);
-	}
-
-	flush_cache (offset, size);
-
-	printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
-	sprintf(buf, "%X", size);
-	setenv("filesize", buf);
+    /*
+     * Gather any trailing characters (for instance, the ^D which
+     * is sent by 'cu' after sending a file), and give the
+     * box some time (100 * 1 ms)
+     */
+    for (i=0; i<100; ++i) {
+        if (tstc()) {
+            (void) getc();
+        }
+        udelay(1000);
+    }
+
+    flush_cache (offset, size);
+
+    printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
+    sprintf(buf, "%X", size);
+    setenv("filesize", buf);
 
-	return offset;
+    return offset;
 }
 
 void send_pad (void)
 {
-	int count = his_pad_count;
+    int count = his_pad_count;
 
-	while (count-- > 0)
-		putc (his_pad_char);
+    while (count-- > 0)
+        putc (his_pad_char);
 }
 
 /* converts escaped kermit char to binary char */
 char ktrans (char in)
 {
-	if ((in & 0x60) == 0x40) {
-		return (char) (in & ~0x40);
-	} else if ((in & 0x7f) == 0x3f) {
-		return (char) (in | 0x40);
-	} else
-		return in;
+    if ((in & 0x60) == 0x40) {
+        return (char) (in & ~0x40);
+    } else if ((in & 0x7f) == 0x3f) {
+        return (char) (in | 0x40);
+    } else
+        return in;
 }
 
 int chk1 (char *buffer)
 {
-	int total = 0;
+    int total = 0;
 
-	while (*buffer) {
-		total += *buffer++;
-	}
-	return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
+    while (*buffer) {
+        total += *buffer++;
+    }
+    return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
 }
 
 void s1_sendpacket (char *packet)
 {
-	send_pad ();
-	while (*packet) {
-		putc (*packet++);
-	}
+    send_pad ();
+    while (*packet) {
+        putc (*packet++);
+    }
 }
 
 static char a_b[24];
 void send_ack (int n)
 {
-	a_b[0] = START_CHAR;
-	a_b[1] = tochar (3);
-	a_b[2] = tochar (n);
-	a_b[3] = ACK_TYPE;
-	a_b[4] = '\0';
-	a_b[4] = tochar (chk1 (&a_b[1]));
-	a_b[5] = his_eol;
-	a_b[6] = '\0';
-	s1_sendpacket (a_b);
+    a_b[0] = START_CHAR;
+    a_b[1] = tochar (3);
+    a_b[2] = tochar (n);
+    a_b[3] = ACK_TYPE;
+    a_b[4] = '\0';
+    a_b[4] = tochar (chk1 (&a_b[1]));
+    a_b[5] = his_eol;
+    a_b[6] = '\0';
+    s1_sendpacket (a_b);
 }
 
 void send_nack (int n)
 {
-	a_b[0] = START_CHAR;
-	a_b[1] = tochar (3);
-	a_b[2] = tochar (n);
-	a_b[3] = NACK_TYPE;
-	a_b[4] = '\0';
-	a_b[4] = tochar (chk1 (&a_b[1]));
-	a_b[5] = his_eol;
-	a_b[6] = '\0';
-	s1_sendpacket (a_b);
+    a_b[0] = START_CHAR;
+    a_b[1] = tochar (3);
+    a_b[2] = tochar (n);
+    a_b[3] = NACK_TYPE;
+    a_b[4] = '\0';
+    a_b[4] = tochar (chk1 (&a_b[1]));
+    a_b[5] = his_eol;
+    a_b[6] = '\0';
+    s1_sendpacket (a_b);
 }
 
 
@@ -637,36 +648,36 @@
 int os_data_header[8];
 static void bin_data_init (void)
 {
-	os_data_state = 0;
-	os_data_count = 0;
-	os_data_addr = bin_start_address;
+    os_data_state = 0;
+    os_data_count = 0;
+    os_data_addr = bin_start_address;
 }
 static void os_data_save (void)
 {
-	os_data_state_saved = os_data_state;
-	os_data_count_saved = os_data_count;
-	os_data_addr_saved = os_data_addr;
+    os_data_state_saved = os_data_state;
+    os_data_count_saved = os_data_count;
+    os_data_addr_saved = os_data_addr;
 }
 static void os_data_restore (void)
 {
-	os_data_state = os_data_state_saved;
-	os_data_count = os_data_count_saved;
-	os_data_addr = os_data_addr_saved;
+    os_data_state = os_data_state_saved;
+    os_data_count = os_data_count_saved;
+    os_data_addr = os_data_addr_saved;
 }
 static void bin_data_char (char new_char)
 {
-	switch (os_data_state) {
-	case 0:					/* data */
-		*os_data_addr++ = new_char;
-		--os_data_count;
-		break;
-	}
+    switch (os_data_state) {
+    case 0:                 /* data */
+        *os_data_addr++ = new_char;
+        --os_data_count;
+        break;
+    }
 }
 static void set_kerm_bin_mode (unsigned long *addr)
 {
-	bin_start_address = (char *) addr;
-	os_data_init = bin_data_init;
-	os_data_char = bin_data_char;
+    bin_start_address = (char *) addr;
+    os_data_init = bin_data_init;
+    os_data_char = bin_data_char;
 }
 
 
@@ -674,34 +685,34 @@
 static int k_data_escape, k_data_escape_saved;
 void k_data_init (void)
 {
-	k_data_escape = 0;
-	os_data_init ();
+    k_data_escape = 0;
+    os_data_init ();
 }
 void k_data_save (void)
 {
-	k_data_escape_saved = k_data_escape;
-	os_data_save ();
+    k_data_escape_saved = k_data_escape;
+    os_data_save ();
 }
 void k_data_restore (void)
 {
-	k_data_escape = k_data_escape_saved;
-	os_data_restore ();
+    k_data_escape = k_data_escape_saved;
+    os_data_restore ();
 }
 void k_data_char (char new_char)
 {
-	if (k_data_escape) {
-		/* last char was escape - translate this character */
-		os_data_char (ktrans (new_char));
-		k_data_escape = 0;
-	} else {
-		if (new_char == his_quote) {
-			/* this char is escape - remember */
-			k_data_escape = 1;
-		} else {
-			/* otherwise send this char as-is */
-			os_data_char (new_char);
-		}
-	}
+    if (k_data_escape) {
+        /* last char was escape - translate this character */
+        os_data_char (ktrans (new_char));
+        k_data_escape = 0;
+    } else {
+        if (new_char == his_quote) {
+            /* this char is escape - remember */
+            k_data_escape = 1;
+        } else {
+            /* otherwise send this char as-is */
+            os_data_char (new_char);
+        }
+    }
 }
 
 #define SEND_DATA_SIZE  20
@@ -712,353 +723,411 @@
    sends an appropriate ack for what we can do */
 void handle_send_packet (int n)
 {
-	int length = 3;
-	int bytes;
+    int length = 3;
+    int bytes;
 
-	/* initialize some protocol parameters */
-	his_eol = END_CHAR;		/* default end of line character */
-	his_pad_count = 0;
-	his_pad_char = '\0';
-	his_quote = K_ESCAPE;
-
-	/* ignore last character if it filled the buffer */
-	if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])
-		--send_ptr;
-	bytes = send_ptr - send_parms;	/* how many bytes we'll process */
-	do {
-		if (bytes-- <= 0)
-			break;
-		/* handle MAXL - max length */
-		/* ignore what he says - most I'll take (here) is 94 */
-		a_b[++length] = tochar (94);
-		if (bytes-- <= 0)
-			break;
-		/* handle TIME - time you should wait for my packets */
-		/* ignore what he says - don't wait for my ack longer than 1 second */
-		a_b[++length] = tochar (1);
-		if (bytes-- <= 0)
-			break;
-		/* handle NPAD - number of pad chars I need */
-		/* remember what he says - I need none */
-		his_pad_count = untochar (send_parms[2]);
-		a_b[++length] = tochar (0);
-		if (bytes-- <= 0)
-			break;
-		/* handle PADC - pad chars I need */
-		/* remember what he says - I need none */
-		his_pad_char = ktrans (send_parms[3]);
-		a_b[++length] = 0x40;	/* He should ignore this */
-		if (bytes-- <= 0)
-			break;
-		/* handle EOL - end of line he needs */
-		/* remember what he says - I need CR */
-		his_eol = untochar (send_parms[4]);
-		a_b[++length] = tochar (END_CHAR);
-		if (bytes-- <= 0)
-			break;
-		/* handle QCTL - quote control char he'll use */
-		/* remember what he says - I'll use '#' */
-		his_quote = send_parms[5];
-		a_b[++length] = '#';
-		if (bytes-- <= 0)
-			break;
-		/* handle QBIN - 8-th bit prefixing */
-		/* ignore what he says - I refuse */
-		a_b[++length] = 'N';
-		if (bytes-- <= 0)
-			break;
-		/* handle CHKT - the clock check type */
-		/* ignore what he says - I do type 1 (for now) */
-		a_b[++length] = '1';
-		if (bytes-- <= 0)
-			break;
-		/* handle REPT - the repeat prefix */
-		/* ignore what he says - I refuse (for now) */
-		a_b[++length] = 'N';
-		if (bytes-- <= 0)
-			break;
-		/* handle CAPAS - the capabilities mask */
-		/* ignore what he says - I only do long packets - I don't do windows */
-		a_b[++length] = tochar (2);	/* only long packets */
-		a_b[++length] = tochar (0);	/* no windows */
-		a_b[++length] = tochar (94);	/* large packet msb */
-		a_b[++length] = tochar (94);	/* large packet lsb */
-	} while (0);
-
-	a_b[0] = START_CHAR;
-	a_b[1] = tochar (length);
-	a_b[2] = tochar (n);
-	a_b[3] = ACK_TYPE;
-	a_b[++length] = '\0';
-	a_b[length] = tochar (chk1 (&a_b[1]));
-	a_b[++length] = his_eol;
-	a_b[++length] = '\0';
-	s1_sendpacket (a_b);
+    /* initialize some protocol parameters */
+    his_eol = END_CHAR;     /* default end of line character */
+    his_pad_count = 0;
+    his_pad_char = '\0';
+    his_quote = K_ESCAPE;
+
+    /* ignore last character if it filled the buffer */
+    if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])
+        --send_ptr;
+    bytes = send_ptr - send_parms;  /* how many bytes we'll process */
+    do {
+        if (bytes-- <= 0)
+            break;
+        /* handle MAXL - max length */
+        /* ignore what he says - most I'll take (here) is 94 */
+        a_b[++length] = tochar (94);
+        if (bytes-- <= 0)
+            break;
+        /* handle TIME - time you should wait for my packets */
+        /* ignore what he says - don't wait for my ack longer than 1 second */
+        a_b[++length] = tochar (1);
+        if (bytes-- <= 0)
+            break;
+        /* handle NPAD - number of pad chars I need */
+        /* remember what he says - I need none */
+        his_pad_count = untochar (send_parms[2]);
+        a_b[++length] = tochar (0);
+        if (bytes-- <= 0)
+            break;
+        /* handle PADC - pad chars I need */
+        /* remember what he says - I need none */
+        his_pad_char = ktrans (send_parms[3]);
+        a_b[++length] = 0x40;   /* He should ignore this */
+        if (bytes-- <= 0)
+            break;
+        /* handle EOL - end of line he needs */
+        /* remember what he says - I need CR */
+        his_eol = untochar (send_parms[4]);
+        a_b[++length] = tochar (END_CHAR);
+        if (bytes-- <= 0)
+            break;
+        /* handle QCTL - quote control char he'll use */
+        /* remember what he says - I'll use '#' */
+        his_quote = send_parms[5];
+        a_b[++length] = '#';
+        if (bytes-- <= 0)
+            break;
+        /* handle QBIN - 8-th bit prefixing */
+        /* ignore what he says - I refuse */
+        a_b[++length] = 'N';
+        if (bytes-- <= 0)
+            break;
+        /* handle CHKT - the clock check type */
+        /* ignore what he says - I do type 1 (for now) */
+        a_b[++length] = '1';
+        if (bytes-- <= 0)
+            break;
+        /* handle REPT - the repeat prefix */
+        /* ignore what he says - I refuse (for now) */
+        a_b[++length] = 'N';
+        if (bytes-- <= 0)
+            break;
+        /* handle CAPAS - the capabilities mask */
+        /* ignore what he says - I only do long packets - I don't do windows */
+        a_b[++length] = tochar (2); /* only long packets */
+        a_b[++length] = tochar (0); /* no windows */
+        a_b[++length] = tochar (94);    /* large packet msb */
+        a_b[++length] = tochar (94);    /* large packet lsb */
+    } while (0);
+
+    a_b[0] = START_CHAR;
+    a_b[1] = tochar (length);
+    a_b[2] = tochar (n);
+    a_b[3] = ACK_TYPE;
+    a_b[++length] = '\0';
+    a_b[length] = tochar (chk1 (&a_b[1]));
+    a_b[++length] = his_eol;
+    a_b[++length] = '\0';
+    s1_sendpacket (a_b);
 }
 
 /* k_recv receives a OS Open image file over kermit line */
 static int k_recv (void)
 {
-	char new_char;
-	char k_state, k_state_saved;
-	int sum;
-	int done;
-	int length;
-	int n, last_n;
-	int z = 0;
-	int len_lo, len_hi;
-
-	/* initialize some protocol parameters */
-	his_eol = END_CHAR;		/* default end of line character */
-	his_pad_count = 0;
-	his_pad_char = '\0';
-	his_quote = K_ESCAPE;
-
-	/* initialize the k_recv and k_data state machine */
-	done = 0;
-	k_state = 0;
-	k_data_init ();
-	k_state_saved = k_state;
-	k_data_save ();
-	n = 0;				/* just to get rid of a warning */
-	last_n = -1;
-
-	/* expect this "type" sequence (but don't check):
-	   S: send initiate
-	   F: file header
-	   D: data (multiple)
-	   Z: end of file
-	   B: break transmission
-	 */
-
-	/* enter main loop */
-	while (!done) {
-		/* set the send packet pointer to begining of send packet parms */
-		send_ptr = send_parms;
-
-		/* With each packet, start summing the bytes starting with the length.
-		   Save the current sequence number.
-		   Note the type of the packet.
-		   If a character less than SPACE (0x20) is received - error.
-		 */
+    char new_char;
+    char k_state, k_state_saved;
+    int sum;
+    int done;
+    int length;
+    int n, last_n;
+    int z = 0;
+    int len_lo, len_hi;
+
+    /* initialize some protocol parameters */
+    his_eol = END_CHAR;     /* default end of line character */
+    his_pad_count = 0;
+    his_pad_char = '\0';
+    his_quote = K_ESCAPE;
+
+    /* initialize the k_recv and k_data state machine */
+    done = 0;
+    k_state = 0;
+    k_data_init ();
+    k_state_saved = k_state;
+    k_data_save ();
+    n = 0;              /* just to get rid of a warning */
+    last_n = -1;
+
+    /* expect this "type" sequence (but don't check):
+       S: send initiate
+       F: file header
+       D: data (multiple)
+       Z: end of file
+       B: break transmission
+     */
+
+    /* enter main loop */
+    while (!done) {
+        /* set the send packet pointer to begining of send packet parms */
+        send_ptr = send_parms;
+
+        /* With each packet, start summing the bytes starting with the length.
+           Save the current sequence number.
+           Note the type of the packet.
+           If a character less than SPACE (0x20) is received - error.
+         */
 
 #if 0
-		/* OLD CODE, Prior to checking sequence numbers */
-		/* first have all state machines save current states */
-		k_state_saved = k_state;
-		k_data_save ();
+        /* OLD CODE, Prior to checking sequence numbers */
+        /* first have all state machines save current states */
+        k_state_saved = k_state;
+        k_data_save ();
 #endif
 
-		/* get a packet */
-		/* wait for the starting character or ^C */
-		for (;;) {
-			switch (getc ()) {
-			case START_CHAR:	/* start packet */
-				goto START;
-			case ETX_CHAR:		/* ^C waiting for packet */
-				return (0);
-			default:
-				;
-			}
-		}
+        /* get a packet */
+        /* wait for the starting character or ^C */
+        for (;;) {
+            switch (getc ()) {
+            case START_CHAR:    /* start packet */
+                goto START;
+            case ETX_CHAR:      /* ^C waiting for packet */
+                return (0);
+            default:
+                ;
+            }
+        }
 START:
-		/* get length of packet */
-		sum = 0;
-		new_char = getc ();
-		if ((new_char & 0xE0) == 0)
-			goto packet_error;
-		sum += new_char & 0xff;
-		length = untochar (new_char);
-		/* get sequence number */
-		new_char = getc ();
-		if ((new_char & 0xE0) == 0)
-			goto packet_error;
-		sum += new_char & 0xff;
-		n = untochar (new_char);
-		--length;
-
-		/* NEW CODE - check sequence numbers for retried packets */
-		/* Note - this new code assumes that the sequence number is correctly
-		 * received.  Handling an invalid sequence number adds another layer
-		 * of complexity that may not be needed - yet!  At this time, I'm hoping
-		 * that I don't need to buffer the incoming data packets and can write
-		 * the data into memory in real time.
-		 */
-		if (n == last_n) {
-			/* same sequence number, restore the previous state */
-			k_state = k_state_saved;
-			k_data_restore ();
-		} else {
-			/* new sequence number, checkpoint the download */
-			last_n = n;
-			k_state_saved = k_state;
-			k_data_save ();
-		}
-		/* END NEW CODE */
-
-		/* get packet type */
-		new_char = getc ();
-		if ((new_char & 0xE0) == 0)
-			goto packet_error;
-		sum += new_char & 0xff;
-		k_state = new_char;
-		--length;
-		/* check for extended length */
-		if (length == -2) {
-			/* (length byte was 0, decremented twice) */
-			/* get the two length bytes */
-			new_char = getc ();
-			if ((new_char & 0xE0) == 0)
-				goto packet_error;
-			sum += new_char & 0xff;
-			len_hi = untochar (new_char);
-			new_char = getc ();
-			if ((new_char & 0xE0) == 0)
-				goto packet_error;
-			sum += new_char & 0xff;
-			len_lo = untochar (new_char);
-			length = len_hi * 95 + len_lo;
-			/* check header checksum */
-			new_char = getc ();
-			if ((new_char & 0xE0) == 0)
-				goto packet_error;
-			if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
-				goto packet_error;
-			sum += new_char & 0xff;
+        /* get length of packet */
+        sum = 0;
+        new_char = getc ();
+        if ((new_char & 0xE0) == 0)
+            goto packet_error;
+        sum += new_char & 0xff;
+        length = untochar (new_char);
+        /* get sequence number */
+        new_char = getc ();
+        if ((new_char & 0xE0) == 0)
+            goto packet_error;
+        sum += new_char & 0xff;
+        n = untochar (new_char);
+        --length;
+
+        /* NEW CODE - check sequence numbers for retried packets */
+        /* Note - this new code assumes that the sequence number is correctly
+         * received.  Handling an invalid sequence number adds another layer
+         * of complexity that may not be needed - yet!  At this time, I'm hoping
+         * that I don't need to buffer the incoming data packets and can write
+         * the data into memory in real time.
+         */
+        if (n == last_n) {
+            /* same sequence number, restore the previous state */
+            k_state = k_state_saved;
+            k_data_restore ();
+        } else {
+            /* new sequence number, checkpoint the download */
+            last_n = n;
+            k_state_saved = k_state;
+            k_data_save ();
+        }
+        /* END NEW CODE */
+
+        /* get packet type */
+        new_char = getc ();
+        if ((new_char & 0xE0) == 0)
+            goto packet_error;
+        sum += new_char & 0xff;
+        k_state = new_char;
+        --length;
+        /* check for extended length */
+        if (length == -2) {
+            /* (length byte was 0, decremented twice) */
+            /* get the two length bytes */
+            new_char = getc ();
+            if ((new_char & 0xE0) == 0)
+                goto packet_error;
+            sum += new_char & 0xff;
+            len_hi = untochar (new_char);
+            new_char = getc ();
+            if ((new_char & 0xE0) == 0)
+                goto packet_error;
+            sum += new_char & 0xff;
+            len_lo = untochar (new_char);
+            length = len_hi * 95 + len_lo;
+            /* check header checksum */
+            new_char = getc ();
+            if ((new_char & 0xE0) == 0)
+                goto packet_error;
+            if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
+                goto packet_error;
+            sum += new_char & 0xff;
 /* --length; */ /* new length includes only data and block check to come */
-		}
-		/* bring in rest of packet */
-		while (length > 1) {
-			new_char = getc ();
-			if ((new_char & 0xE0) == 0)
-				goto packet_error;
-			sum += new_char & 0xff;
-			--length;
-			if (k_state == DATA_TYPE) {
-				/* pass on the data if this is a data packet */
-				k_data_char (new_char);
-			} else if (k_state == SEND_TYPE) {
-				/* save send pack in buffer as is */
-				*send_ptr++ = new_char;
-				/* if too much data, back off the pointer */
-				if (send_ptr >= &send_parms[SEND_DATA_SIZE])
-					--send_ptr;
-			}
-		}
-		/* get and validate checksum character */
-		new_char = getc ();
-		if ((new_char & 0xE0) == 0)
-			goto packet_error;
-		if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
-			goto packet_error;
-		/* get END_CHAR */
-		new_char = getc ();
-		if (new_char != END_CHAR) {
-		  packet_error:
-			/* restore state machines */
-			k_state = k_state_saved;
-			k_data_restore ();
-			/* send a negative acknowledge packet in */
-			send_nack (n);
-		} else if (k_state == SEND_TYPE) {
-			/* crack the protocol parms, build an appropriate ack packet */
-			handle_send_packet (n);
-		} else {
-			/* send simple acknowledge packet in */
-			send_ack (n);
-			/* quit if end of transmission */
-			if (k_state == BREAK_TYPE)
-				done = 1;
-		}
-		++z;
-	}
-	return ((ulong) os_data_addr - (ulong) bin_start_address);
+        }
+        /* bring in rest of packet */
+        while (length > 1) {
+            new_char = getc ();
+            if ((new_char & 0xE0) == 0)
+                goto packet_error;
+            sum += new_char & 0xff;
+            --length;
+            if (k_state == DATA_TYPE) {
+                /* pass on the data if this is a data packet */
+                k_data_char (new_char);
+            } else if (k_state == SEND_TYPE) {
+                /* save send pack in buffer as is */
+                *send_ptr++ = new_char;
+                /* if too much data, back off the pointer */
+                if (send_ptr >= &send_parms[SEND_DATA_SIZE])
+                    --send_ptr;
+            }
+        }
+        /* get and validate checksum character */
+        new_char = getc ();
+        if ((new_char & 0xE0) == 0)
+            goto packet_error;
+        if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
+            goto packet_error;
+        /* get END_CHAR */
+        new_char = getc ();
+        if (new_char != END_CHAR) {
+          packet_error:
+            /* restore state machines */
+            k_state = k_state_saved;
+            k_data_restore ();
+            /* send a negative acknowledge packet in */
+            send_nack (n);
+        } else if (k_state == SEND_TYPE) {
+            /* crack the protocol parms, build an appropriate ack packet */
+            handle_send_packet (n);
+        } else {
+            /* send simple acknowledge packet in */
+            send_ack (n);
+            /* quit if end of transmission */
+            if (k_state == BREAK_TYPE)
+                done = 1;
+        }
+        ++z;
+    }
+    return ((ulong) os_data_addr - (ulong) bin_start_address);
 }
 
 static int getcxmodem(void) {
-	if (tstc())
-		return (getc());
-	return -1;
+    if (tstc())
+        return (getc());
+    return -1;
+}
+
+/* support xmodem, www.100ask.net */
+static ulong load_serial_xmodem (ulong offset)
+{
+    int size;
+    char buf[32];
+    int err;
+    int res;
+    connection_info_t info;
+    char xmodemBuf[1024];
+    ulong store_addr = ~0;
+    ulong addr = 0;
+
+    size = 0;
+    info.mode = xyzModem_xmodem;
+    res = xyzModem_stream_open (&info, &err);
+    if (!res) {
+
+        while ((res =
+            xyzModem_stream_read (xmodemBuf, 1024, &err)) > 0) {
+            store_addr = addr + offset;
+            size += res;
+            addr += res;
+#ifndef CFG_NO_FLASH
+            if (addr2info (store_addr)) {
+                int rc;
+
+                rc = flash_write ((char *) xmodemBuf,
+                          store_addr, res);
+                if (rc != 0) {
+                    flash_perror (rc);
+                    return (~0);
+                }
+            } else
+#endif
+            {
+                memcpy ((char *) (store_addr), xmodemBuf,
+                    res);
+            }
+
+        }
+    } else {
+        printf ("%s\n", xyzModem_error (err));
+    }
+
+    xyzModem_stream_close (&err);
+    xyzModem_stream_terminate (false, &getcxmodem);
+
+
+    flush_cache (offset, size);
+
+    printf ("## Total Size      = 0x%08x = %d Bytes\n", size, size);
+    sprintf (buf, "%X", size);
+    setenv ("filesize", buf);
+
+    return offset;
 }
+
 static ulong load_serial_ymodem (ulong offset)
 {
-	int size;
-	char buf[32];
-	int err;
-	int res;
-	connection_info_t info;
-	char ymodemBuf[1024];
-	ulong store_addr = ~0;
-	ulong addr = 0;
-
-	size = 0;
-	info.mode = xyzModem_ymodem;
-	res = xyzModem_stream_open (&info, &err);
-	if (!res) {
-
-		while ((res =
-			xyzModem_stream_read (ymodemBuf, 1024, &err)) > 0) {
-			store_addr = addr + offset;
-			size += res;
-			addr += res;
+    int size;
+    char buf[32];
+    int err;
+    int res;
+    connection_info_t info;
+    char ymodemBuf[1024];
+    ulong store_addr = ~0;
+    ulong addr = 0;
+
+    size = 0;
+    info.mode = xyzModem_ymodem;
+    res = xyzModem_stream_open (&info, &err);
+    if (!res) {
+
+        while ((res =
+            xyzModem_stream_read (ymodemBuf, 1024, &err)) > 0) {
+            store_addr = addr + offset;
+            size += res;
+            addr += res;
 #ifndef CFG_NO_FLASH
-			if (addr2info (store_addr)) {
-				int rc;
+            if (addr2info (store_addr)) {
+                int rc;
 
-				rc = flash_write ((char *) ymodemBuf,
-						  store_addr, res);
-				if (rc != 0) {
-					flash_perror (rc);
-					return (~0);
-				}
-			} else
+                rc = flash_write ((char *) ymodemBuf,
+                          store_addr, res);
+                if (rc != 0) {
+                    flash_perror (rc);
+                    return (~0);
+                }
+            } else
 #endif
-			{
-				memcpy ((char *) (store_addr), ymodemBuf,
-					res);
-			}
+            {
+                memcpy ((char *) (store_addr), ymodemBuf,
+                    res);
+            }
 
-		}
-	} else {
-		printf ("%s\n", xyzModem_error (err));
-	}
+        }
+    } else {
+        printf ("%s\n", xyzModem_error (err));
+    }
 
-	xyzModem_stream_close (&err);
-	xyzModem_stream_terminate (false, &getcxmodem);
+    xyzModem_stream_close (&err);
+    xyzModem_stream_terminate (false, &getcxmodem);
 
 
-	flush_cache (offset, size);
+    flush_cache (offset, size);
 
-	printf ("## Total Size      = 0x%08x = %d Bytes\n", size, size);
-	sprintf (buf, "%X", size);
-	setenv ("filesize", buf);
+    printf ("## Total Size      = 0x%08x = %d Bytes\n", size, size);
+    sprintf (buf, "%X", size);
+    setenv ("filesize", buf);
 
-	return offset;
+    return offset;
 }
 
-#endif	/* CFG_CMD_LOADB */
+#endif  /* CFG_CMD_LOADB */
 
 /* -------------------------------------------------------------------- */
 
 #if (CONFIG_COMMANDS & CFG_CMD_LOADS)
 
-#ifdef	CFG_LOADS_BAUD_CHANGE
+#ifdef  CFG_LOADS_BAUD_CHANGE
 U_BOOT_CMD(
-	loads, 3, 0,	do_load_serial,
-	"loads   - load S-Record file over serial line\n",
-	"[ off ] [ baud ]\n"
-	"    - load S-Record file over serial line"
-	" with offset 'off' and baudrate 'baud'\n"
+    loads, 3, 0,    do_load_serial,
+    "loads   - load S-Record file over serial line\n",
+    "[ off ] [ baud ]\n"
+    "    - load S-Record file over serial line"
+    " with offset 'off' and baudrate 'baud'\n"
 );
 
-#else	/* ! CFG_LOADS_BAUD_CHANGE */
+#else   /* ! CFG_LOADS_BAUD_CHANGE */
 U_BOOT_CMD(
-	loads, 2, 0,	do_load_serial,
-	"loads   - load S-Record file over serial line\n",
-	"[ off ]\n"
-	"    - load S-Record file over serial line with offset 'off'\n"
+    loads, 2, 0,    do_load_serial,
+    "loads   - load S-Record file over serial line\n",
+    "[ off ]\n"
+    "    - load S-Record file over serial line with offset 'off'\n"
 );
-#endif	/* CFG_LOADS_BAUD_CHANGE */
+#endif  /* CFG_LOADS_BAUD_CHANGE */
 
 /*
  * SAVES always requires LOADS support, but not vice versa
@@ -1066,71 +1135,80 @@
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_SAVES)
-#ifdef	CFG_LOADS_BAUD_CHANGE
+#ifdef  CFG_LOADS_BAUD_CHANGE
 U_BOOT_CMD(
-	saves, 4, 0,	do_save_serial,
-	"saves   - save S-Record file over serial line\n",
-	"[ off ] [size] [ baud ]\n"
-	"    - save S-Record file over serial line"
-	" with offset 'off', size 'size' and baudrate 'baud'\n"
+    saves, 4, 0,    do_save_serial,
+    "saves   - save S-Record file over serial line\n",
+    "[ off ] [size] [ baud ]\n"
+    "    - save S-Record file over serial line"
+    " with offset 'off', size 'size' and baudrate 'baud'\n"
 );
-#else	/* ! CFG_LOADS_BAUD_CHANGE */
+#else   /* ! CFG_LOADS_BAUD_CHANGE */
 U_BOOT_CMD(
-	saves, 3, 0,	do_save_serial,
-	"saves   - save S-Record file over serial line\n",
-	"[ off ] [size]\n"
-	"    - save S-Record file over serial line with offset 'off' and size 'size'\n"
+    saves, 3, 0,    do_save_serial,
+    "saves   - save S-Record file over serial line\n",
+    "[ off ] [size]\n"
+    "    - save S-Record file over serial line with offset 'off' and size 'size'\n"
 );
-#endif	/* CFG_LOADS_BAUD_CHANGE */
-#endif	/* CFG_CMD_SAVES */
-#endif	/* CFG_CMD_LOADS */
+#endif  /* CFG_LOADS_BAUD_CHANGE */
+#endif  /* CFG_CMD_SAVES */
+#endif  /* CFG_CMD_LOADS */
 
 
 #if (CONFIG_COMMANDS & CFG_CMD_LOADB)
 U_BOOT_CMD(
-	loadb, 3, 0,	do_load_serial_bin,
-	"loadb   - load binary file over serial line (kermit mode)\n",
-	"[ off ] [ baud ]\n"
-	"    - load binary file over serial line"
-	" with offset 'off' and baudrate 'baud'\n"
+    loadb, 3, 0,    do_load_serial_bin,
+    "loadb   - load binary file over serial line (kermit mode)\n",
+    "[ off ] [ baud ]\n"
+    "    - load binary file over serial line"
+    " with offset 'off' and baudrate 'baud'\n"
+);
+
+/* support xmodem, www.100ask.net */
+U_BOOT_CMD(
+    loadx, 3, 0,    do_load_serial_bin,
+    "loadx   - load binary file over serial line (xmodem mode)\n",
+    "[ off ] [ baud ]\n"
+    "    - load binary file over serial line"
+    " with offset 'off' and baudrate 'baud'\n"
 );
 
 U_BOOT_CMD(
-	loady, 3, 0,	do_load_serial_bin,
-	"loady   - load binary file over serial line (ymodem mode)\n",
-	"[ off ] [ baud ]\n"
-	"    - load binary file over serial line"
-	" with offset 'off' and baudrate 'baud'\n"
+    loady, 3, 0,    do_load_serial_bin,
+    "loady   - load binary file over serial line (ymodem mode)\n",
+    "[ off ] [ baud ]\n"
+    "    - load binary file over serial line"
+    " with offset 'off' and baudrate 'baud'\n"
 );
 
-#endif	/* CFG_CMD_LOADB */
+#endif  /* CFG_CMD_LOADB */
 
 /* -------------------------------------------------------------------- */
 
 #if (CONFIG_COMMANDS & CFG_CMD_HWFLOW)
 int do_hwflow (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	extern int hwflow_onoff(int);
+    extern int hwflow_onoff(int);
 
-	if (argc == 2) {
-		if (strcmp(argv[1], "off") == 0)
-			hwflow_onoff(-1);
-		else
-			if (strcmp(argv[1], "on") == 0)
-				hwflow_onoff(1);
-			else
-				printf("Usage: %s\n", cmdtp->usage);
-	}
-	printf("RTS/CTS hardware flow control: %s\n", hwflow_onoff(0) ? "on" : "off");
-	return 0;
+    if (argc == 2) {
+        if (strcmp(argv[1], "off") == 0)
+            hwflow_onoff(-1);
+        else
+            if (strcmp(argv[1], "on") == 0)
+                hwflow_onoff(1);
+            else
+                printf("Usage: %s\n", cmdtp->usage);
+    }
+    printf("RTS/CTS hardware flow control: %s\n", hwflow_onoff(0) ? "on" : "off");
+    return 0;
 }
 
 /* -------------------------------------------------------------------- */
 
 U_BOOT_CMD(
-	hwflow, 2, 0,	do_hwflow,
-	"hwflow  - turn the harwdare flow control on/off\n",
-	"[on|off]\n - change RTS/CTS hardware flow control over serial line\n"
+    hwflow, 2, 0,   do_hwflow,
+    "hwflow  - turn the harwdare flow control on/off\n",
+    "[on|off]\n - change RTS/CTS hardware flow control over serial line\n"
 );
 
 #endif /* CFG_CMD_HWFLOW */
diff -urN u-boot-1.1.6/common/cmd_menu.c u-boot-1.1.6_jz2440/common/cmd_menu.c
--- u-boot-1.1.6/common/cmd_menu.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/common/cmd_menu.c	2010-11-26 12:54:38.158053077 +0800
@@ -0,0 +1,310 @@
+/*
+ * thisway.diy@163.com, www.100ask.net
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <def.h>
+#include <nand.h>
+
+extern char console_buffer[];
+extern int readline (const char *const prompt);
+extern char awaitkey(unsigned long delay, int* error_p);
+extern void download_nkbin_to_flash(void);
+
+/**
+ * Parses a string into a number.  The number stored at ptr is
+ * potentially suffixed with K (for kilobytes, or 1024 bytes),
+ * M (for megabytes, or 1048576 bytes), or G (for gigabytes, or
+ * 1073741824).  If the number is suffixed with K, M, or G, then
+ * the return value is the number multiplied by one kilobyte, one
+ * megabyte, or one gigabyte, respectively.
+ *
+ * @param ptr where parse begins
+ * @param retptr output pointer to next char after parse completes (output)
+ * @return resulting unsigned int
+ */
+static unsigned long memsize_parse2 (const char *const ptr, const char **retptr)
+{
+	unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
+    int sixteen = 1;
+
+	switch (**retptr) {
+		case 'G':
+		case 'g':
+			ret <<= 10;
+		case 'M':
+		case 'm':
+			ret <<= 10;
+		case 'K':
+		case 'k':
+			ret <<= 10;
+			(*retptr)++;
+            sixteen = 0;
+		default:
+			break;
+	}
+
+    if (sixteen)
+        return simple_strtoul(ptr, NULL, 16);
+    
+	return ret;
+}
+
+
+void param_menu_usage()
+{
+    printf("\r\n##### Parameter Menu #####\r\n");
+    printf("[v] View the parameters\r\n");
+    printf("[s] Set parameter \r\n");
+    printf("[d] Delete parameter \r\n");
+    printf("[w] Write the parameters to flash memeory \r\n");
+    printf("[q] Quit \r\n");
+    printf("Enter your selection: ");
+}
+
+
+void param_menu_shell(void)
+{
+    char c;
+    char cmd_buf[256];
+    char name_buf[20];
+    char val_buf[256];
+    
+    while (1)
+    {
+        param_menu_usage();
+        c = awaitkey(-1, NULL);
+        printf("%c\n", c);
+        switch (c)
+        {
+            case 'v':
+            {
+                strcpy(cmd_buf, "printenv ");
+                printf("Name(enter to view all paramters): ");
+                readline(NULL);
+                strcat(cmd_buf, console_buffer);
+                run_command(cmd_buf, 0);
+                break;
+            }
+            
+            case 's':
+            {
+                sprintf(cmd_buf, "setenv ");
+
+                printf("Name: ");
+                readline(NULL);
+                strcat(cmd_buf, console_buffer);
+
+                printf("Value: ");
+                readline(NULL);
+                strcat(cmd_buf, " ");
+                strcat(cmd_buf, console_buffer);
+
+                run_command(cmd_buf, 0);
+                break;
+            }
+            
+            case 'd':
+            {
+                sprintf(cmd_buf, "setenv ");
+
+                printf("Name: ");
+                readline(NULL);
+                strcat(cmd_buf, console_buffer);
+
+                run_command(cmd_buf, 0);
+                break;
+            }
+            
+            case 'w':
+            {
+                sprintf(cmd_buf, "saveenv");
+                run_command(cmd_buf, 0);
+                break;
+            }
+            
+            case 'q':
+            {
+                return;
+                break;
+            }
+        }
+    }
+}
+
+
+void main_menu_usage(void)
+{
+    printf("\r\n##### 100ask Bootloader for OpenJTAG #####\r\n");
+
+    printf("[n] Download u-boot to Nand Flash\r\n");
+	if (bBootFrmNORFlash())
+	    printf("[o] Download u-boot to Nor Flash\r\n");
+    printf("[k] Download Linux kernel uImage\r\n");
+    printf("[j] Download root_jffs2 image\r\n");
+//    printf("[c] Download root_cramfs image\r\n");
+    printf("[y] Download root_yaffs image\r\n");
+    printf("[d] Download to SDRAM & Run\r\n");
+    printf("[z] Download zImage into RAM\r\n");
+    printf("[g] Boot linux from RAM\r\n");
+    printf("[f] Format the Nand Flash\r\n");
+    printf("[s] Set the boot parameters\r\n");
+    printf("[b] Boot the system\r\n");
+    printf("[r] Reboot u-boot\r\n");
+    printf("[q] Quit from menu\r\n");
+    printf("Enter your selection: ");
+}
+
+
+void menu_shell(void)
+{
+    char c;
+    char cmd_buf[200];
+    char *p = NULL;
+    unsigned long size;
+    unsigned long offset;
+    struct mtd_info *mtd = &nand_info[nand_curr_device];
+
+    while (1)
+    {
+        main_menu_usage();
+        c = awaitkey(-1, NULL);
+        printf("%c\n", c);
+        switch (c)
+        {
+			case 'n':
+			{
+                strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase bootloader; nand write.jffs2 0x30000000 bootloader $(filesize)");
+                run_command(cmd_buf, 0);
+                break;
+			}
+            case 'o':
+            {
+                if (bBootFrmNORFlash())
+                {
+                    strcpy(cmd_buf, "usbslave 1 0x30000000; protect off all; erase 0 +$(filesize); cp.b 0x30000000 0 $(filesize)");
+                    run_command(cmd_buf, 0);
+                }
+				break;
+            }
+            
+            case 'k':
+            {
+                strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase kernel; nand write.jffs2 0x30000000 kernel $(filesize)");
+                run_command(cmd_buf, 0);
+                break;
+            }
+
+            case 'j':
+            {
+                strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase root; nand write.jffs2 0x30000000 root $(filesize)");
+                run_command(cmd_buf, 0);
+                break;
+            }
+#if 0
+            case 'c':
+            {
+                strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase root; nand write.jffs2 0x30000000 root $(filesize)");
+                run_command(cmd_buf, 0);
+                break;
+            }
+#endif
+            case 'y':
+            {
+                strcpy(cmd_buf, "usbslave 1 0x30000000; nand erase root; nand write.yaffs 0x30000000 root $(filesize)");
+                run_command(cmd_buf, 0);
+                break;
+            }
+
+            case 'd':
+            {
+                extern volatile U32 downloadAddress;
+                extern int download_run;
+                
+                download_run = 1;
+                strcpy(cmd_buf, "usbslave 1");
+                run_command(cmd_buf, 0);
+                download_run = 0;
+                sprintf(cmd_buf, "go %x", downloadAddress);
+                run_command(cmd_buf, 0);
+                break;
+            }
+
+			case 'z':
+			{
+				strcpy(cmd_buf, "usbslave 1 0x30008000");
+				run_command(cmd_buf, 0);
+				break;
+			}
+
+			case 'g':
+			{
+				extern void do_bootm_rawLinux (ulong addr);
+				do_bootm_rawLinux(0x30008000);
+			}
+
+            case 'b':
+            {
+                printf("Booting Linux ...\n");
+                strcpy(cmd_buf, "nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0");
+                run_command(cmd_buf, 0);
+                break;
+            }
+
+            case 'f':
+            {
+                strcpy(cmd_buf, "nand erase ");
+
+                printf("Start address: ");
+                readline(NULL);
+                strcat(cmd_buf, console_buffer);
+
+                printf("Size(eg. 4000000, 0x4000000, 64m and so on): ");
+                readline(NULL);
+                p = console_buffer;
+                size = memsize_parse2(p, &p);
+                sprintf(console_buffer, " %x", size);
+                strcat(cmd_buf, console_buffer);
+
+                run_command(cmd_buf, 0);
+                break;
+            }
+
+            case 's':
+            {
+                param_menu_shell();
+                break;
+            }
+
+            case 'r':
+            {
+				strcpy(cmd_buf, "reset");
+				run_command(cmd_buf, 0);
+                break;
+            }
+            
+            case 'q':
+            {
+                return;    
+                break;
+            }
+
+        }
+                
+    }
+}
+
+int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    menu_shell();
+    return 0;
+}
+
+U_BOOT_CMD(
+	menu,	3,	0,	do_menu,
+	"menu - display a menu, to select the items to do something\n",
+	" - display a menu, to select the items to do something"
+);
+
diff -urN u-boot-1.1.6/common/cmd_nand.c u-boot-1.1.6_jz2440/common/cmd_nand.c
--- u-boot-1.1.6/common/cmd_nand.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/common/cmd_nand.c	2010-11-26 12:54:38.154066984 +0800
@@ -28,7 +28,7 @@
 
 #ifdef CONFIG_SHOW_BOOT_PROGRESS
 # include <status_led.h>
-# define SHOW_BOOT_PROGRESS(arg)	show_boot_progress(arg)
+# define SHOW_BOOT_PROGRESS(arg)    show_boot_progress(arg)
 #else
 # define SHOW_BOOT_PROGRESS(arg)
 #endif
@@ -42,572 +42,635 @@
 int mtdparts_init(void);
 int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
 int find_dev_and_part(const char *id, struct mtd_device **dev,
-		u8 *part_num, struct part_info **part);
+        u8 *part_num, struct part_info **part);
 #endif
 
 extern nand_info_t nand_info[];       /* info for NAND chips */
 
 static int nand_dump_oob(nand_info_t *nand, ulong off)
 {
-	return 0;
+    return 0;
 }
 
 static int nand_dump(nand_info_t *nand, ulong off)
 {
-	int i;
-	u_char *buf, *p;
+    int i;
+    u_char *buf, *p;
 
-	buf = malloc(nand->oobblock + nand->oobsize);
-	if (!buf) {
-		puts("No memory for page buffer\n");
-		return 1;
-	}
-	off &= ~(nand->oobblock - 1);
-	i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
-	if (i < 0) {
-		printf("Error (%d) reading page %08x\n", i, off);
-		free(buf);
-		return 1;
-	}
-	printf("Page %08x dump:\n", off);
-	i = nand->oobblock >> 4; p = buf;
-	while (i--) {
-		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
-			"  %02x %02x %02x %02x %02x %02x %02x %02x\n",
-			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
-			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
-		p += 16;
-	}
-	puts("OOB:\n");
-	i = nand->oobsize >> 3;
-	while (i--) {
-		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
-			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-		p += 8;
-	}
-	free(buf);
+    buf = malloc(nand->oobblock + nand->oobsize);
+    if (!buf) {
+        puts("No memory for page buffer\n");
+        return 1;
+    }
+    off &= ~(nand->oobblock - 1);
+    i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
+    if (i < 0) {
+        printf("Error (%d) reading page %08x\n", i, off);
+        free(buf);
+        return 1;
+    }
+    printf("Page %08x dump:\n", off);
+    i = nand->oobblock >> 4; p = buf;
+    while (i--) {
+        printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
+            "  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+            p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+            p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
+        p += 16;
+    }
+    puts("OOB:\n");
+    i = nand->oobsize >> 3;
+    while (i--) {
+        printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+            p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+        p += 8;
+    }
+    free(buf);
 
-	return 0;
+    return 0;
 }
 
 /* ------------------------------------------------------------------------- */
 
 static inline int str2long(char *p, ulong *num)
 {
-	char *endptr;
+    char *endptr;
 
-	*num = simple_strtoul(p, &endptr, 16);
-	return (*p != '\0' && *endptr == '\0') ? 1 : 0;
+    *num = simple_strtoul(p, &endptr, 16);
+    return (*p != '\0' && *endptr == '\0') ? 1 : 0;
 }
 
 static int
 arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, ulong *size)
 {
-	int idx = nand_curr_device;
+    int idx = nand_curr_device;
 #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
-	struct mtd_device *dev;
-	struct part_info *part;
-	u8 pnum;
-
-	if (argc >= 1 && !(str2long(argv[0], off))) {
-		if ((mtdparts_init() == 0) &&
-		    (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {
-			if (dev->id->type != MTD_DEV_TYPE_NAND) {
-				puts("not a NAND device\n");
-				return -1;
-			}
-			*off = part->offset;
-			if (argc >= 2) {
-				if (!(str2long(argv[1], size))) {
-					printf("'%s' is not a number\n", argv[1]);
-					return -1;
-				}
-				if (*size > part->size)
-					*size = part->size;
-			} else {
-				*size = part->size;
-			}
-			idx = dev->id->num;
-			*nand = nand_info[idx];
-			goto out;
-		}
-	}
-#endif
-
-	if (argc >= 1) {
-		if (!(str2long(argv[0], off))) {
-			printf("'%s' is not a number\n", argv[0]);
-			return -1;
-		}
-	} else {
-		*off = 0;
-	}
-
-	if (argc >= 2) {
-		if (!(str2long(argv[1], size))) {
-			printf("'%s' is not a number\n", argv[1]);
-			return -1;
-		}
-	} else {
-		*size = nand->size - *off;
-	}
+    struct mtd_device *dev;
+    struct part_info *part;
+    u8 pnum;
+
+    if (argc >= 1 && !(str2long(argv[0], off))) {
+        if ((mtdparts_init() == 0) &&
+            (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {
+            if (dev->id->type != MTD_DEV_TYPE_NAND) {
+                puts("not a NAND device\n");
+                return -1;
+            }
+            *off = part->offset;
+            if (argc >= 2) {
+                if (!(str2long(argv[1], size))) {
+                    printf("'%s' is not a number\n", argv[1]);
+                    return -1;
+                }
+                if (*size > part->size)
+                    *size = part->size;
+            } else {
+                *size = part->size;
+            }
+            idx = dev->id->num;
+            *nand = nand_info[idx];
+            goto out;
+        }
+    }
+#endif
+
+    if (argc >= 1) {
+        if (!(str2long(argv[0], off))) {
+            printf("'%s' is not a number\n", argv[0]);
+            return -1;
+        }
+    } else {
+        *off = 0;
+    }
+
+    if (argc >= 2) {
+        if (!(str2long(argv[1], size))) {
+            printf("'%s' is not a number\n", argv[1]);
+            return -1;
+        }
+    } else {
+        *size = nand->size - *off;
+    }
 
 #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
 out:
 #endif
-	printf("device %d ", idx);
-	if (*size == nand->size)
-		puts("whole chip\n");
-	else
-		printf("offset 0x%x, size 0x%x\n", *off, *size);
-	return 0;
+    printf("device %d ", idx);
+    if (*size == nand->size)
+        puts("whole chip\n");
+    else
+        printf("offset 0x%x, size 0x%x\n", *off, *size);
+    return 0;
 }
 
 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
-	int i, dev, ret;
-	ulong addr, off, size;
-	char *cmd, *s;
-	nand_info_t *nand;
-	int quiet = 0;
-	const char *quiet_str = getenv("quiet");
-
-	/* at least two arguments please */
-	if (argc < 2)
-		goto usage;
-
-	if (quiet_str)
-		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
-
-	cmd = argv[1];
-
-	if (strcmp(cmd, "info") == 0) {
-
-		putc('\n');
-		for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
-			if (nand_info[i].name)
-				printf("Device %d: %s, sector size %lu KiB\n",
-					i, nand_info[i].name,
-					nand_info[i].erasesize >> 10);
-		}
-		return 0;
-	}
-
-	if (strcmp(cmd, "device") == 0) {
-
-		if (argc < 3) {
-			if ((nand_curr_device < 0) ||
-			    (nand_curr_device >= CFG_MAX_NAND_DEVICE))
-				puts("\nno devices available\n");
-			else
-				printf("\nDevice %d: %s\n", nand_curr_device,
-					nand_info[nand_curr_device].name);
-			return 0;
-		}
-		dev = (int)simple_strtoul(argv[2], NULL, 10);
-		if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
-			puts("No such device\n");
-			return 1;
-		}
-		printf("Device %d: %s", dev, nand_info[dev].name);
-		puts("... is now current device\n");
-		nand_curr_device = dev;
+    int i, dev, ret;
+    ulong addr, off, size;
+    char *cmd, *s;
+    nand_info_t *nand;
+    int quiet = 0;
+    const char *quiet_str = getenv("quiet");
+
+    /* at least two arguments please */
+    if (argc < 2)
+        goto usage;
+
+    if (quiet_str)
+        quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
+
+    cmd = argv[1];
+
+    if (strcmp(cmd, "info") == 0) {
+
+        putc('\n');
+        for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
+            if (nand_info[i].name)
+                printf("Device %d: %s, sector size %lu KiB\n",
+                    i, nand_info[i].name,
+                    nand_info[i].erasesize >> 10);
+        }
+        return 0;
+    }
+
+    if (strcmp(cmd, "device") == 0) {
+
+        if (argc < 3) {
+            if ((nand_curr_device < 0) ||
+                (nand_curr_device >= CFG_MAX_NAND_DEVICE))
+                puts("\nno devices available\n");
+            else
+                printf("\nDevice %d: %s\n", nand_curr_device,
+                    nand_info[nand_curr_device].name);
+            return 0;
+        }
+        dev = (int)simple_strtoul(argv[2], NULL, 10);
+        if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
+            puts("No such device\n");
+            return 1;
+        }
+        printf("Device %d: %s", dev, nand_info[dev].name);
+        puts("... is now current device\n");
+        nand_curr_device = dev;
 
 #ifdef CFG_NAND_SELECT_DEVICE
-		/*
-		 * Select the chip in the board/cpu specific driver
-		 */
-		board_nand_select_device(nand_info[dev].priv, dev);
-#endif
-
-		return 0;
-	}
-
-	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
-	    strncmp(cmd, "dump", 4) != 0 &&
-	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
-	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
-	    strcmp(cmd, "biterr") != 0 &&
-	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
-		goto usage;
-
-	/* the following commands operate on the current device */
-	if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
-	    !nand_info[nand_curr_device].name) {
-		puts("\nno devices available\n");
-		return 1;
-	}
-	nand = &nand_info[nand_curr_device];
-
-	if (strcmp(cmd, "bad") == 0) {
-		printf("\nDevice %d bad blocks:\n", nand_curr_device);
-		for (off = 0; off < nand->size; off += nand->erasesize)
-			if (nand_block_isbad(nand, off))
-				printf("  %08x\n", off);
-		return 0;
-	}
-
-	/*
-	 * Syntax is:
-	 *   0    1     2       3    4
-	 *   nand erase [clean] [off size]
-	 */
-	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
-		nand_erase_options_t opts;
-		/* "clean" at index 2 means request to write cleanmarker */
-		int clean = argc > 2 && !strcmp("clean", argv[2]);
-		int o = clean ? 3 : 2;
-		int scrub = !strcmp(cmd, "scrub");
-
-		printf("\nNAND %s: ", scrub ? "scrub" : "erase");
-		/* skip first two or three arguments, look for offset and size */
-		if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
-			return 1;
-
-		memset(&opts, 0, sizeof(opts));
-		opts.offset = off;
-		opts.length = size;
-		opts.jffs2  = clean;
-		opts.quiet  = quiet;
-
-		if (scrub) {
-			puts("Warning: "
-			     "scrub option will erase all factory set "
-			     "bad blocks!\n"
-			     "         "
-			     "There is no reliable way to recover them.\n"
-			     "         "
-			     "Use this command only for testing purposes "
-			     "if you\n"
-			     "         "
-			     "are sure of what you are doing!\n"
-			     "\nReally scrub this NAND flash? <y/N>\n");
-
-			if (getc() == 'y' && getc() == '\r') {
-				opts.scrub = 1;
-			} else {
-				puts("scrub aborted\n");
-				return -1;
-			}
-		}
-		ret = nand_erase_opts(nand, &opts);
-		printf("%s\n", ret ? "ERROR" : "OK");
-
-		return ret == 0 ? 0 : 1;
-	}
-
-	if (strncmp(cmd, "dump", 4) == 0) {
-		if (argc < 3)
-			goto usage;
-
-		s = strchr(cmd, '.');
-		off = (int)simple_strtoul(argv[2], NULL, 16);
-
-		if (s != NULL && strcmp(s, ".oob") == 0)
-			ret = nand_dump_oob(nand, off);
-		else
-			ret = nand_dump(nand, off);
-
-		return ret == 0 ? 1 : 0;
-
-	}
-
-	/* read write */
-	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
-		int read;
-
-		if (argc < 4)
-			goto usage;
-
-		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
-
-		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
-		printf("\nNAND %s: ", read ? "read" : "write");
-		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
-			return 1;
-
-		s = strchr(cmd, '.');
-		if (s != NULL &&
-		    (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
-			if (read) {
-				/* read */
-				nand_read_options_t opts;
-				memset(&opts, 0, sizeof(opts));
-				opts.buffer	= (u_char*) addr;
-				opts.length	= size;
-				opts.offset	= off;
-				opts.quiet      = quiet;
-				ret = nand_read_opts(nand, &opts);
-			} else {
-				/* write */
-				nand_write_options_t opts;
-				memset(&opts, 0, sizeof(opts));
-				opts.buffer	= (u_char*) addr;
-				opts.length	= size;
-				opts.offset	= off;
-				/* opts.forcejffs2 = 1; */
-				opts.pad	= 1;
-				opts.blockalign = 1;
-				opts.quiet      = quiet;
-				ret = nand_write_opts(nand, &opts);
-			}
-		} else {
-			if (read)
-				ret = nand_read(nand, off, &size, (u_char *)addr);
-			else
-				ret = nand_write(nand, off, &size, (u_char *)addr);
-		}
-
-		printf(" %d bytes %s: %s\n", size,
-		       read ? "read" : "written", ret ? "ERROR" : "OK");
-
-		return ret == 0 ? 0 : 1;
-	}
-
-	if (strcmp(cmd, "markbad") == 0) {
-		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
-
-		int ret = nand->block_markbad(nand, addr);
-		if (ret == 0) {
-			printf("block 0x%08lx successfully marked as bad\n",
-			       (ulong) addr);
-			return 0;
-		} else {
-			printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
-			       (ulong) addr, ret);
-		}
-		return 1;
-	}
-	if (strcmp(cmd, "biterr") == 0) {
-		/* todo */
-		return 1;
-	}
-
-	if (strcmp(cmd, "lock") == 0) {
-		int tight  = 0;
-		int status = 0;
-		if (argc == 3) {
-			if (!strcmp("tight", argv[2]))
-				tight = 1;
-			if (!strcmp("status", argv[2]))
-				status = 1;
-		}
-
-		if (status) {
-			ulong block_start = 0;
-			ulong off;
-			int last_status = -1;
-
-			struct nand_chip *nand_chip = nand->priv;
-			/* check the WP bit */
-			nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1);
-			printf("device is %swrite protected\n",
-			       (nand_chip->read_byte(nand) & 0x80 ?
-				"NOT " : "" ) );
-
-			for (off = 0; off < nand->size; off += nand->oobblock) {
-				int s = nand_get_lock_status(nand, off);
-
-				/* print message only if status has changed
-				 * or at end of chip
-				 */
-				if (off == nand->size - nand->oobblock
-				    || (s != last_status && off != 0))	{
-
-					printf("%08x - %08x: %8d pages %s%s%s\n",
-					       block_start,
-					       off-1,
-					       (off-block_start)/nand->oobblock,
-					       ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
-					       ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
-					       ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
-				}
-
-				last_status = s;
-		       }
-		} else {
-			if (!nand_lock(nand, tight)) {
-				puts("NAND flash successfully locked\n");
-			} else {
-				puts("Error locking NAND flash\n");
-				return 1;
-			}
-		}
-		return 0;
-	}
-
-	if (strcmp(cmd, "unlock") == 0) {
-		if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
-			return 1;
-
-		if (!nand_unlock(nand, off, size)) {
-			puts("NAND flash successfully unlocked\n");
-		} else {
-			puts("Error unlocking NAND flash, "
-			     "write and erase will probably fail\n");
-			return 1;
-		}
-		return 0;
-	}
+        /*
+         * Select the chip in the board/cpu specific driver
+         */
+        board_nand_select_device(nand_info[dev].priv, dev);
+#endif
+
+        return 0;
+    }
+
+    if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
+        strncmp(cmd, "dump", 4) != 0 &&
+        strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
+        strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
+        strcmp(cmd, "biterr") != 0 &&
+        strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
+        goto usage;
+
+    /* the following commands operate on the current device */
+    if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
+        !nand_info[nand_curr_device].name) {
+        puts("\nno devices available\n");
+        return 1;
+    }
+    nand = &nand_info[nand_curr_device];
+
+    if (strcmp(cmd, "bad") == 0) {
+        printf("\nDevice %d bad blocks:\n", nand_curr_device);
+        for (off = 0; off < nand->size; off += nand->erasesize)
+            if (nand_block_isbad(nand, off))
+                printf("  %08x\n", off);
+        return 0;
+    }
+
+    /*
+     * Syntax is:
+     *   0    1     2       3    4
+     *   nand erase [clean] [off size]
+     */
+    if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
+        nand_erase_options_t opts;
+        /* "clean" at index 2 means request to write cleanmarker */
+        int clean = argc > 2 && !strcmp("clean", argv[2]);
+        int o = clean ? 3 : 2;
+        int scrub = !strcmp(cmd, "scrub");
+
+        printf("\nNAND %s: ", scrub ? "scrub" : "erase");
+        /* skip first two or three arguments, look for offset and size */
+        if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
+            return 1;
+
+        memset(&opts, 0, sizeof(opts));
+        opts.offset = off;
+        opts.length = size;
+        opts.jffs2  = clean;
+        opts.quiet  = quiet;
+
+        if (scrub) {
+            puts("Warning: "
+                 "scrub option will erase all factory set "
+                 "bad blocks!\n"
+                 "         "
+                 "There is no reliable way to recover them.\n"
+                 "         "
+                 "Use this command only for testing purposes "
+                 "if you\n"
+                 "         "
+                 "are sure of what you are doing!\n"
+                 "\nReally scrub this NAND flash? <y/N>\n");
+
+            if (getc() == 'y' && getc() == '\r') {
+                opts.scrub = 1;
+            } else {
+                puts("scrub aborted\n");
+                return -1;
+            }
+        }
+        ret = nand_erase_opts(nand, &opts);
+        printf("%s\n", ret ? "ERROR" : "OK");
+
+        return ret == 0 ? 0 : 1;
+    }
+
+    if (strncmp(cmd, "dump", 4) == 0) {
+        if (argc < 3)
+            goto usage;
+
+        s = strchr(cmd, '.');
+        off = (int)simple_strtoul(argv[2], NULL, 16);
+
+        if (s != NULL && strcmp(s, ".oob") == 0)
+            ret = nand_dump_oob(nand, off);
+        else
+            ret = nand_dump(nand, off);
+
+        return ret == 0 ? 1 : 0;
+
+    }
+
+    /* read write */
+    if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+        int read;
+
+        if (argc < 4)
+            goto usage;
+
+        addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+
+        read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
+        printf("\nNAND %s: ", read ? "read" : "write");
+        if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
+            return 1;
+
+        s = strchr(cmd, '.');
+        if (s != NULL &&
+            (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
+            if (read) {
+                /* read */
+                nand_read_options_t opts;
+                memset(&opts, 0, sizeof(opts));
+                opts.buffer = (u_char*) addr;
+                opts.length = size;
+                opts.offset = off;
+                opts.quiet      = quiet;
+                ret = nand_read_opts(nand, &opts);
+            } else {
+                /* write */
+                nand_write_options_t opts;
+                memset(&opts, 0, sizeof(opts));
+                opts.buffer = (u_char*) addr;
+                opts.length = size;
+                opts.offset = off;
+                /* opts.forcejffs2 = 1; */
+                opts.pad    = 1;
+                opts.blockalign = 1;
+                opts.quiet      = quiet;
+                ret = nand_write_opts(nand, &opts);
+            }
+        }else if (  s != NULL && !strcmp(s, ".yaffs")){
+            if (read) {
+                /* read */
+                nand_read_options_t opts;
+                memset(&opts, 0, sizeof(opts));
+                opts.buffer = (u_char*) addr;
+                opts.length = size;
+                opts.offset = off;
+                opts.readoob = 1;
+                opts.quiet      = quiet;
+                ret = nand_read_opts(nand, &opts);
+            } else {
+                /* write */
+                nand_write_options_t opts;
+                memset(&opts, 0, sizeof(opts));
+                opts.buffer = (u_char*) addr;
+                opts.length = size;
+                opts.offset = off;
+                /* opts.forceyaffs = 1; */
+                opts.noecc = 1;
+                opts.writeoob = 1;
+                opts.blockalign = 1;
+                opts.quiet      = quiet;
+                opts.skipfirstblk = 1;
+                ret = nand_write_opts(nand, &opts);
+            }
+        }else if (  s != NULL && !strcmp(s, ".raw")){
+            if (read) {
+                /* read */
+                nand_read_options_t opts;
+                memset(&opts, 0, sizeof(opts));
+                opts.buffer = (u_char*) addr;
+                opts.length = size;
+                opts.offset = off;
+                opts.readoob = 0;
+                opts.quiet      = quiet;
+                opts.noecc  = 1;
+                opts.nocheckbadblk = 1;
+                ret = nand_read_opts(nand, &opts);
+            } else {
+                /* write */
+                nand_write_options_t opts;
+                memset(&opts, 0, sizeof(opts));
+                opts.buffer = (u_char*) addr;
+                opts.length = size;
+                opts.offset = off;
+                /* opts.forceyaffs = 1; */
+                opts.noecc = 1;
+                opts.writeoob = 0;
+                opts.blockalign = 1;
+                opts.quiet      = quiet;
+                opts.skipfirstblk = 0;
+                opts.nocheckbadblk = 1;
+                ret = nand_write_opts(nand, &opts);
+            }
+        }        else {
+            if (read)
+                ret = nand_read(nand, off, &size, (u_char *)addr);
+            else
+                ret = nand_write(nand, off, &size, (u_char *)addr);
+        }
+
+        printf(" %d bytes %s: %s\n", size,
+               read ? "read" : "written", ret ? "ERROR" : "OK");
+
+        return ret == 0 ? 0 : 1;
+    }
+
+    if (strcmp(cmd, "markbad") == 0) {
+        addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+
+        int ret = nand->block_markbad(nand, addr);
+        if (ret == 0) {
+            printf("block 0x%08lx successfully marked as bad\n",
+                   (ulong) addr);
+            return 0;
+        } else {
+            printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
+                   (ulong) addr, ret);
+        }
+        return 1;
+    }
+    if (strcmp(cmd, "biterr") == 0) {
+        /* todo */
+        return 1;
+    }
+
+    if (strcmp(cmd, "lock") == 0) {
+        int tight  = 0;
+        int status = 0;
+        if (argc == 3) {
+            if (!strcmp("tight", argv[2]))
+                tight = 1;
+            if (!strcmp("status", argv[2]))
+                status = 1;
+        }
+
+        if (status) {
+            ulong block_start = 0;
+            ulong off;
+            int last_status = -1;
+
+            struct nand_chip *nand_chip = nand->priv;
+            /* check the WP bit */
+            nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1);
+            printf("device is %swrite protected\n",
+                   (nand_chip->read_byte(nand) & 0x80 ?
+                "NOT " : "" ) );
+
+            for (off = 0; off < nand->size; off += nand->oobblock) {
+                int s = nand_get_lock_status(nand, off);
+
+                /* print message only if status has changed
+                 * or at end of chip
+                 */
+                if (off == nand->size - nand->oobblock
+                    || (s != last_status && off != 0))  {
+
+                    printf("%08x - %08x: %8d pages %s%s%s\n",
+                           block_start,
+                           off-1,
+                           (off-block_start)/nand->oobblock,
+                           ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
+                           ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
+                           ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
+                }
+
+                last_status = s;
+               }
+        } else {
+            if (!nand_lock(nand, tight)) {
+                puts("NAND flash successfully locked\n");
+            } else {
+                puts("Error locking NAND flash\n");
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    if (strcmp(cmd, "unlock") == 0) {
+        if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
+            return 1;
+
+        if (!nand_unlock(nand, off, size)) {
+            puts("NAND flash successfully unlocked\n");
+        } else {
+            puts("Error unlocking NAND flash, "
+                 "write and erase will probably fail\n");
+            return 1;
+        }
+        return 0;
+    }
 
 usage:
-	printf("Usage:\n%s\n", cmdtp->usage);
-	return 1;
+    printf("Usage:\n%s\n", cmdtp->usage);
+    return 1;
 }
 
 U_BOOT_CMD(nand, 5, 1, do_nand,
-	"nand    - NAND sub-system\n",
-	"info                  - show available NAND devices\n"
-	"nand device [dev]     - show or set current device\n"
-	"nand read[.jffs2]     - addr off|partition size\n"
-	"nand write[.jffs2]    - addr off|partiton size - read/write `size' bytes starting\n"
-	"    at offset `off' to/from memory address `addr'\n"
-	"nand erase [clean] [off size] - erase `size' bytes from\n"
-	"    offset `off' (entire device if not specified)\n"
-	"nand bad - show bad blocks\n"
-	"nand dump[.oob] off - dump page\n"
-	"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
-	"nand markbad off - mark bad block at offset (UNSAFE)\n"
-	"nand biterr off - make a bit error at offset (UNSAFE)\n"
-	"nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
-	"nand unlock [offset] [size] - unlock section\n");
+    "nand    - NAND sub-system\n",
+    "info                  - show available NAND devices\n"
+    "nand device [dev]     - show or set current device\n"
+    "nand read[.jffs2]     - addr off|partition size\n"
+    "nand write[.jffs2]    - addr off|partiton size - read/write `size' bytes starting\n"
+    "    at offset `off' to/from memory address `addr'\n"
+    "nand read.yaffs addr off size - read the `size' byte yaffs image starting\n"
+    "    at offset `off' to memory address `addr'\n"
+    "nand write.yaffs addr off size - write the `size' byte yaffs image starting\n"
+    "    at offset `off' from memory address `addr'\n"
+    "nand read.raw addr off size - read the `size' bytes starting\n"
+    "    at offset `off' to memory address `addr', without oob and ecc\n"
+    "nand write.raw addr off size - write the `size' bytes starting\n"
+    "    at offset `off' from memory address `addr', without oob and ecc\n"
+    "nand erase [clean] [off size] - erase `size' bytes from\n"
+    "    offset `off' (entire device if not specified)\n"
+    "nand bad - show bad blocks\n"
+    "nand dump[.oob] off - dump page\n"
+    "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
+    "nand markbad off - mark bad block at offset (UNSAFE)\n"
+    "nand biterr off - make a bit error at offset (UNSAFE)\n"
+    "nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
+    "nand unlock [offset] [size] - unlock section\n");
 
 static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
-			   ulong offset, ulong addr, char *cmd)
+               ulong offset, ulong addr, char *cmd)
 {
-	int r;
-	char *ep;
-	ulong cnt;
-	image_header_t *hdr;
-
-	printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
-
-	cnt = nand->oobblock;
-	r = nand_read(nand, offset, &cnt, (u_char *) addr);
-	if (r) {
-		puts("** Read error\n");
-		SHOW_BOOT_PROGRESS(-1);
-		return 1;
-	}
-
-	hdr = (image_header_t *) addr;
-
-	if (ntohl(hdr->ih_magic) != IH_MAGIC) {
-		printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
-		SHOW_BOOT_PROGRESS(-1);
-		return 1;
-	}
-
-	print_image_hdr(hdr);
-
-	cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
-
-	r = nand_read(nand, offset, &cnt, (u_char *) addr);
-	if (r) {
-		puts("** Read error\n");
-		SHOW_BOOT_PROGRESS(-1);
-		return 1;
-	}
-
-	/* Loading ok, update default load address */
-
-	load_addr = addr;
-
-	/* Check if we should attempt an auto-start */
-	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
-		char *local_args[2];
-		extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
-
-		local_args[0] = cmd;
-		local_args[1] = NULL;
-
-		printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
-
-		do_bootm(cmdtp, 0, 1, local_args);
-		return 1;
-	}
-	return 0;
+    int r;
+    char *ep;
+    ulong cnt;
+    image_header_t *hdr;
+
+    printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
+
+    cnt = nand->oobblock;
+    r = nand_read(nand, offset, &cnt, (u_char *) addr);
+    if (r) {
+        puts("** Read error\n");
+        SHOW_BOOT_PROGRESS(-1);
+        return 1;
+    }
+
+    hdr = (image_header_t *) addr;
+
+    if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+        printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
+        SHOW_BOOT_PROGRESS(-1);
+        return 1;
+    }
+
+    print_image_hdr(hdr);
+
+    cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
+
+    r = nand_read(nand, offset, &cnt, (u_char *) addr);
+    if (r) {
+        puts("** Read error\n");
+        SHOW_BOOT_PROGRESS(-1);
+        return 1;
+    }
+
+    /* Loading ok, update default load address */
+
+    load_addr = addr;
+
+    /* Check if we should attempt an auto-start */
+    if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
+        char *local_args[2];
+        extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
+
+        local_args[0] = cmd;
+        local_args[1] = NULL;
+
+        printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+        do_bootm(cmdtp, 0, 1, local_args);
+        return 1;
+    }
+    return 0;
 }
 
 int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
-	char *boot_device = NULL;
-	int idx;
-	ulong addr, offset = 0;
+    char *boot_device = NULL;
+    int idx;
+    ulong addr, offset = 0;
 #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
-	struct mtd_device *dev;
-	struct part_info *part;
-	u8 pnum;
-
-	if (argc >= 2) {
-		char *p = (argc == 2) ? argv[1] : argv[2];
-		if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
-		    (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
-			if (dev->id->type != MTD_DEV_TYPE_NAND) {
-				puts("Not a NAND device\n");
-				return 1;
-			}
-			if (argc > 3)
-				goto usage;
-			if (argc == 3)
-				addr = simple_strtoul(argv[2], NULL, 16);
-			else
-				addr = CFG_LOAD_ADDR;
-			return nand_load_image(cmdtp, &nand_info[dev->id->num],
-					       part->offset, addr, argv[0]);
-		}
-	}
-#endif
-
-	switch (argc) {
-	case 1:
-		addr = CFG_LOAD_ADDR;
-		boot_device = getenv("bootdevice");
-		break;
-	case 2:
-		addr = simple_strtoul(argv[1], NULL, 16);
-		boot_device = getenv("bootdevice");
-		break;
-	case 3:
-		addr = simple_strtoul(argv[1], NULL, 16);
-		boot_device = argv[2];
-		break;
-	case 4:
-		addr = simple_strtoul(argv[1], NULL, 16);
-		boot_device = argv[2];
-		offset = simple_strtoul(argv[3], NULL, 16);
-		break;
-	default:
+    struct mtd_device *dev;
+    struct part_info *part;
+    u8 pnum;
+
+    if (argc >= 2) {
+        char *p = (argc == 2) ? argv[1] : argv[2];
+        if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
+            (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
+            if (dev->id->type != MTD_DEV_TYPE_NAND) {
+                puts("Not a NAND device\n");
+                return 1;
+            }
+            if (argc > 3)
+                goto usage;
+            if (argc == 3)
+                addr = simple_strtoul(argv[1], NULL, 16);
+            else
+                addr = CFG_LOAD_ADDR;
+            return nand_load_image(cmdtp, &nand_info[dev->id->num],
+                           part->offset, addr, argv[0]);
+        }
+    }
+#endif
+
+    switch (argc) {
+    case 1:
+        addr = CFG_LOAD_ADDR;
+        boot_device = getenv("bootdevice");
+        break;
+    case 2:
+        addr = simple_strtoul(argv[1], NULL, 16);
+        boot_device = getenv("bootdevice");
+        break;
+    case 3:
+        addr = simple_strtoul(argv[1], NULL, 16);
+        boot_device = argv[2];
+        break;
+    case 4:
+        addr = simple_strtoul(argv[1], NULL, 16);
+        boot_device = argv[2];
+        offset = simple_strtoul(argv[3], NULL, 16);
+        break;
+    default:
 #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
 usage:
 #endif
-		printf("Usage:\n%s\n", cmdtp->usage);
-		SHOW_BOOT_PROGRESS(-1);
-		return 1;
-	}
-
-	if (!boot_device) {
-		puts("\n** No boot device **\n");
-		SHOW_BOOT_PROGRESS(-1);
-		return 1;
-	}
-
-	idx = simple_strtoul(boot_device, NULL, 16);
-
-	if (idx < 0 || idx >= CFG_MAX_NAND_DEVICE || !nand_info[idx].name) {
-		printf("\n** Device %d not available\n", idx);
-		SHOW_BOOT_PROGRESS(-1);
-		return 1;
-	}
+        printf("Usage:\n%s\n", cmdtp->usage);
+        SHOW_BOOT_PROGRESS(-1);
+        return 1;
+    }
+
+    if (!boot_device) {
+        puts("\n** No boot device **\n");
+        SHOW_BOOT_PROGRESS(-1);
+        return 1;
+    }
+
+    idx = simple_strtoul(boot_device, NULL, 16);
+
+    if (idx < 0 || idx >= CFG_MAX_NAND_DEVICE || !nand_info[idx].name) {
+        printf("\n** Device %d not available\n", idx);
+        SHOW_BOOT_PROGRESS(-1);
+        return 1;
+    }
 
-	return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
+    return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
 }
 
 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
-	"nboot   - boot from NAND device\n",
-	"[partition] | [[[loadAddr] dev] offset]\n");
+    "nboot   - boot from NAND device\n",
+    "[[loadAddr] partition] | [[[loadAddr] dev] offset]\n");
 
-#endif				/* (CONFIG_COMMANDS & CFG_CMD_NAND) */
+#endif              /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
 
 #else /* CFG_NAND_LEGACY */
 /*
@@ -622,7 +685,7 @@
 
 #ifdef CONFIG_SHOW_BOOT_PROGRESS
 # include <status_led.h>
-# define SHOW_BOOT_PROGRESS(arg)	show_boot_progress(arg)
+# define SHOW_BOOT_PROGRESS(arg)    show_boot_progress(arg)
 #else
 # define SHOW_BOOT_PROGRESS(arg)
 #endif
@@ -640,8 +703,8 @@
 
 #define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))
 
-#undef	NAND_DEBUG
-#undef	PSYCHO_DEBUG
+#undef  NAND_DEBUG
+#undef  PSYCHO_DEBUG
 
 /* ****************** WARNING *********************
  * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
@@ -656,16 +719,16 @@
  * and attempting to program or erase bad blocks can affect
  * the data in _other_ (good) blocks.
  */
-#define	 ALLOW_ERASE_BAD_DEBUG 0
+#define  ALLOW_ERASE_BAD_DEBUG 0
 
 #define CONFIG_MTD_NAND_ECC  /* enable ECC */
 #define CONFIG_MTD_NAND_ECC_JFFS2
 
 /* bits for nand_legacy_rw() `cmd'; or together as needed */
-#define NANDRW_READ	0x01
-#define NANDRW_WRITE	0x00
-#define NANDRW_JFFS2	0x02
-#define NANDRW_JFFS2_SKIP	0x04
+#define NANDRW_READ 0x01
+#define NANDRW_WRITE    0x00
+#define NANDRW_JFFS2    0x02
+#define NANDRW_JFFS2_SKIP   0x04
 
 /*
  * Imports from nand_legacy.c
@@ -673,15 +736,15 @@
 extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
 extern int curr_device;
 extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
-			    size_t len, int clean);
+                size_t len, int clean);
 extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
-			 size_t len, size_t *retlen, u_char *buf);
+             size_t len, size_t *retlen, u_char *buf);
 extern void nand_print(struct nand_chip *nand);
 extern void nand_print_bad(struct nand_chip *nand);
 extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
-			       size_t len, size_t *retlen, u_char *buf);
+                   size_t len, size_t *retlen, u_char *buf);
 extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
-				size_t len, size_t *retlen, const u_char *buf);
+                size_t len, size_t *retlen, const u_char *buf);
 
 
 int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
@@ -691,294 +754,294 @@
     switch (argc) {
     case 0:
     case 1:
-	printf ("Usage:\n%s\n", cmdtp->usage);
-	return 1;
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return 1;
     case 2:
-	if (strcmp(argv[1],"info") == 0) {
-		int i;
+    if (strcmp(argv[1],"info") == 0) {
+        int i;
 
-		putc ('\n');
+        putc ('\n');
 
-		for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
-			if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
-				continue; /* list only known devices */
-			printf ("Device %d: ", i);
-			nand_print(&nand_dev_desc[i]);
-		}
-		return 0;
-
-	} else if (strcmp(argv[1],"device") == 0) {
-		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
-			puts ("\nno devices available\n");
-			return 1;
-		}
-		printf ("\nDevice %d: ", curr_device);
-		nand_print(&nand_dev_desc[curr_device]);
-		return 0;
-
-	} else if (strcmp(argv[1],"bad") == 0) {
-		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
-			puts ("\nno devices available\n");
-			return 1;
-		}
-		printf ("\nDevice %d bad blocks:\n", curr_device);
-		nand_print_bad(&nand_dev_desc[curr_device]);
-		return 0;
-
-	}
-	printf ("Usage:\n%s\n", cmdtp->usage);
-	return 1;
-    case 3:
-	if (strcmp(argv[1],"device") == 0) {
-		int dev = (int)simple_strtoul(argv[2], NULL, 10);
+        for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
+            if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
+                continue; /* list only known devices */
+            printf ("Device %d: ", i);
+            nand_print(&nand_dev_desc[i]);
+        }
+        return 0;
+
+    } else if (strcmp(argv[1],"device") == 0) {
+        if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+            puts ("\nno devices available\n");
+            return 1;
+        }
+        printf ("\nDevice %d: ", curr_device);
+        nand_print(&nand_dev_desc[curr_device]);
+        return 0;
+
+    } else if (strcmp(argv[1],"bad") == 0) {
+        if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+            puts ("\nno devices available\n");
+            return 1;
+        }
+        printf ("\nDevice %d bad blocks:\n", curr_device);
+        nand_print_bad(&nand_dev_desc[curr_device]);
+        return 0;
 
-		printf ("\nDevice %d: ", dev);
-		if (dev >= CFG_MAX_NAND_DEVICE) {
-			puts ("unknown device\n");
-			return 1;
-		}
-		nand_print(&nand_dev_desc[dev]);
-		/*nand_print (dev);*/
+    }
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return 1;
+    case 3:
+    if (strcmp(argv[1],"device") == 0) {
+        int dev = (int)simple_strtoul(argv[2], NULL, 10);
 
-		if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
-			return 1;
-		}
+        printf ("\nDevice %d: ", dev);
+        if (dev >= CFG_MAX_NAND_DEVICE) {
+            puts ("unknown device\n");
+            return 1;
+        }
+        nand_print(&nand_dev_desc[dev]);
+        /*nand_print (dev);*/
+
+        if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
+            return 1;
+        }
 
-		curr_device = dev;
+        curr_device = dev;
 
-		puts ("... is now current device\n");
+        puts ("... is now current device\n");
 
-		return 0;
-	}
-	else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
-		struct nand_chip* nand = &nand_dev_desc[curr_device];
-		ulong off = 0;
-		ulong size = nand->totlen;
-		int ret;
+        return 0;
+    }
+    else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
+        struct nand_chip* nand = &nand_dev_desc[curr_device];
+        ulong off = 0;
+        ulong size = nand->totlen;
+        int ret;
 
-		printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
-			curr_device, off, size);
+        printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
+            curr_device, off, size);
 
-		ret = nand_legacy_erase (nand, off, size, 1);
+        ret = nand_legacy_erase (nand, off, size, 1);
 
-		printf("%s\n", ret ? "ERROR" : "OK");
+        printf("%s\n", ret ? "ERROR" : "OK");
 
-		return ret;
-	}
+        return ret;
+    }
 
-	printf ("Usage:\n%s\n", cmdtp->usage);
-	return 1;
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return 1;
     default:
-	/* at least 4 args */
+    /* at least 4 args */
 
-	if (strncmp(argv[1], "read", 4) == 0 ||
-	    strncmp(argv[1], "write", 5) == 0) {
-		ulong addr = simple_strtoul(argv[2], NULL, 16);
-		ulong off  = simple_strtoul(argv[3], NULL, 16);
-		ulong size = simple_strtoul(argv[4], NULL, 16);
-		int cmd    = (strncmp(argv[1], "read", 4) == 0) ?
-				NANDRW_READ : NANDRW_WRITE;
-		int ret, total;
-		char* cmdtail = strchr(argv[1], '.');
-
-		if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
-			/* read out-of-band data */
-			if (cmd & NANDRW_READ) {
-				ret = nand_read_oob(nand_dev_desc + curr_device,
-						    off, size, (size_t *)&total,
-						    (u_char*)addr);
-			}
-			else {
-				ret = nand_write_oob(nand_dev_desc + curr_device,
-						     off, size, (size_t *)&total,
-						     (u_char*)addr);
-			}
-			return ret;
-		}
-		else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
-			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
-		else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
-			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
-			if (cmd & NANDRW_READ)
-				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
-		}
+    if (strncmp(argv[1], "read", 4) == 0 ||
+        strncmp(argv[1], "write", 5) == 0) {
+        ulong addr = simple_strtoul(argv[2], NULL, 16);
+        ulong off  = simple_strtoul(argv[3], NULL, 16);
+        ulong size = simple_strtoul(argv[4], NULL, 16);
+        int cmd    = (strncmp(argv[1], "read", 4) == 0) ?
+                NANDRW_READ : NANDRW_WRITE;
+        int ret, total;
+        char* cmdtail = strchr(argv[1], '.');
+
+        if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
+            /* read out-of-band data */
+            if (cmd & NANDRW_READ) {
+                ret = nand_read_oob(nand_dev_desc + curr_device,
+                            off, size, (size_t *)&total,
+                            (u_char*)addr);
+            }
+            else {
+                ret = nand_write_oob(nand_dev_desc + curr_device,
+                             off, size, (size_t *)&total,
+                             (u_char*)addr);
+            }
+            return ret;
+        }
+        else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
+            cmd |= NANDRW_JFFS2;    /* skip bad blocks */
+        else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
+            cmd |= NANDRW_JFFS2;    /* skip bad blocks (on read too) */
+            if (cmd & NANDRW_READ)
+                cmd |= NANDRW_JFFS2_SKIP;   /* skip bad blocks (on read too) */
+        }
 #ifdef SXNI855T
-		/* need ".e" same as ".j" for compatibility with older units */
-		else if (cmdtail && !strcmp(cmdtail, ".e"))
-			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
+        /* need ".e" same as ".j" for compatibility with older units */
+        else if (cmdtail && !strcmp(cmdtail, ".e"))
+            cmd |= NANDRW_JFFS2;    /* skip bad blocks */
 #endif
 #ifdef CFG_NAND_SKIP_BAD_DOT_I
-		/* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
-		/* ".i" for image -> read skips bad block (no 0xff) */
-		else if (cmdtail && !strcmp(cmdtail, ".i")) {
-			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
-			if (cmd & NANDRW_READ)
-				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
-		}
+        /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
+        /* ".i" for image -> read skips bad block (no 0xff) */
+        else if (cmdtail && !strcmp(cmdtail, ".i")) {
+            cmd |= NANDRW_JFFS2;    /* skip bad blocks (on read too) */
+            if (cmd & NANDRW_READ)
+                cmd |= NANDRW_JFFS2_SKIP;   /* skip bad blocks (on read too) */
+        }
 #endif /* CFG_NAND_SKIP_BAD_DOT_I */
-		else if (cmdtail) {
-			printf ("Usage:\n%s\n", cmdtp->usage);
-			return 1;
-		}
-
-		printf ("\nNAND %s: device %d offset %ld, size %ld ...\n",
-			(cmd & NANDRW_READ) ? "read" : "write",
-			curr_device, off, size);
-
-		ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,
-			     (size_t *)&total, (u_char*)addr);
-
-		printf (" %d bytes %s: %s\n", total,
-			(cmd & NANDRW_READ) ? "read" : "written",
-			ret ? "ERROR" : "OK");
-
-		return ret;
-	} else if (strcmp(argv[1],"erase") == 0 &&
-		   (argc == 4 || strcmp("clean", argv[2]) == 0)) {
-		int clean = argc == 5;
-		ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
-		ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
-		int ret;
-
-		printf ("\nNAND erase: device %d offset %ld, size %ld ...\n",
-			curr_device, off, size);
-
-		ret = nand_legacy_erase (nand_dev_desc + curr_device,
-					off, size, clean);
-
-		printf("%s\n", ret ? "ERROR" : "OK");
-
-		return ret;
-	} else {
-		printf ("Usage:\n%s\n", cmdtp->usage);
-		rcode = 1;
-	}
+        else if (cmdtail) {
+            printf ("Usage:\n%s\n", cmdtp->usage);
+            return 1;
+        }
+
+        printf ("\nNAND %s: device %d offset %ld, size %ld ...\n",
+            (cmd & NANDRW_READ) ? "read" : "write",
+            curr_device, off, size);
+
+        ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,
+                 (size_t *)&total, (u_char*)addr);
+
+        printf (" %d bytes %s: %s\n", total,
+            (cmd & NANDRW_READ) ? "read" : "written",
+            ret ? "ERROR" : "OK");
+
+        return ret;
+    } else if (strcmp(argv[1],"erase") == 0 &&
+           (argc == 4 || strcmp("clean", argv[2]) == 0)) {
+        int clean = argc == 5;
+        ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
+        ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
+        int ret;
+
+        printf ("\nNAND erase: device %d offset %ld, size %ld ...\n",
+            curr_device, off, size);
+
+        ret = nand_legacy_erase (nand_dev_desc + curr_device,
+                    off, size, clean);
+
+        printf("%s\n", ret ? "ERROR" : "OK");
+
+        return ret;
+    } else {
+        printf ("Usage:\n%s\n", cmdtp->usage);
+        rcode = 1;
+    }
 
-	return rcode;
+    return rcode;
     }
 }
 
 U_BOOT_CMD(
-	nand,	5,	1,	do_nand,
-	"nand    - legacy NAND sub-system\n",
-	"info  - show available NAND devices\n"
-	"nand device [dev] - show or set current device\n"
-	"nand read[.jffs2[s]]  addr off size\n"
-	"nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
-	"    at offset `off' to/from memory address `addr'\n"
-	"nand erase [clean] [off size] - erase `size' bytes from\n"
-	"    offset `off' (entire device if not specified)\n"
-	"nand bad - show bad blocks\n"
-	"nand read.oob addr off size - read out-of-band data\n"
-	"nand write.oob addr off size - read out-of-band data\n"
+    nand,   5,  1,  do_nand,
+    "nand    - legacy NAND sub-system\n",
+    "info  - show available NAND devices\n"
+    "nand device [dev] - show or set current device\n"
+    "nand read[.jffs2[s]]  addr off size\n"
+    "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
+    "    at offset `off' to/from memory address `addr'\n"
+    "nand erase [clean] [off size] - erase `size' bytes from\n"
+    "    offset `off' (entire device if not specified)\n"
+    "nand bad - show bad blocks\n"
+    "nand read.oob addr off size - read out-of-band data\n"
+    "nand write.oob addr off size - read out-of-band data\n"
 );
 
 int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
-	char *boot_device = NULL;
-	char *ep;
-	int dev;
-	ulong cnt;
-	ulong addr;
-	ulong offset = 0;
-	image_header_t *hdr;
-	int rcode = 0;
-	switch (argc) {
-	case 1:
-		addr = CFG_LOAD_ADDR;
-		boot_device = getenv ("bootdevice");
-		break;
-	case 2:
-		addr = simple_strtoul(argv[1], NULL, 16);
-		boot_device = getenv ("bootdevice");
-		break;
-	case 3:
-		addr = simple_strtoul(argv[1], NULL, 16);
-		boot_device = argv[2];
-		break;
-	case 4:
-		addr = simple_strtoul(argv[1], NULL, 16);
-		boot_device = argv[2];
-		offset = simple_strtoul(argv[3], NULL, 16);
-		break;
-	default:
-		printf ("Usage:\n%s\n", cmdtp->usage);
-		SHOW_BOOT_PROGRESS (-1);
-		return 1;
-	}
-
-	if (!boot_device) {
-		puts ("\n** No boot device **\n");
-		SHOW_BOOT_PROGRESS (-1);
-		return 1;
-	}
-
-	dev = simple_strtoul(boot_device, &ep, 16);
-
-	if ((dev >= CFG_MAX_NAND_DEVICE) ||
-	    (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
-		printf ("\n** Device %d not available\n", dev);
-		SHOW_BOOT_PROGRESS (-1);
-		return 1;
-	}
-
-	printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
-		dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
-		offset);
-
-	if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
-			SECTORSIZE, NULL, (u_char *)addr)) {
-		printf ("** Read error on %d\n", dev);
-		SHOW_BOOT_PROGRESS (-1);
-		return 1;
-	}
-
-	hdr = (image_header_t *)addr;
-
-	if (ntohl(hdr->ih_magic) == IH_MAGIC) {
-
-		print_image_hdr (hdr);
-
-		cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
-		cnt -= SECTORSIZE;
-	} else {
-		printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));
-		SHOW_BOOT_PROGRESS (-1);
-		return 1;
-	}
-
-	if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
-			offset + SECTORSIZE, cnt, NULL,
-			(u_char *)(addr+SECTORSIZE))) {
-		printf ("** Read error on %d\n", dev);
-		SHOW_BOOT_PROGRESS (-1);
-		return 1;
-	}
-
-	/* Loading ok, update default load address */
-
-	load_addr = addr;
-
-	/* Check if we should attempt an auto-start */
-	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
-		char *local_args[2];
-		extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
-
-		local_args[0] = argv[0];
-		local_args[1] = NULL;
-
-		printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
-
-		do_bootm (cmdtp, 0, 1, local_args);
-		rcode = 1;
-	}
-	return rcode;
+    char *boot_device = NULL;
+    char *ep;
+    int dev;
+    ulong cnt;
+    ulong addr;
+    ulong offset = 0;
+    image_header_t *hdr;
+    int rcode = 0;
+    switch (argc) {
+    case 1:
+        addr = CFG_LOAD_ADDR;
+        boot_device = getenv ("bootdevice");
+        break;
+    case 2:
+        addr = simple_strtoul(argv[1], NULL, 16);
+        boot_device = getenv ("bootdevice");
+        break;
+    case 3:
+        addr = simple_strtoul(argv[1], NULL, 16);
+        boot_device = argv[2];
+        break;
+    case 4:
+        addr = simple_strtoul(argv[1], NULL, 16);
+        boot_device = argv[2];
+        offset = simple_strtoul(argv[3], NULL, 16);
+        break;
+    default:
+        printf ("Usage:\n%s\n", cmdtp->usage);
+        SHOW_BOOT_PROGRESS (-1);
+        return 1;
+    }
+
+    if (!boot_device) {
+        puts ("\n** No boot device **\n");
+        SHOW_BOOT_PROGRESS (-1);
+        return 1;
+    }
+
+    dev = simple_strtoul(boot_device, &ep, 16);
+
+    if ((dev >= CFG_MAX_NAND_DEVICE) ||
+        (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
+        printf ("\n** Device %d not available\n", dev);
+        SHOW_BOOT_PROGRESS (-1);
+        return 1;
+    }
+
+    printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
+        dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
+        offset);
+
+    if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
+            SECTORSIZE, NULL, (u_char *)addr)) {
+        printf ("** Read error on %d\n", dev);
+        SHOW_BOOT_PROGRESS (-1);
+        return 1;
+    }
+
+    hdr = (image_header_t *)addr;
+
+    if (ntohl(hdr->ih_magic) == IH_MAGIC) {
+
+        print_image_hdr (hdr);
+
+        cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
+        cnt -= SECTORSIZE;
+    } else {
+        printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));
+        SHOW_BOOT_PROGRESS (-1);
+        return 1;
+    }
+
+    if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
+            offset + SECTORSIZE, cnt, NULL,
+            (u_char *)(addr+SECTORSIZE))) {
+        printf ("** Read error on %d\n", dev);
+        SHOW_BOOT_PROGRESS (-1);
+        return 1;
+    }
+
+    /* Loading ok, update default load address */
+
+    load_addr = addr;
+
+    /* Check if we should attempt an auto-start */
+    if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
+        char *local_args[2];
+        extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+        local_args[0] = argv[0];
+        local_args[1] = NULL;
+
+        printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+        do_bootm (cmdtp, 0, 1, local_args);
+        rcode = 1;
+    }
+    return rcode;
 }
 
 U_BOOT_CMD(
-	nboot,	4,	1,	do_nandboot,
-	"nboot   - boot from NAND device\n",
-	"loadAddr dev\n"
+    nboot,  4,  1,  do_nandboot,
+    "nboot   - boot from NAND device\n",
+    "loadAddr dev\n"
 );
 
 #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
diff -urN u-boot-1.1.6/common/cmd_nand_legacy.c u-boot-1.1.6_jz2440/common/cmd_nand_legacy.c
--- u-boot-1.1.6/common/cmd_nand_legacy.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/common/cmd_nand_legacy.c	2010-11-26 12:54:38.130318758 +0800
@@ -0,0 +1,999 @@
+/*
+ * Driver for NAND support, Rick Bronson
+ * borrowed heavily from:
+ * (c) 1999 Machine Vision Holdings, Inc.
+ * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
+ *
+ * Added 16-bit nand support
+ * (C) 2004 Texas Instruments
+ */
+
+#include <common.h>
+
+
+#ifndef CFG_NAND_LEGACY
+/*
+ *
+ * New NAND support
+ *
+ */
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+
+#include <command.h>
+#include <watchdog.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)	show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#include <jffs2/jffs2.h>
+#include <nand.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+
+/* parition handling routines */
+int mtdparts_init(void);
+int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+		u8 *part_num, struct part_info **part);
+#endif
+
+extern nand_info_t nand_info[];       /* info for NAND chips */
+
+static int nand_dump_oob(nand_info_t *nand, ulong off)
+{
+	return 0;
+}
+
+static int nand_dump(nand_info_t *nand, ulong off)
+{
+	int i;
+	u_char *buf, *p;
+
+	buf = malloc(nand->oobblock + nand->oobsize);
+	if (!buf) {
+		puts("No memory for page buffer\n");
+		return 1;
+	}
+	off &= ~(nand->oobblock - 1);
+	i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
+	if (i < 0) {
+		printf("Error (%d) reading page %08x\n", i, off);
+		free(buf);
+		return 1;
+	}
+	printf("Page %08x dump:\n", off);
+	i = nand->oobblock >> 4; p = buf;
+	while (i--) {
+		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
+			"  %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+			p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
+		p += 16;
+	}
+	puts("OOB:\n");
+	i = nand->oobsize >> 3;
+	while (i--) {
+		printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
+			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+		p += 8;
+	}
+	free(buf);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static inline int str2long(char *p, ulong *num)
+{
+	char *endptr;
+
+	*num = simple_strtoul(p, &endptr, 16);
+	return (*p != '\0' && *endptr == '\0') ? 1 : 0;
+}
+
+static int
+arg_off_size(int argc, char *argv[], nand_info_t *nand, ulong *off, ulong *size)
+{
+	int idx = nand_curr_device;
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+	struct mtd_device *dev;
+	struct part_info *part;
+	u8 pnum;
+
+	if (argc >= 1 && !(str2long(argv[0], off))) {
+		if ((mtdparts_init() == 0) &&
+		    (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {
+			if (dev->id->type != MTD_DEV_TYPE_NAND) {
+				puts("not a NAND device\n");
+				return -1;
+			}
+			*off = part->offset;
+			if (argc >= 2) {
+				if (!(str2long(argv[1], size))) {
+					printf("'%s' is not a number\n", argv[1]);
+					return -1;
+				}
+				if (*size > part->size)
+					*size = part->size;
+			} else {
+				*size = part->size;
+			}
+			idx = dev->id->num;
+			*nand = nand_info[idx];
+			goto out;
+		}
+	}
+#endif
+
+	if (argc >= 1) {
+		if (!(str2long(argv[0], off))) {
+			printf("'%s' is not a number\n", argv[0]);
+			return -1;
+		}
+	} else {
+		*off = 0;
+	}
+
+	if (argc >= 2) {
+		if (!(str2long(argv[1], size))) {
+			printf("'%s' is not a number\n", argv[1]);
+			return -1;
+		}
+	} else {
+		*size = nand->size - *off;
+	}
+
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+out:
+#endif
+	printf("device %d ", idx);
+	if (*size == nand->size)
+		puts("whole chip\n");
+	else
+		printf("offset 0x%x, size 0x%x\n", *off, *size);
+	return 0;
+}
+
+int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	int i, dev, ret;
+	ulong addr, off, size;
+	char *cmd, *s;
+	nand_info_t *nand;
+	int quiet = 0;
+	const char *quiet_str = getenv("quiet");
+
+	/* at least two arguments please */
+	if (argc < 2)
+		goto usage;
+
+	if (quiet_str)
+		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
+
+	cmd = argv[1];
+
+	if (strcmp(cmd, "info") == 0) {
+
+		putc('\n');
+		for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
+			if (nand_info[i].name)
+				printf("Device %d: %s, sector size %lu KiB\n",
+					i, nand_info[i].name,
+					nand_info[i].erasesize >> 10);
+		}
+		return 0;
+	}
+
+	if (strcmp(cmd, "device") == 0) {
+
+		if (argc < 3) {
+			if ((nand_curr_device < 0) ||
+			    (nand_curr_device >= CFG_MAX_NAND_DEVICE))
+				puts("\nno devices available\n");
+			else
+				printf("\nDevice %d: %s\n", nand_curr_device,
+					nand_info[nand_curr_device].name);
+			return 0;
+		}
+		dev = (int)simple_strtoul(argv[2], NULL, 10);
+		if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
+			puts("No such device\n");
+			return 1;
+		}
+		printf("Device %d: %s", dev, nand_info[dev].name);
+		puts("... is now current device\n");
+		nand_curr_device = dev;
+
+#ifdef CFG_NAND_SELECT_DEVICE
+		/*
+		 * Select the chip in the board/cpu specific driver
+		 */
+		board_nand_select_device(nand_info[dev].priv, dev);
+#endif
+
+		return 0;
+	}
+
+	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
+	    strncmp(cmd, "dump", 4) != 0 &&
+	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
+	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
+	    strcmp(cmd, "biterr") != 0 &&
+	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
+		goto usage;
+
+	/* the following commands operate on the current device */
+	if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
+	    !nand_info[nand_curr_device].name) {
+		puts("\nno devices available\n");
+		return 1;
+	}
+	nand = &nand_info[nand_curr_device];
+
+	if (strcmp(cmd, "bad") == 0) {
+		printf("\nDevice %d bad blocks:\n", nand_curr_device);
+		for (off = 0; off < nand->size; off += nand->erasesize)
+			if (nand_block_isbad(nand, off))
+				printf("  %08x\n", off);
+		return 0;
+	}
+
+	/*
+	 * Syntax is:
+	 *   0    1     2       3    4
+	 *   nand erase [clean] [off size]
+	 */
+	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
+		nand_erase_options_t opts;
+		/* "clean" at index 2 means request to write cleanmarker */
+		int clean = argc > 2 && !strcmp("clean", argv[2]);
+		int o = clean ? 3 : 2;
+		int scrub = !strcmp(cmd, "scrub");
+
+		printf("\nNAND %s: ", scrub ? "scrub" : "erase");
+		/* skip first two or three arguments, look for offset and size */
+		if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
+			return 1;
+
+		memset(&opts, 0, sizeof(opts));
+		opts.offset = off;
+		opts.length = size;
+		opts.jffs2  = clean;
+		opts.quiet  = quiet;
+
+		if (scrub) {
+			puts("Warning: "
+			     "scrub option will erase all factory set "
+			     "bad blocks!\n"
+			     "         "
+			     "There is no reliable way to recover them.\n"
+			     "         "
+			     "Use this command only for testing purposes "
+			     "if you\n"
+			     "         "
+			     "are sure of what you are doing!\n"
+			     "\nReally scrub this NAND flash? <y/N>\n");
+
+			if (getc() == 'y' && getc() == '\r') {
+				opts.scrub = 1;
+			} else {
+				puts("scrub aborted\n");
+				return -1;
+			}
+		}
+		ret = nand_erase_opts(nand, &opts);
+		printf("%s\n", ret ? "ERROR" : "OK");
+
+		return ret == 0 ? 0 : 1;
+	}
+
+	if (strncmp(cmd, "dump", 4) == 0) {
+		if (argc < 3)
+			goto usage;
+
+		s = strchr(cmd, '.');
+		off = (int)simple_strtoul(argv[2], NULL, 16);
+
+		if (s != NULL && strcmp(s, ".oob") == 0)
+			ret = nand_dump_oob(nand, off);
+		else
+			ret = nand_dump(nand, off);
+
+		return ret == 0 ? 1 : 0;
+
+	}
+
+	/* read write */
+	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+		int read;
+
+		if (argc < 4)
+			goto usage;
+
+		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+
+		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
+		printf("\nNAND %s: ", read ? "read" : "write");
+		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
+			return 1;
+
+		s = strchr(cmd, '.');
+		if (s != NULL &&
+		    (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
+			if (read) {
+				/* read */
+				nand_read_options_t opts;
+				memset(&opts, 0, sizeof(opts));
+				opts.buffer	= (u_char*) addr;
+				opts.length	= size;
+				opts.offset	= off;
+				opts.quiet      = quiet;
+				ret = nand_read_opts(nand, &opts);
+			} else {
+				/* write */
+				nand_write_options_t opts;
+				memset(&opts, 0, sizeof(opts));
+				opts.buffer	= (u_char*) addr;
+				opts.length	= size;
+				opts.offset	= off;
+				/* opts.forcejffs2 = 1; */
+				opts.pad	= 1;
+				opts.blockalign = 1;
+				opts.quiet      = quiet;
+				ret = nand_write_opts(nand, &opts);
+			}
+		} else {
+			if (read)
+				ret = nand_read(nand, off, &size, (u_char *)addr);
+			else
+				ret = nand_write(nand, off, &size, (u_char *)addr);
+		}
+
+		printf(" %d bytes %s: %s\n", size,
+		       read ? "read" : "written", ret ? "ERROR" : "OK");
+
+		return ret == 0 ? 0 : 1;
+	}
+
+	if (strcmp(cmd, "markbad") == 0) {
+		addr = (ulong)simple_strtoul(argv[2], NULL, 16);
+
+		int ret = nand->block_markbad(nand, addr);
+		if (ret == 0) {
+			printf("block 0x%08lx successfully marked as bad\n",
+			       (ulong) addr);
+			return 0;
+		} else {
+			printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
+			       (ulong) addr, ret);
+		}
+		return 1;
+	}
+	if (strcmp(cmd, "biterr") == 0) {
+		/* todo */
+		return 1;
+	}
+
+	if (strcmp(cmd, "lock") == 0) {
+		int tight  = 0;
+		int status = 0;
+		if (argc == 3) {
+			if (!strcmp("tight", argv[2]))
+				tight = 1;
+			if (!strcmp("status", argv[2]))
+				status = 1;
+		}
+
+		if (status) {
+			ulong block_start = 0;
+			ulong off;
+			int last_status = -1;
+
+			struct nand_chip *nand_chip = nand->priv;
+			/* check the WP bit */
+			nand_chip->cmdfunc (nand, NAND_CMD_STATUS, -1, -1);
+			printf("device is %swrite protected\n",
+			       (nand_chip->read_byte(nand) & 0x80 ?
+				"NOT " : "" ) );
+
+			for (off = 0; off < nand->size; off += nand->oobblock) {
+				int s = nand_get_lock_status(nand, off);
+
+				/* print message only if status has changed
+				 * or at end of chip
+				 */
+				if (off == nand->size - nand->oobblock
+				    || (s != last_status && off != 0))	{
+
+					printf("%08x - %08x: %8d pages %s%s%s\n",
+					       block_start,
+					       off-1,
+					       (off-block_start)/nand->oobblock,
+					       ((last_status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""),
+					       ((last_status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""),
+					       ((last_status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
+				}
+
+				last_status = s;
+		       }
+		} else {
+			if (!nand_lock(nand, tight)) {
+				puts("NAND flash successfully locked\n");
+			} else {
+				puts("Error locking NAND flash\n");
+				return 1;
+			}
+		}
+		return 0;
+	}
+
+	if (strcmp(cmd, "unlock") == 0) {
+		if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
+			return 1;
+
+		if (!nand_unlock(nand, off, size)) {
+			puts("NAND flash successfully unlocked\n");
+		} else {
+			puts("Error unlocking NAND flash, "
+			     "write and erase will probably fail\n");
+			return 1;
+		}
+		return 0;
+	}
+
+usage:
+	printf("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+}
+
+U_BOOT_CMD(nand, 5, 1, do_nand,
+	"nand    - NAND sub-system\n",
+	"info                  - show available NAND devices\n"
+	"nand device [dev]     - show or set current device\n"
+	"nand read[.jffs2]     - addr off|partition size\n"
+	"nand write[.jffs2]    - addr off|partiton size - read/write `size' bytes starting\n"
+	"    at offset `off' to/from memory address `addr'\n"
+	"nand erase [clean] [off size] - erase `size' bytes from\n"
+	"    offset `off' (entire device if not specified)\n"
+	"nand bad - show bad blocks\n"
+	"nand dump[.oob] off - dump page\n"
+	"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
+	"nand markbad off - mark bad block at offset (UNSAFE)\n"
+	"nand biterr off - make a bit error at offset (UNSAFE)\n"
+	"nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
+	"nand unlock [offset] [size] - unlock section\n");
+
+static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
+			   ulong offset, ulong addr, char *cmd)
+{
+	int r;
+	char *ep;
+	ulong cnt;
+	image_header_t *hdr;
+
+	printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
+
+	cnt = nand->oobblock;
+	r = nand_read(nand, offset, &cnt, (u_char *) addr);
+	if (r) {
+		puts("** Read error\n");
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	hdr = (image_header_t *) addr;
+
+	if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+		printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	print_image_hdr(hdr);
+
+	cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
+
+	r = nand_read(nand, offset, &cnt, (u_char *) addr);
+	if (r) {
+		puts("** Read error\n");
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	/* Loading ok, update default load address */
+
+	load_addr = addr;
+
+	/* Check if we should attempt an auto-start */
+	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
+		char *local_args[2];
+		extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
+
+		local_args[0] = cmd;
+		local_args[1] = NULL;
+
+		printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+		do_bootm(cmdtp, 0, 1, local_args);
+		return 1;
+	}
+	return 0;
+}
+
+int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	char *boot_device = NULL;
+	int idx;
+	ulong addr, offset = 0;
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+	struct mtd_device *dev;
+	struct part_info *part;
+	u8 pnum;
+
+	if (argc >= 2) {
+		char *p = (argc == 2) ? argv[1] : argv[2];
+		if (!(str2long(p, &addr)) && (mtdparts_init() == 0) &&
+		    (find_dev_and_part(p, &dev, &pnum, &part) == 0)) {
+			if (dev->id->type != MTD_DEV_TYPE_NAND) {
+				puts("Not a NAND device\n");
+				return 1;
+			}
+			if (argc > 3)
+				goto usage;
+			if (argc == 3)
+				addr = simple_strtoul(argv[2], NULL, 16);
+			else
+				addr = CFG_LOAD_ADDR;
+			return nand_load_image(cmdtp, &nand_info[dev->id->num],
+					       part->offset, addr, argv[0]);
+		}
+	}
+#endif
+
+	switch (argc) {
+	case 1:
+		addr = CFG_LOAD_ADDR;
+		boot_device = getenv("bootdevice");
+		break;
+	case 2:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = getenv("bootdevice");
+		break;
+	case 3:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = argv[2];
+		break;
+	case 4:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = argv[2];
+		offset = simple_strtoul(argv[3], NULL, 16);
+		break;
+	default:
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
+usage:
+#endif
+		printf("Usage:\n%s\n", cmdtp->usage);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	if (!boot_device) {
+		puts("\n** No boot device **\n");
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	idx = simple_strtoul(boot_device, NULL, 16);
+
+	if (idx < 0 || idx >= CFG_MAX_NAND_DEVICE || !nand_info[idx].name) {
+		printf("\n** Device %d not available\n", idx);
+		SHOW_BOOT_PROGRESS(-1);
+		return 1;
+	}
+
+	return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
+}
+
+U_BOOT_CMD(nboot, 4, 1, do_nandboot,
+	"nboot   - boot from NAND device\n",
+	"[partition] | [[[loadAddr] dev] offset]\n");
+
+#endif				/* (CONFIG_COMMANDS & CFG_CMD_NAND) */
+
+#else /* CFG_NAND_LEGACY */
+/*
+ *
+ * Legacy NAND support - to be phased out
+ *
+ */
+#include <command.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)	show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+#include <linux/mtd/nand_legacy.h>
+#if 0
+#include <linux/mtd/nand_ids.h>
+#include <jffs2/jffs2.h>
+#endif
+
+#ifdef CONFIG_OMAP1510
+void archflashwp(void *archdata, int wp);
+#endif
+
+#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))
+
+#undef	NAND_DEBUG
+#undef	PSYCHO_DEBUG
+
+/* ****************** WARNING *********************
+ * When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
+ * erase (or at least attempt to erase) blocks that are marked
+ * bad. This can be very handy if you are _sure_ that the block
+ * is OK, say because you marked a good block bad to test bad
+ * block handling and you are done testing, or if you have
+ * accidentally marked blocks bad.
+ *
+ * Erasing factory marked bad blocks is a _bad_ idea. If the
+ * erase succeeds there is no reliable way to find them again,
+ * and attempting to program or erase bad blocks can affect
+ * the data in _other_ (good) blocks.
+ */
+#define	 ALLOW_ERASE_BAD_DEBUG 0
+
+#define CONFIG_MTD_NAND_ECC  /* enable ECC */
+#define CONFIG_MTD_NAND_ECC_JFFS2
+
+/* bits for nand_legacy_rw() `cmd'; or together as needed */
+#define NANDRW_READ	0x01
+#define NANDRW_WRITE	0x00
+#define NANDRW_JFFS2	0x02
+#define NANDRW_JFFS2_SKIP	0x04
+#define NANDRW_YAFFS	0x08    /* to write yaffs image, www.100ask.net */
+
+/*
+ * Imports from nand_legacy.c
+ */
+extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
+extern int curr_device;
+extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
+			    size_t len, int clean);
+extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
+			 size_t len, size_t *retlen, u_char *buf);
+extern void nand_print(struct nand_chip *nand);
+extern void nand_print_bad(struct nand_chip *nand);
+extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
+			       size_t len, size_t *retlen, u_char *buf);
+extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
+				size_t len, size_t *retlen, const u_char *buf);
+
+
+int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    int rcode = 0;
+
+    switch (argc) {
+    case 0:
+    case 1:
+	printf ("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+    case 2:
+	if (strcmp(argv[1],"info") == 0) {
+		int i;
+
+		putc ('\n');
+
+		for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
+			if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
+				continue; /* list only known devices */
+			printf ("Device %d: ", i);
+			nand_print(&nand_dev_desc[i]);
+		}
+		return 0;
+
+	} else if (strcmp(argv[1],"device") == 0) {
+		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+			puts ("\nno devices available\n");
+			return 1;
+		}
+		printf ("\nDevice %d: ", curr_device);
+		nand_print(&nand_dev_desc[curr_device]);
+		return 0;
+
+	} else if (strcmp(argv[1],"bad") == 0) {
+		if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
+			puts ("\nno devices available\n");
+			return 1;
+		}
+		printf ("\nDevice %d bad blocks:\n", curr_device);
+		nand_print_bad(&nand_dev_desc[curr_device]);
+		return 0;
+
+	}
+	printf ("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+    case 3:
+	if (strcmp(argv[1],"device") == 0) {
+		int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+		printf ("\nDevice %d: ", dev);
+		if (dev >= CFG_MAX_NAND_DEVICE) {
+			puts ("unknown device\n");
+			return 1;
+		}
+		nand_print(&nand_dev_desc[dev]);
+		/*nand_print (dev);*/
+
+		if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
+			return 1;
+		}
+
+		curr_device = dev;
+
+		puts ("... is now current device\n");
+
+		return 0;
+	}
+	else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
+		struct nand_chip* nand = &nand_dev_desc[curr_device];
+		ulong off = 0;
+		ulong size = nand->totlen;
+		int ret;
+
+		printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
+			curr_device, off, size);
+
+		ret = nand_legacy_erase (nand, off, size, 1);
+
+		printf("%s\n", ret ? "ERROR" : "OK");
+
+		return ret;
+	}
+
+	printf ("Usage:\n%s\n", cmdtp->usage);
+	return 1;
+    default:
+	/* at least 4 args */
+
+	if (strncmp(argv[1], "read", 4) == 0 ||
+	    strncmp(argv[1], "write", 5) == 0) {
+		ulong addr = simple_strtoul(argv[2], NULL, 16);
+		ulong off  = simple_strtoul(argv[3], NULL, 16);
+		ulong size = simple_strtoul(argv[4], NULL, 16);
+		int cmd    = (strncmp(argv[1], "read", 4) == 0) ?
+				NANDRW_READ : NANDRW_WRITE;
+		int ret, total;
+		char* cmdtail = strchr(argv[1], '.');
+
+		// if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
+		/* fixed by www.100ask.net */
+		if (cmdtail && !strcmp(cmdtail, ".oob")) {
+			/* read out-of-band data */
+			if (cmd & NANDRW_READ) {
+				ret = nand_read_oob(nand_dev_desc + curr_device,
+						    off, size, (size_t *)&total,
+						    (u_char*)addr);
+			}
+			else {
+				ret = nand_write_oob(nand_dev_desc + curr_device,
+						     off, size, (size_t *)&total,
+						     (u_char*)addr);
+			}
+			return ret;
+		}
+		//else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
+		/* fixed by www.100ask.net */
+		else if (cmdtail && !strcmp(cmdtail, ".jffs2"))
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
+		//else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
+		/* fixed by www.100ask.net */
+		else if ((cmd & NANDRW_WRITE) && cmdtail && !strcmp(cmdtail, ".jffs2s")) {
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
+			if (cmd & NANDRW_READ)
+				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
+		}
+        /* write yaffs image, www.100ask.net */
+		else if (cmdtail && !strcmp(cmdtail, ".yaffs")) {
+			cmd |= NANDRW_YAFFS;
+		}
+#ifdef SXNI855T
+		/* need ".e" same as ".j" for compatibility with older units */
+		else if (cmdtail && !strcmp(cmdtail, ".e"))
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks */
+#endif
+#ifdef CFG_NAND_SKIP_BAD_DOT_I
+		/* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
+		/* ".i" for image -> read skips bad block (no 0xff) */
+		else if (cmdtail && !strcmp(cmdtail, ".i")) {
+			cmd |= NANDRW_JFFS2;	/* skip bad blocks (on read too) */
+			if (cmd & NANDRW_READ)
+				cmd |= NANDRW_JFFS2_SKIP;	/* skip bad blocks (on read too) */
+		}
+#endif /* CFG_NAND_SKIP_BAD_DOT_I */
+		else if (cmdtail) {
+			printf ("Usage:\n%s\n", cmdtp->usage);
+			return 1;
+		}
+
+		printf ("\nNAND %s: device %d offset %ld, size %ld ...\n",
+			(cmd & NANDRW_READ) ? "read" : "write",
+			curr_device, off, size);
+
+		ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,
+			     (size_t *)&total, (u_char*)addr);
+
+		printf (" %d bytes %s: %s\n", total,
+			(cmd & NANDRW_READ) ? "read" : "written",
+			ret ? "ERROR" : "OK");
+
+		return ret;
+	} else if (strcmp(argv[1],"erase") == 0 &&
+		   (argc == 4 || strcmp("clean", argv[2]) == 0)) {
+		int clean = argc == 5;
+		ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
+		ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
+		int ret;
+
+		printf ("\nNAND erase: device %d offset %ld, size %ld ...\n",
+			curr_device, off, size);
+
+		ret = nand_legacy_erase (nand_dev_desc + curr_device,
+					off, size, clean);
+
+		printf("%s\n", ret ? "ERROR" : "OK");
+
+		return ret;
+	} else {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		rcode = 1;
+	}
+
+	return rcode;
+    }
+}
+
+U_BOOT_CMD(
+	nand,	5,	1,	do_nand,
+	"nand    - legacy NAND sub-system\n",
+	"info  - show available NAND devices\n"
+	"nand device [dev] - show or set current device\n"
+	"nand read[.jffs2[s]]  addr off size\n"
+	"nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
+	"    at offset `off' to/from memory address `addr'\n"
+	"nand erase [clean] [off size] - erase `size' bytes from\n"
+	"    offset `off' (entire device if not specified)\n"
+	"nand bad - show bad blocks\n"
+	"nand read.oob addr off size - read out-of-band data\n"
+	"nand write.oob addr off size - read out-of-band data\n"
+	"nand write.yaffs addr off size - write the `size' byte yaffs image starting\n"
+	"    at offset `off' from memory address `addr'\n"
+);
+
+int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	char *boot_device = NULL;
+	char *ep;
+	int dev;
+	ulong cnt;
+	ulong addr;
+	ulong offset = 0;
+	image_header_t *hdr;
+	int rcode = 0;
+	switch (argc) {
+	case 1:
+		addr = CFG_LOAD_ADDR;
+		boot_device = getenv ("bootdevice");
+		break;
+	case 2:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = getenv ("bootdevice");
+		break;
+	case 3:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = argv[2];
+		break;
+	case 4:
+		addr = simple_strtoul(argv[1], NULL, 16);
+		boot_device = argv[2];
+		offset = simple_strtoul(argv[3], NULL, 16);
+		break;
+	default:
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		SHOW_BOOT_PROGRESS (-1);
+		return 1;
+	}
+
+	if (!boot_device) {
+		puts ("\n** No boot device **\n");
+		SHOW_BOOT_PROGRESS (-1);
+		return 1;
+	}
+
+	dev = simple_strtoul(boot_device, &ep, 16);
+
+	if ((dev >= CFG_MAX_NAND_DEVICE) ||
+	    (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
+		printf ("\n** Device %d not available\n", dev);
+		SHOW_BOOT_PROGRESS (-1);
+		return 1;
+	}
+
+	printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
+		dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
+		offset);
+
+	if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
+			SECTORSIZE, NULL, (u_char *)addr)) {
+		printf ("** Read error on %d\n", dev);
+		SHOW_BOOT_PROGRESS (-1);
+		return 1;
+	}
+
+	hdr = (image_header_t *)addr;
+
+	if (ntohl(hdr->ih_magic) == IH_MAGIC) {
+
+		print_image_hdr (hdr);
+
+		cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
+		cnt -= SECTORSIZE;
+	} else {
+		printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));
+		SHOW_BOOT_PROGRESS (-1);
+		return 1;
+	}
+
+	if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
+			offset + SECTORSIZE, cnt, NULL,
+			(u_char *)(addr+SECTORSIZE))) {
+		printf ("** Read error on %d\n", dev);
+		SHOW_BOOT_PROGRESS (-1);
+		return 1;
+	}
+
+	/* Loading ok, update default load address */
+
+	load_addr = addr;
+
+	/* Check if we should attempt an auto-start */
+	if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
+		char *local_args[2];
+		extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
+
+		local_args[0] = argv[0];
+		local_args[1] = NULL;
+
+		printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
+
+		do_bootm (cmdtp, 0, 1, local_args);
+		rcode = 1;
+	}
+	return rcode;
+}
+
+U_BOOT_CMD(
+	nboot,	4,	1,	do_nandboot,
+	"nboot   - boot from NAND device\n",
+	"loadAddr dev\n"
+);
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
+
+#endif /* CFG_NAND_LEGACY */
diff -urN u-boot-1.1.6/common/cmd_usbslave.c u-boot-1.1.6_jz2440/common/cmd_usbslave.c
--- u-boot-1.1.6/common/cmd_usbslave.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/common/cmd_usbslave.c	2010-11-26 12:54:38.154066984 +0800
@@ -0,0 +1,78 @@
+/*
+ * thisway.diy@163.com, www.100ask.net
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/byteorder.h>
+#include <def.h>
+
+#ifdef CONFIG_USB_DEVICE
+
+int g_bUSBWait = 1;
+u32 g_dwDownloadLen = 0;
+
+extern int download_run;
+extern volatile U32 dwUSBBufBase;
+extern volatile u32 dwUSBBufSize;
+
+extern __u32 usb_receive(char *buf, size_t len, U32 wait);
+
+int do_usbslave (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+    int i;
+    size_t len = ~0UL;
+    char buf[32];
+
+    /* download_run为1时表示将文件保存在USB Host发送工具dnw指定的位置
+     * download_run为0时表示将文件保存在参数argv[2]指定的位置
+     * 要下载程序到内存，然后直接运行时，要设置download_run=1，这也是这个参数名字的来由
+     */
+    download_run = 1;
+    switch (argc) {
+        case 1:
+        {
+            break;
+        }
+        case 2:
+        {
+            g_bUSBWait = (int)simple_strtoul(argv[1], NULL, 16);
+            break;
+        }
+
+        case 3:
+        {
+            g_bUSBWait = (int)simple_strtoul(argv[1], NULL, 16);
+            load_addr = simple_strtoul(argv[2], NULL, 16);
+            download_run = 0;
+            break;
+        }
+        
+        default: 
+        {
+            printf ("Usage:\n%s\n", cmdtp->usage);
+    		return 1;
+        }
+    }
+
+    dwUSBBufBase = load_addr;  
+    dwUSBBufSize = (FREE_RAM_SIZE&(~(0x80000-1)));  
+    if (g_bUSBWait)
+        len = FREE_RAM_SIZE;
+
+    g_dwDownloadLen = usb_receive(dwUSBBufBase, len, g_bUSBWait);
+    sprintf(buf, "%X", g_dwDownloadLen);
+    setenv("filesize", buf);
+    
+	return 0;
+}
+
+U_BOOT_CMD(
+	usbslave,	3,	0,	do_usbslave,
+	"usbslave - get file from host(PC)\n",
+	"[wait] [loadAddress]\n"
+	"\"wait\" is 0 or 1, 0 means for return immediately, not waits for the finish of transferring\n"
+);
+
+#endif
diff -urN u-boot-1.1.6/common/env_nand.c u-boot-1.1.6_jz2440/common/env_nand.c
--- u-boot-1.1.6/common/env_nand.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/common/env_nand.c	2010-11-26 12:54:38.170264643 +0800
@@ -268,10 +268,9 @@
 void env_relocate_spec (void)
 {
 #if !defined(ENV_IS_EMBEDDED)
-	ulong total;
+	ulong total = CFG_ENV_SIZE;
 	int ret;
 
-	total = CFG_ENV_SIZE;
 	ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);
   	if (ret || total != CFG_ENV_SIZE)
 		return use_default();
diff -urN u-boot-1.1.6/common/main.c u-boot-1.1.6_jz2440/common/main.c
--- u-boot-1.1.6/common/main.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/common/main.c	2010-11-26 12:54:38.154066984 +0800
@@ -257,14 +257,20 @@
 		/* delay 100 * 10ms */
 		for (i=0; !abort && i<100; ++i) {
 			if (tstc()) {	/* we got a key press	*/
+# ifdef CONFIG_MENUKEY
 				abort  = 1;	/* don't auto boot	*/
 				bootdelay = 0;	/* no more delay	*/
-# ifdef CONFIG_MENUKEY
 				menukey = getc();
+				break;
 # else
-				(void) getc();  /* consume input	*/
+				/* consume input	*/
+				if (getc() == ' ') {
+					abort  = 1; /* don't auto boot	*/
+					bootdelay = 0;	/* no more delay	*/
+					break;
+				}
 # endif
-				break;
+
 			}
 			udelay (10000);
 		}
@@ -363,6 +369,18 @@
 	install_auto_complete();
 #endif
 
+#ifdef CONFIG_JFFS2_CMDLINE
+    extern int mtdparts_init(void);
+    if (!getenv("mtdparts"))
+    {
+        run_command("mtdparts default", 0);
+    }
+    else
+    {
+        mtdparts_init();
+    }
+#endif
+
 #ifdef CONFIG_PREBOOT
 	if ((p = getenv ("preboot")) != NULL) {
 # ifdef CONFIG_AUTOBOOT_KEYED
@@ -392,6 +410,17 @@
 	init_cmd_timeout ();
 # endif	/* CONFIG_BOOT_RETRY_TIME */
 
+	if (PreLoadedONRAM)	{
+		printf("Use these steps to program the image to flash:\n");
+		printf("1. In OpenOCD\n");
+		printf("   Run the 'halt' command to halt u-boot\n");
+		printf("   Run the 'load_image <file> <address>' command to load file to SDRAM\n");
+		printf("   Run the 'resume' command to resume u-boot\n");
+		printf("2. In u-boot, use the flash commands to program the image to flash\n");
+		printf("Or, use the tftp or nfs command to download file, and then program the flash.\n");
+		goto PROMPT;
+	}
+
 #ifdef CONFIG_BOOTCOUNT_LIMIT
 	if (bootlimit && (bootcount > bootlimit)) {
 		printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
@@ -410,7 +439,10 @@
 # endif
 
 # ifndef CFG_HUSH_PARSER
-		run_command (s, 0);
+        {
+            printf("Booting Linux ...\n");            
+    	    run_command (s, 0);
+        }
 # else
 		parse_string_outer(s, FLAG_PARSE_SEMICOLON |
 				    FLAG_EXIT_FROM_LOOP);
@@ -443,9 +475,11 @@
 	}
 #endif
 
+    run_command("menu", 0);
 	/*
 	 * Main Loop for Monitor Command Processing
 	 */
+PROMPT:
 #ifdef CFG_HUSH_PARSER
 	parse_file_outer();
 	/* This point is never reached */
diff -urN u-boot-1.1.6/common/Makefile u-boot-1.1.6_jz2440/common/Makefile
--- u-boot-1.1.6/common/Makefile	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/common/Makefile	2010-11-26 12:54:38.150155640 +0800
@@ -40,7 +40,7 @@
 	  cmd_nand.o cmd_net.o cmd_nvedit.o \
 	  cmd_pci.o cmd_pcmcia.o cmd_portio.o \
 	  cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o \
-	  cmd_usb.o cmd_vfd.o \
+	  cmd_usb.o cmd_usbslave.o cmd_menu.o cmd_vfd.o \
 	  command.o console.o devices.o dlmalloc.o docecc.o \
 	  environment.o env_common.o \
 	  env_nand.o env_dataflash.o env_flash.o env_eeprom.o \
diff -urN u-boot-1.1.6/cpu/arm920t/cpu.c u-boot-1.1.6_jz2440/cpu/arm920t/cpu.c
--- u-boot-1.1.6/cpu/arm920t/cpu.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/cpu/arm920t/cpu.c	2010-11-26 12:54:37.714311555 +0800
@@ -88,7 +88,6 @@
 #define C1_IC		(1<<12)		/* icache off/on */
 #define C1_HIGH_VECTORS	(1<<13)		/* location of vectors: low/high addresses */
 
-
 int cpu_init (void)
 {
 	/*
@@ -97,6 +96,11 @@
 #ifdef CONFIG_USE_IRQ
 	IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
 	FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
+    FREE_RAM_END = FIQ_STACK_START - CONFIG_STACKSIZE_FIQ - CONFIG_STACKSIZE;
+    FREE_RAM_SIZE = FREE_RAM_END - PHYS_SDRAM_1;
+#else    
+    FREE_RAM_END = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4 - CONFIG_STACKSIZE;
+    FREE_RAM_SIZE = FREE_RAM_END - PHYS_SDRAM_1;
 #endif
 	return 0;
 }
diff -urN u-boot-1.1.6/cpu/arm920t/s3c24x0/interrupts.c u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/interrupts.c
--- u-boot-1.1.6/cpu/arm920t/s3c24x0/interrupts.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/interrupts.c	2010-11-26 12:54:37.726297356 +0800
@@ -216,4 +216,125 @@
 	/*NOTREACHED*/
 }
 
+/* Start : add by www.100ask.net */
+void (*isr_handle_array[50])(void);
+S3C24X0_INTERRUPT * intregs;
+    
+extern void IsrUsbd(void);
+extern void IsrDma2(void);
+
+/************************* Timer ********************************/
+static int intCount;
+
+void IsrWatchdog(void);
+
+void ClearPending(int bit) 
+{
+    intregs->SRCPND = bit;
+    intregs->INTPND = bit;
+}
+
+void Timer_InitEx(void)
+{
+	intCount=0;	
+	intregs->SUBSRCPND	= (1<<13);
+	ClearPending(BIT_WDT_AC97/*BIT_WDT*/);
+	intregs->INTMSK&=~(BIT_WDT_AC97 /*BIT_WDT*/);
+	intregs->INTSUBMSK &= ~(1<<13);
+}
+
+
+void Timer_StartEx(void)
+{
+    S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
+    
+	wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2);	// 16us
+	wdtregs->WTDAT=0xffff;
+	wdtregs->WTCNT=0xffff;   
+
+	// 1/16/(65+1),interrupt enable,reset disable,watchdog enable
+	wdtregs->WTCON=((get_PCLK()/1000000-1)<<8)|(0<<3)|(1<<2)|(0<<0)|(1<<5);   
+}
+
+unsigned int Timer_StopEx(void)
+{
+	int count;
+    S3C24X0_WATCHDOG * const wdtregs = S3C24X0_GetBase_WATCHDOG();
+
+	wdtregs->WTCON=((get_PCLK()/1000000-1)<<8);
+	intregs->INTMSK|=BIT_WDT_AC97; //BIT_WDT;
+	intregs->INTSUBMSK |= (1<<13);
+	
+	count=(0xffff-wdtregs->WTCNT)+(intCount*0xffff);
+	return ((unsigned int)count*16/1000000);
+}
+
+
+void  IsrWatchdog(void)
+{
+	intregs->SUBSRCPND	= (1<<13);
+	ClearPending(BIT_WDT_AC97 /* BIT_WDT */);
+	intCount++;   	
+}
+
+int g_TimerIntHappen;
+void  IsrTimer4(void)
+{
+	ClearPending(BIT_TIMER4);
+	*(volatile int *)&g_TimerIntHappen = 1;
+}
+
+
+void Dummy_isr(void)
+{
+    printf("Dummy_isr error, interrupt number: %d, INTMSK = 0x%x\n", intregs->INTOFFSET, intregs->INTMSK);
+    while(1);
+}
+
+void Isr_Init(void)
+{
+    int i = 0;
+    intregs = S3C24X0_GetBase_INTERRUPT();
+    
+    for (i = 0; i < sizeof(isr_handle_array) / sizeof(isr_handle_array[0]); i++ )
+    {
+        isr_handle_array[i] = Dummy_isr;
+    }
+
+    intregs->INTMOD=0x0;	      // All=IRQ mode
+    intregs->INTMSK=BIT_ALLMSK;	  // All interrupt is masked.
+
+    //pISR_URXD0=(unsigned)Uart0_RxInt;	
+    //rINTMSK=~(BIT_URXD0);   //enable UART0 RX Default value=0xffffffff
+
+	isr_handle_array[ISR_TIMER4_OFT] = IsrTimer4;
+	isr_handle_array[ISR_WDT_OFT]  = IsrWatchdog;
+
+#ifdef CONFIG_USB_DEVICE
+    isr_handle_array[ISR_USBD_OFT] = IsrUsbd;
+    isr_handle_array[ISR_DMA2_OFT] = IsrDma2;
+    ClearPending(BIT_DMA2);
+    ClearPending(BIT_USBD);
+#endif    
+}
+
+
+void IRQ_Handle()
+{
+	unsigned long oft = intregs->INTOFFSET;
+    S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
+    
+//    printk("IRQ_Handle: %d\n", oft);
+    
+	//清中断
+	if( oft == 4 ) gpio->EINTPEND = 1<<7;		//EINT4-7合用IRQ4，注意EINTPEND[3:0]保留未用，向这些位写入1可能导致未知结果
+	intregs->SRCPND = 1<<oft;	
+	intregs->INTPND	= intregs->INTPND;	 
+
+    /* run the isr */
+    isr_handle_array[oft]();
+}
+
+/* End : add by www.100ask.net */
+
 #endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */
diff -urN u-boot-1.1.6/cpu/arm920t/s3c24x0/Makefile u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/Makefile
--- u-boot-1.1.6/cpu/arm920t/s3c24x0/Makefile	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/Makefile	2010-11-26 12:54:37.726297356 +0800
@@ -26,7 +26,7 @@
 LIB	= $(obj)lib$(SOC).a
 
 COBJS	= i2c.o interrupts.o serial.o speed.o \
-	  usb_ohci.o
+	  usb_ohci.o nand_flash.o
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff -urN u-boot-1.1.6/cpu/arm920t/s3c24x0/nand_flash.c u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/nand_flash.c
--- u-boot-1.1.6/cpu/arm920t/s3c24x0/nand_flash.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/nand_flash.c	2010-11-26 12:54:37.726297356 +0800
@@ -0,0 +1,186 @@
+/*
+ * Nand flash interface of s3c2410/s3c2440, by www.100ask.net
+ * Changed from drivers/mtd/nand/s3c2410.c of kernel 2.6.13
+ */
+
+#include <common.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
+#include <s3c2410.h>
+#include <nand.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define S3C2410_NFSTAT_READY    (1<<0)
+#define S3C2410_NFCONF_nFCE     (1<<11)
+
+#define S3C2440_NFSTAT_READY    (1<<0)
+#define S3C2440_NFCONT_nFCE     (1<<1)
+
+
+/* select chip, for s3c2410 */
+static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+
+    if (chip == -1) {
+        s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
+    } else {
+        s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
+    }
+}
+
+/* command and control functions, for s3c2410 
+ *
+ * Note, these all use tglx's method of changing the IO_ADDR_W field
+ * to make the code simpler, and use the nand layer's code to issue the
+ * command and address sequences via the proper IO ports.
+ *
+*/
+static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+    struct nand_chip *chip = mtd->priv;
+
+    switch (cmd) {
+    case NAND_CTL_SETNCE:
+    case NAND_CTL_CLRNCE:
+        printf("%s: called for NCE\n", __FUNCTION__);
+        break;
+
+    case NAND_CTL_SETCLE:
+        chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
+        break;
+
+    case NAND_CTL_SETALE:
+        chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
+        break;
+
+        /* NAND_CTL_CLRCLE: */
+        /* NAND_CTL_CLRALE: */
+    default:
+        chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
+        break;
+    }
+}
+
+/* s3c2410_nand_devready()
+ *
+ * returns 0 if the nand is busy, 1 if it is ready
+ */
+static int s3c2410_nand_devready(struct mtd_info *mtd)
+{
+    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+
+    return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
+}
+
+
+/* select chip, for s3c2440 */
+static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (chip == -1) {
+        s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
+    } else {
+        s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
+    }
+}
+
+/* command and control functions */
+static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+    struct nand_chip *chip = mtd->priv;
+
+    switch (cmd) {
+    case NAND_CTL_SETNCE:
+    case NAND_CTL_CLRNCE:
+        printf("%s: called for NCE\n", __FUNCTION__);
+        break;
+
+    case NAND_CTL_SETCLE:
+        chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
+        break;
+
+    case NAND_CTL_SETALE:
+        chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
+        break;
+
+        /* NAND_CTL_CLRCLE: */
+        /* NAND_CTL_CLRALE: */
+    default:
+        chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
+        break;
+    }
+}
+
+/* s3c2440_nand_devready()
+ *
+ * returns 0 if the nand is busy, 1 if it is ready
+ */
+static int s3c2440_nand_devready(struct mtd_info *mtd)
+{
+    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
+}
+
+/*
+ * Nand flash hardware initialization:
+ * Set the timing, enable NAND flash controller
+ */
+static void s3c24x0_nand_inithw(void)
+{
+    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+#define TACLS   0
+#define TWRPH0  4
+#define TWRPH1  2
+
+    if (isS3C2410)
+    {
+        /* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */
+        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
+    }
+    else
+    {
+        /* Set flash memory timing */
+        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
+        /* Initialize ECC, enable chip select, NAND flash controller enable */
+        s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
+    }
+}
+
+/*
+ * Called by drivers/nand/nand.c, initialize the interface of nand flash
+ */
+void board_nand_init(struct nand_chip *chip)
+{
+    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    s3c24x0_nand_inithw();
+
+    if (isS3C2410) {
+        chip->IO_ADDR_R    = (void *)&s3c2410nand->NFDATA;
+        chip->IO_ADDR_W    = (void *)&s3c2410nand->NFDATA;
+        chip->hwcontrol    = s3c2410_nand_hwcontrol;
+        chip->dev_ready    = s3c2410_nand_devready;
+        chip->select_chip  = s3c2410_nand_select_chip;
+        chip->options      = 0;
+    } else {
+        chip->IO_ADDR_R    = (void *)&s3c2440nand->NFDATA;
+        chip->IO_ADDR_W    = (void *)&s3c2440nand->NFDATA;
+        chip->hwcontrol    = s3c2440_nand_hwcontrol;
+        chip->dev_ready    = s3c2440_nand_devready;
+        chip->select_chip  = s3c2440_nand_select_chip;
+        chip->options      = 0;
+    }
+
+    chip->eccmode       = NAND_ECC_SOFT;
+}
+
+#endif
diff -urN u-boot-1.1.6/cpu/arm920t/s3c24x0/nand_flash_legacy.c u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/nand_flash_legacy.c
--- u-boot-1.1.6/cpu/arm920t/s3c24x0/nand_flash_legacy.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/nand_flash_legacy.c	2010-11-26 12:54:37.726297356 +0800
@@ -0,0 +1,222 @@
+/* add by www.100ask.net */
+/*-----------------------------------------------------------------------
+ * NAND flash settings
+ */
+#include <common.h>
+#include <s3c2410.h>
+#if (CONFIG_COMMANDS & CFG_CMD_NAND)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* only has two value: NFCE_LOW, NFCE_HIGH */
+#define NFCE_STATE  int 
+
+void NF_Conf(u16 conf)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    	s3c2410nand->NFCONF = conf;
+    else
+        s3c2440nand->NFCONF = conf;
+}
+
+/* only for s3c2440 */
+void NF_Cont(u16 cont)
+{
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number != MACH_TYPE_SMDK2410)
+        s3c2440nand->NFCONT = cont;
+}
+
+void NF_Cmd(u8 cmd)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    	s3c2410nand->NFCMD = cmd;
+    else
+    	s3c2440nand->NFCMD = cmd;
+}
+
+void NF_CmdW(u8 cmd)
+{
+	NF_Cmd(cmd);
+    udelay(1);
+}
+
+void NF_Addr(u8 addr)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    	s3c2410nand->NFADDR = addr;
+    else
+    	s3c2440nand->NFADDR = addr;
+    udelay(15);
+}
+
+void NF_SetCE(NFCE_STATE s)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+	switch (s) {
+		case NFCE_LOW:
+            if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+		    	s3c2410nand->NFCONF &= ~(1<<11);
+            else
+		    	s3c2440nand->NFCONT &= ~(1<<1);                
+			break;
+
+		case NFCE_HIGH:
+            if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    			s3c2410nand->NFCONF |= (1<<11);
+            else
+		    	s3c2440nand->NFCONT |= (1<<1);
+			break;
+	}
+}
+
+/* only for s3c2440 */
+void NF_ClrRB(void)
+{
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number != MACH_TYPE_SMDK2410)
+    {
+        s3c2440nand->NFSTAT |= (1<<2);
+    }
+}
+
+void NF_WaitRB(void)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    {
+    	while (!(s3c2410nand->NFSTAT & (1<<0)));
+    }
+    else
+    {
+    	while (!(s3c2440nand->NFSTAT & (1<<0)));
+        s3c2440nand->NFSTAT |= (1<<2);
+    }
+}
+
+void NF_Write(u8 data)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+    volatile unsigned char *puc = (volatile unsigned char *)&s3c2440nand->NFDATA;
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    	s3c2410nand->NFDATA = data;
+    else
+    	*puc = data;    /* s3c2440's NFDATA must be accessed by 'u8*', www.100ask.net */
+    
+}
+
+u8 NF_Read(void)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+    volatile unsigned char *puc = (volatile unsigned char *)&s3c2440nand->NFDATA;
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    	return(s3c2410nand->NFDATA);
+    else
+    	return(*puc);   /* s3c2440's NFDATA must be accessed by 'u8*', www.100ask.net */
+}
+
+void NF_Init_ECC(void)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    	s3c2410nand->NFCONF |= (1<<12);
+    else
+    {
+        s3c2440nand->NFCONT |= (1<<4);   // Reset ECC
+        s3c2440nand->NFCONT &= ~(1<<5);  // UnLock MECC
+    }
+}
+
+u32 NF_Read_ECC(void)
+{
+	S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
+	S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    	return(s3c2410nand->NFECC);
+    else
+    {
+        s3c2440nand->NFCONT |= (1<<5);  // Lock MECC
+        return(s3c2440nand->NFMECC0);   // Read MECC
+    }
+}
+
+extern ulong
+nand_probe(ulong physadr);
+
+
+static inline void NF_Reset(void)
+{
+    int i;
+
+    NF_Cont((1<<4)|(0<<1)|(1<<0));  /* only for s3c2440, Initialize ECC, enable chip select, NAND flash controller enable */
+    NF_SetCE(NFCE_LOW); /* enable chip select */
+    NF_ClrRB();         /* only for s3c2440 */
+    NF_Cmd(0xFF);		/* reset command */
+    for(i = 0; i < 10; i++);	/* tWB = 100ns. */
+    NF_WaitRB();		/* wait 200~500us; */
+    NF_SetCE(NFCE_HIGH);
+}
+
+static inline void NF_Init(void)
+{
+#if 0 /* a little bit too optimistic */
+#define TACLS   0
+#define TWRPH0  3
+#define TWRPH1  0
+#else
+#define TACLS   0
+#define TWRPH0  4
+#define TWRPH1  2
+#endif
+
+    /* Set flash memory timing */
+    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
+    {
+        NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
+        /*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
+        /* 1  1    1     1,   1      xxx,  r xxx,   r xxx */
+        /* En 512B 4step ECCR nFCE=H tACLS   tWRPH0   tWRPH1 */
+    }
+    else
+    {
+        NF_Conf((3<<12)|(7<<8)|(7<<4));
+    }
+
+    NF_Reset();
+}
+
+void
+nand_init(void)
+{
+	S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
+
+	NF_Init();
+#ifdef DEBUG
+	printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
+#endif
+	printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
+}
+#endif	/* CONFIG_COMMANDS & CFG_CMD_NAND */
+
diff -urN u-boot-1.1.6/cpu/arm920t/s3c24x0/speed.c u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/speed.c
--- u-boot-1.1.6/cpu/arm920t/s3c24x0/speed.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/cpu/arm920t/s3c24x0/speed.c	2010-11-26 12:54:37.730289845 +0800
@@ -38,6 +38,8 @@
 #include <s3c2410.h>
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define MPLL 0
 #define UPLL 1
 
@@ -57,17 +59,21 @@
     ulong r, m, p, s;
 
     if (pllreg == MPLL)
-	r = clk_power->MPLLCON;
+    r = clk_power->MPLLCON;
     else if (pllreg == UPLL)
-	r = clk_power->UPLLCON;
+    r = clk_power->UPLLCON;
     else
-	hang();
+    hang();
 
     m = ((r & 0xFF000) >> 12) + 8;
     p = ((r & 0x003F0) >> 4) + 2;
     s = r & 0x3;
 
-    return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
+    /* support both of S3C2410 and S3C2440, by www.100ask.net */
+    if (isS3C2410)
+        return((CONFIG_SYS_CLK_FREQ * m) / (p << s));
+    else
+        return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));   /* S3C2440 */
 }
 
 /* return FCLK frequency */
@@ -76,20 +82,99 @@
     return(get_PLLCLK(MPLL));
 }
 
+/* for s3c2440 */
+#define S3C2440_CLKDIVN_PDIVN        (1<<0)
+#define S3C2440_CLKDIVN_HDIVN_MASK   (3<<1)
+#define S3C2440_CLKDIVN_HDIVN_1      (0<<1)
+#define S3C2440_CLKDIVN_HDIVN_2      (1<<1)
+#define S3C2440_CLKDIVN_HDIVN_4_8    (2<<1)
+#define S3C2440_CLKDIVN_HDIVN_3_6    (3<<1)
+#define S3C2440_CLKDIVN_UCLK         (1<<3)
+
+#define S3C2440_CAMDIVN_CAMCLK_MASK  (0xf<<0)
+#define S3C2440_CAMDIVN_CAMCLK_SEL   (1<<4)
+#define S3C2440_CAMDIVN_HCLK3_HALF   (1<<8)
+#define S3C2440_CAMDIVN_HCLK4_HALF   (1<<9)
+#define S3C2440_CAMDIVN_DVSEN        (1<<12)
+
 /* return HCLK frequency */
 ulong get_HCLK(void)
 {
     S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+    unsigned long clkdiv;
+    unsigned long camdiv;
+    int hdiv = 1;
+
+    /* support both of S3C2410 and S3C2440, by www.100ask.net */
+    if (isS3C2410)
+        return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
+    else
+    {
+        clkdiv = clk_power->CLKDIVN;
+        camdiv = clk_power->CAMDIVN;
+
+        /* work out clock scalings */
+
+        switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+        case S3C2440_CLKDIVN_HDIVN_1:
+            hdiv = 1;
+            break;
+
+        case S3C2440_CLKDIVN_HDIVN_2:
+            hdiv = 2;
+            break;
+
+        case S3C2440_CLKDIVN_HDIVN_4_8:
+            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+            break;
+
+        case S3C2440_CLKDIVN_HDIVN_3_6:
+            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+            break;
+        }
 
-    return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());
+        return get_FCLK() / hdiv;
+    }
 }
 
 /* return PCLK frequency */
 ulong get_PCLK(void)
 {
     S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
+    unsigned long clkdiv;
+    unsigned long camdiv;
+    int hdiv = 1;
+
+    /* support both of S3C2410 and S3C2440, by www.100ask.net */
+    if (isS3C2410)
+        return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());
+    else
+    {   
+        clkdiv = clk_power->CLKDIVN;
+        camdiv = clk_power->CAMDIVN;
+
+        /* work out clock scalings */
+
+        switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+        case S3C2440_CLKDIVN_HDIVN_1:
+            hdiv = 1;
+            break;
+
+        case S3C2440_CLKDIVN_HDIVN_2:
+            hdiv = 2;
+            break;
+
+        case S3C2440_CLKDIVN_HDIVN_4_8:
+            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+            break;
+
+        case S3C2440_CLKDIVN_HDIVN_3_6:
+            hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+            break;
+        }
 
-    return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());
+        return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+    }        
 }
 
 /* return UCLK frequency */
diff -urN u-boot-1.1.6/cpu/arm920t/start.S u-boot-1.1.6_jz2440/cpu/arm920t/start.S
--- u-boot-1.1.6/cpu/arm920t/start.S	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/cpu/arm920t/start.S	2010-11-26 12:54:37.718042180 +0800
@@ -90,6 +90,18 @@
 _bss_end:
 	.word _end
 
+.globl FREE_RAM_END
+FREE_RAM_END:
+	.word	0x0badc0de
+
+.globl FREE_RAM_SIZE
+FREE_RAM_SIZE:
+	.word	0x0badc0de
+
+.globl PreLoadedONRAM
+PreLoadedONRAM:
+	.word	0
+
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
 .globl IRQ_STACK_START
@@ -123,6 +135,7 @@
 # define CLKDIVN	0x14800014	/* clock divisor register */
 #elif defined(CONFIG_S3C2410)
 # define pWTCON		0x53000000
+# define INTMOD     0X4A000004
 # define INTMSK		0x4A000008	/* Interupt-Controller base addresses */
 # define INTSUBMSK	0x4A00001C
 # define CLKDIVN	0x4C000014	/* clock divisor register */
@@ -145,11 +158,13 @@
 	str	r1, [r0]
 # endif
 
+#if 0
 	/* FCLK:HCLK:PCLK = 1:2:4 */
 	/* default FCLK is 120 MHz ! */
 	ldr	r0, =CLKDIVN
 	mov	r1, #3
 	str	r1, [r0]
+#endif
 #endif	/* CONFIG_S3C2400 || CONFIG_S3C2410 */
 
 	/*
@@ -157,19 +172,40 @@
 	 * not when booting from ram!
 	 */
 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
-	bl	cpu_init_crit
+	adr	r0, _start		/* r0 <- current position of code   */
+	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
+	cmp     r0, r1                  /* don't reloc during debug         */
+	blne	cpu_init_crit
+#endif
+
+	/* Set up the stack						    */
+stack_setup:
+	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
+	sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area                      */
+	sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
+
+#ifdef CONFIG_USE_IRQ
+	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
 #endif
+	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+    bl clock_init
+#endif    
 
 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
 relocate:				/* relocate U-Boot to RAM	    */
 	adr	r0, _start		/* r0 <- current position of code   */
 	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
 	cmp     r0, r1                  /* don't reloc during debug         */
-	beq     stack_setup
-
+	beq     clear_bss
+	
 	ldr	r2, _armboot_start
 	ldr	r3, _bss_start
 	sub	r2, r3, r2		/* r2 <- size of armboot            */
+#if 1
+	bl  CopyCode2Ram	/* r0: source, r1: dest, r2: size */
+#else
 	add	r2, r0, r2		/* r2 <- source end address         */
 
 copy_loop:
@@ -177,17 +213,8 @@
 	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */
 	cmp	r0, r2			/* until source end addreee [r2]    */
 	ble	copy_loop
-#endif	/* CONFIG_SKIP_RELOCATE_UBOOT */
-
-	/* Set up the stack						    */
-stack_setup:
-	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */
-	sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area                      */
-	sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
-#ifdef CONFIG_USE_IRQ
-	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
 #endif
-	sub	sp, r0, #12		/* leave 3 words for abort-stack    */
+#endif	/* CONFIG_SKIP_RELOCATE_UBOOT */
 
 clear_bss:
 	ldr	r0, _bss_start		/* find start of bss segment        */
@@ -199,6 +226,15 @@
 	cmp	r0, r1
 	ble	clbss_l
 
+SetLoadFlag:
+	/* Set a global flag, PreLoadedONRAM */
+	adr	r0, _start		/* r0 <- current position of code   */
+	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
+	cmp     r0, r1                  /* don't reloc during debug         */
+	ldr r2, =PreLoadedONRAM
+	mov r3, #1
+	streq r3, [r2]
+
 #if 0
 	/* try doing this stuff after the relocation */
 	ldr     r0, =pWTCON
@@ -400,14 +436,88 @@
 	bad_save_user_regs
 	bl 	do_not_used
 
+@ thisway.diy, 2006.06.24
+.globl Launch
+    .align	4
+Launch:    
+    mov r7, r0
+    @ diable interrupt
+	@ disable watch dog timer
+	mov	r1, #0x53000000
+	mov	r2, #0x0
+	str	r2, [r1]
+
+    ldr r1,=INTMSK
+    ldr r2,=0xffffffff  @ all interrupt disable
+    str r2,[r1]
+
+    ldr r1,=INTSUBMSK
+    ldr r2,=0x7ff       @ all sub interrupt disable
+    str r2,[r1]
+
+    ldr     r1, = INTMOD
+    mov r2, #0x0        @ set all interrupt as IRQ (not FIQ)
+    str     r2, [r1]
+
+    @ 
+	mov	ip, #0
+	mcr	p15, 0, ip, c13, c0, 0      @	/* zero PID */
+	mcr	p15, 0, ip, c7, c7, 0       @	/* invalidate I,D caches */
+	mcr	p15, 0, ip, c7, c10, 4      @	/* drain write buffer */
+	mcr	p15, 0, ip, c8, c7, 0       @	/* invalidate I,D TLBs */
+	mrc	p15, 0, ip, c1, c0, 0       @	/* get control register */
+	bic	ip, ip, #0x0001             @	/* disable MMU */
+	mcr	p15, 0, ip, c1, c0, 0       @	/* write control register */
+
+    @ MMU_EnableICache
+    @mrc p15,0,r1,c1,c0,0
+    @orr r1,r1,#(1<<12)
+    @mcr p15,0,r1,c1,c0,0
+
+    @ clear SDRAM: the end of free mem(has wince on it now) to the end of SDRAM
+    ldr     r3, FREE_RAM_END
+    ldr     r4, =PHYS_SDRAM_1+PHYS_SDRAM_1_SIZE    @ must clear all the memory unused to zero
+    mov     r5, #0
+
+    ldr     r1, _armboot_start
+    ldr     r2, =On_Steppingstone
+    sub     r2, r2, r1
+    mov     pc, r2
+On_Steppingstone:
+2:  stmia   r3!, {r5}
+    cmp     r3, r4
+    bne     2b
+
+    @ set sp = 0 on sys mode
+    mov sp, #0
+
+    @ add by thisway.diy 2006.06.26, switch to SVC mode
+	msr	cpsr_c,	#0xdf	@ set the I-bit = 1, diable the IRQ interrupt
+	msr	cpsr_c,	#0xd3	@ set the I-bit = 1, diable the IRQ interrupt
+    ldr sp, =0x31ff5800	
+    
+    nop
+	nop
+    nop
+	nop
+
+	mov     pc, r7  @ Jump to PhysicalAddress
+	nop
+    mov pc, lr
+
 #ifdef CONFIG_USE_IRQ
 
 	.align	5
 irq:
-	get_irq_stack
-	irq_save_user_regs
-	bl 	do_irq
-	irq_restore_user_regs
+/* add by www.100ask.net to use IRQ for USB and DMA */
+	sub	lr, lr, #4			        @ the return address
+	ldr	sp, IRQ_STACK_START	        @ the stack for irq
+	stmdb	sp!, 	{ r0-r12,lr }	@ save registers
+	
+	ldr	lr,	=int_return		        @ set the return addr
+	ldr	pc, =IRQ_Handle		        @ call the isr
+int_return:
+	ldmia	sp!, 	{ r0-r12,pc }^	@ return from interrupt
 
 	.align	5
 fiq:
diff -urN u-boot-1.1.6/doc/README.SBC8560 u-boot-1.1.6_jz2440/doc/README.SBC8560
--- u-boot-1.1.6/doc/README.SBC8560	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/doc/README.SBC8560	1970-01-01 07:00:00.000000000 +0700
@@ -1,57 +0,0 @@
-The port was tested on Wind River System Sbc8560 board
-<www.windriver.com>. U-Boot was installed on the flash memory of the
-CPU card (no the SODIMM).
-
-NOTE: Please configure uboot compile to the proper PCI frequency and
-setup the appropriate DIP switch settings.
-
-SBC8560 board:
-
-Make sure boards switches are set to their appropriate conditions.
-Refer to the Engineering Reference Guide ERG-00300-002. Of particular
-importance are: 1) the settings for JP4 (JP4 1-3 and 2-4), which
-select the on-board FLASH device (Intel 28F128Jx); 2) The settings
-for the Clock SW9 (33 MHz or 66 MHz).
-
-	Note:	SW9 Settings: 66 MHz
-		4:1 ratio CCB clocks:SYSCLK
-		3:1 ration e500 Core:CCB
-		pos1 - on, pos2 - on, pos3 - off, pos4 - on, pos5 - off, pos6 - on
-	Note:	SW9 Settings: 33 MHz
-		8:1 ratio CCB clocks:SYSCLK
-		3:1 ration e500 Core:CCB
-		pos1 - on, pos2 - on, pos3 - on, pos4 - off, pos5 - off, pos6 - on
-
-
-Flashing the FLASH device with the "Wind River ICE":
-
-1) Properly connect and configure the Wind River ICE to the target
-   JTAG port. This includes running the SBC8560 register script. Make
-   sure target memory can be read and written.
-
-2) Build the u-boot image:
-	make distclean
-	make SBC8560_66_config or SBC8560_33_config
-	make CROSS_COMPILE=.../ELDK3.0/ppc_8xx-/ all
-
-   Note: reference is made to the ELDK3.0 compiler. Further, it seems
-	 the ppc_8xx compiler is required for the 85xx (no 85xx
-	 designated compiler in ELDK3.0)
-
-3) Convert the uboot (.elf) file to a uboot.bin file (using
-   visionClick converter). The bin file should be converted from
-   fffc0000 to ffffffff
-
-4) Setup the Flash Utility (tools menu) for:
-
-   Do a "dc clr" [visionClick] to load the default register settings
-   Determine the clock speed of the PCI bus and set SW9 accordingly
-	Note: the speed of the PCI bus defaults to the slowest PCI card
-   PlayBack the "default" register file for the SBC8560
-   Select the uboot.bin file with zero bias
-   Select the initialize Target prior to programming
-   Select the V28F640Jx (8192 x 8) 1 device FLASH Algorithm
-   Select the erase base address from FFFC0000 to FFFFFFFF
-   Select the start address from 0 with size of 4000
-
-5) Erase and Program
diff -urN u-boot-1.1.6/drivers/cfi_flash.c u-boot-1.1.6_jz2440/drivers/cfi_flash.c
--- u-boot-1.1.6/drivers/cfi_flash.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/drivers/cfi_flash.c	2010-11-26 12:54:38.306059089 +0800
@@ -4,11 +4,12 @@
  *
  * Copyright (C) 2003 Arabella Software Ltd.
  * Yuli Barcohen <yuli@arabellasw.com>
- * Modified to work with AMD flashes
  *
  * Copyright (C) 2004
  * Ed Okerson
- * Modified to work with little-endian systems.
+ *
+ * Copyright (C) 2006
+ * Tolunay Orkun <listmember@orkun.us>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -28,17 +29,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  *
- * History
- * 01/20/2004 - combined variants of original driver.
- * 01/22/2004 - Write performance enhancements for parallel chips (Tolunay)
- * 01/23/2004 - Support for x8/x16 chips (Rune Raknerud)
- * 01/27/2004 - Little endian support Ed Okerson
- *
- * Tested Architectures
- * Port Width  Chip Width    # of banks	   Flash Chip  Board
- * 32	       16	     1		   28F128J3    seranoa/eagle
- * 64	       16	     1		   28F128J3    seranoa/falcon
- *
  */
 
 /* The DEBUG define must be before common to enable debugging */
@@ -46,29 +36,30 @@
 
 #include <common.h>
 #include <asm/processor.h>
+#include <asm/io.h>
 #include <asm/byteorder.h>
 #include <environment.h>
 #ifdef	CFG_FLASH_CFI_DRIVER
 
 /*
- * This file implements a Common Flash Interface (CFI) driver for U-Boot.
- * The width of the port and the width of the chips are determined at initialization.
- * These widths are used to calculate the address for access CFI data structures.
- * It has been tested on an Intel Strataflash implementation and AMD 29F016D.
+ * This file implements a Common Flash Interface (CFI) driver for
+ * U-Boot.
+ *
+ * The width of the port and the width of the chips are determined at
+ * initialization.  These widths are used to calculate the address for
+ * access CFI data structures.
  *
  * References
  * JEDEC Standard JESD68 - Common Flash Interface (CFI)
  * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes
  * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets
  * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet
+ * AMD CFI Specification, Release 2.0 December 1, 2001
+ * AMD/Spansion Application Note: Migration from Single-byte to Three-byte
+ *   Device IDs, Publication Number 25538 Revision A, November 8, 2001
  *
- * TODO
- *
- * Use Primary Extended Query table (PRI) and Alternate Algorithm Query
- * Table (ALT) to determine if protection is available
- *
- * Add support for other command sets Use the PRI and ALT to determine command set
- * Verify erase and program timeouts.
+ * Define CFG_WRITE_SWAPPED_DATA, if you have to swap the Bytes between
+ * reading and writing ... (yes there is such a Hardware).
  */
 
 #ifndef CFG_FLASH_BANKS_LIST
@@ -85,7 +76,9 @@
 #define FLASH_CMD_PROTECT_SET		0x01
 #define FLASH_CMD_PROTECT_CLEAR		0xD0
 #define FLASH_CMD_CLEAR_STATUS		0x50
+#define FLASH_CMD_READ_STATUS		0x70
 #define FLASH_CMD_WRITE_TO_BUFFER	0xE8
+#define FLASH_CMD_WRITE_BUFFER_PROG	0xE9
 #define FLASH_CMD_WRITE_BUFFER_CONFIRM	0xD0
 
 #define FLASH_STATUS_DONE		0x80
@@ -110,14 +103,16 @@
 #define AMD_STATUS_TOGGLE		0x40
 #define AMD_STATUS_ERROR		0x20
 
-#define AMD_ADDR_ERASE_START	((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
-#define AMD_ADDR_START		((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
-#define AMD_ADDR_ACK		((info->portwidth == FLASH_CFI_8BIT) ? 0x555 : 0x2AA)
-
+#define FLASH_OFFSET_MANUFACTURER_ID	0x00
+#define FLASH_OFFSET_DEVICE_ID		0x01
+#define FLASH_OFFSET_DEVICE_ID2		0x0E
+#define FLASH_OFFSET_DEVICE_ID3		0x0F
 #define FLASH_OFFSET_CFI		0x55
+#define FLASH_OFFSET_CFI_ALT		0x555
 #define FLASH_OFFSET_CFI_RESP		0x10
 #define FLASH_OFFSET_PRIMARY_VENDOR	0x13
-#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR	0x15	/* extended query table primary addr */
+/* extended query table primary address */
+#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR	0x15
 #define FLASH_OFFSET_WTOUT		0x1F
 #define FLASH_OFFSET_WBTOUT		0x20
 #define FLASH_OFFSET_ETOUT		0x21
@@ -135,22 +130,19 @@
 #define FLASH_OFFSET_USER_PROTECTION	0x85
 #define FLASH_OFFSET_INTEL_PROTECTION	0x81
 
-
-#define FLASH_MAN_CFI			0x01000000
-
-#define CFI_CMDSET_NONE		    0
-#define CFI_CMDSET_INTEL_EXTENDED   1
-#define CFI_CMDSET_AMD_STANDARD	    2
-#define CFI_CMDSET_INTEL_STANDARD   3
-#define CFI_CMDSET_AMD_EXTENDED	    4
-#define CFI_CMDSET_MITSU_STANDARD   256
-#define CFI_CMDSET_MITSU_EXTENDED   257
-#define CFI_CMDSET_SST		    258
-
+#define CFI_CMDSET_NONE			0
+#define CFI_CMDSET_INTEL_EXTENDED	1
+#define CFI_CMDSET_AMD_STANDARD		2
+#define CFI_CMDSET_INTEL_STANDARD	3
+#define CFI_CMDSET_AMD_EXTENDED		4
+#define CFI_CMDSET_MITSU_STANDARD	256
+#define CFI_CMDSET_MITSU_EXTENDED	257
+#define CFI_CMDSET_SST			258
+#define CFI_CMDSET_INTEL_PROG_REGIONS	512
 
 #ifdef CFG_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on UC100 */
 # undef  FLASH_CMD_RESET
-# define FLASH_CMD_RESET                AMD_CMD_RESET /* use AMD-Reset instead */
+# define FLASH_CMD_RESET	AMD_CMD_RESET /* use AMD-Reset instead */
 #endif
 
 
@@ -161,24 +153,19 @@
 	unsigned long long ll;
 } cfiword_t;
 
-typedef union {
-	volatile unsigned char *cp;
-	volatile unsigned short *wp;
-	volatile unsigned long *lp;
-	volatile unsigned long long *llp;
-} cfiptr_t;
+#define NUM_ERASE_REGIONS	4 /* max. number of erase regions */
 
-#define NUM_ERASE_REGIONS 4
+static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT };
 
 /* use CFG_MAX_FLASH_BANKS_DETECT if defined */
 #ifdef CFG_MAX_FLASH_BANKS_DETECT
-static ulong bank_base[CFG_MAX_FLASH_BANKS_DETECT] = CFG_FLASH_BANKS_LIST;
-flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT];	/* FLASH chips info */
+# define CFI_MAX_FLASH_BANKS	CFG_MAX_FLASH_BANKS_DETECT
 #else
-static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST;
-flash_info_t flash_info[CFG_MAX_FLASH_BANKS];		/* FLASH chips info */
+# define CFI_MAX_FLASH_BANKS	CFG_MAX_FLASH_BANKS
 #endif
 
+flash_info_t flash_info[CFI_MAX_FLASH_BANKS];	/* FLASH chips info */
+
 /*
  * Check if chip width is defined. If not, start detecting with 8bit.
  */
@@ -186,45 +173,187 @@
 #define CFG_FLASH_CFI_WIDTH	FLASH_CFI_8BIT
 #endif
 
+typedef unsigned long flash_sect_t;
 
-/*-----------------------------------------------------------------------
- * Functions
+/* CFI standard query structure */
+struct cfi_qry {
+	u8	qry[3];
+	u16	p_id;
+	u16	p_adr;
+	u16	a_id;
+	u16	a_adr;
+	u8	vcc_min;
+	u8	vcc_max;
+	u8	vpp_min;
+	u8	vpp_max;
+	u8	word_write_timeout_typ;
+	u8	buf_write_timeout_typ;
+	u8	block_erase_timeout_typ;
+	u8	chip_erase_timeout_typ;
+	u8	word_write_timeout_max;
+	u8	buf_write_timeout_max;
+	u8	block_erase_timeout_max;
+	u8	chip_erase_timeout_max;
+	u8	dev_size;
+	u16	interface_desc;
+	u16	max_buf_write_size;
+	u8	num_erase_regions;
+	u32	erase_region_info[NUM_ERASE_REGIONS];
+} __attribute__((packed));
+
+struct cfi_pri_hdr {
+	u8	pri[3];
+	u8	major_version;
+	u8	minor_version;
+} __attribute__((packed));
+
+/*
+ * Given a physical address and a length, return a virtual address
+ * that can be used to access the memory range with the caching
+ * properties specified by "flags".
  */
+#define MAP_NOCACHE	(0)
+#define MAP_WRCOMBINE	(0)
+#define MAP_WRBACK	(0)
+#define MAP_WRTHROUGH	(0)
 
-typedef unsigned long flash_sect_t;
+#define sync()		/* nothing */
 
-static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c);
-static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf);
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect);
-static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
-static int flash_detect_cfi (flash_info_t * info);
-static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
-static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
-				    ulong tout, char *prompt);
-ulong flash_get_size (ulong base, int banknum);
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+	return (void *)paddr;
+}
+
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+
+}
+
+static void flash_write8(u8 value, void *addr)
+{
+	__raw_writeb(value, addr);
+}
+
+static void flash_write16(u16 value, void *addr)
+{
+	__raw_writew(value, addr);
+}
+
+static void flash_write32(u32 value, void *addr)
+{
+	__raw_writel(value, addr);
+}
+
+static void flash_write64(u64 value, void *addr)
+{
+	/* No architectures currently implement __raw_writeq() */
+	*(volatile u64 *)addr = value;
+}
+
+static u8 flash_read8(void *addr)
+{
+	return __raw_readb(addr);
+}
+
+static u16 flash_read16(void *addr)
+{
+	return __raw_readw(addr);
+}
+
+static u32 flash_read32(void *addr)
+{
+	return __raw_readl(addr);
+}
+
+static u64 __flash_read64(void *addr)
+{
+	/* No architectures currently implement __raw_readq() */
+	return *(volatile u64 *)addr;
+}
+
+u64 flash_read64(void *addr)__attribute__((weak, alias("__flash_read64")));
+
+/*-----------------------------------------------------------------------
+ */
 #if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
-static flash_info_t *flash_get_info(ulong base);
-#endif
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
-static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len);
+static flash_info_t *flash_get_info(ulong base)
+{
+	int i;
+	flash_info_t * info = 0;
+
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
+		info = & flash_info[i];
+		if (info->size && info->start[0] <= base &&
+		    base <= info->start[0] + info->size - 1)
+			break;
+	}
+
+	return i == CFG_MAX_FLASH_BANKS ? 0 : info;
+}
 #endif
 
+unsigned long flash_sector_size(flash_info_t *info, flash_sect_t sect)
+{
+	if (sect != (info->sector_count - 1))
+		return info->start[sect + 1] - info->start[sect];
+	else
+		return info->start[0] + info->size - info->start[sect];
+}
+
 /*-----------------------------------------------------------------------
  * create an address based on the offset and the port width
  */
-inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)
+static inline void *
+flash_map (flash_info_t * info, flash_sect_t sect, uint offset)
+{
+	unsigned int byte_offset = offset * info->portwidth;
+
+	return map_physmem(info->start[sect] + byte_offset,
+			flash_sector_size(info, sect) - byte_offset,
+			MAP_NOCACHE);
+}
+
+static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
+		unsigned int offset, void *addr)
+{
+	unsigned int byte_offset = offset * info->portwidth;
+
+	unmap_physmem(addr, flash_sector_size(info, sect) - byte_offset);
+}
+
+/*-----------------------------------------------------------------------
+ * make a proper sized command based on the port and chip widths
+ */
+static void flash_make_cmd(flash_info_t *info, u32 cmd, void *cmdbuf)
 {
-	return ((uchar *) (info->start[sect] + (offset * info->portwidth)));
+	int i;
+	int cword_offset;
+	int cp_offset;
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
+	u32 cmd_le = cpu_to_le32(cmd);
+#endif
+	uchar val;
+	uchar *cp = (uchar *) cmdbuf;
+
+	for (i = info->portwidth; i > 0; i--){
+		cword_offset = (info->portwidth-i)%info->chipwidth;
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
+		cp_offset = info->portwidth - i;
+		val = *((uchar*)&cmd_le + cword_offset);
+#else
+		cp_offset = i - 1;
+		val = *((uchar*)&cmd + sizeof(u32) - cword_offset - 1);
+#endif
+		cp[cp_offset] = (cword_offset >= sizeof(u32)) ? 0x00 : val;
+	}
 }
 
 #ifdef DEBUG
 /*-----------------------------------------------------------------------
  * Debug support
  */
-void print_longlong (char *str, unsigned long long data)
+static void print_longlong (char *str, unsigned long long data)
 {
 	int i;
 	char *cp;
@@ -233,28 +362,25 @@
 	for (i = 0; i < 8; i++)
 		sprintf (&str[i * 2], "%2.2x", *cp++);
 }
-static void flash_printqry (flash_info_t * info, flash_sect_t sect)
+
+static void flash_printqry (struct cfi_qry *qry)
 {
-	cfiptr_t cptr;
+	u8 *p = (u8 *)qry;
 	int x, y;
 
-	for (x = 0; x < 0x40; x += 16U / info->portwidth) {
-		cptr.cp =
-			flash_make_addr (info, sect,
-					 x + FLASH_OFFSET_CFI_RESP);
-		debug ("%p : ", cptr.cp);
-		for (y = 0; y < 16; y++) {
-			debug ("%2.2x ", cptr.cp[y]);
-		}
-		debug (" ");
+	for (x = 0; x < sizeof(struct cfi_qry); x += 16) {
+		debug("%02x : ", x);
+		for (y = 0; y < 16; y++)
+			debug("%2.2x ", p[x + y]);
+		debug(" ");
 		for (y = 0; y < 16; y++) {
-			if (cptr.cp[y] >= 0x20 && cptr.cp[y] <= 0x7e) {
-				debug ("%c", cptr.cp[y]);
-			} else {
-				debug (".");
-			}
+			unsigned char c = p[x + y];
+			if (c >= 0x20 && c <= 0x7e)
+				debug("%c", c);
+			else
+				debug(".");
 		}
-		debug ("\n");
+		debug("\n");
 	}
 }
 #endif
@@ -263,54 +389,41 @@
 /*-----------------------------------------------------------------------
  * read a character at a port width address
  */
-inline uchar flash_read_uchar (flash_info_t * info, uint offset)
+static inline uchar flash_read_uchar (flash_info_t * info, uint offset)
 {
 	uchar *cp;
+	uchar retval;
 
-	cp = flash_make_addr (info, 0, offset);
-#if defined(__LITTLE_ENDIAN)
-	return (cp[0]);
+	cp = flash_map (info, 0, offset);
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
+	retval = flash_read8(cp);
 #else
-	return (cp[info->portwidth - 1]);
+	retval = flash_read8(cp + info->portwidth - 1);
 #endif
+	flash_unmap (info, 0, offset, cp);
+	return retval;
 }
 
 /*-----------------------------------------------------------------------
- * read a short word by swapping for ppc format.
+ * read a word at a port width address, assume 16bit bus
  */
-ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)
+static inline ushort flash_read_word (flash_info_t * info, uint offset)
 {
-	uchar *addr;
-	ushort retval;
+	ushort *addr, retval;
 
-#ifdef DEBUG
-	int x;
-#endif
-	addr = flash_make_addr (info, sect, offset);
-
-#ifdef DEBUG
-	debug ("ushort addr is at %p info->portwidth = %d\n", addr,
-	       info->portwidth);
-	for (x = 0; x < 2 * info->portwidth; x++) {
-		debug ("addr[%x] = 0x%x\n", x, addr[x]);
-	}
-#endif
-#if defined(__LITTLE_ENDIAN)
-	retval = ((addr[(info->portwidth)] << 8) | addr[0]);
-#else
-	retval = ((addr[(2 * info->portwidth) - 1] << 8) |
-		  addr[info->portwidth - 1]);
-#endif
-
-	debug ("retval = 0x%x\n", retval);
+	addr = flash_map (info, 0, offset);
+	retval = flash_read16 (addr);
+	flash_unmap (info, 0, offset, addr);
 	return retval;
 }
 
+
 /*-----------------------------------------------------------------------
- * read a long word by picking the least significant byte of each maiximum
+ * read a long word by picking the least significant byte of each maximum
  * port size word. Swap for ppc format.
  */
-ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
+static ulong flash_read_long (flash_info_t * info, flash_sect_t sect,
+			      uint offset)
 {
 	uchar *addr;
 	ulong retval;
@@ -318,449 +431,224 @@
 #ifdef DEBUG
 	int x;
 #endif
-	addr = flash_make_addr (info, sect, offset);
+	addr = flash_map (info, sect, offset);
 
 #ifdef DEBUG
 	debug ("long addr is at %p info->portwidth = %d\n", addr,
 	       info->portwidth);
 	for (x = 0; x < 4 * info->portwidth; x++) {
-		debug ("addr[%x] = 0x%x\n", x, addr[x]);
+		debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
 	}
 #endif
-#if defined(__LITTLE_ENDIAN)
-	retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) |
-		(addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);
+#if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA)
+	retval = ((flash_read8(addr) << 16) |
+		  (flash_read8(addr + info->portwidth) << 24) |
+		  (flash_read8(addr + 2 * info->portwidth)) |
+		  (flash_read8(addr + 3 * info->portwidth) << 8));
 #else
-	retval = (addr[(2 * info->portwidth) - 1] << 24) |
-		(addr[(info->portwidth) - 1] << 16) |
-		(addr[(4 * info->portwidth) - 1] << 8) |
-		addr[(3 * info->portwidth) - 1];
+	retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) |
+		  (flash_read8(addr + info->portwidth - 1) << 16) |
+		  (flash_read8(addr + 4 * info->portwidth - 1) << 8) |
+		  (flash_read8(addr + 3 * info->portwidth - 1)));
 #endif
+	flash_unmap(info, sect, offset, addr);
+
 	return retval;
 }
 
-
-/*-----------------------------------------------------------------------
+/*
+ * Write a proper sized command to the correct address
  */
-unsigned long flash_init (void)
+static void flash_write_cmd (flash_info_t * info, flash_sect_t sect,
+			     uint offset, u32 cmd)
 {
-	unsigned long size = 0;
-	int i;
-
-#ifdef CFG_FLASH_PROTECTION
-	char *s = getenv("unlock");
-#endif
-
-	/* Init: no FLASHes known */
-	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
-		flash_info[i].flash_id = FLASH_UNKNOWN;
-		size += flash_info[i].size = flash_get_size (bank_base[i], i);
-		if (flash_info[i].flash_id == FLASH_UNKNOWN) {
-#ifndef CFG_FLASH_QUIET_TEST
-			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
-				i, flash_info[i].size, flash_info[i].size << 20);
-#endif /* CFG_FLASH_QUIET_TEST */
-		}
-#ifdef CFG_FLASH_PROTECTION
-		else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
-			/*
-			 * Only the U-Boot image and it's environment is protected,
-			 * all other sectors are unprotected (unlocked) if flash
-			 * hardware protection is used (CFG_FLASH_PROTECTION) and
-			 * the environment variable "unlock" is set to "yes".
-			 */
-			if (flash_info[i].legacy_unlock) {
-				int k;
 
-				/*
-				 * Disable legacy_unlock temporarily, since
-				 * flash_real_protect would relock all other sectors
-				 * again otherwise.
-				 */
-				flash_info[i].legacy_unlock = 0;
+	void *addr;
+	cfiword_t cword;
 
-				/*
-				 * Legacy unlocking (e.g. Intel J3) -> unlock only one
-				 * sector. This will unlock all sectors.
-				 */
-				flash_real_protect (&flash_info[i], 0, 0);
+	addr = flash_map (info, sect, offset);
+	flash_make_cmd (info, cmd, &cword);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
+		       cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		flash_write8(cword.c, addr);
+		break;
+	case FLASH_CFI_16BIT:
+		debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
+		       cmd, cword.w,
+		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		flash_write16(cword.w, addr);
+		break;
+	case FLASH_CFI_32BIT:
+		debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
+		       cmd, cword.l,
+		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		flash_write32(cword.l, addr);
+		break;
+	case FLASH_CFI_64BIT:
+#ifdef DEBUG
+		{
+			char str[20];
 
-				flash_info[i].legacy_unlock = 1;
+			print_longlong (str, cword.ll);
 
-				/*
-				 * Manually mark other sectors as unlocked (unprotected)
-				 */
-				for (k = 1; k < flash_info[i].sector_count; k++)
-					flash_info[i].protect[k] = 0;
-			} else {
-				/*
-				 * No legancy unlocking -> unlock all sectors
-				 */
-				flash_protect (FLAG_PROTECT_CLEAR,
-					       flash_info[i].start[0],
-					       flash_info[i].start[0] + flash_info[i].size - 1,
-					       &flash_info[i]);
-			}
+			debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
+			       addr, cmd, str,
+			       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
 		}
-#endif /* CFG_FLASH_PROTECTION */
+#endif
+		flash_write64(cword.ll, addr);
+		break;
 	}
 
-	/* Monitor protection ON by default */
-#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
-	flash_protect (FLAG_PROTECT_SET,
-		       CFG_MONITOR_BASE,
-		       CFG_MONITOR_BASE + monitor_flash_len  - 1,
-		       flash_get_info(CFG_MONITOR_BASE));
-#endif
+	/* Ensure all the instructions are fully finished */
+	sync();
 
-	/* Environment protection ON by default */
-#ifdef CFG_ENV_IS_IN_FLASH
-	flash_protect (FLAG_PROTECT_SET,
-		       CFG_ENV_ADDR,
-		       CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
-		       flash_get_info(CFG_ENV_ADDR));
-#endif
+	flash_unmap(info, sect, offset, addr);
+}
 
-	/* Redundant environment protection ON by default */
-#ifdef CFG_ENV_ADDR_REDUND
-	flash_protect (FLAG_PROTECT_SET,
-		       CFG_ENV_ADDR_REDUND,
-		       CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
-		       flash_get_info(CFG_ENV_ADDR_REDUND));
-#endif
-	return (size);
+static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
+{
+	flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START);
+	flash_write_cmd (info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
 }
 
 /*-----------------------------------------------------------------------
  */
-#if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
-static flash_info_t *flash_get_info(ulong base)
+static int flash_isequal (flash_info_t * info, flash_sect_t sect,
+			  uint offset, uchar cmd)
 {
-	int i;
-	flash_info_t * info = 0;
+	void *addr;
+	cfiword_t cword;
+	int retval;
 
-	for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
-		info = & flash_info[i];
-		if (info->size && info->start[0] <= base &&
-		    base <= info->start[0] + info->size - 1)
-			break;
+	addr = flash_map (info, sect, offset);
+	flash_make_cmd (info, cmd, &cword);
+
+	debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		debug ("is= %x %x\n", flash_read8(addr), cword.c);
+		retval = (flash_read8(addr) == cword.c);
+		break;
+	case FLASH_CFI_16BIT:
+		debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
+		retval = (flash_read16(addr) == cword.w);
+		break;
+	case FLASH_CFI_32BIT:
+		debug ("is= %8.8lx %8.8lx\n", flash_read32(addr), cword.l);
+		retval = (flash_read32(addr) == cword.l);
+		break;
+	case FLASH_CFI_64BIT:
+#ifdef DEBUG
+		{
+			char str1[20];
+			char str2[20];
+
+			print_longlong (str1, flash_read64(addr));
+			print_longlong (str2, cword.ll);
+			debug ("is= %s %s\n", str1, str2);
+		}
+#endif
+		retval = (flash_read64(addr) == cword.ll);
+		break;
+	default:
+		retval = 0;
+		break;
 	}
+	flash_unmap(info, sect, offset, addr);
 
-	return i == CFG_MAX_FLASH_BANKS ? 0 : info;
+	return retval;
 }
-#endif
 
 /*-----------------------------------------------------------------------
  */
-int flash_erase (flash_info_t * info, int s_first, int s_last)
+static int flash_isset (flash_info_t * info, flash_sect_t sect,
+			uint offset, uchar cmd)
 {
-	int rcode = 0;
-	int prot;
-	flash_sect_t sect;
-
-	if (info->flash_id != FLASH_MAN_CFI) {
-		puts ("Can't erase unknown flash type - aborted\n");
-		return 1;
-	}
-	if ((s_first < 0) || (s_first > s_last)) {
-		puts ("- no sectors to erase\n");
-		return 1;
-	}
+	void *addr;
+	cfiword_t cword;
+	int retval;
 
-	prot = 0;
-	for (sect = s_first; sect <= s_last; ++sect) {
-		if (info->protect[sect]) {
-			prot++;
-		}
-	}
-	if (prot) {
-		printf ("- Warning: %d protected sectors will not be erased!\n", prot);
-	} else {
-		putc ('\n');
-	}
-
-
-	for (sect = s_first; sect <= s_last; sect++) {
-		if (info->protect[sect] == 0) { /* not protected */
-			switch (info->vendor) {
-			case CFI_CMDSET_INTEL_STANDARD:
-			case CFI_CMDSET_INTEL_EXTENDED:
-				flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS);
-				flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE);
-				flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
-				break;
-			case CFI_CMDSET_AMD_STANDARD:
-			case CFI_CMDSET_AMD_EXTENDED:
-				flash_unlock_seq (info, sect);
-				flash_write_cmd (info, sect, AMD_ADDR_ERASE_START,
-							AMD_CMD_ERASE_START);
-				flash_unlock_seq (info, sect);
-				flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);
-				break;
-			default:
-				debug ("Unkown flash vendor %d\n",
-				       info->vendor);
-				break;
-			}
-
-			if (flash_full_status_check
-			    (info, sect, info->erase_blk_tout, "erase")) {
-				rcode = 1;
-			} else
-				putc ('.');
-		}
-	}
-	puts (" done\n");
-	return rcode;
-}
-
-/*-----------------------------------------------------------------------
- */
-void flash_print_info (flash_info_t * info)
-{
-	int i;
-
-	if (info->flash_id != FLASH_MAN_CFI) {
-		puts ("missing or unknown FLASH type\n");
-		return;
+	addr = flash_map (info, sect, offset);
+	flash_make_cmd (info, cmd, &cword);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		retval = ((flash_read8(addr) & cword.c) == cword.c);
+		break;
+	case FLASH_CFI_16BIT:
+		retval = ((flash_read16(addr) & cword.w) == cword.w);
+		break;
+	case FLASH_CFI_32BIT:
+		retval = ((flash_read32(addr) & cword.l) == cword.l);
+		break;
+	case FLASH_CFI_64BIT:
+		retval = ((flash_read64(addr) & cword.ll) == cword.ll);
+		break;
+	default:
+		retval = 0;
+		break;
 	}
+	flash_unmap(info, sect, offset, addr);
 
-	printf ("CFI conformant FLASH (%d x %d)",
-		(info->portwidth << 3), (info->chipwidth << 3));
-	printf ("  Size: %ld MB in %d Sectors\n",
-		info->size >> 20, info->sector_count);
-	printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n",
-		info->erase_blk_tout,
-		info->write_tout,
-		info->buffer_write_tout,
-		info->buffer_size);
-
-	puts ("  Sector Start Addresses:");
-	for (i = 0; i < info->sector_count; ++i) {
-#ifdef CFG_FLASH_EMPTY_INFO
-		int k;
-		int size;
-		int erased;
-		volatile unsigned long *flash;
-
-		/*
-		 * Check if whole sector is erased
-		 */
-		if (i != (info->sector_count - 1))
-			size = info->start[i + 1] - info->start[i];
-		else
-			size = info->start[0] + info->size - info->start[i];
-		erased = 1;
-		flash = (volatile unsigned long *) info->start[i];
-		size = size >> 2;	/* divide by 4 for longword access */
-		for (k = 0; k < size; k++) {
-			if (*flash++ != 0xffffffff) {
-				erased = 0;
-				break;
-			}
-		}
-
-		if ((i % 5) == 0)
-			printf ("\n");
-		/* print empty and read-only info */
-		printf (" %08lX%s%s",
-			info->start[i],
-			erased ? " E" : "  ",
-			info->protect[i] ? "RO " : "   ");
-#else	/* ! CFG_FLASH_EMPTY_INFO */
-		if ((i % 5) == 0)
-			printf ("\n   ");
-		printf (" %08lX%s",
-			info->start[i], info->protect[i] ? " (RO)" : "     ");
-#endif
-	}
-	putc ('\n');
-	return;
+	return retval;
 }
 
 /*-----------------------------------------------------------------------
- * Copy memory to flash, returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
  */
-int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+static int flash_toggle (flash_info_t * info, flash_sect_t sect,
+			 uint offset, uchar cmd)
 {
-	ulong wp;
-	ulong cp;
-	int aln;
+	void *addr;
 	cfiword_t cword;
-	int i, rc;
-
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
-	int buffered_size;
-#endif
-	/* get lower aligned address */
-	/* get lower aligned address */
-	wp = (addr & ~(info->portwidth - 1));
-
-	/* handle unaligned start */
-	if ((aln = addr - wp) != 0) {
-		cword.l = 0;
-		cp = wp;
-		for (i = 0; i < aln; ++i, ++cp)
-			flash_add_byte (info, &cword, (*(uchar *) cp));
-
-		for (; (i < info->portwidth) && (cnt > 0); i++) {
-			flash_add_byte (info, &cword, *src++);
-			cnt--;
-			cp++;
-		}
-		for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp)
-			flash_add_byte (info, &cword, (*(uchar *) cp));
-		if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
-			return rc;
-		wp = cp;
-	}
-
-	/* handle the aligned part */
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
-	buffered_size = (info->portwidth / info->chipwidth);
-	buffered_size *= info->buffer_size;
-	while (cnt >= info->portwidth) {
-		/* prohibit buffer write when buffer_size is 1 */
-		if (info->buffer_size == 1) {
-			cword.l = 0;
-			for (i = 0; i < info->portwidth; i++)
-				flash_add_byte (info, &cword, *src++);
-			if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
-				return rc;
-			wp += info->portwidth;
-			cnt -= info->portwidth;
-			continue;
-		}
-
-		/* write buffer until next buffered_size aligned boundary */
-		i = buffered_size - (wp % buffered_size);
-		if (i > cnt)
-			i = cnt;
-		if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
-			return rc;
-		i -= i & (info->portwidth - 1);
-		wp += i;
-		src += i;
-		cnt -= i;
-	}
-#else
-	while (cnt >= info->portwidth) {
-		cword.l = 0;
-		for (i = 0; i < info->portwidth; i++) {
-			flash_add_byte (info, &cword, *src++);
-		}
-		if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
-			return rc;
-		wp += info->portwidth;
-		cnt -= info->portwidth;
-	}
-#endif /* CFG_FLASH_USE_BUFFER_WRITE */
-	if (cnt == 0) {
-		return (0);
-	}
-
-	/*
-	 * handle unaligned tail bytes
-	 */
-	cword.l = 0;
-	for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) {
-		flash_add_byte (info, &cword, *src++);
-		--cnt;
-	}
-	for (; i < info->portwidth; ++i, ++cp) {
-		flash_add_byte (info, &cword, (*(uchar *) cp));
-	}
-
-	return flash_write_cfiword (info, wp, cword);
-}
-
-/*-----------------------------------------------------------------------
- */
-#ifdef CFG_FLASH_PROTECTION
-
-int flash_real_protect (flash_info_t * info, long sector, int prot)
-{
-	int retcode = 0;
-
-	flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
-	flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
-	if (prot)
-		flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
-	else
-		flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
-
-	if ((retcode =
-	     flash_full_status_check (info, sector, info->erase_blk_tout,
-				      prot ? "protect" : "unprotect")) == 0) {
-
-		info->protect[sector] = prot;
-
-		/*
-		 * On some of Intel's flash chips (marked via legacy_unlock)
-		 * unprotect unprotects all locking.
-		 */
-		if ((prot == 0) && (info->legacy_unlock)) {
-			flash_sect_t i;
+	int retval;
 
-			for (i = 0; i < info->sector_count; i++) {
-				if (info->protect[i])
-					flash_real_protect (info, i, 1);
-			}
-		}
+	addr = flash_map (info, sect, offset);
+	flash_make_cmd (info, cmd, &cword);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		retval = flash_read8(addr) != flash_read8(addr);
+		break;
+	case FLASH_CFI_16BIT:
+		retval = flash_read16(addr) != flash_read16(addr);
+		break;
+	case FLASH_CFI_32BIT:
+		retval = flash_read32(addr) != flash_read32(addr);
+		break;
+	case FLASH_CFI_64BIT:
+		retval = flash_read64(addr) != flash_read64(addr);
+		break;
+	default:
+		retval = 0;
+		break;
 	}
-	return retcode;
-}
+	flash_unmap(info, sect, offset, addr);
 
-/*-----------------------------------------------------------------------
- * flash_read_user_serial - read the OneTimeProgramming cells
- */
-void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
-			     int len)
-{
-	uchar *src;
-	uchar *dst;
-
-	dst = buffer;
-	src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
-	flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
-	memcpy (dst, src + offset, len);
-	flash_write_cmd (info, 0, 0, info->cmd_reset);
-}
-
-/*
- * flash_read_factory_serial - read the device Id from the protection area
- */
-void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
-				int len)
-{
-	uchar *src;
-
-	src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
-	flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
-	memcpy (buffer, src + offset, len);
-	flash_write_cmd (info, 0, 0, info->cmd_reset);
+	return retval;
 }
 
-#endif /* CFG_FLASH_PROTECTION */
-
 /*
  * flash_is_busy - check to see if the flash is busy
- * This routine checks the status of the chip and returns true if the chip is busy
+ *
+ * This routine checks the status of the chip and returns true if the
+ * chip is busy.
  */
 static int flash_is_busy (flash_info_t * info, flash_sect_t sect)
 {
 	int retval;
 
 	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
 	case CFI_CMDSET_INTEL_STANDARD:
 	case CFI_CMDSET_INTEL_EXTENDED:
 		retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
 		break;
 	case CFI_CMDSET_AMD_STANDARD:
 	case CFI_CMDSET_AMD_EXTENDED:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
+#endif
 		retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
 		break;
 	default:
@@ -799,7 +687,9 @@
 }
 
 /*-----------------------------------------------------------------------
- * Wait for XSR.7 to be set, if it times out print an error, otherwise do a full status check.
+ * Wait for XSR.7 to be set, if it times out print an error, otherwise
+ * do a full status check.
+ *
  * This routine sets the flash to read-array mode.
  */
 static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
@@ -809,6 +699,7 @@
 
 	retcode = flash_status_check (info, sector, tout, prompt);
 	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
 	case CFI_CMDSET_INTEL_EXTENDED:
 	case CFI_CMDSET_INTEL_STANDARD:
 		if ((retcode == ERR_OK)
@@ -816,12 +707,15 @@
 			retcode = ERR_INVAL;
 			printf ("Flash %s error at address %lx\n", prompt,
 				info->start[sector]);
-			if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
+			if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS |
+					 FLASH_STATUS_PSLBS)) {
 				puts ("Command Sequence Error.\n");
-			} else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
+			} else if (flash_isset (info, sector, 0,
+						FLASH_STATUS_ECLBS)) {
 				puts ("Block Erase Error.\n");
 				retcode = ERR_NOT_ERASED;
-			} else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
+			} else if (flash_isset (info, sector, 0,
+						FLASH_STATUS_PSLBS)) {
 				puts ("Locking Error\n");
 			}
 			if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
@@ -843,7 +737,7 @@
  */
 static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c)
 {
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
 	unsigned short	w;
 	unsigned int	l;
 	unsigned long long ll;
@@ -854,7 +748,7 @@
 		cword->c = c;
 		break;
 	case FLASH_CFI_16BIT:
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
 		w = c;
 		w <<= 8;
 		cword->w = (cword->w >> 8) | w;
@@ -863,7 +757,7 @@
 #endif
 		break;
 	case FLASH_CFI_32BIT:
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
 		l = c;
 		l <<= 24;
 		cword->l = (cword->l >> 8) | l;
@@ -872,7 +766,7 @@
 #endif
 		break;
 	case FLASH_CFI_64BIT:
-#if defined(__LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA)
 		ll = c;
 		ll <<= 56;
 		cword->ll = (cword->ll >> 8) | ll;
@@ -883,199 +777,922 @@
 	}
 }
 
-
-/*-----------------------------------------------------------------------
- * make a proper sized command based on the port and chip widths
+/* loop through the sectors from the highest address when the passed
+ * address is greater or equal to the sector address we have a match
  */
-static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)
+static flash_sect_t find_sector (flash_info_t * info, ulong addr)
 {
-	int i;
-	uchar *cp = (uchar *) cmdbuf;
+	flash_sect_t sector;
 
-#if defined(__LITTLE_ENDIAN)
-	for (i = info->portwidth; i > 0; i--)
-#else
-	for (i = 1; i <= info->portwidth; i++)
-#endif
-		*cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
+	for (sector = info->sector_count - 1; sector >= 0; sector--) {
+		if (addr >= info->start[sector])
+			break;
+	}
+	return sector;
 }
 
-/*
- * Write a proper sized command to the correct address
+/*-----------------------------------------------------------------------
  */
-static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
+static int flash_write_cfiword (flash_info_t * info, ulong dest,
+				cfiword_t cword)
 {
+	void *dstaddr;
+	int flag;
 
-	volatile cfiptr_t addr;
-	cfiword_t cword;
+	dstaddr = map_physmem(dest, info->portwidth, MAP_NOCACHE);
 
-	addr.cp = flash_make_addr (info, sect, offset);
-	flash_make_cmd (info, cmd, &cword);
+	/* Check if Flash is (sufficiently) erased */
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd,
-		       cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
-		*addr.cp = cword.c;
-#ifdef CONFIG_BLACKFIN
-		asm("ssync;");
-#endif
+		flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
 		break;
 	case FLASH_CFI_16BIT:
-		debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp,
-		       cmd, cword.w,
-		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
-		*addr.wp = cword.w;
-#ifdef CONFIG_BLACKFIN
-		asm("ssync;");
-#endif
+		flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
 		break;
 	case FLASH_CFI_32BIT:
-		debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp,
-		       cmd, cword.l,
-		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
-		*addr.lp = cword.l;
-#ifdef CONFIG_BLACKFIN
-		asm("ssync;");
-#endif
+		flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
 		break;
 	case FLASH_CFI_64BIT:
-#ifdef DEBUG
-		{
-			char str[20];
+		flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
+		break;
+	default:
+		flag = 0;
+		break;
+	}
+	if (!flag) {
+		unmap_physmem(dstaddr, info->portwidth);
+		return ERR_NOT_ERASED;
+	}
 
-			print_longlong (str, cword.ll);
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts ();
 
-			debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
-			       addr.llp, cmd, str,
-			       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
-		}
-#endif
-		*addr.llp = cword.ll;
-#ifdef CONFIG_BLACKFIN
-		asm("ssync;");
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_EXTENDED:
+	case CFI_CMDSET_INTEL_STANDARD:
+		flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
+		flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
+		break;
+	case CFI_CMDSET_AMD_EXTENDED:
+	case CFI_CMDSET_AMD_STANDARD:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
 #endif
+		flash_unlock_seq (info, 0);
+		flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE);
 		break;
 	}
-}
-
-static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)
-{
-	flash_write_cmd (info, sect, AMD_ADDR_START, AMD_CMD_UNLOCK_START);
-	flash_write_cmd (info, sect, AMD_ADDR_ACK, AMD_CMD_UNLOCK_ACK);
-}
-
-/*-----------------------------------------------------------------------
- */
-static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
-{
-	cfiptr_t cptr;
-	cfiword_t cword;
-	int retval;
-
-	cptr.cp = flash_make_addr (info, sect, offset);
-	flash_make_cmd (info, cmd, &cword);
 
-	debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp);
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		debug ("is= %x %x\n", cptr.cp[0], cword.c);
-		retval = (cptr.cp[0] == cword.c);
+		flash_write8(cword.c, dstaddr);
 		break;
 	case FLASH_CFI_16BIT:
-		debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w);
-		retval = (cptr.wp[0] == cword.w);
+		flash_write16(cword.w, dstaddr);
 		break;
 	case FLASH_CFI_32BIT:
-		debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l);
-		retval = (cptr.lp[0] == cword.l);
+		flash_write32(cword.l, dstaddr);
 		break;
 	case FLASH_CFI_64BIT:
-#ifdef DEBUG
-		{
-			char str1[20];
-			char str2[20];
-
-			print_longlong (str1, cptr.llp[0]);
-			print_longlong (str2, cword.ll);
-			debug ("is= %s %s\n", str1, str2);
-		}
-#endif
-		retval = (cptr.llp[0] == cword.ll);
-		break;
-	default:
-		retval = 0;
+		flash_write64(cword.ll, dstaddr);
 		break;
 	}
-	return retval;
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts ();
+
+	unmap_physmem(dstaddr, info->portwidth);
+
+	return flash_full_status_check (info, find_sector (info, dest),
+					info->write_tout, "write");
 }
 
-/*-----------------------------------------------------------------------
- */
-static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+
+static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
+				  int len)
 {
-	cfiptr_t cptr;
-	cfiword_t cword;
-	int retval;
+	flash_sect_t sector;
+	int cnt;
+	int retcode;
+	void *src = cp;
+	void *dst = map_physmem(dest, len, MAP_NOCACHE);
+	void *dst2 = dst;
+	int flag = 0;
+	uint offset = 0;
+	unsigned int shift;
+	uchar write_cmd;
 
-	cptr.cp = flash_make_addr (info, sect, offset);
-	flash_make_cmd (info, cmd, &cword);
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		retval = ((cptr.cp[0] & cword.c) == cword.c);
+		shift = 0;
 		break;
 	case FLASH_CFI_16BIT:
-		retval = ((cptr.wp[0] & cword.w) == cword.w);
+		shift = 1;
 		break;
 	case FLASH_CFI_32BIT:
-		retval = ((cptr.lp[0] & cword.l) == cword.l);
+		shift = 2;
 		break;
 	case FLASH_CFI_64BIT:
-		retval = ((cptr.llp[0] & cword.ll) == cword.ll);
+		shift = 3;
 		break;
 	default:
-		retval = 0;
+		retcode = ERR_INVAL;
+		goto out_unmap;
+	}
+
+	cnt = len >> shift;
+
+	while ((cnt-- > 0) && (flag == 0)) {
+		switch (info->portwidth) {
+		case FLASH_CFI_8BIT:
+			flag = ((flash_read8(dst2) & flash_read8(src)) ==
+				flash_read8(src));
+			src += 1, dst2 += 1;
+			break;
+		case FLASH_CFI_16BIT:
+			flag = ((flash_read16(dst2) & flash_read16(src)) ==
+				flash_read16(src));
+			src += 2, dst2 += 2;
+			break;
+		case FLASH_CFI_32BIT:
+			flag = ((flash_read32(dst2) & flash_read32(src)) ==
+				flash_read32(src));
+			src += 4, dst2 += 4;
+			break;
+		case FLASH_CFI_64BIT:
+			flag = ((flash_read64(dst2) & flash_read64(src)) ==
+				flash_read64(src));
+			src += 8, dst2 += 8;
+			break;
+		}
+	}
+	if (!flag) {
+		retcode = ERR_NOT_ERASED;
+		goto out_unmap;
+	}
+
+	src = cp;
+	sector = find_sector (info, dest);
+
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_STANDARD:
+	case CFI_CMDSET_INTEL_EXTENDED:
+		write_cmd = (info->vendor == CFI_CMDSET_INTEL_PROG_REGIONS) ?
+					FLASH_CMD_WRITE_BUFFER_PROG : FLASH_CMD_WRITE_TO_BUFFER;
+		flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+		flash_write_cmd (info, sector, 0, FLASH_CMD_READ_STATUS);
+		flash_write_cmd (info, sector, 0, write_cmd);
+		retcode = flash_status_check (info, sector,
+					      info->buffer_write_tout,
+					      "write to buffer");
+		if (retcode == ERR_OK) {
+			/* reduce the number of loops by the width of
+			 * the port */
+			cnt = len >> shift;
+			flash_write_cmd (info, sector, 0, cnt - 1);
+			while (cnt-- > 0) {
+				switch (info->portwidth) {
+				case FLASH_CFI_8BIT:
+					flash_write8(flash_read8(src), dst);
+					src += 1, dst += 1;
+					break;
+				case FLASH_CFI_16BIT:
+					flash_write16(flash_read16(src), dst);
+					src += 2, dst += 2;
+					break;
+				case FLASH_CFI_32BIT:
+					flash_write32(flash_read32(src), dst);
+					src += 4, dst += 4;
+					break;
+				case FLASH_CFI_64BIT:
+					flash_write64(flash_read64(src), dst);
+					src += 8, dst += 8;
+					break;
+				default:
+					retcode = ERR_INVAL;
+					goto out_unmap;
+				}
+			}
+			flash_write_cmd (info, sector, 0,
+					 FLASH_CMD_WRITE_BUFFER_CONFIRM);
+			retcode = flash_full_status_check (
+				info, sector, info->buffer_write_tout,
+				"buffer write");
+		}
+
+		break;
+
+	case CFI_CMDSET_AMD_STANDARD:
+	case CFI_CMDSET_AMD_EXTENDED:
+		flash_unlock_seq(info,0);
+
+#ifdef CONFIG_FLASH_SPANSION_S29WS_N
+		offset = ((unsigned long)dst - info->start[sector]) >> shift;
+#endif
+		flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER);
+		cnt = len >> shift;
+		flash_write_cmd(info, sector, offset, (uchar)cnt - 1);
+
+		switch (info->portwidth) {
+		case FLASH_CFI_8BIT:
+			while (cnt-- > 0) {
+				flash_write8(flash_read8(src), dst);
+				src += 1, dst += 1;
+			}
+			break;
+		case FLASH_CFI_16BIT:
+			while (cnt-- > 0) {
+				flash_write16(flash_read16(src), dst);
+				src += 2, dst += 2;
+			}
+			break;
+		case FLASH_CFI_32BIT:
+			while (cnt-- > 0) {
+				flash_write32(flash_read32(src), dst);
+				src += 4, dst += 4;
+			}
+			break;
+		case FLASH_CFI_64BIT:
+			while (cnt-- > 0) {
+				flash_write64(flash_read64(src), dst);
+				src += 8, dst += 8;
+			}
+			break;
+		default:
+			retcode = ERR_INVAL;
+			goto out_unmap;
+		}
+
+		flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
+		retcode = flash_full_status_check (info, sector,
+						   info->buffer_write_tout,
+						   "buffer write");
+		break;
+
+	default:
+		debug ("Unknown Command Set\n");
+		retcode = ERR_INVAL;
 		break;
 	}
-	return retval;
+
+out_unmap:
+	unmap_physmem(dst, len);
+	return retcode;
+}
+#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+	int rcode = 0;
+	int prot;
+	flash_sect_t sect;
+
+	if (info->flash_id != FLASH_MAN_CFI) {
+		puts ("Can't erase unknown flash type - aborted\n");
+		return 1;
+	}
+	if ((s_first < 0) || (s_first > s_last)) {
+		puts ("- no sectors to erase\n");
+		return 1;
+	}
+
+	prot = 0;
+	for (sect = s_first; sect <= s_last; ++sect) {
+		if (info->protect[sect]) {
+			prot++;
+		}
+	}
+	if (prot) {
+		printf ("- Warning: %d protected sectors will not be erased!\n",
+			prot);
+	} else {
+		putc ('\n');
+	}
+
+
+	for (sect = s_first; sect <= s_last; sect++) {
+		if (info->protect[sect] == 0) { /* not protected */
+			switch (info->vendor) {
+			case CFI_CMDSET_INTEL_PROG_REGIONS:
+			case CFI_CMDSET_INTEL_STANDARD:
+			case CFI_CMDSET_INTEL_EXTENDED:
+				flash_write_cmd (info, sect, 0,
+						 FLASH_CMD_CLEAR_STATUS);
+				flash_write_cmd (info, sect, 0,
+						 FLASH_CMD_BLOCK_ERASE);
+				flash_write_cmd (info, sect, 0,
+						 FLASH_CMD_ERASE_CONFIRM);
+				break;
+			case CFI_CMDSET_AMD_STANDARD:
+			case CFI_CMDSET_AMD_EXTENDED:
+				flash_unlock_seq (info, 0);
+				flash_write_cmd (info, 0,
+						info->addr_unlock1,
+						AMD_CMD_ERASE_START);
+				flash_unlock_seq (info, 0);
+				flash_write_cmd (info, sect, 0,
+						 AMD_CMD_ERASE_SECTOR);
+				break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+			case CFI_CMDSET_AMD_LEGACY:
+				flash_unlock_seq (info, 0);
+				flash_write_cmd (info, 0, info->addr_unlock1,
+						AMD_CMD_ERASE_START);
+				flash_unlock_seq (info, 0);
+				flash_write_cmd (info, sect, 0,
+						AMD_CMD_ERASE_SECTOR);
+				break;
+#endif
+			default:
+				debug ("Unkown flash vendor %d\n",
+				       info->vendor);
+				break;
+			}
+
+			if (flash_full_status_check
+			    (info, sect, info->erase_blk_tout, "erase")) {
+				rcode = 1;
+			} else
+				putc ('.');
+		}
+	}
+	puts (" done\n");
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t * info)
+{
+	int i;
+
+	if (info->flash_id != FLASH_MAN_CFI) {
+		puts ("missing or unknown FLASH type\n");
+		return;
+	}
+
+	printf ("%s FLASH (%d x %d)",
+		info->name,
+		(info->portwidth << 3), (info->chipwidth << 3));
+	if (info->size < 1024*1024)
+		printf ("  Size: %ld kB in %d Sectors\n",
+			info->size >> 10, info->sector_count);
+	else
+		printf ("  Size: %ld MB in %d Sectors\n",
+			info->size >> 20, info->sector_count);
+	printf ("  ");
+	switch (info->vendor) {
+		case CFI_CMDSET_INTEL_PROG_REGIONS:
+			printf ("Intel Prog Regions");
+			break;
+		case CFI_CMDSET_INTEL_STANDARD:
+			printf ("Intel Standard");
+			break;
+		case CFI_CMDSET_INTEL_EXTENDED:
+			printf ("Intel Extended");
+			break;
+		case CFI_CMDSET_AMD_STANDARD:
+			printf ("AMD Standard");
+			break;
+		case CFI_CMDSET_AMD_EXTENDED:
+			printf ("AMD Extended");
+			break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+		case CFI_CMDSET_AMD_LEGACY:
+			printf ("AMD Legacy");
+			break;
+#endif
+		default:
+			printf ("Unknown (%d)", info->vendor);
+			break;
+	}
+	printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
+		info->manufacturer_id, info->device_id);
+	if (info->device_id == 0x7E) {
+		printf("%04X", info->device_id2);
+	}
+	printf ("\n  Erase timeout: %ld ms, write timeout: %ld ms\n",
+		info->erase_blk_tout,
+		info->write_tout);
+	if (info->buffer_size > 1) {
+		printf ("  Buffer write timeout: %ld ms, "
+			"buffer size: %d bytes\n",
+		info->buffer_write_tout,
+		info->buffer_size);
+	}
+
+	puts ("\n  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf ("\n");
+#ifdef CFG_FLASH_EMPTY_INFO
+		int k;
+		int size;
+		int erased;
+		volatile unsigned long *flash;
+
+		/*
+		 * Check if whole sector is erased
+		 */
+		size = flash_sector_size(info, i);
+		erased = 1;
+		flash = (volatile unsigned long *) info->start[i];
+		size = size >> 2;	/* divide by 4 for longword access */
+		for (k = 0; k < size; k++) {
+			if (*flash++ != 0xffffffff) {
+				erased = 0;
+				break;
+			}
+		}
+
+		/* print empty and read-only info */
+		printf ("  %08lX %c %s ",
+			info->start[i],
+			erased ? 'E' : ' ',
+			info->protect[i] ? "RO" : "  ");
+#else	/* ! CFG_FLASH_EMPTY_INFO */
+		printf ("  %08lX   %s ",
+			info->start[i],
+			info->protect[i] ? "RO" : "  ");
+#endif
+	}
+	putc ('\n');
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ * This is used in a few places in write_buf() to show programming
+ * progress.  Making it a function is nasty because it needs to do side
+ * effect updates to digit and dots.  Repeated code is nasty too, so
+ * we define it once here.
+ */
+#ifdef CONFIG_FLASH_SHOW_PROGRESS
+#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub) \
+	dots -= dots_sub; \
+	if ((scale > 0) && (dots <= 0)) { \
+		if ((digit % 5) == 0) \
+			printf ("%d", digit / 5); \
+		else \
+			putc ('.'); \
+		digit--; \
+		dots += scale; \
+	}
+#else
+#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub)
+#endif
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+	ulong wp;
+	uchar *p;
+	int aln;
+	cfiword_t cword;
+	int i, rc;
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+	int buffered_size;
+#endif
+#ifdef CONFIG_FLASH_SHOW_PROGRESS
+	int digit = CONFIG_FLASH_SHOW_PROGRESS;
+	int scale = 0;
+	int dots  = 0;
+
+	/*
+	 * Suppress if there are fewer than CONFIG_FLASH_SHOW_PROGRESS writes.
+	 */
+	if (cnt >= CONFIG_FLASH_SHOW_PROGRESS) {
+		scale = (int)((cnt + CONFIG_FLASH_SHOW_PROGRESS - 1) /
+			CONFIG_FLASH_SHOW_PROGRESS);
+	}
+#endif
+
+	/* get lower aligned address */
+	wp = (addr & ~(info->portwidth - 1));
+
+	/* handle unaligned start */
+	if ((aln = addr - wp) != 0) {
+		cword.l = 0;
+		p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
+		for (i = 0; i < aln; ++i)
+			flash_add_byte (info, &cword, flash_read8(p + i));
+
+		for (; (i < info->portwidth) && (cnt > 0); i++) {
+			flash_add_byte (info, &cword, *src++);
+			cnt--;
+		}
+		for (; (cnt == 0) && (i < info->portwidth); ++i)
+			flash_add_byte (info, &cword, flash_read8(p + i));
+
+		rc = flash_write_cfiword (info, wp, cword);
+		unmap_physmem(p, info->portwidth);
+		if (rc != 0)
+			return rc;
+
+		wp += i;
+		FLASH_SHOW_PROGRESS(scale, dots, digit, i);
+	}
+
+	/* handle the aligned part */
+#ifdef CFG_FLASH_USE_BUFFER_WRITE
+	buffered_size = (info->portwidth / info->chipwidth);
+	buffered_size *= info->buffer_size;
+	while (cnt >= info->portwidth) {
+		/* prohibit buffer write when buffer_size is 1 */
+		if (info->buffer_size == 1 || info->buffer_size == 0) {
+			cword.l = 0;
+			for (i = 0; i < info->portwidth; i++)
+				flash_add_byte (info, &cword, *src++);
+			if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
+				return rc;
+			wp += info->portwidth;
+			cnt -= info->portwidth;
+			continue;
+		}
+
+		/* write buffer until next buffered_size aligned boundary */
+		i = buffered_size - (wp % buffered_size);
+		if (i > cnt)
+			i = cnt;
+		if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
+			return rc;
+		i -= i & (info->portwidth - 1);
+		wp += i;
+		src += i;
+		cnt -= i;
+		FLASH_SHOW_PROGRESS(scale, dots, digit, i);
+	}
+#else
+	while (cnt >= info->portwidth) {
+		cword.l = 0;
+		for (i = 0; i < info->portwidth; i++) {
+			flash_add_byte (info, &cword, *src++);
+		}
+		if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
+			return rc;
+		wp += info->portwidth;
+		cnt -= info->portwidth;
+		FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth);
+	}
+#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+
+	if (cnt == 0) {
+		return (0);
+	}
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	cword.l = 0;
+	p = map_physmem(wp, info->portwidth, MAP_NOCACHE);
+	for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
+		flash_add_byte (info, &cword, *src++);
+		--cnt;
+	}
+	for (; i < info->portwidth; ++i)
+		flash_add_byte (info, &cword, flash_read8(p + i));
+	unmap_physmem(p, info->portwidth);
+
+	return flash_write_cfiword (info, wp, cword);
+}
+
+/*-----------------------------------------------------------------------
+ */
+#ifdef CFG_FLASH_PROTECTION
+
+int flash_real_protect (flash_info_t * info, long sector, int prot)
+{
+	int retcode = 0;
+
+	flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+	flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
+	if (prot)
+		flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
+	else
+		flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
+
+	if ((retcode =
+	     flash_full_status_check (info, sector, info->erase_blk_tout,
+				      prot ? "protect" : "unprotect")) == 0) {
+
+		info->protect[sector] = prot;
+
+		/*
+		 * On some of Intel's flash chips (marked via legacy_unlock)
+		 * unprotect unprotects all locking.
+		 */
+		if ((prot == 0) && (info->legacy_unlock)) {
+			flash_sect_t i;
+
+			for (i = 0; i < info->sector_count; i++) {
+				if (info->protect[i])
+					flash_real_protect (info, i, 1);
+			}
+		}
+	}
+	return retcode;
+}
+
+/*-----------------------------------------------------------------------
+ * flash_read_user_serial - read the OneTimeProgramming cells
+ */
+void flash_read_user_serial (flash_info_t * info, void *buffer, int offset,
+			     int len)
+{
+	uchar *src;
+	uchar *dst;
+
+	dst = buffer;
+	src = flash_map (info, 0, FLASH_OFFSET_USER_PROTECTION);
+	flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
+	memcpy (dst, src + offset, len);
+	flash_write_cmd (info, 0, 0, info->cmd_reset);
+	flash_unmap(info, 0, FLASH_OFFSET_USER_PROTECTION, src);
+}
+
+/*
+ * flash_read_factory_serial - read the device Id from the protection area
+ */
+void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset,
+				int len)
+{
+	uchar *src;
+
+	src = flash_map (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
+	flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
+	memcpy (buffer, src + offset, len);
+	flash_write_cmd (info, 0, 0, info->cmd_reset);
+	flash_unmap(info, 0, FLASH_OFFSET_INTEL_PROTECTION, src);
+}
+
+#endif /* CFG_FLASH_PROTECTION */
+
+/*-----------------------------------------------------------------------
+ * Reverse the order of the erase regions in the CFI QRY structure.
+ * This is needed for chips that are either a) correctly detected as
+ * top-boot, or b) buggy.
+ */
+static void cfi_reverse_geometry(struct cfi_qry *qry)
+{
+	unsigned int i, j;
+	u32 tmp;
+
+	for (i = 0, j = qry->num_erase_regions - 1; i < j; i++, j--) {
+		tmp = qry->erase_region_info[i];
+		qry->erase_region_info[i] = qry->erase_region_info[j];
+		qry->erase_region_info[j] = tmp;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ * read jedec ids from device and set corresponding fields in info struct
+ *
+ * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
+ *
+ */
+static void cmdset_intel_read_jedec_ids(flash_info_t *info)
+{
+	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+	flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
+	udelay(1000); /* some flash are slow to respond */
+	info->manufacturer_id = flash_read_uchar (info,
+					FLASH_OFFSET_MANUFACTURER_ID);
+	info->device_id = flash_read_uchar (info,
+					FLASH_OFFSET_DEVICE_ID);
+	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+}
+
+static int cmdset_intel_init(flash_info_t *info, struct cfi_qry *qry)
+{
+	info->cmd_reset = FLASH_CMD_RESET;
+
+	cmdset_intel_read_jedec_ids(info);
+	flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+#ifdef CFG_FLASH_PROTECTION
+	/* read legacy lock/unlock bit from intel flash */
+	if (info->ext_addr) {
+		info->legacy_unlock = flash_read_uchar (info,
+				info->ext_addr + 5) & 0x08;
+	}
+#endif
+
+	return 0;
+}
+
+static void cmdset_amd_read_jedec_ids(flash_info_t *info)
+{
+	flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+	flash_unlock_seq(info, 0);
+	flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
+	udelay(1000); /* some flash are slow to respond */
+
+	info->manufacturer_id = flash_read_uchar (info,
+					FLASH_OFFSET_MANUFACTURER_ID);
+
+	switch (info->chipwidth){
+	case FLASH_CFI_8BIT:
+		info->device_id = flash_read_uchar (info,
+						FLASH_OFFSET_DEVICE_ID);
+		if (info->device_id == 0x7E) {
+			/* AMD 3-byte (expanded) device ids */
+			info->device_id2 = flash_read_uchar (info,
+						FLASH_OFFSET_DEVICE_ID2);
+			info->device_id2 <<= 8;
+			info->device_id2 |= flash_read_uchar (info,
+						FLASH_OFFSET_DEVICE_ID3);
+		}
+		break;
+	case FLASH_CFI_16BIT:
+		info->device_id = flash_read_word (info,
+						FLASH_OFFSET_DEVICE_ID);
+		break;
+	default:
+		break;
+	}
+	flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+}
+
+static int cmdset_amd_init(flash_info_t *info, struct cfi_qry *qry)
+{
+	info->cmd_reset = AMD_CMD_RESET;
+
+	cmdset_amd_read_jedec_ids(info);
+	flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+	return 0;
+}
+
+#ifdef CONFIG_FLASH_CFI_LEGACY
+void flash_read_jedec_ids (flash_info_t * info)
+{
+	info->manufacturer_id = 0;
+	info->device_id       = 0;
+	info->device_id2      = 0;
+
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_STANDARD:
+	case CFI_CMDSET_INTEL_EXTENDED:
+		cmdset_intel_read_jedec_ids(info);
+		break;
+	case CFI_CMDSET_AMD_STANDARD:
+	case CFI_CMDSET_AMD_EXTENDED:
+		cmdset_amd_read_jedec_ids(info);
+		break;
+	default:
+		break;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ * Call board code to request info about non-CFI flash.
+ * board_flash_get_legacy needs to fill in at least:
+ * info->portwidth, info->chipwidth and info->interface for Jedec probing.
+ */
+static int flash_detect_legacy(ulong base, int banknum)
+{
+	flash_info_t *info = &flash_info[banknum];
+
+	if (board_flash_get_legacy(base, banknum, info)) {
+		/* board code may have filled info completely. If not, we
+		   use JEDEC ID probing. */
+		if (!info->vendor) {
+			int modes[] = {
+				CFI_CMDSET_AMD_STANDARD,
+				CFI_CMDSET_INTEL_STANDARD
+			};
+			int i;
+
+			for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
+				int ret = 0;
+				info->vendor = modes[i];
+				info->start[0] = base;
+
+				if (info->vendor == CFI_CMDSET_INTEL_STANDARD) {
+					flash_read_jedec_ids(info);
+					debug("JEDEC PROBE: ID %x %x %x\n",
+							info->manufacturer_id,
+							info->device_id,
+							info->device_id2);
+					ret = jedec_flash_match(info, base);
+				} else {
+					ret = jedec_flash_probe(info, base);
+				}
+				
+				if (ret)
+					break;
+			}
+		}
+
+		switch(info->vendor) {
+		case CFI_CMDSET_INTEL_PROG_REGIONS:
+		case CFI_CMDSET_INTEL_STANDARD:
+		case CFI_CMDSET_INTEL_EXTENDED:
+			info->cmd_reset = FLASH_CMD_RESET;
+			break;
+		case CFI_CMDSET_AMD_STANDARD:
+		case CFI_CMDSET_AMD_EXTENDED:
+		case CFI_CMDSET_AMD_LEGACY:
+			info->cmd_reset = AMD_CMD_RESET;
+			break;
+		}
+		info->flash_id = FLASH_MAN_CFI;
+		return 1;
+	}
+	return 0; /* use CFI */
+}
+#else
+static inline int flash_detect_legacy(ulong base, int banknum)
+{
+	return 0; /* use CFI */
 }
+#endif
 
 /*-----------------------------------------------------------------------
+ * detect if flash is compatible with the Common Flash Interface (CFI)
+ * http://www.jedec.org/download/search/jesd68.pdf
  */
-static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
+static void flash_read_cfi (flash_info_t *info, void *buf,
+		unsigned int start, size_t len)
 {
-	cfiptr_t cptr;
-	cfiword_t cword;
-	int retval;
+	u8 *p = buf;
+	unsigned int i;
 
-	cptr.cp = flash_make_addr (info, sect, offset);
-	flash_make_cmd (info, cmd, &cword);
-	switch (info->portwidth) {
-	case FLASH_CFI_8BIT:
-		retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c));
-		break;
-	case FLASH_CFI_16BIT:
-		retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w));
-		break;
-	case FLASH_CFI_32BIT:
-		retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l));
-		break;
-	case FLASH_CFI_64BIT:
-		retval = ((cptr.llp[0] & cword.ll) !=
-			  (cptr.llp[0] & cword.ll));
-		break;
-	default:
-		retval = 0;
-		break;
+	for (i = 0; i < len; i++)
+		p[i] = flash_read_uchar(info, start + i);
+}
+
+static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
+{
+	int cfi_offset;
+
+	/* We do not yet know what kind of commandset to use, so we issue
+	   the reset command in both Intel and AMD variants, in the hope
+	   that AMD flash roms ignore the Intel command. */
+	flash_write_cmd (info, 0, 0, AMD_CMD_RESET);
+	flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
+
+	for (cfi_offset=0;
+	     cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
+	     cfi_offset++) {
+		flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset],
+				 FLASH_CMD_CFI);
+		if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
+		    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
+		    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
+			flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
+					sizeof(struct cfi_qry));
+			info->interface	= le16_to_cpu(qry->interface_desc);
+
+			info->cfi_offset = flash_offset_cfi[cfi_offset];
+			debug ("device interface is %d\n",
+			       info->interface);
+			debug ("found port %d chip %d ",
+			       info->portwidth, info->chipwidth);
+			debug ("port %d bits chip %d bits\n",
+			       info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+			       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+
+			/* calculate command offsets as in the Linux driver */
+			info->addr_unlock1 = 0x555;
+			info->addr_unlock2 = 0x2aa;
+
+			/*
+			 * modify the unlock address if we are
+			 * in compatibility mode
+			 */
+			if (	/* x8/x16 in x8 mode */
+				((info->chipwidth == FLASH_CFI_BY8) &&
+					(info->interface == FLASH_CFI_X8X16)) ||
+				/* x16/x32 in x16 mode */
+				((info->chipwidth == FLASH_CFI_BY16) &&
+					(info->interface == FLASH_CFI_X16X32)))
+			{
+				info->addr_unlock1 = 0xaaa;
+				info->addr_unlock2 = 0x555;
+			}
+
+			info->name = "CFI conformant";
+			return 1;
+		}
 	}
-	return retval;
+
+	return 0;
 }
 
-/*-----------------------------------------------------------------------
- * detect if flash is compatible with the Common Flash Interface (CFI)
- * http://www.jedec.org/download/search/jesd68.pdf
- *
-*/
-static int flash_detect_cfi (flash_info_t * info)
+static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry)
 {
 	debug ("flash detect cfi\n");
 
@@ -1083,29 +1700,58 @@
 	     info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
 		for (info->chipwidth = FLASH_CFI_BY8;
 		     info->chipwidth <= info->portwidth;
-		     info->chipwidth <<= 1) {
-			flash_write_cmd (info, 0, 0, info->cmd_reset);
-			flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI);
-			if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
-			    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
-			    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
-				info->interface = flash_read_ushort (info, 0, FLASH_OFFSET_INTERFACE);
-				debug ("device interface is %d\n",
-				       info->interface);
-				debug ("found port %d chip %d ",
-				       info->portwidth, info->chipwidth);
-				debug ("port %d bits chip %d bits\n",
-				       info->portwidth << CFI_FLASH_SHIFT_WIDTH,
-				       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		     info->chipwidth <<= 1)
+			if (__flash_detect_cfi(info, qry))
 				return 1;
-			}
-		}
 	}
 	debug ("not found\n");
 	return 0;
 }
 
 /*
+ * Manufacturer-specific quirks. Add workarounds for geometry
+ * reversal, etc. here.
+ */
+static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry)
+{
+	/* check if flash geometry needs reversal */
+	if (qry->num_erase_regions > 1) {
+		/* reverse geometry if top boot part */
+		if (info->cfi_version < 0x3131) {
+			/* CFI < 1.1, try to guess from device id */
+			if ((info->device_id & 0x80) != 0)
+				cfi_reverse_geometry(qry);
+		} else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
+			/* CFI >= 1.1, deduct from top/bottom flag */
+			/* note: ext_addr is valid since cfi_version > 0 */
+			cfi_reverse_geometry(qry);
+		}
+	}
+}
+
+static void flash_fixup_atmel(flash_info_t *info, struct cfi_qry *qry)
+{
+	int reverse_geometry = 0;
+
+	/* Check the "top boot" bit in the PRI */
+	if (info->ext_addr && !(flash_read_uchar(info, info->ext_addr + 6) & 1))
+		reverse_geometry = 1;
+
+	/* AT49BV6416(T) list the erase regions in the wrong order.
+	 * However, the device ID is identical with the non-broken
+	 * AT49BV642D since u-boot only reads the low byte (they
+	 * differ in the high byte.) So leave out this fixup for now.
+	 */
+#if 0
+	if (info->device_id == 0xd6 || info->device_id == 0xd2)
+		reverse_geometry = !reverse_geometry;
+#endif
+
+	if (reverse_geometry)
+		cfi_reverse_geometry(qry);
+}
+
+/*
  * The following code cannot be run from FLASH!
  *
  */
@@ -1120,45 +1766,78 @@
 	uchar num_erase_regions;
 	int erase_region_size;
 	int erase_region_count;
+	struct cfi_qry qry;
+
+	memset(&qry, 0, sizeof(qry));
+
+	info->ext_addr = 0;
+	info->cfi_version = 0;
 #ifdef CFG_FLASH_PROTECTION
-	int ext_addr;
 	info->legacy_unlock = 0;
 #endif
 
 	info->start[0] = base;
 
-	if (flash_detect_cfi (info)) {
-		info->vendor = flash_read_ushort (info, 0, FLASH_OFFSET_PRIMARY_VENDOR);
+	if (flash_detect_cfi (info, &qry)) {
+		info->vendor = le16_to_cpu(qry.p_id);
+		info->ext_addr = le16_to_cpu(qry.p_adr);
+		num_erase_regions = qry.num_erase_regions;
+
+		if (info->ext_addr) {
+			info->cfi_version = (ushort) flash_read_uchar (info,
+						info->ext_addr + 3) << 8;
+			info->cfi_version |= (ushort) flash_read_uchar (info,
+						info->ext_addr + 4);
+		}
+
 #ifdef DEBUG
-		flash_printqry (info, 0);
+		flash_printqry (&qry);
 #endif
+
 		switch (info->vendor) {
+		case CFI_CMDSET_INTEL_PROG_REGIONS:
 		case CFI_CMDSET_INTEL_STANDARD:
 		case CFI_CMDSET_INTEL_EXTENDED:
-		default:
-			info->cmd_reset = FLASH_CMD_RESET;
-#ifdef CFG_FLASH_PROTECTION
-			/* read legacy lock/unlock bit from intel flash */
-			ext_addr = flash_read_ushort (info, 0,
-						      FLASH_OFFSET_EXT_QUERY_T_P_ADDR);
-			info->legacy_unlock =
-				flash_read_uchar (info, ext_addr + 5) & 0x08;
-#endif
+			cmdset_intel_init(info, &qry);
 			break;
 		case CFI_CMDSET_AMD_STANDARD:
 		case CFI_CMDSET_AMD_EXTENDED:
-			info->cmd_reset = AMD_CMD_RESET;
+			cmdset_amd_init(info, &qry);
+			break;
+		default:
+			printf("CFI: Unknown command set 0x%x\n",
+					info->vendor);
+			/*
+			 * Unfortunately, this means we don't know how
+			 * to get the chip back to Read mode. Might
+			 * as well try an Intel-style reset...
+			 */
+			flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+			return 0;
+		}
+
+		/* Do manufacturer-specific fixups */
+		switch (info->manufacturer_id) {
+		case 0x0001:
+			flash_fixup_amd(info, &qry);
+			break;
+		case 0x001f:
+			flash_fixup_atmel(info, &qry);
 			break;
 		}
 
 		debug ("manufacturer is %d\n", info->vendor);
+		debug ("manufacturer id is 0x%x\n", info->manufacturer_id);
+		debug ("device id is 0x%x\n", info->device_id);
+		debug ("device id2 is 0x%x\n", info->device_id2);
+		debug ("cfi version is 0x%04x\n", info->cfi_version);
+
 		size_ratio = info->portwidth / info->chipwidth;
 		/* if the chip is x8/x16 reduce the ratio by half */
 		if ((info->interface == FLASH_CFI_X8X16)
 		    && (info->chipwidth == FLASH_CFI_BY8)) {
 			size_ratio >>= 1;
 		}
-		num_erase_regions = flash_read_uchar (info, FLASH_OFFSET_NUM_ERASE_REGIONS);
 		debug ("size_ratio %d port %d bits chip %d bits\n",
 		       size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
 		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
@@ -1171,23 +1850,30 @@
 					num_erase_regions, NUM_ERASE_REGIONS);
 				break;
 			}
-			tmp = flash_read_long (info, 0,
-					       FLASH_OFFSET_ERASE_REGIONS +
-					       i * 4);
+
+			tmp = le32_to_cpu(qry.erase_region_info[i]);
+			debug("erase region %u: 0x%08lx\n", i, tmp);
+
+			erase_region_count = (tmp & 0xffff) + 1;
+			tmp >>= 16;
 			erase_region_size =
 				(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
-			tmp >>= 16;
-			erase_region_count = (tmp & 0xffff) + 1;
 			debug ("erase_region_count = %d erase_region_size = %d\n",
 				erase_region_count, erase_region_size);
 			for (j = 0; j < erase_region_count; j++) {
+				if (sect_cnt >= CFG_MAX_FLASH_SECT) {
+					printf("ERROR: too many flash sectors\n");
+					break;
+				}
 				info->start[sect_cnt] = sector;
 				sector += (erase_region_size * size_ratio);
 
 				/*
-				 * Only read protection status from supported devices (intel...)
+				 * Only read protection status from
+				 * supported devices (intel...)
 				 */
 				switch (info->vendor) {
+				case CFI_CMDSET_INTEL_PROG_REGIONS:
 				case CFI_CMDSET_INTEL_EXTENDED:
 				case CFI_CMDSET_INTEL_STANDARD:
 					info->protect[sect_cnt] =
@@ -1196,7 +1882,8 @@
 							     FLASH_STATUS_PROTECT);
 					break;
 				default:
-					info->protect[sect_cnt] = 0; /* default: not protected */
+					/* default: not protected */
+					info->protect[sect_cnt] = 0;
 				}
 
 				sect_cnt++;
@@ -1204,20 +1891,27 @@
 		}
 
 		info->sector_count = sect_cnt;
+		info->size = 1 << qry.dev_size;
 		/* multiply the size by the number of chips */
-		info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio;
-		info->buffer_size = (1 << flash_read_ushort (info, 0, FLASH_OFFSET_BUFFER_SIZE));
-		tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT);
-		info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
-		tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT)) *
-			(1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT));
-		info->buffer_write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
-		tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) *
-		      (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT));
-		info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
+		info->size *= size_ratio;
+		info->buffer_size = 1 << le16_to_cpu(qry.max_buf_write_size);
+		tmp = 1 << qry.block_erase_timeout_typ;
+		info->erase_blk_tout = tmp *
+			(1 << qry.block_erase_timeout_max);
+		tmp = (1 << qry.buf_write_timeout_typ) *
+			(1 << qry.buf_write_timeout_max);
+
+		/* round up when converting to ms */
+		info->buffer_write_tout = (tmp + 999) / 1000;
+		tmp = (1 << qry.word_write_timeout_typ) *
+			(1 << qry.word_write_timeout_max);
+		/* round up when converting to ms */
+		info->write_tout = (tmp + 999) / 1000;
 		info->flash_id = FLASH_MAN_CFI;
-		if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
-			info->portwidth >>= 1;	/* XXX - Need to test on x8/x16 in parallel. */
+		if ((info->interface == FLASH_CFI_X8X16) &&
+		    (info->chipwidth == FLASH_CFI_BY8)) {
+			/* XXX - Need to test on x8/x16 in parallel. */
+			info->portwidth >>= 1;
 		}
 	}
 
@@ -1225,203 +1919,125 @@
 	return (info->size);
 }
 
-/* loop through the sectors from the highest address
- * when the passed address is greater or equal to the sector address
- * we have a match
- */
-static flash_sect_t find_sector (flash_info_t * info, ulong addr)
-{
-	flash_sect_t sector;
-
-	for (sector = info->sector_count - 1; sector >= 0; sector--) {
-		if (addr >= info->start[sector])
-			break;
-	}
-	return sector;
-}
-
 /*-----------------------------------------------------------------------
  */
-static int flash_write_cfiword (flash_info_t * info, ulong dest,
-				cfiword_t cword)
+unsigned long flash_init (void)
 {
-	cfiptr_t ctladdr;
-	cfiptr_t cptr;
-	int flag;
-
-	ctladdr.cp = flash_make_addr (info, 0, 0);
-	cptr.cp = (uchar *) dest;
-
-
-	/* Check if Flash is (sufficiently) erased */
-	switch (info->portwidth) {
-	case FLASH_CFI_8BIT:
-		flag = ((cptr.cp[0] & cword.c) == cword.c);
-		break;
-	case FLASH_CFI_16BIT:
-		flag = ((cptr.wp[0] & cword.w) == cword.w);
-		break;
-	case FLASH_CFI_32BIT:
-		flag = ((cptr.lp[0] & cword.l) == cword.l);
-		break;
-	case FLASH_CFI_64BIT:
-		flag = ((cptr.llp[0] & cword.ll) == cword.ll);
-		break;
-	default:
-		return 2;
-	}
-	if (!flag)
-		return 2;
+	unsigned long size = 0;
+	int i;
+#if defined(CFG_FLASH_AUTOPROTECT_LIST)
+	struct apl_s {
+		ulong start;
+		ulong size;
+	} apl[] = CFG_FLASH_AUTOPROTECT_LIST;
+#endif
 
-	/* Disable interrupts which might cause a timeout here */
-	flag = disable_interrupts ();
+#ifdef CFG_FLASH_PROTECTION
+	char *s = getenv("unlock");
+#endif
 
-	switch (info->vendor) {
-	case CFI_CMDSET_INTEL_EXTENDED:
-	case CFI_CMDSET_INTEL_STANDARD:
-		flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS);
-		flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE);
-		break;
-	case CFI_CMDSET_AMD_EXTENDED:
-	case CFI_CMDSET_AMD_STANDARD:
-		flash_unlock_seq (info, 0);
-		flash_write_cmd (info, 0, AMD_ADDR_START, AMD_CMD_WRITE);
-		break;
-	}
+#define BANK_BASE(i)	(((unsigned long [CFI_MAX_FLASH_BANKS])CFG_FLASH_BANKS_LIST)[i])
 
-	switch (info->portwidth) {
-	case FLASH_CFI_8BIT:
-		cptr.cp[0] = cword.c;
-		break;
-	case FLASH_CFI_16BIT:
-		cptr.wp[0] = cword.w;
-		break;
-	case FLASH_CFI_32BIT:
-		cptr.lp[0] = cword.l;
-		break;
-	case FLASH_CFI_64BIT:
-		cptr.llp[0] = cword.ll;
-		break;
-	}
+	/* Init: no FLASHes known */
+	for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
 
-	/* re-enable interrupts if necessary */
-	if (flag)
-		enable_interrupts ();
+		if (!flash_detect_legacy (BANK_BASE(i), i))
+			flash_get_size (BANK_BASE(i), i);
+		size += flash_info[i].size;
+		if (flash_info[i].flash_id == FLASH_UNKNOWN) {
+#ifndef CFG_FLASH_QUIET_TEST
+			printf ("## Unknown FLASH on Bank %d "
+				"- Size = 0x%08lx = %ld MB\n",
+				i+1, flash_info[i].size,
+				flash_info[i].size << 20);
+#endif /* CFG_FLASH_QUIET_TEST */
+		}
+#ifdef CFG_FLASH_PROTECTION
+		else if ((s != NULL) && (strcmp(s, "yes") == 0)) {
+			/*
+			 * Only the U-Boot image and it's environment
+			 * is protected, all other sectors are
+			 * unprotected (unlocked) if flash hardware
+			 * protection is used (CFG_FLASH_PROTECTION)
+			 * and the environment variable "unlock" is
+			 * set to "yes".
+			 */
+			if (flash_info[i].legacy_unlock) {
+				int k;
 
-	return flash_full_status_check (info, find_sector (info, dest),
-					info->write_tout, "write");
-}
+				/*
+				 * Disable legacy_unlock temporarily,
+				 * since flash_real_protect would
+				 * relock all other sectors again
+				 * otherwise.
+				 */
+				flash_info[i].legacy_unlock = 0;
 
-#ifdef CFG_FLASH_USE_BUFFER_WRITE
+				/*
+				 * Legacy unlocking (e.g. Intel J3) ->
+				 * unlock only one sector. This will
+				 * unlock all sectors.
+				 */
+				flash_real_protect (&flash_info[i], 0, 0);
 
-static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
-				  int len)
-{
-	flash_sect_t sector;
-	int cnt;
-	int retcode;
-	volatile cfiptr_t src;
-	volatile cfiptr_t dst;
+				flash_info[i].legacy_unlock = 1;
 
-	switch (info->vendor) {
-	case CFI_CMDSET_INTEL_STANDARD:
-	case CFI_CMDSET_INTEL_EXTENDED:
-		src.cp = cp;
-		dst.cp = (uchar *) dest;
-		sector = find_sector (info, dest);
-		flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
-		flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
-		if ((retcode = flash_status_check (info, sector, info->buffer_write_tout,
-						   "write to buffer")) == ERR_OK) {
-			/* reduce the number of loops by the width of the port	*/
-			switch (info->portwidth) {
-			case FLASH_CFI_8BIT:
-				cnt = len;
-				break;
-			case FLASH_CFI_16BIT:
-				cnt = len >> 1;
-				break;
-			case FLASH_CFI_32BIT:
-				cnt = len >> 2;
-				break;
-			case FLASH_CFI_64BIT:
-				cnt = len >> 3;
-				break;
-			default:
-				return ERR_INVAL;
-				break;
-			}
-			flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
-			while (cnt-- > 0) {
-				switch (info->portwidth) {
-				case FLASH_CFI_8BIT:
-					*dst.cp++ = *src.cp++;
-					break;
-				case FLASH_CFI_16BIT:
-					*dst.wp++ = *src.wp++;
-					break;
-				case FLASH_CFI_32BIT:
-					*dst.lp++ = *src.lp++;
-					break;
-				case FLASH_CFI_64BIT:
-					*dst.llp++ = *src.llp++;
-					break;
-				default:
-					return ERR_INVAL;
-					break;
-				}
+				/*
+				 * Manually mark other sectors as
+				 * unlocked (unprotected)
+				 */
+				for (k = 1; k < flash_info[i].sector_count; k++)
+					flash_info[i].protect[k] = 0;
+			} else {
+				/*
+				 * No legancy unlocking -> unlock all sectors
+				 */
+				flash_protect (FLAG_PROTECT_CLEAR,
+					       flash_info[i].start[0],
+					       flash_info[i].start[0]
+					       + flash_info[i].size - 1,
+					       &flash_info[i]);
 			}
-			flash_write_cmd (info, sector, 0,
-					 FLASH_CMD_WRITE_BUFFER_CONFIRM);
-			retcode = flash_full_status_check (info, sector,
-							   info->buffer_write_tout,
-							   "buffer write");
 		}
-		return retcode;
-
-	case CFI_CMDSET_AMD_STANDARD:
-	case CFI_CMDSET_AMD_EXTENDED:
-		src.cp = cp;
-		dst.cp = (uchar *) dest;
-		sector = find_sector (info, dest);
+#endif /* CFG_FLASH_PROTECTION */
+	}
 
-		flash_unlock_seq(info,0);
-		flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
+	/* Monitor protection ON by default */
+#if (CFG_MONITOR_BASE >= CFG_FLASH_BASE)
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_MONITOR_BASE,
+		       CFG_MONITOR_BASE + monitor_flash_len  - 1,
+		       flash_get_info(CFG_MONITOR_BASE));
+#endif
 
-		switch (info->portwidth) {
-		case FLASH_CFI_8BIT:
-			cnt = len;
-			flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
-			while (cnt-- > 0) *dst.cp++ = *src.cp++;
-			break;
-		case FLASH_CFI_16BIT:
-			cnt = len >> 1;
-			flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
-			while (cnt-- > 0) *dst.wp++ = *src.wp++;
-			break;
-		case FLASH_CFI_32BIT:
-			cnt = len >> 2;
-			flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
-			while (cnt-- > 0) *dst.lp++ = *src.lp++;
-			break;
-		case FLASH_CFI_64BIT:
-			cnt = len >> 3;
-			flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
-			while (cnt-- > 0) *dst.llp++ = *src.llp++;
-			break;
-		default:
-			return ERR_INVAL;
-		}
+	/* Environment protection ON by default */
+#ifdef CFG_ENV_IS_IN_FLASH
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_ENV_ADDR,
+		       CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
+		       flash_get_info(CFG_ENV_ADDR));
+#endif
 
-		flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
-		retcode = flash_full_status_check (info, sector, info->buffer_write_tout,
-						   "buffer write");
-		return retcode;
+	/* Redundant environment protection ON by default */
+#ifdef CFG_ENV_ADDR_REDUND
+	flash_protect (FLAG_PROTECT_SET,
+		       CFG_ENV_ADDR_REDUND,
+		       CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1,
+		       flash_get_info(CFG_ENV_ADDR_REDUND));
+#endif
 
-	default:
-		debug ("Unknown Command Set\n");
-		return ERR_INVAL;
+#if defined(CFG_FLASH_AUTOPROTECT_LIST)
+	for (i = 0; i < (sizeof(apl) / sizeof(struct apl_s)); i++) {
+		debug("autoprotecting from %08x to %08x\n",
+		      apl[i].start, apl[i].start + apl[i].size - 1);
+		flash_protect (FLAG_PROTECT_SET,
+			       apl[i].start,
+			       apl[i].start + apl[i].size - 1,
+			       flash_get_info(apl[i].start));
 	}
+#endif
+	return (size);
 }
-#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+
 #endif /* CFG_FLASH_CFI */
diff -urN u-boot-1.1.6/drivers/dm9000x.c u-boot-1.1.6_jz2440/drivers/dm9000x.c
--- u-boot-1.1.6/drivers/dm9000x.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/drivers/dm9000x.c	2010-11-26 12:54:38.306059089 +0800
@@ -17,17 +17,17 @@
   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
 
 V0.11	06/20/2001	REG_0A bit3=1, default enable BP with DA match
-	06/22/2001 	Support DM9801 progrmming
-	 	 	E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
-		 	E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
-     		R17 = (R17 & 0xfff0) | NF + 3
-		 	E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
-     		R17 = (R17 & 0xfff0) | NF
+	06/22/2001	Support DM9801 progrmming
+			E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
+			E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
+		R17 = (R17 & 0xfff0) | NF + 3
+			E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
+		R17 = (R17 & 0xfff0) | NF
 
-v1.00               	modify by simon 2001.9.5
+v1.00			modify by simon 2001.9.5
 	                change for kernel 2.4.x
 
-v1.1   11/09/2001      	fix force mode bug
+v1.1   11/09/2001	fix force mode bug
 
 v1.2   03/18/2003       Weilun Huang <weilun_huang@davicom.com.tw>:
 			Fixed phy reset.
@@ -36,17 +36,32 @@
 
 --------------------------------------
 
-       12/15/2003       Initial port to u-boot by Sascha Hauer <saschahauer@web.de>
+       12/15/2003       Initial port to u-boot by
+       			Sascha Hauer <saschahauer@web.de>
+
+       06/03/2008	Remy Bohmer <linux@bohmer.net>
+			- Fixed the driver to work with DM9000A.
+			  (check on ISR receive status bit before reading the
+			  FIFO as described in DM9000 programming guide and
+			  application notes)
+			- Added autodetect of databus width.
+			- Made debug code compile again.
+			- Adapt eth_send such that it matches the DM9000*
+			  application notes. Needed to make it work properly
+			  for DM9000A.
+			- Adapted reset procedure to match DM9000 application
+			  notes (i.e. double reset)
+			- some minor code cleanups
+			These changes are tested with DM9000{A,EP,E} together
+			with a 200MHz Atmel AT91SAM92161 core
 
 TODO: Homerun NIC and longrun NIC are not functional, only internal at the
       moment.
 */
-
 #include <common.h>
 #include <command.h>
 #include <net.h>
 #include <asm/io.h>
-
 #ifdef CONFIG_DRIVER_DM9000
 
 #include "dm9000x.h"
@@ -59,10 +74,22 @@
 /* #define CONFIG_DM9000_DEBUG */
 
 #ifdef CONFIG_DM9000_DEBUG
-#define DM9000_DBG(fmt,args...) printf(fmt ,##args)
-#else				/*  */
+#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
+#define DM9000_DMP_PACKET(func,packet,length)  \
+	do { \
+		int i; 							\
+		printf(func ": length: %d\n", length);			\
+		for (i = 0; i < length; i++) {				\
+			if (i % 8 == 0)					\
+				printf("\n%s: %02x: ", func, i);	\
+			printf("%02x ", ((unsigned char *) packet)[i]);	\
+		} printf("\n");						\
+	} while(0)
+#else
 #define DM9000_DBG(fmt,args...)
-#endif				/*  */
+#define DM9000_DMP_PACKET(func,packet,length)
+#endif
+
 enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =
 	    1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO =
 	    8, DM9000_1M_HPNA = 0x10
@@ -84,8 +111,11 @@
 	u8 device_wait_reset;	/* device state */
 	u8 nic_type;		/* NIC type */
 	unsigned char srom[128];
+	void (*outblk)(volatile void *data_ptr, int count);
+	void (*inblk)(void *data_ptr, int count);
+	void (*rx_status)(u16 *RxStatus, u16 *RxLen);
 } board_info_t;
-board_info_t dmfe_info;
+static board_info_t dm9000_info;
 
 /* For module input parameter */
 static int media_mode = DM9000_AUTO;
@@ -99,7 +129,7 @@
 static int dm9000_probe(void);
 static u16 phy_read(int);
 static void phy_write(int, u16);
-static u16 read_srom_word(int);
+u16 read_srom_word(int);
 static u8 DM9000_ior(int);
 static void DM9000_iow(int reg, u8 value);
 
@@ -112,6 +142,16 @@
 #define DM9000_inw(r) (*(volatile u16 *)r)
 #define DM9000_inl(r) (*(volatile u32 *)r)
 
+static inline int is_zero_ether_addr(const u8 *addr)
+{
+	return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
+static inline int is_multicast_ether_addr(const u8 *addr)
+{
+	return (0x01 & addr[0]);
+}
+
 #ifdef CONFIG_DM9000_DEBUG
 static void
 dump_regs(void)
@@ -124,10 +164,85 @@
 	DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
 	DM9000_DBG("RCR   (0x05): %02x\n", DM9000_ior(5));
 	DM9000_DBG("RSR   (0x06): %02x\n", DM9000_ior(6));
-	DM9000_DBG("ISR   (0xFE): %02x\n", DM9000_ior(ISR));
+	DM9000_DBG("ISR   (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
 	DM9000_DBG("\n");
 }
-#endif				/*  */
+#endif
+
+static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
+{
+	int i;
+	for (i = 0; i < count; i++)
+		DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
+}
+
+static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
+{
+	int i;
+	u32 tmplen = (count + 1) / 2;
+
+	for (i = 0; i < tmplen; i++)
+		DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
+}
+static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
+{
+	int i;
+	u32 tmplen = (count + 3) / 4;
+
+	for (i = 0; i < tmplen; i++)
+		DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
+}
+
+static void dm9000_inblk_8bit(void *data_ptr, int count)
+{
+	int i;
+	for (i = 0; i < count; i++)
+		((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
+}
+
+static void dm9000_inblk_16bit(void *data_ptr, int count)
+{
+	int i;
+	u32 tmplen = (count + 1) / 2;
+
+	for (i = 0; i < tmplen; i++)
+		((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
+}
+static void dm9000_inblk_32bit(void *data_ptr, int count)
+{
+	int i;
+	u32 tmplen = (count + 3) / 4;
+
+	for (i = 0; i < tmplen; i++)
+		((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
+}
+
+static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
+{
+	u32 tmpdata;
+
+	DM9000_outb(DM9000_MRCMD, DM9000_IO);
+
+	tmpdata = DM9000_inl(DM9000_DATA);
+	*RxStatus = tmpdata;
+	*RxLen = tmpdata >> 16;
+}
+
+static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
+{
+	DM9000_outb(DM9000_MRCMD, DM9000_IO);
+
+	*RxStatus = DM9000_inw(DM9000_DATA);
+	*RxLen = DM9000_inw(DM9000_DATA);
+}
+
+static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
+{
+	DM9000_outb(DM9000_MRCMD, DM9000_IO);
+
+	*RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
+	*RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
+}
 
 /*
   Search DM9000 board, allocate space and register it
@@ -236,7 +351,7 @@
 static void
 identify_nic(void)
 {
-	struct board_info *db = &dmfe_info;	/* Point a board information structure */
+	struct board_info *db = &dm9000_info;
 	u16 phy_reg3;
 	DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
 	phy_reg3 = phy_read(3);
@@ -263,9 +378,35 @@
 static void
 dm9000_reset(void)
 {
-	DM9000_DBG("resetting\n");
-	DM9000_iow(DM9000_NCR, NCR_RST);
-	udelay(1000);		/* delay 1ms */
+	DM9000_DBG("resetting DM9000\n");
+
+	/* Reset DM9000,
+	   see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
+
+	/* DEBUG: Make all GPIO pins outputs */
+	DM9000_iow(DM9000_GPCR, 0x0F);
+	/* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
+	DM9000_iow(DM9000_GPR, 0);
+	/* Step 2: Software reset */
+	DM9000_iow(DM9000_NCR, 3);
+
+	do {
+		DM9000_DBG("resetting the DM9000, 1st reset\n");
+		udelay(25); /* Wait at least 20 us */
+	} while (DM9000_ior(DM9000_NCR) & 1);
+
+	DM9000_iow(DM9000_NCR, 0);
+	DM9000_iow(DM9000_NCR, 3); /* Issue a second reset */
+
+	do {
+		DM9000_DBG("resetting the DM9000, 2nd reset\n");
+		udelay(25); /* Wait at least 20 us */
+	} while (DM9000_ior(DM9000_NCR) & 1);
+
+	/* Check whether the ethernet controller is present */
+	if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
+	    (DM9000_ior(DM9000_PIDH) != 0x90))
+		printf("ERROR: resetting DM9000 -> not responding\n");
 }
 
 /* Initilize dm9000 board
@@ -274,12 +415,46 @@
 eth_init(bd_t * bd)
 {
 	int i, oft, lnk;
+	u8 io_mode;
+	struct board_info *db = &dm9000_info;
+
 	DM9000_DBG("eth_init()\n");
 
 	/* RESET device */
 	dm9000_reset();
 	dm9000_probe();
 
+	/* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
+	io_mode = DM9000_ior(DM9000_ISR) >> 6;
+
+	switch (io_mode) {
+	case 0x0:  /* 16-bit mode */
+		printf("DM9000: running in 16 bit mode\n");
+		db->outblk    = dm9000_outblk_16bit;
+		db->inblk     = dm9000_inblk_16bit;
+		db->rx_status = dm9000_rx_status_16bit;
+		break;
+	case 0x01:  /* 32-bit mode */
+		printf("DM9000: running in 32 bit mode\n");
+		db->outblk    = dm9000_outblk_32bit;
+		db->inblk     = dm9000_inblk_32bit;
+		db->rx_status = dm9000_rx_status_32bit;
+		break;
+	case 0x02: /* 8 bit mode */
+		printf("DM9000: running in 8 bit mode\n");
+		db->outblk    = dm9000_outblk_8bit;
+		db->inblk     = dm9000_inblk_8bit;
+		db->rx_status = dm9000_rx_status_8bit;
+		break;
+	default:
+		/* Assume 8 bit mode, will probably not work anyway */
+		printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
+		db->outblk    = dm9000_outblk_8bit;
+		db->inblk     = dm9000_inblk_8bit;
+		db->rx_status = dm9000_rx_status_8bit;
+		break;
+	}
+
 	/* NIC Type: FASTETHER, HOMERUN, LONGRUN */
 	identify_nic();
 
@@ -289,19 +464,43 @@
 	/* Set PHY */
 	set_PHY_mode();
 
-	/* Program operating register */
-	DM9000_iow(DM9000_NCR, 0x0);	/* only intern phy supported by now */
-	DM9000_iow(DM9000_TCR, 0);	/* TX Polling clear */
-	DM9000_iow(DM9000_BPTR, 0x3f);	/* Less 3Kb, 200us */
-	DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));	/* Flow Control : High/Low Water */
-	DM9000_iow(DM9000_FCR, 0x0);	/* SH FIXME: This looks strange! Flow Control */
-	DM9000_iow(DM9000_SMCR, 0);	/* Special Mode */
-	DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);	/* clear TX status */
-	DM9000_iow(DM9000_ISR, 0x0f);	/* Clear interrupt status */
+	/* Program operating register, only intern phy supported by now */
+	DM9000_iow(DM9000_NCR, 0x0);
+	/* TX Polling clear */
+	DM9000_iow(DM9000_TCR, 0);
+	/* Less 3Kb, 200us */
+	DM9000_iow(DM9000_BPTR, 0x3f);
+	/* Flow Control : High/Low Water */
+	DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
+	/* SH FIXME: This looks strange! Flow Control */
+	DM9000_iow(DM9000_FCR, 0x0);
+	/* Special Mode */
+	DM9000_iow(DM9000_SMCR, 0);
+	/* clear TX status */
+	DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
+	/* Clear interrupt status */
+	DM9000_iow(DM9000_ISR, 0x0f);
 
 	/* Set Node address */
+#ifndef CONFIG_AT91SAM9261EK
 	for (i = 0; i < 6; i++)
 		((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
+#endif
+
+	if (is_zero_ether_addr(bd->bi_enetaddr) ||
+	    is_multicast_ether_addr(bd->bi_enetaddr)) {
+		/* try reading from environment */
+		u8 i;
+		char *s, *e;
+		s = getenv ("ethaddr");
+		for (i = 0; i < 6; ++i) {
+			bd->bi_enetaddr[i] = s ?
+				simple_strtoul (s, &e, 16) : 0;
+			if (s)
+				s = (*e) ? e + 1 : e;
+		}
+	}
+
 	printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
 	       bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
 	       bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
@@ -316,8 +515,11 @@
 	DM9000_DBG("\n");
 
 	/* Activate DM9000 */
-	DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);	/* RX enable */
-	DM9000_iow(DM9000_IMR, IMR_PAR);	/* Enable TX/RX interrupt mask */
+	/* RX enable */
+	DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
+	/* Enable TX/RX interrupt mask */
+	DM9000_iow(DM9000_IMR, IMR_PAR);
+
 	i = 0;
 	while (!(phy_read(1) & 0x20)) {	/* autonegation complete bit */
 		udelay(1000);
@@ -359,54 +561,37 @@
 int
 eth_send(volatile void *packet, int length)
 {
-	char *data_ptr;
-	u32 tmplen, i;
 	int tmo;
-	DM9000_DBG("eth_send: length: %d\n", length);
-	for (i = 0; i < length; i++) {
-		if (i % 8 == 0)
-			DM9000_DBG("\nSend: 02x: ", i);
-		DM9000_DBG("%02x ", ((unsigned char *) packet)[i]);
-	} DM9000_DBG("\n");
+	struct board_info *db = &dm9000_info;
 
-	/* Move data to DM9000 TX RAM */
-	data_ptr = (char *) packet;
-	DM9000_outb(DM9000_MWCMD, DM9000_IO);
+	DM9000_DMP_PACKET("eth_send", packet, length);
 
-#ifdef CONFIG_DM9000_USE_8BIT
-	/* Byte mode */
-	for (i = 0; i < length; i++)
-		DM9000_outb((data_ptr[i] & 0xff), DM9000_DATA);
-
-#endif				/*  */
-#ifdef CONFIG_DM9000_USE_16BIT
-	tmplen = (length + 1) / 2;
-	for (i = 0; i < tmplen; i++)
-		DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
+	DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
 
-#endif				/*  */
-#ifdef CONFIG_DM9000_USE_32BIT
-	tmplen = (length + 3) / 4;
-	for (i = 0; i < tmplen; i++)
-		DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
+	/* Move data to DM9000 TX RAM */
+	DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
 
-#endif				/*  */
+	/* push the data to the TX-fifo */
+	(db->outblk)(packet, length);
 
 	/* Set TX length to DM9000 */
 	DM9000_iow(DM9000_TXPLL, length & 0xff);
 	DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
 
 	/* Issue TX polling command */
-	DM9000_iow(DM9000_TCR, TCR_TXREQ);	/* Cleared after TX complete */
+	DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
 
 	/* wait for end of transmission */
 	tmo = get_timer(0) + 5 * CFG_HZ;
-	while (DM9000_ior(DM9000_TCR) & TCR_TXREQ) {
+	while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
+		!(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
 		if (get_timer(0) >= tmo) {
 			printf("transmission timeout\n");
 			break;
 		}
 	}
+	DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
+
 	DM9000_DBG("transmit done\n\n");
 	return 0;
 }
@@ -435,86 +620,67 @@
 {
 	u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
 	u16 RxStatus, RxLen = 0;
-	u32 tmplen, i;
-#ifdef CONFIG_DM9000_USE_32BIT
-	u32 tmpdata;
-#endif
+	struct board_info *db = &dm9000_info;
 
-	/* Check packet ready or not */
-	DM9000_ior(DM9000_MRCMDX);	/* Dummy read */
-	rxbyte = DM9000_inb(DM9000_DATA);	/* Got most updated data */
-	if (rxbyte == 0)
+	/* Check packet ready or not, we must check
+	   the ISR status first for DM9000A */
+	if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
 		return 0;
 
-	/* Status check: this byte must be 0 or 1 */
-	if (rxbyte > 1) {
-		DM9000_iow(DM9000_RCR, 0x00);	/* Stop Device */
-		DM9000_iow(DM9000_ISR, 0x80);	/* Stop INT request */
-		DM9000_DBG("rx status check: %d\n", rxbyte);
-	}
-	DM9000_DBG("receiving packet\n");
-
-	/* A packet ready now  & Get status/length */
-	DM9000_outb(DM9000_MRCMD, DM9000_IO);
+	DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
 
-#ifdef CONFIG_DM9000_USE_8BIT
-	RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
-	RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
-
-#endif				/*  */
-#ifdef CONFIG_DM9000_USE_16BIT
-	RxStatus = DM9000_inw(DM9000_DATA);
-	RxLen = DM9000_inw(DM9000_DATA);
+	/* There is _at least_ 1 package in the fifo, read them all */
+	for (;;) {
+		DM9000_ior(DM9000_MRCMDX);	/* Dummy read */
+
+		/* Get most updated data,
+		   only look at bits 0:1, See application notes DM9000 */
+		rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
+
+		/* Status check: this byte must be 0 or 1 */
+		if (rxbyte > DM9000_PKT_RDY) {
+			DM9000_iow(DM9000_RCR, 0x00);	/* Stop Device */
+			DM9000_iow(DM9000_ISR, 0x80);	/* Stop INT request */
+			printf("DM9000 error: status check fail: 0x%x\n",
+				rxbyte);
+			return 0;
+		}
 
-#endif				/*  */
-#ifdef CONFIG_DM9000_USE_32BIT
-	tmpdata = DM9000_inl(DM9000_DATA);
-	RxStatus = tmpdata;
-	RxLen = tmpdata >> 16;
+		if (rxbyte != DM9000_PKT_RDY)
+			return 0; /* No packet received, ignore */
 
-#endif				/*  */
-	DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
+		DM9000_DBG("receiving packet\n");
 
-	/* Move data from DM9000 */
-	/* Read received packet from RX SRAM */
-#ifdef CONFIG_DM9000_USE_8BIT
-	for (i = 0; i < RxLen; i++)
-		rdptr[i] = DM9000_inb(DM9000_DATA);
-
-#endif				/*  */
-#ifdef CONFIG_DM9000_USE_16BIT
-	tmplen = (RxLen + 1) / 2;
-	for (i = 0; i < tmplen; i++)
-		((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA);
+		/* A packet ready now  & Get status/length */
+		(db->rx_status)(&RxStatus, &RxLen);
 
-#endif				/*  */
-#ifdef CONFIG_DM9000_USE_32BIT
-	tmplen = (RxLen + 3) / 4;
-	for (i = 0; i < tmplen; i++)
-		((u32 *) rdptr)[i] = DM9000_inl(DM9000_DATA);
+		DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
+
+		/* Move data from DM9000 */
+		/* Read received packet from RX SRAM */
+		(db->inblk)(rdptr, RxLen);
+
+		if ((RxStatus & 0xbf00) || (RxLen < 0x40)
+			|| (RxLen > DM9000_PKT_MAX)) {
+			if (RxStatus & 0x100) {
+				printf("rx fifo error\n");
+			}
+			if (RxStatus & 0x200) {
+				printf("rx crc error\n");
+			}
+			if (RxStatus & 0x8000) {
+				printf("rx length error\n");
+			}
+			if (RxLen > DM9000_PKT_MAX) {
+				printf("rx length too big\n");
+				dm9000_reset();
+			}
+		} else {
+			DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
 
-#endif				/*  */
-	if ((RxStatus & 0xbf00) || (RxLen < 0x40)
-	    || (RxLen > DM9000_PKT_MAX)) {
-		if (RxStatus & 0x100) {
-			printf("rx fifo error\n");
+			DM9000_DBG("passing packet to upper layer\n");
+			NetReceive(NetRxPackets[0], RxLen);
 		}
-		if (RxStatus & 0x200) {
-			printf("rx crc error\n");
-		}
-		if (RxStatus & 0x8000) {
-			printf("rx length error\n");
-		}
-		if (RxLen > DM9000_PKT_MAX) {
-			printf("rx length too big\n");
-			dm9000_reset();
-		}
-	} else {
-
-		/* Pass to upper layer */
-		DM9000_DBG("passing packet to upper layer\n");
-		NetReceive(NetRxPackets[0], RxLen);
-		return RxLen;
 	}
 	return 0;
 }
@@ -522,16 +688,28 @@
 /*
   Read a word data from SROM
 */
-static u16
+u16
 read_srom_word(int offset)
 {
 	DM9000_iow(DM9000_EPAR, offset);
 	DM9000_iow(DM9000_EPCR, 0x4);
-	udelay(200);
+	udelay(8000);
 	DM9000_iow(DM9000_EPCR, 0x0);
 	return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
 }
 
+void
+write_srom_word(int offset, u16 val)
+{
+	DM9000_iow(DM9000_EPAR, offset);
+	DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
+	DM9000_iow(DM9000_EPDRL, (val & 0xff));
+	DM9000_iow(DM9000_EPCR, 0x12);
+	udelay(8000);
+	DM9000_iow(DM9000_EPCR, 0);
+}
+
+
 /*
    Read a byte from I/O port
 */
@@ -563,12 +741,12 @@
 	/* Fill the phyxcer register into REG_0C */
 	DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
 	DM9000_iow(DM9000_EPCR, 0xc);	/* Issue phyxcer read command */
-	udelay(100);		/* Wait read complete */
+	udelay(100);			/* Wait read complete */
 	DM9000_iow(DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
 	val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
 
 	/* The read data keeps on REG_0D & REG_0E */
-	DM9000_DBG("phy_read(%d): %d\n", reg, val);
+	DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
 	return val;
 }
 
@@ -586,8 +764,9 @@
 	DM9000_iow(DM9000_EPDRL, (value & 0xff));
 	DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
 	DM9000_iow(DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
-	udelay(500);		/* Wait write complete */
+	udelay(500);			/* Wait write complete */
 	DM9000_iow(DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
-	DM9000_DBG("phy_write(reg:%d, value:%d)\n", reg, value);
+	DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
 }
-#endif				/* CONFIG_DRIVER_DM9000 */
+
+#endif /* CONFIG_DRIVER_DM9000 */
diff -urN u-boot-1.1.6/drivers/jedec_flash.c u-boot-1.1.6_jz2440/drivers/jedec_flash.c
--- u-boot-1.1.6/drivers/jedec_flash.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/jedec_flash.c	2010-11-26 12:54:38.462156280 +0800
@@ -0,0 +1,1894 @@
+/*
+ * (C) Copyright 2007
+ * Michael Schwingen, <michael@schwingen.org>
+ *
+ * based in great part on jedec_probe.c from linux kernel:
+ * (C) 2000 Red Hat. GPL'd.
+ * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
+ *
+ * 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
+ *
+ */
+
+/* The DEBUG define must be before common to enable debugging */
+/*#define DEBUG*/
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <environment.h>
+
+#define P_ID_NONE               0x0000
+#define P_ID_INTEL_EXT          0x0001
+#define P_ID_AMD_STD            0x0002
+#define P_ID_INTEL_STD          0x0003
+#define P_ID_AMD_EXT            0x0004
+#define P_ID_WINBOND            0x0006
+#define P_ID_ST_ADV             0x0020
+#define P_ID_MITSUBISHI_STD     0x0100
+#define P_ID_MITSUBISHI_EXT     0x0101
+#define P_ID_SST_PAGE           0x0102
+#define P_ID_INTEL_PERFORMANCE  0x0200
+#define P_ID_INTEL_DATA         0x0210
+#define P_ID_RESERVED           0xffff
+
+
+/* Manufacturers */
+#define MANUFACTURER_AMD	0x0001
+#define MANUFACTURER_ATMEL	0x001f
+#define MANUFACTURER_FUJITSU	0x0004
+#define MANUFACTURER_HYUNDAI	0x00AD
+#define MANUFACTURER_INTEL	0x0089
+#define MANUFACTURER_MACRONIX	0x00C2
+#define MANUFACTURER_NEC	0x0010
+#define MANUFACTURER_PMC	0x009D
+#define MANUFACTURER_SHARP	0x00b0
+#define MANUFACTURER_SST	0x00BF
+#define MANUFACTURER_ST		0x0020
+#define MANUFACTURER_TOSHIBA	0x0098
+#define MANUFACTURER_WINBOND	0x00da
+
+
+/* AMD */
+#define AM29DL800BB	0x22C8
+#define AM29DL800BT	0x224A
+
+#define AM29F800BB	0x2258
+#define AM29F800BT	0x22D6
+#define AM29LV400BB	0x22BA
+#define AM29LV400BT	0x22B9
+#define AM29LV800BB	0x225B
+#define AM29LV800BT	0x22DA
+#define AM29LV160DT	0x22C4
+#define AM29LV160DB	0x2249
+#define AM29F017D	0x003D
+#define AM29F016D	0x00AD
+#define AM29F080	0x00D5
+#define AM29F040	0x00A4
+#define AM29LV040B	0x004F
+#define AM29F032B	0x0041
+#define AM29F002T	0x00B0
+
+/* Atmel */
+#define AT49BV512	0x0003
+#define AT29LV512	0x003d
+#define AT49BV16X	0x00C0
+#define AT49BV16XT	0x00C2
+#define AT49BV32X	0x00C8
+#define AT49BV32XT	0x00C9
+
+/* Fujitsu */
+#define MBM29F040C	0x00A4
+#define MBM29LV650UE	0x22D7
+#define MBM29LV320TE	0x22F6
+#define MBM29LV320BE	0x22F9
+#define MBM29LV160TE	0x22C4
+#define MBM29LV160BE	0x2249
+#define MBM29LV800BA	0x225B
+#define MBM29LV800TA	0x22DA
+#define MBM29LV400TC	0x22B9
+#define MBM29LV400BC	0x22BA
+
+/* Hyundai */
+#define HY29F002T	0x00B0
+
+/* Intel */
+#define I28F004B3T	0x00d4
+#define I28F004B3B	0x00d5
+#define I28F400B3T	0x8894
+#define I28F400B3B	0x8895
+#define I28F008S5	0x00a6
+#define I28F016S5	0x00a0
+#define I28F008SA	0x00a2
+#define I28F008B3T	0x00d2
+#define I28F008B3B	0x00d3
+#define I28F800B3T	0x8892
+#define I28F800B3B	0x8893
+#define I28F016S3	0x00aa
+#define I28F016B3T	0x00d0
+#define I28F016B3B	0x00d1
+#define I28F160B3T	0x8890
+#define I28F160B3B	0x8891
+#define I28F320B3T	0x8896
+#define I28F320B3B	0x8897
+#define I28F640B3T	0x8898
+#define I28F640B3B	0x8899
+#define I82802AB	0x00ad
+#define I82802AC	0x00ac
+
+/* Macronix */
+#define MX29LV040C	0x004F
+#define MX29LV160T	0x22C4
+#define MX29LV160B	0x2249
+#define MX29F040	0x00A4
+#define MX29F016	0x00AD
+#define MX29F002T	0x00B0
+#define MX29F004T	0x0045
+#define MX29F004B	0x0046
+
+/* NEC */
+#define UPD29F064115	0x221C
+
+/* PMC */
+#define PM49FL002	0x006D
+#define PM49FL004	0x006E
+#define PM49FL008	0x006A
+
+/* Sharp */
+#define LH28F640BF	0x00b0
+
+/* ST - www.st.com */
+#define M29W800DT	0x00D7
+#define M29W800DB	0x005B
+#define M29W160DT	0x22C4
+#define M29W160DB	0x2249
+#define M29W040B	0x00E3
+#define M50FW040	0x002C
+#define M50FW080	0x002D
+#define M50FW016	0x002E
+#define M50LPW080       0x002F
+
+/* SST */
+#define SST29EE020	0x0010
+#define SST29LE020	0x0012
+#define SST29EE512	0x005d
+#define SST29LE512	0x003d
+#define SST39LF800	0x2781
+#define SST39LF160	0x2782
+#define SST39VF1601	0x234b
+#define SST39LF512	0x00D4
+#define SST39LF010	0x00D5
+#define SST39LF020	0x00D6
+#define SST39LF040	0x00D7
+#define SST39SF010A	0x00B5
+#define SST39SF020A	0x00B6
+#define SST49LF004B	0x0060
+#define SST49LF040B	0x0050
+#define SST49LF008A	0x005a
+#define SST49LF030A	0x001C
+#define SST49LF040A	0x0051
+#define SST49LF080A	0x005B
+
+/* Toshiba */
+#define TC58FVT160	0x00C2
+#define TC58FVB160	0x0043
+#define TC58FVT321	0x009A
+#define TC58FVB321	0x009C
+#define TC58FVT641	0x0093
+#define TC58FVB641	0x0095
+
+/* Winbond */
+#define W49V002A	0x00b0
+
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+
+struct unlock_addr {
+	u32 addr1;
+	u32 addr2;
+};
+
+/*
+ * Unlock address sets for AMD command sets.
+ * Intel command sets use the MTD_UADDR_UNNECESSARY.
+ * Each identifier, except MTD_UADDR_UNNECESSARY, and
+ * MTD_UADDR_NO_SUPPORT must be defined below in unlock_addrs[].
+ * MTD_UADDR_NOT_SUPPORTED must be 0 so that structure
+ * initialization need not require initializing all of the
+ * unlock addresses for all bit widths.
+ */
+enum uaddr {
+	MTD_UADDR_NOT_SUPPORTED = 0,	/* data width not supported */
+	MTD_UADDR_0x0555_0x02AA,
+	MTD_UADDR_0x0555_0x0AAA,
+	MTD_UADDR_0x5555_0x2AAA,
+	MTD_UADDR_0x0AAA_0x0555,
+	MTD_UADDR_DONT_CARE,		/* Requires an arbitrary address */
+	MTD_UADDR_UNNECESSARY,		/* Does not require any address */
+};
+
+
+
+
+/*
+ * I don't like the fact that the first entry in unlock_addrs[]
+ * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore,
+ * should not be used.  The  problem is that structures with
+ * initializers have extra fields initialized to 0.  It is _very_
+ * desireable to have the unlock address entries for unsupported
+ * data widths automatically initialized - that means that
+ * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here
+ * must go unused.
+ */
+static const struct unlock_addr  unlock_addrs[] = {
+	[MTD_UADDR_NOT_SUPPORTED] = {
+		.addr1 = 0xffff,
+		.addr2 = 0xffff
+	},
+
+	[MTD_UADDR_0x0555_0x02AA] = {
+		.addr1 = 0x0555,
+		.addr2 = 0x02aa
+	},
+
+	[MTD_UADDR_0x0555_0x0AAA] = {
+		.addr1 = 0x0555,
+		.addr2 = 0x0aaa
+	},
+
+	[MTD_UADDR_0x5555_0x2AAA] = {
+		.addr1 = 0x5555,
+		.addr2 = 0x2aaa
+	},
+
+	[MTD_UADDR_0x0AAA_0x0555] = {
+		.addr1 = 0x0AAA,
+		.addr2 = 0x0555
+	},
+
+	[MTD_UADDR_DONT_CARE] = {
+		.addr1 = 0x0000,      /* Doesn't matter which address */
+		.addr2 = 0x0000       /* is used - must be last entry */
+	},
+
+	[MTD_UADDR_UNNECESSARY] = {
+		.addr1 = 0x0000,
+		.addr2 = 0x0000
+	}
+};
+
+struct amd_flash_info {
+	const __u16 mfr_id;
+	const __u16 dev_id;
+	const char *name;
+	const int DevSize;
+	const int NumEraseRegions;
+	const int CmdSet;
+	const __u8 uaddr[4];		/* unlock addrs for 8, 16, 32, 64 */
+	const ulong regions[6];
+};
+
+#define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
+
+#define SIZE_64KiB  16
+#define SIZE_128KiB 17
+#define SIZE_256KiB 18
+#define SIZE_512KiB 19
+#define SIZE_1MiB   20
+#define SIZE_2MiB   21
+#define SIZE_4MiB   22
+#define SIZE_8MiB   23
+
+
+/*
+ * Please keep this list ordered by manufacturer!
+ * Fortunately, the list isn't searched often and so a
+ * slow, linear search isn't so bad.
+ */
+static const struct amd_flash_info jedec_table[] = {
+	{
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F032B,
+		.name		= "AMD AM29F032B",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,64)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29LV160DT,
+		.name		= "AMD AM29LV160DT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA   /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,31),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29LV160DB,
+		.name		= "AMD AM29LV160DB",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA   /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,31)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29LV400BB,
+		.name		= "AMD AM29LV400BB",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,7)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29LV400BT,
+		.name		= "AMD AM29LV400BT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,7),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29LV800BB,
+		.name		= "AMD AM29LV800BB",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,15),
+		}
+	}, {
+/* add DL */
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29DL800BB,
+		.name		= "AMD AM29DL800BB",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 6,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,4),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x10000,14)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29DL800BT,
+		.name		= "AMD AM29DL800BT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 6,
+		.regions	= {
+			ERASEINFO(0x10000,14),
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,4),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F800BB,
+		.name		= "AMD AM29F800BB",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,15),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29LV800BT,
+		.name		= "AMD AM29LV800BT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,15),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F800BT,
+		.name		= "AMD AM29F800BT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,15),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F017D,
+		.name		= "AMD AM29F017D",
+		.uaddr		= {
+			[0] = MTD_UADDR_DONT_CARE     /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,32),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F016D,
+		.name		= "AMD AM29F016D",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,32),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F080,
+		.name		= "AMD AM29F080",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,16),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F040,
+		.name		= "AMD AM29F040",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29LV040B,
+		.name		= "AMD AM29LV040B",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_AMD,
+		.dev_id		= AM29F002T,
+		.name		= "AMD AM29F002T",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_256KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,3),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ATMEL,
+		.dev_id		= AT49BV512,
+		.name		= "Atmel AT49BV512",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_64KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ATMEL,
+		.dev_id		= AT29LV512,
+		.name		= "Atmel AT29LV512",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_64KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x80,256),
+			ERASEINFO(0x80,256)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ATMEL,
+		.dev_id		= AT49BV16X,
+		.name		= "Atmel AT49BV16X",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000,8),
+			ERASEINFO(0x10000,31)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ATMEL,
+		.dev_id		= AT49BV16XT,
+		.name		= "Atmel AT49BV16XT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000,31),
+			ERASEINFO(0x02000,8)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ATMEL,
+		.dev_id		= AT49BV32X,
+		.name		= "Atmel AT49BV32X",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000,8),
+			ERASEINFO(0x10000,63)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ATMEL,
+		.dev_id		= AT49BV32XT,
+		.name		= "Atmel AT49BV32XT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x0AAA,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x0AAA   /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000,63),
+			ERASEINFO(0x02000,8)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29F040C,
+		.name		= "Fujitsu MBM29F040C",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV650UE,
+		.name		= "Fujitsu MBM29LV650UE",
+		.uaddr		= {
+			[0] = MTD_UADDR_DONT_CARE     /* x16 */
+		},
+		.DevSize	= SIZE_8MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,128)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV320TE,
+		.name		= "Fujitsu MBM29LV320TE",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000,63),
+			ERASEINFO(0x02000,8)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV320BE,
+		.name		= "Fujitsu MBM29LV320BE",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000,8),
+			ERASEINFO(0x10000,63)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV160TE,
+		.name		= "Fujitsu MBM29LV160TE",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,31),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV160BE,
+		.name		= "Fujitsu MBM29LV160BE",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,31)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV800BA,
+		.name		= "Fujitsu MBM29LV800BA",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,15)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV800TA,
+		.name		= "Fujitsu MBM29LV800TA",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,15),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV400BC,
+		.name		= "Fujitsu MBM29LV400BC",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,7)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_FUJITSU,
+		.dev_id		= MBM29LV400TC,
+		.name		= "Fujitsu MBM29LV400TC",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,7),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_HYUNDAI,
+		.dev_id		= HY29F002T,
+		.name		= "Hyundai HY29F002T",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_256KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,3),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F004B3B,
+		.name		= "Intel 28F004B3B",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 7),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F004B3T,
+		.name		= "Intel 28F004B3T",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 7),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F400B3B,
+		.name		= "Intel 28F400B3B",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 7),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F400B3T,
+		.name		= "Intel 28F400B3T",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 7),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F008B3B,
+		.name		= "Intel 28F008B3B",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 15),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F008B3T,
+		.name		= "Intel 28F008B3T",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 15),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F008S5,
+		.name		= "Intel 28F008S5",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,16),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F016S5,
+		.name		= "Intel 28F016S5",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,32),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F008SA,
+		.name		= "Intel 28F008SA",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000, 16),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F800B3B,
+		.name		= "Intel 28F800B3B",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 15),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F800B3T,
+		.name		= "Intel 28F800B3T",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 15),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F016B3B,
+		.name		= "Intel 28F016B3B",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 31),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F016S3,
+		.name		= "Intel I28F016S3",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000, 32),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F016B3T,
+		.name		= "Intel 28F016B3T",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 31),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F160B3B,
+		.name		= "Intel 28F160B3B",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 31),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F160B3T,
+		.name		= "Intel 28F160B3T",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 31),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F320B3B,
+		.name		= "Intel 28F320B3B",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 63),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F320B3T,
+		.name		= "Intel 28F320B3T",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 63),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F640B3B,
+		.name		= "Intel 28F640B3B",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_8MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000, 8),
+			ERASEINFO(0x10000, 127),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I28F640B3T,
+		.name		= "Intel 28F640B3T",
+		.uaddr		= {
+			[1] = MTD_UADDR_UNNECESSARY,    /* x16 */
+		},
+		.DevSize	= SIZE_8MiB,
+		.CmdSet		= P_ID_INTEL_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000, 127),
+			ERASEINFO(0x02000, 8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I82802AB,
+		.name		= "Intel 82802AB",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_INTEL,
+		.dev_id		= I82802AC,
+		.name		= "Intel 82802AC",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,16),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29LV040C,
+		.name		= "Macronix MX29LV040C",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29LV160T,
+		.name		= "MXIC MX29LV160T",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,31),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_NEC,
+		.dev_id		= UPD29F064115,
+		.name		= "NEC uPD29F064115",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_8MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 3,
+		.regions	= {
+			ERASEINFO(0x2000,8),
+			ERASEINFO(0x10000,126),
+			ERASEINFO(0x2000,8),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29LV160B,
+		.name		= "MXIC MX29LV160B",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,31)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29F040,
+		.name		= "Macronix MX29F040",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29F016,
+		.name		= "Macronix MX29F016",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,32),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29F004T,
+		.name		= "Macronix MX29F004T",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,7),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29F004B,
+		.name		= "Macronix MX29F004B",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,7),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_MACRONIX,
+		.dev_id		= MX29F002T,
+		.name		= "Macronix MX29F002T",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_256KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,3),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_PMC,
+		.dev_id		= PM49FL002,
+		.name		= "PMC Pm49FL002",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_256KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO( 0x01000, 64 )
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_PMC,
+		.dev_id		= PM49FL004,
+		.name		= "PMC Pm49FL004",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO( 0x01000, 128 )
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_PMC,
+		.dev_id		= PM49FL008,
+		.name		= "PMC Pm49FL008",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO( 0x01000, 256 )
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_SHARP,
+		.dev_id		= LH28F640BF,
+		.name		= "LH28F640BF",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet         = P_ID_INTEL_STD,
+		.NumEraseRegions= 1,
+		.regions        = {
+			ERASEINFO(0x40000,16),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST39LF512,
+		.name		= "SST 39LF512",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_64KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,16),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST39LF010,
+		.name		= "SST 39LF010",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_128KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,32),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_SST,
+ 		.dev_id 	= SST29EE020,
+		.name		= "SST 29EE020",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+ 		.DevSize	= SIZE_256KiB,
+ 		.CmdSet		= P_ID_SST_PAGE,
+ 		.NumEraseRegions= 1,
+ 		.regions = {ERASEINFO(0x01000,64),
+ 		}
+         }, {
+ 		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST29LE020,
+ 		.name		= "SST 29LE020",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+ 		.DevSize	= SIZE_256KiB,
+ 		.CmdSet		= P_ID_SST_PAGE,
+ 		.NumEraseRegions= 1,
+ 		.regions = {ERASEINFO(0x01000,64),
+ 		}
+	}, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST39LF020,
+		.name		= "SST 39LF020",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_256KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,64),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST39LF040,
+		.name		= "SST 39LF040",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,128),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST39SF010A,
+		.name		= "SST 39SF010A",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_128KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,32),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST39SF020A,
+		.name		= "SST 39SF020A",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_256KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,64),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id         = SST49LF040B,
+		.name           = "SST 49LF040B",
+		.uaddr          = {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize        = SIZE_512KiB,
+		.CmdSet         = P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions        = {
+			ERASEINFO(0x01000,128),
+		}
+	}, {
+
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST49LF004B,
+		.name		= "SST 49LF004B",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,128),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST49LF008A,
+		.name		= "SST 49LF008A",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,256),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST49LF030A,
+		.name		= "SST 49LF030A",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,96),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST49LF040A,
+		.name		= "SST 49LF040A",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,128),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_SST,
+		.dev_id		= SST49LF080A,
+		.name		= "SST 49LF080A",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x01000,256),
+		}
+	}, {
+               .mfr_id         = MANUFACTURER_SST,     /* should be CFI */
+               .dev_id         = SST39LF160,
+               .name           = "SST 39LF160",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
+                       [1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
+               },
+               .DevSize        = SIZE_2MiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 2,
+               .regions        = {
+                       ERASEINFO(0x1000,256),
+                       ERASEINFO(0x1000,256)
+               }
+	}, {
+               .mfr_id         = MANUFACTURER_SST,     /* should be CFI */
+               .dev_id         = SST39VF1601,
+               .name           = "SST 39VF1601",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
+                       [1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
+               },
+               .DevSize        = SIZE_2MiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 2,
+               .regions        = {
+                       ERASEINFO(0x1000,256),
+                       ERASEINFO(0x1000,256)
+               }
+
+       }, {
+		.mfr_id		= MANUFACTURER_ST,	/* FIXME - CFI device? */
+		.dev_id		= M29W800DT,
+		.name		= "ST M29W800DT",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
+			[1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,15),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ST,	/* FIXME - CFI device? */
+		.dev_id		= M29W800DB,
+		.name		= "ST M29W800DB",
+ 		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
+			[1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,15)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ST,	/* FIXME - CFI device? */
+		.dev_id		= M29W160DT,
+		.name		= "ST M29W160DT",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,31),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ST,	/* FIXME - CFI device? */
+		.dev_id		= M29W160DB,
+		.name		= "ST M29W160DB",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,31)
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_ST,
+		.dev_id		= M29W040B,
+		.name		= "ST M29W040B",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_ST,
+		.dev_id		= M50FW040,
+		.name		= "ST M50FW040",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_512KiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,8),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_ST,
+		.dev_id		= M50FW080,
+		.name		= "ST M50FW080",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,16),
+		}
+        }, {
+		.mfr_id		= MANUFACTURER_ST,
+		.dev_id		= M50FW016,
+		.name		= "ST M50FW016",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,32),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_ST,
+		.dev_id		= M50LPW080,
+		.name		= "ST M50LPW080",
+		.uaddr		= {
+			[0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+		},
+		.DevSize	= SIZE_1MiB,
+		.CmdSet		= P_ID_INTEL_EXT,
+		.NumEraseRegions= 1,
+		.regions	= {
+			ERASEINFO(0x10000,16),
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_TOSHIBA,
+		.dev_id		= TC58FVT160,
+		.name		= "Toshiba TC58FVT160",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000,31),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x04000,1)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_TOSHIBA,
+		.dev_id		= TC58FVB160,
+		.name		= "Toshiba TC58FVB160",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
+		},
+		.DevSize	= SIZE_2MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x04000,1),
+			ERASEINFO(0x02000,2),
+			ERASEINFO(0x08000,1),
+			ERASEINFO(0x10000,31)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_TOSHIBA,
+		.dev_id		= TC58FVB321,
+		.name		= "Toshiba TC58FVB321",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000,8),
+			ERASEINFO(0x10000,63)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_TOSHIBA,
+		.dev_id		= TC58FVT321,
+		.name		= "Toshiba TC58FVT321",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA  /* x16 */
+		},
+		.DevSize	= SIZE_4MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000,63),
+			ERASEINFO(0x02000,8)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_TOSHIBA,
+		.dev_id		= TC58FVB641,
+		.name		= "Toshiba TC58FVB641",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
+		},
+		.DevSize	= SIZE_8MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x02000,8),
+			ERASEINFO(0x10000,127)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_TOSHIBA,
+		.dev_id		= TC58FVT641,
+		.name		= "Toshiba TC58FVT641",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
+			[1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
+		},
+		.DevSize	= SIZE_8MiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 2,
+		.regions	= {
+			ERASEINFO(0x10000,127),
+			ERASEINFO(0x02000,8)
+		}
+	}, {
+		.mfr_id		= MANUFACTURER_WINBOND,
+		.dev_id		= W49V002A,
+		.name		= "Winbond W49V002A",
+		.uaddr		= {
+			[0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+		},
+		.DevSize	= SIZE_256KiB,
+		.CmdSet		= P_ID_AMD_STD,
+		.NumEraseRegions= 4,
+		.regions	= {
+			ERASEINFO(0x10000, 3),
+			ERASEINFO(0x08000, 1),
+			ERASEINFO(0x02000, 2),
+			ERASEINFO(0x04000, 1),
+		}
+	}
+};
+
+static inline void fill_info(flash_info_t *info, const struct amd_flash_info *jedec_entry, ulong base)
+{
+	int i,j;
+	int sect_cnt;
+	int size_ratio;
+	int total_size;
+	enum uaddr uaddr_idx;
+
+	size_ratio = info->portwidth / info->chipwidth;
+
+	debug("Found JEDEC Flash: %s\n", jedec_entry->name);
+	info->vendor = jedec_entry->CmdSet;
+	/* Todo: do we need device-specific timeouts? */
+	info->erase_blk_tout = 30000;
+	info->buffer_write_tout = 1000;
+	info->write_tout = 100;
+	info->name = jedec_entry->name;
+
+	/* copy unlock addresses from device table to CFI info struct. This
+	   is just here because the addresses are in the table anyway - if
+	   the flash is not detected due to wrong unlock addresses,
+	   flash_detect_legacy would have to try all of them before we even
+	   get here. */
+	switch(info->chipwidth) {
+	case FLASH_CFI_8BIT:
+		uaddr_idx = jedec_entry->uaddr[0];
+		break;
+	case FLASH_CFI_16BIT:
+		uaddr_idx = jedec_entry->uaddr[1];
+		break;
+	case FLASH_CFI_32BIT:
+		uaddr_idx = jedec_entry->uaddr[2];
+		break;
+	default:
+		uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
+		break;
+	}
+
+	debug("unlock address index %d\n", uaddr_idx);
+	info->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
+	info->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
+	debug("unlock addresses are 0x%x/0x%x\n", info->addr_unlock1, info->addr_unlock2);
+
+	sect_cnt = 0;
+	total_size = 0;
+	for (i = 0; i < jedec_entry->NumEraseRegions; i++) {
+		ulong erase_region_size = jedec_entry->regions[i] >> 8;
+		ulong erase_region_count = (jedec_entry->regions[i] & 0xff) + 1;
+
+		total_size += erase_region_size * erase_region_count;
+		debug ("erase_region_count = %d erase_region_size = %d\n",
+		       erase_region_count, erase_region_size);
+		for (j = 0; j < erase_region_count; j++) {
+			if (sect_cnt >= CFG_MAX_FLASH_SECT) {
+				printf("ERROR: too many flash sectors\n");
+				break;
+			}
+			info->start[sect_cnt] = base;
+			base += (erase_region_size * size_ratio);
+			sect_cnt++;
+		}
+	}
+	info->sector_count = sect_cnt;
+	info->size = total_size * size_ratio;
+}
+
+/*-----------------------------------------------------------------------
+ * match jedec ids against table. If a match is found, fill flash_info entry
+ */
+int jedec_flash_match(flash_info_t *info, ulong base)
+{
+	int ret = 0;
+	int i;
+	ulong mask = 0xFFFF;
+	if (info->chipwidth == 1)
+		mask = 0xFF;
+
+	for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
+		if ((jedec_table[i].mfr_id & mask) == (info->manufacturer_id & mask) &&
+		    (jedec_table[i].dev_id & mask) == (info->device_id & mask)) {
+			fill_info(info, &jedec_table[i], base);
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+extern void flash_read_jedec_ids (flash_info_t * info);
+
+int jedec_flash_probe(flash_info_t *info, ulong base)
+{
+	int u;
+	for (u = MTD_UADDR_0x0555_0x02AA; u <= MTD_UADDR_UNNECESSARY; u++) {
+		info->addr_unlock1 = unlock_addrs[u].addr1;
+		info->addr_unlock2 = unlock_addrs[u].addr2;
+		flash_read_jedec_ids(info);
+		debug("JEDEC PROBE: ID %x %x %x\n",
+				info->manufacturer_id,
+				info->device_id,
+				info->device_id2);
+		if (jedec_flash_match(info, base))
+			return 1;
+	}
+	return 0;
+}
+
diff -urN u-boot-1.1.6/drivers/Makefile u-boot-1.1.6_jz2440/drivers/Makefile
--- u-boot-1.1.6/drivers/Makefile	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/drivers/Makefile	2010-11-26 12:54:38.422209313 +0800
@@ -28,7 +28,7 @@
 LIB	= $(obj)libdrivers.a
 
 COBJS	= 3c589.o 5701rls.o ali512x.o atmel_usart.o \
-	  bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \
+	  bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o jedec_flash.o \
 	  cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \
 	  e1000.o eepro100.o \
 	  i8042.o inca-ip_sw.o keyboard.o \
diff -urN u-boot-1.1.6/drivers/nand/nand_base.c u-boot-1.1.6_jz2440/drivers/nand/nand_base.c
--- u-boot-1.1.6/drivers/nand/nand_base.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/drivers/nand/nand_base.c	2010-11-26 12:54:38.406038793 +0800
@@ -88,6 +88,12 @@
 #include <jffs2/jffs2.h>
 #endif
 
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
 /* Define default oob placement schemes for large and small page devices */
 static struct nand_oobinfo nand_oob_8 = {
 	.useecc = MTD_NANDECC_AUTOPLACE,
@@ -427,17 +433,17 @@
 	struct nand_chip *this = mtd->priv;
 	u16 bad;
 
+	page = (int)(ofs >> this->page_shift);
+	chipnr = (int)(ofs >> this->chip_shift);
+
 	if (getchip) {
-		page = (int)(ofs >> this->page_shift);
-		chipnr = (int)(ofs >> this->chip_shift);
 
 		/* Grab the lock and see if the device is available */
 		nand_get_device (this, mtd, FL_READING);
 
 		/* Select the NAND device */
 		this->select_chip(mtd, chipnr);
-	} else
-		page = (int) ofs;
+	} 
 
 	if (this->options & NAND_BUSWIDTH_16) {
 		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask);
@@ -447,9 +453,17 @@
 		if ((bad & 0xFF) != 0xff)
 			res = 1;
 	} else {
-		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);
-		if (this->read_byte(mtd) != 0xff)
-			res = 1;
+    		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);
+    		if (this->read_byte(mtd) != 0xff)
+    			res = 1;
+
+        // Apply delay or wait for ready/busy pin
+        // add by www.100ask.net, if not, the erase will be failed
+		if (!this->dev_ready)
+			udelay (this->chip_delay);
+		else
+			while (!this->dev_ready(mtd));
+
 	}
 
 	if (getchip) {
@@ -517,11 +531,11 @@
 {
 	struct nand_chip *this = mtd->priv;
 
-	if (!this->bbt)
+//	if (!this->bbt)
 		return this->block_bad(mtd, ofs, getchip);
 
 	/* Return info from the table */
-	return nand_isbad_bbt (mtd, ofs, allowbbt);
+//	return nand_isbad_bbt (mtd, ofs, allowbbt);
 }
 
 /**
@@ -573,13 +587,17 @@
 			if (this->options & NAND_BUSWIDTH_16)
 				column >>= 1;
 			this->write_byte(mtd, column);
+			udelay(15);
 		}
 		if (page_addr != -1) {
 			this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
+			udelay(15);
 			this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
+			udelay(15);
 			/* One more address cycle for devices > 32MiB */
 			if (this->chipsize > (32 << 20))
 				this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
+   			    udelay(15);
 		}
 		/* Latch in address */
 		this->hwcontrol(mtd, NAND_CTL_CLRALE);
@@ -662,9 +680,11 @@
 
 		/* Serially input address */
 		if (column != -1) {
+#if 0			
 			/* Adjust columns for 16 bit buswidth */
 			if (this->options & NAND_BUSWIDTH_16)
 				column >>= 1;
+#endif			
 			this->write_byte(mtd, column & 0xff);
 			this->write_byte(mtd, column >> 8);
 		}
@@ -907,7 +927,7 @@
 	switch (eccmode) {
 	/* No ecc, write all */
 	case NAND_ECC_NONE:
-		printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
+		//printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
 		this->write_buf(mtd, this->data_poi, mtd->oobblock);
 		break;
 
@@ -943,8 +963,21 @@
 	/* Write out OOB data */
 	if (this->options & NAND_HWECC_SYNDROME)
 		this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
-	else
+	else if (eccmode != NAND_ECC_NONE)
 		this->write_buf(mtd, oob_buf, mtd->oobsize);
+	else {
+		for (i = 0; i < mtd->oobsize; i++) {
+			if (oob_buf[i] != 0xff)
+				break;
+		}
+		if (i < mtd->oobsize) {
+			printf("Bad oob_buf: page = 0x%x, data = ", page);
+			for (i = 0; i < mtd->oobsize; i++) {
+				printf("%02x ", oob_buf[i]);
+			}
+			printf("\n");
+		}
+	}
 
 	/* Send command to actually program the data */
 	this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
@@ -1216,7 +1249,7 @@
 				lastwhinge = jiffies;
 			}
 #else
-			puts("Reading data from NAND FLASH without ECC is not recommended\n");
+			//puts("Reading data from NAND FLASH without ECC is not recommended\n");
 #endif
 			this->read_buf(mtd, data_poi, end);
 			break;
@@ -1560,8 +1593,10 @@
 	}
 
 	/* If we have no autoplacement or no fs buffer use the internal one */
-	if (!autoplace || !fsbuf)
-		return this->oob_buf;
+        if (!autoplace || !fsbuf) {
+                this->oobdirty = 1;                     // by thisway.diy, www.100ask.net
+                return this->oob_buf;
+        }
 
 	/* Walk through the pages and place the data */
 	this->oobdirty = 1;
@@ -1751,6 +1786,126 @@
 }
 
 
+/*
+ * NAND write
+ */
+int
+nand_write_calmecc(struct mtd_info *mtd, loff_t to, size_t len, 
+           size_t *retlen, const u_char *buf, unsigned int *pdwECCVal)
+{
+	int i, page, col, cnt, status, chipnr;    
+	struct nand_chip *this = mtd->priv;
+    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
+
+	DEBUG(MTD_DEBUG_LEVEL3,
+		"%s(): to = 0x%08x, len = %i\n", __FUNCTION__, (unsigned int)to,
+		(int) len);
+
+	/* Do not allow write past end of page */
+	if ((to + len) > mtd->size) {
+		DEBUG(MTD_DEBUG_LEVEL0,
+			"%s(): Attempted write past end of device\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* Shift to get page */
+	page = ((int)to) >> this->page_shift;
+
+	/* Get the starting column */
+	col = to & (mtd->oobblock - 1);
+
+	/* Initialize return length value */
+	*retlen = 0;
+
+	/* Grab the lock and see if the device is available */
+	nand_get_device (this, mtd, FL_WRITING);
+
+	/* Calculate chipnr */
+	chipnr = (int)(to >> this->chip_shift);
+	/* Select the NAND device */
+	this->select_chip(mtd, chipnr);
+
+	/* Check, if it is write protected */
+	if (nand_check_wp(mtd))
+		goto nand_write_exit;
+
+	/* Loop until all data is written */
+	while (*retlen < len) {
+		/* Write data into buffer */
+		if ((col + len) >= mtd->oobblock)
+			for (i = col, cnt = 0; i < mtd->oobblock; i++, cnt++)
+				this->data_buf[i] = buf[(*retlen + cnt)];
+		else
+			for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++)
+				this->data_buf[i] = buf[(*retlen + cnt)];
+		/* Write ones for partial page programming */
+		for (i = mtd->oobblock; i < (mtd->oobblock + mtd->oobsize); i++)
+			this->data_buf[i] = 0xff;
+		
+		/* Write pre-padding bytes into buffer */
+		for (i = 0; i < col; i++)
+			this->data_buf[i] = 0xff;
+
+		/* Write post-padding bytes into buffer */
+		if ((col + (len - *retlen)) < mtd->oobblock) {
+			for (i = (col + cnt); i < mtd->oobblock; i++)
+				this->data_buf[i] = 0xff;
+		}
+
+        /* thisway.diy for cal ECC */
+        s3c2440nand->NFCONT |= (1<<4);   // Reset ECC
+        s3c2440nand->NFCONT &= ~(1<<5);  // UnLock MECC
+
+		/* Send command to begin auto page programming */
+		this->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+
+		/* Write out complete page of data */
+		this->write_buf(mtd, this->data_buf, mtd->oobblock);
+
+        s3c2440nand->NFCONT |= (1<<5);   // Lock MECC
+        *pdwECCVal = s3c2440nand->NFMECC0; // Read MECC
+
+		this->write_buf(mtd, &this->data_buf[mtd->oobblock], mtd->oobsize);
+        
+    	/* Send command to actually program the data */
+    	this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+    	/* call wait ready function */
+    	status = this->waitfunc (mtd, this, FL_WRITING);
+    	/* See if device thinks it succeeded */
+    	if (status & 0x01) {
+    		DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
+    		return -EIO;
+    	}
+
+		/* 
+		 * If we are writing a large amount of data and/or it
+		 * crosses page or half-page boundaries, we set the
+		 * the column to zero. It simplifies the program logic.
+		 */
+		if (col)
+			col = 0x00;
+
+		/* Update written bytes count */
+		*retlen += cnt;
+
+		/* Increment page address */
+		page++;
+		
+	}
+
+	/* Return happy */
+	*retlen = len;
+	i = 0;
+
+nand_write_exit:
+	/* Deselect and wake up anyone waiting on the device */
+	nand_release_device(mtd);
+
+	return i;
+}
+
+
 /**
  * nand_write_oob - [MTD Interface] NAND write out-of-band
  * @mtd:	MTD device structure
@@ -2631,7 +2786,7 @@
 	mtd->owner = THIS_MODULE;
 #endif
 	/* Build bad block table */
-	return this->scan_bbt (mtd);
+	return 0; //this->scan_bbt (mtd); // cancelled by www.100ask.net, scan_bbt uses more time
 }
 
 /**
diff -urN u-boot-1.1.6/drivers/nand/nand_ids.c u-boot-1.1.6_jz2440/drivers/nand/nand_ids.c
--- u-boot-1.1.6/drivers/nand/nand_ids.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/drivers/nand/nand_ids.c	2010-11-26 12:54:38.402251606 +0800
@@ -67,7 +67,8 @@
 
 	{"NAND 256MiB 3,3V 8-bit", 	0x71, 512, 256, 0x4000, 0},
 
-	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 512, 512, 0x4000, 0},
+/*	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 512, 512, 0x4000, 0}, */
+	{"NAND 512MiB 3,3V 8-bit",	0xDC, 0, 512, 0, 0},
 
 	/* These are the new chips with large page size. The pagesize
 	* and the erasesize is determined from the extended id bytes
diff -urN u-boot-1.1.6/drivers/nand/nand_util.c u-boot-1.1.6_jz2440/drivers/nand/nand_util.c
--- u-boot-1.1.6/drivers/nand/nand_util.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/drivers/nand/nand_util.c	2010-11-26 12:54:38.402251606 +0800
@@ -4,12 +4,12 @@
  * Copyright (C) 2006 by Weiss-Electronic GmbH.
  * All rights reserved.
  *
- * @author:	Guido Classen <clagix@gmail.com>
- * @descr:	NAND Flash support
+ * @author: Guido Classen <clagix@gmail.com>
+ * @descr:  NAND Flash support
  * @references: borrowed heavily from Linux mtd-utils code:
- *		flash_eraseall.c by Arcom Control System Ltd
- *		nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
- *			       and Thomas Gleixner (tglx@linutronix.de)
+ *      flash_eraseall.c by Arcom Control System Ltd
+ *      nandwrite.c by Steven J. Hill (sjhill@realitydiluted.com)
+ *                 and Thomas Gleixner (tglx@linutronix.de)
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -20,7 +20,7 @@
  *
  * 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
+ * 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
@@ -42,7 +42,7 @@
 #include <jffs2/jffs2.h>
 
 typedef struct erase_info erase_info_t;
-typedef struct mtd_info	  mtd_info_t;
+typedef struct mtd_info   mtd_info_t;
 
 /* support only for native endian JFFS2 */
 #define cpu_to_je16(x) (x)
@@ -51,199 +51,199 @@
 /*****************************************************************************/
 static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip)
 {
-	return 0;
+    return 0;
 }
 
 /**
  * nand_erase_opts: - erase NAND flash with support for various options
- *		      (jffs2 formating)
+ *            (jffs2 formating)
  *
- * @param meminfo	NAND device to erase
- * @param opts		options,  @see struct nand_erase_options
- * @return		0 in case of success
+ * @param meminfo   NAND device to erase
+ * @param opts      options,  @see struct nand_erase_options
+ * @return      0 in case of success
  *
  * This code is ported from flash_eraseall.c from Linux mtd utils by
  * Arcom Control System Ltd.
  */
 int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
 {
-	struct jffs2_unknown_node cleanmarker;
-	int clmpos = 0;
-	int clmlen = 8;
-	erase_info_t erase;
-	ulong erase_length;
-	int isNAND;
-	int bbtest = 1;
-	int result;
-	int percent_complete = -1;
-	int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;
-	const char *mtd_device = meminfo->name;
-
-	memset(&erase, 0, sizeof(erase));
-
-	erase.mtd = meminfo;
-	erase.len  = meminfo->erasesize;
-	erase.addr = opts->offset;
-	erase_length = opts->length;
-
-	isNAND = meminfo->type == MTD_NANDFLASH ? 1 : 0;
-
-	if (opts->jffs2) {
-		cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
-		cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-		if (isNAND) {
-			struct nand_oobinfo *oobinfo = &meminfo->oobinfo;
-
-			/* check for autoplacement */
-			if (oobinfo->useecc == MTD_NANDECC_AUTOPLACE) {
-				/* get the position of the free bytes */
-				if (!oobinfo->oobfree[0][1]) {
-					printf(" Eeep. Autoplacement selected "
-					       "and no empty space in oob\n");
-					return -1;
-				}
-				clmpos = oobinfo->oobfree[0][0];
-				clmlen = oobinfo->oobfree[0][1];
-				if (clmlen > 8)
-					clmlen = 8;
-			} else {
-				/* legacy mode */
-				switch (meminfo->oobsize) {
-				case 8:
-					clmpos = 6;
-					clmlen = 2;
-					break;
-				case 16:
-					clmpos = 8;
-					clmlen = 8;
-					break;
-				case 64:
-					clmpos = 16;
-					clmlen = 8;
-					break;
-				}
-			}
-
-			cleanmarker.totlen = cpu_to_je32(8);
-		} else {
-			cleanmarker.totlen =
-				cpu_to_je32(sizeof(struct jffs2_unknown_node));
-		}
-		cleanmarker.hdr_crc =  cpu_to_je32(
-			crc32_no_comp(0, (unsigned char *) &cleanmarker,
-				      sizeof(struct jffs2_unknown_node) - 4));
-	}
-
-	/* scrub option allows to erase badblock. To prevent internal
-	 * check from erase() method, set block check method to dummy
-	 * and disable bad block table while erasing.
-	 */
-	if (opts->scrub) {
-		struct nand_chip *priv_nand = meminfo->priv;
-
-		nand_block_bad_old = priv_nand->block_bad;
-		priv_nand->block_bad = nand_block_bad_scrub;
-		/* we don't need the bad block table anymore...
-		 * after scrub, there are no bad blocks left!
-		 */
-		if (priv_nand->bbt) {
-			kfree(priv_nand->bbt);
-		}
-		priv_nand->bbt = NULL;
-	}
-
-	for (;
-	     erase.addr < opts->offset + erase_length;
-	     erase.addr += meminfo->erasesize) {
-
-		WATCHDOG_RESET ();
-
-		if (!opts->scrub && bbtest) {
-			int ret = meminfo->block_isbad(meminfo, erase.addr);
-			if (ret > 0) {
-				if (!opts->quiet)
-					printf("\rSkipping bad block at  "
-					       "0x%08x                   "
-					       "                         \n",
-					       erase.addr);
-				continue;
-
-			} else if (ret < 0) {
-				printf("\n%s: MTD get bad block failed: %d\n",
-				       mtd_device,
-				       ret);
-				return -1;
-			}
-		}
-
-		result = meminfo->erase(meminfo, &erase);
-		if (result != 0) {
-			printf("\n%s: MTD Erase failure: %d\n",
-			       mtd_device, result);
-			continue;
-		}
-
-		/* format for JFFS2 ? */
-		if (opts->jffs2) {
-
-			/* write cleanmarker */
-			if (isNAND) {
-				size_t written;
-				result = meminfo->write_oob(meminfo,
-							    erase.addr + clmpos,
-							    clmlen,
-							    &written,
-							    (unsigned char *)
-							    &cleanmarker);
-				if (result != 0) {
-					printf("\n%s: MTD writeoob failure: %d\n",
-					       mtd_device, result);
-					continue;
-				}
-			} else {
-				printf("\n%s: this erase routine only supports"
-				       " NAND devices!\n",
-				       mtd_device);
-			}
-		}
-
-		if (!opts->quiet) {
-			int percent = (int)
-				((unsigned long long)
-				 (erase.addr+meminfo->erasesize-opts->offset)
-				 * 100 / erase_length);
-
-			/* output progress message only at whole percent
-			 * steps to reduce the number of messages printed
-			 * on (slow) serial consoles
-			 */
-			if (percent != percent_complete) {
-				percent_complete = percent;
-
-				printf("\rErasing at 0x%x -- %3d%% complete.",
-				       erase.addr, percent);
-
-				if (opts->jffs2 && result == 0)
-					printf(" Cleanmarker written at 0x%x.",
-					       erase.addr);
-			}
-		}
-	}
-	if (!opts->quiet)
-		printf("\n");
-
-	if (nand_block_bad_old) {
-		struct nand_chip *priv_nand = meminfo->priv;
-
-		priv_nand->block_bad = nand_block_bad_old;
-		priv_nand->scan_bbt(meminfo);
-	}
+    struct jffs2_unknown_node cleanmarker;
+    int clmpos = 0;
+    int clmlen = 8;
+    erase_info_t erase;
+    ulong erase_length;
+    int isNAND;
+    int bbtest = 1;
+    int result;
+    int percent_complete = -1;
+    int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL;
+    const char *mtd_device = meminfo->name;
+
+    memset(&erase, 0, sizeof(erase));
+
+    erase.mtd = meminfo;
+    erase.len  = meminfo->erasesize;
+    erase.addr = opts->offset;
+    erase_length = opts->length;
+
+    isNAND = meminfo->type == MTD_NANDFLASH ? 1 : 0;
+
+    if (opts->jffs2) {
+        cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
+        cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
+        if (isNAND) {
+            struct nand_oobinfo *oobinfo = &meminfo->oobinfo;
+
+            /* check for autoplacement */
+            if (oobinfo->useecc == MTD_NANDECC_AUTOPLACE) {
+                /* get the position of the free bytes */
+                if (!oobinfo->oobfree[0][1]) {
+                    printf(" Eeep. Autoplacement selected "
+                           "and no empty space in oob\n");
+                    return -1;
+                }
+                clmpos = oobinfo->oobfree[0][0];
+                clmlen = oobinfo->oobfree[0][1];
+                if (clmlen > 8)
+                    clmlen = 8;
+            } else {
+                /* legacy mode */
+                switch (meminfo->oobsize) {
+                case 8:
+                    clmpos = 6;
+                    clmlen = 2;
+                    break;
+                case 16:
+                    clmpos = 8;
+                    clmlen = 8;
+                    break;
+                case 64:
+                    clmpos = 16;
+                    clmlen = 8;
+                    break;
+                }
+            }
+
+            cleanmarker.totlen = cpu_to_je32(8);
+        } else {
+            cleanmarker.totlen =
+                cpu_to_je32(sizeof(struct jffs2_unknown_node));
+        }
+        cleanmarker.hdr_crc =  cpu_to_je32(
+            crc32_no_comp(0, (unsigned char *) &cleanmarker,
+                      sizeof(struct jffs2_unknown_node) - 4));
+    }
+
+    /* scrub option allows to erase badblock. To prevent internal
+     * check from erase() method, set block check method to dummy
+     * and disable bad block table while erasing.
+     */
+    if (opts->scrub) {
+        struct nand_chip *priv_nand = meminfo->priv;
+
+        nand_block_bad_old = priv_nand->block_bad;
+        priv_nand->block_bad = nand_block_bad_scrub;
+        /* we don't need the bad block table anymore...
+         * after scrub, there are no bad blocks left!
+         */
+        if (priv_nand->bbt) {
+            kfree(priv_nand->bbt);
+        }
+        priv_nand->bbt = NULL;
+    }
+
+    for (;
+         erase.addr < opts->offset + erase_length;
+         erase.addr += meminfo->erasesize) {
+
+        WATCHDOG_RESET ();
+
+        if (!opts->scrub && bbtest) {
+            int ret = meminfo->block_isbad(meminfo, erase.addr);
+            if (ret > 0) {
+                if (!opts->quiet)
+                    printf("\rSkipping bad block at  "
+                           "0x%08x                   "
+                           "                         \n",
+                           erase.addr);
+                continue;
+
+            } else if (ret < 0) {
+                printf("\n%s: MTD get bad block failed: %d\n",
+                       mtd_device,
+                       ret);
+                return -1;
+            }
+        }
+
+        result = meminfo->erase(meminfo, &erase);
+        if (result != 0) {
+            printf("\n%s: MTD Erase failure: %d\n",
+                   mtd_device, result);
+            continue;
+        }
+
+        /* format for JFFS2 ? */
+        if (opts->jffs2) {
+
+            /* write cleanmarker */
+            if (isNAND) {
+                size_t written;
+                result = meminfo->write_oob(meminfo,
+                                erase.addr + clmpos,
+                                clmlen,
+                                &written,
+                                (unsigned char *)
+                                &cleanmarker);
+                if (result != 0) {
+                    printf("\n%s: MTD writeoob failure: %d\n",
+                           mtd_device, result);
+                    continue;
+                }
+            } else {
+                printf("\n%s: this erase routine only supports"
+                       " NAND devices!\n",
+                       mtd_device);
+            }
+        }
+
+        if (!opts->quiet) {
+            int percent = (int)
+                ((unsigned long long)
+                 (erase.addr+meminfo->erasesize-opts->offset)
+                 * 100 / erase_length);
+
+            /* output progress message only at whole percent
+             * steps to reduce the number of messages printed
+             * on (slow) serial consoles
+             */
+            if (percent != percent_complete) {
+                percent_complete = percent;
+
+                printf("\rErasing at 0x%x -- %3d%% complete.",
+                       erase.addr, percent);
+
+                if (opts->jffs2 && result == 0)
+                    printf(" Cleanmarker written at 0x%x.",
+                           erase.addr);
+            }
+        }
+    }
+    if (!opts->quiet)
+        printf("\n");
+
+    if (nand_block_bad_old) {
+        struct nand_chip *priv_nand = meminfo->priv;
+
+        priv_nand->block_bad = nand_block_bad_old;
+        priv_nand->scan_bbt(meminfo);
+    }
 
-	return 0;
+    return 0;
 }
 
-#define MAX_PAGE_SIZE	2048
-#define MAX_OOB_SIZE	64
+#define MAX_PAGE_SIZE   2048
+#define MAX_OOB_SIZE    64
 
 /*
  * buffer array used for writing data
@@ -253,454 +253,485 @@
 
 /* OOB layouts to pass into the kernel as default */
 static struct nand_oobinfo none_oobinfo = {
-	.useecc = MTD_NANDECC_OFF,
+    .useecc = MTD_NANDECC_OFF,
 };
 
 static struct nand_oobinfo jffs2_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 0, 1, 2, 3, 6, 7 }
+    .useecc = MTD_NANDECC_PLACE,
+    .eccbytes = 6,
+    .eccpos = { 0, 1, 2, 3, 6, 7 }
 };
 
 static struct nand_oobinfo yaffs_oobinfo = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 8, 9, 10, 13, 14, 15}
+    .useecc = MTD_NANDECC_PLACE,
+    .eccbytes = 6,
+    .eccpos = { 8, 9, 10, 13, 14, 15}
 };
 
 static struct nand_oobinfo autoplace_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE
+    .useecc = MTD_NANDECC_AUTOPLACE
 };
 
 /**
  * nand_write_opts: - write image to NAND flash with support for various options
  *
- * @param meminfo	NAND device to erase
- * @param opts		write options (@see nand_write_options)
- * @return		0 in case of success
+ * @param meminfo   NAND device to erase
+ * @param opts      write options (@see nand_write_options)
+ * @return      0 in case of success
  *
  * This code is ported from nandwrite.c from Linux mtd utils by
  * Steven J. Hill and Thomas Gleixner.
  */
 int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)
 {
-	int imglen = 0;
-	int pagelen;
-	int baderaseblock;
-	int blockstart = -1;
-	loff_t offs;
-	int readlen;
-	int oobinfochanged = 0;
-	int percent_complete = -1;
-	struct nand_oobinfo old_oobinfo;
-	ulong mtdoffset = opts->offset;
-	ulong erasesize_blockalign;
-	u_char *buffer = opts->buffer;
-	size_t written;
-	int result;
-
-	if (opts->pad && opts->writeoob) {
-		printf("Can't pad when oob data is present.\n");
-		return -1;
-	}
-
-	/* set erasesize to specified number of blocks - to match
-	 * jffs2 (virtual) block size */
-	if (opts->blockalign == 0) {
-		erasesize_blockalign = meminfo->erasesize;
-	} else {
-		erasesize_blockalign = meminfo->erasesize * opts->blockalign;
-	}
-
-	/* make sure device page sizes are valid */
-	if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
-	    && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
-	    && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
-		printf("Unknown flash (not normal NAND)\n");
-		return -1;
-	}
-
-	/* read the current oob info */
-	memcpy(&old_oobinfo, &meminfo->oobinfo, sizeof(old_oobinfo));
-
-	/* write without ecc? */
-	if (opts->noecc) {
-		memcpy(&meminfo->oobinfo, &none_oobinfo,
-		       sizeof(meminfo->oobinfo));
-		oobinfochanged = 1;
-	}
-
-	/* autoplace ECC? */
-	if (opts->autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
-
-		memcpy(&meminfo->oobinfo, &autoplace_oobinfo,
-		       sizeof(meminfo->oobinfo));
-		oobinfochanged = 1;
-	}
-
-	/* force OOB layout for jffs2 or yaffs? */
-	if (opts->forcejffs2 || opts->forceyaffs) {
-		struct nand_oobinfo *oobsel =
-			opts->forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
-
-		if (meminfo->oobsize == 8) {
-			if (opts->forceyaffs) {
-				printf("YAFSS cannot operate on "
-				       "256 Byte page size\n");
-				goto restoreoob;
-			}
-			/* Adjust number of ecc bytes */
-			jffs2_oobinfo.eccbytes = 3;
-		}
-
-		memcpy(&meminfo->oobinfo, oobsel, sizeof(meminfo->oobinfo));
-	}
-
-	/* get image length */
-	imglen = opts->length;
-	pagelen = meminfo->oobblock
-		+ ((opts->writeoob != 0) ? meminfo->oobsize : 0);
-
-	/* check, if file is pagealigned */
-	if ((!opts->pad) && ((imglen % pagelen) != 0)) {
-		printf("Input block length is not page aligned\n");
-		goto restoreoob;
-	}
-
-	/* check, if length fits into device */
-	if (((imglen / pagelen) * meminfo->oobblock)
-	     > (meminfo->size - opts->offset)) {
-		printf("Image %d bytes, NAND page %d bytes, "
-		       "OOB area %u bytes, device size %u bytes\n",
-		       imglen, pagelen, meminfo->oobblock, meminfo->size);
-		printf("Input block does not fit into device\n");
-		goto restoreoob;
-	}
-
-	if (!opts->quiet)
-		printf("\n");
-
-	/* get data from input and write to the device */
-	while (imglen && (mtdoffset < meminfo->size)) {
-
-		WATCHDOG_RESET ();
-
-		/*
-		 * new eraseblock, check for bad block(s). Stay in the
-		 * loop to be sure if the offset changes because of
-		 * a bad block, that the next block that will be
-		 * written to is also checked. Thus avoiding errors if
-		 * the block(s) after the skipped block(s) is also bad
-		 * (number of blocks depending on the blockalign
-		 */
-		while (blockstart != (mtdoffset & (~erasesize_blockalign+1))) {
-			blockstart = mtdoffset & (~erasesize_blockalign+1);
-			offs = blockstart;
-			baderaseblock = 0;
-
-			/* check all the blocks in an erase block for
-			 * bad blocks */
-			do {
-				int ret = meminfo->block_isbad(meminfo, offs);
-
-				if (ret < 0) {
-					printf("Bad block check failed\n");
-					goto restoreoob;
-				}
-				if (ret == 1) {
-					baderaseblock = 1;
-					if (!opts->quiet)
-						printf("\rBad block at 0x%lx "
-						       "in erase block from "
-						       "0x%x will be skipped\n",
-						       (long) offs,
-						       blockstart);
-				}
-
-				if (baderaseblock) {
-					mtdoffset = blockstart
-						+ erasesize_blockalign;
-				}
-				offs +=	 erasesize_blockalign
-					/ opts->blockalign;
-			} while (offs < blockstart + erasesize_blockalign);
-		}
-
-		readlen = meminfo->oobblock;
-		if (opts->pad && (imglen < readlen)) {
-			readlen = imglen;
-			memset(data_buf + readlen, 0xff,
-			       meminfo->oobblock - readlen);
-		}
-
-		/* read page data from input memory buffer */
-		memcpy(data_buf, buffer, readlen);
-		buffer += readlen;
-
-		if (opts->writeoob) {
-			/* read OOB data from input memory block, exit
-			 * on failure */
-			memcpy(oob_buf, buffer, meminfo->oobsize);
-			buffer += meminfo->oobsize;
-
-			/* write OOB data first, as ecc will be placed
-			 * in there*/
-			result = meminfo->write_oob(meminfo,
-						    mtdoffset,
-						    meminfo->oobsize,
-						    &written,
-						    (unsigned char *)
-						    &oob_buf);
-
-			if (result != 0) {
-				printf("\nMTD writeoob failure: %d\n",
-				       result);
-				goto restoreoob;
-			}
-			imglen -= meminfo->oobsize;
-		}
-
-		/* write out the page data */
-		result = meminfo->write(meminfo,
-					mtdoffset,
-					meminfo->oobblock,
-					&written,
-					(unsigned char *) &data_buf);
-
-		if (result != 0) {
-			printf("writing NAND page at offset 0x%lx failed\n",
-			       mtdoffset);
-			goto restoreoob;
-		}
-		imglen -= readlen;
-
-		if (!opts->quiet) {
-			int percent = (int)
-				((unsigned long long)
-				 (opts->length-imglen) * 100
-				 / opts->length);
-			/* output progress message only at whole percent
-			 * steps to reduce the number of messages printed
-			 * on (slow) serial consoles
-			 */
-			if (percent != percent_complete) {
-				printf("\rWriting data at 0x%x "
-				       "-- %3d%% complete.",
-				       mtdoffset, percent);
-				percent_complete = percent;
-			}
-		}
+    int imglen = 0;
+    int pagelen;
+    int baderaseblock;
+    int blockstart = -1;
+    loff_t offs;
+    int readlen;
+    int oobinfochanged = 0;
+    int percent_complete = -1;
+    struct nand_oobinfo old_oobinfo;
+    ulong mtdoffset = opts->offset;
+    ulong erasesize_blockalign;
+    u_char *buffer = opts->buffer;
+    size_t written;
+    int result;
+    int skipfirstblk = opts->skipfirstblk;
+
+    if (opts->pad && opts->writeoob) {
+        printf("Can't pad when oob data is present.\n");
+        return -1;
+    }
+
+    /* set erasesize to specified number of blocks - to match
+     * jffs2 (virtual) block size */
+    if (opts->blockalign == 0) {
+        erasesize_blockalign = meminfo->erasesize;
+    } else {
+        erasesize_blockalign = meminfo->erasesize * opts->blockalign;
+    }
+
+    /* make sure device page sizes are valid */
+    if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
+        && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
+        && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
+        printf("Unknown flash (not normal NAND)\n");
+        return -1;
+    }
+
+    /* read the current oob info */
+    memcpy(&old_oobinfo, &meminfo->oobinfo, sizeof(old_oobinfo));
+
+    /* write without ecc? */
+    if (opts->noecc) {
+        memcpy(&meminfo->oobinfo, &none_oobinfo,
+               sizeof(meminfo->oobinfo));
+        oobinfochanged = 1;
+    }
+
+    /* autoplace ECC? */
+    if (opts->autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {
+
+        memcpy(&meminfo->oobinfo, &autoplace_oobinfo,
+               sizeof(meminfo->oobinfo));
+        oobinfochanged = 1;
+    }
+
+    /* force OOB layout for jffs2 or yaffs? */
+    if (opts->forcejffs2 || opts->forceyaffs) {
+        struct nand_oobinfo *oobsel =
+            opts->forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;
+
+        if (meminfo->oobsize == 8) {
+            if (opts->forceyaffs) {
+                printf("YAFSS cannot operate on "
+                       "256 Byte page size\n");
+                goto restoreoob;
+            }
+            /* Adjust number of ecc bytes */
+            jffs2_oobinfo.eccbytes = 3;
+        }
+
+        memcpy(&meminfo->oobinfo, oobsel, sizeof(meminfo->oobinfo));
+		oobinfochanged = 1;   /* add by thisway.diy, www.100ask.net */
+    }
+
+    /* get image length */
+    imglen = opts->length;
+    pagelen = meminfo->oobblock
+        + ((opts->writeoob != 0) ? meminfo->oobsize : 0);
+
+    /* check, if file is pagealigned */
+    if ((!opts->pad) && ((imglen % pagelen) != 0)) {
+        printf("Input block length is not page aligned\n");
+        goto restoreoob;
+    }
+
+    /* check, if length fits into device */
+    if (((imglen / pagelen) * meminfo->oobblock)
+         > (meminfo->size - opts->offset)) {
+        printf("Image %d bytes, NAND page %d bytes, "
+               "OOB area %u bytes, device size %u bytes\n",
+               imglen, pagelen, meminfo->oobblock, meminfo->size);
+        printf("Input block does not fit into device\n");
+        goto restoreoob;
+    }
+
+    if (!opts->quiet)
+        printf("\n");
+
+    /* get data from input and write to the device */
+    while (imglen && (mtdoffset < meminfo->size)) {
+
+        WATCHDOG_RESET ();
+
+        /*
+         * new eraseblock, check for bad block(s). Stay in the
+         * loop to be sure if the offset changes because of
+         * a bad block, that the next block that will be
+         * written to is also checked. Thus avoiding errors if
+         * the block(s) after the skipped block(s) is also bad
+         * (number of blocks depending on the blockalign
+         */
+        while (blockstart != (mtdoffset & (~erasesize_blockalign+1))) {
+            blockstart = mtdoffset & (~erasesize_blockalign+1);
+            offs = blockstart;
+            baderaseblock = 0;
+
+            /* check all the blocks in an erase block for
+             * bad blocks */
+            if (!opts->nocheckbadblk) {
+                do {
+                    int ret = meminfo->block_isbad(meminfo, offs);
+
+                    if (ret < 0) {
+                        printf("Bad block check failed\n");
+                        goto restoreoob;
+                    }
+                    if (ret == 1) {
+                        baderaseblock = 1;
+                        if (!opts->quiet)
+                            printf("\rBad block at 0x%lx "
+                                   "in erase block from "
+                                   "0x%x will be skipped\n",
+                                   (long) offs,
+                                   blockstart);
+                    }
+
+                    if (baderaseblock) {
+                        mtdoffset = blockstart
+                            + erasesize_blockalign;
+                    }
+                    offs +=  erasesize_blockalign
+                        / opts->blockalign;
+                } while (offs < blockstart + erasesize_blockalign);
+            }
+        }
+
+        /* skip the first good block when wirte yaffs image, by www.100ask.net */
+        if (skipfirstblk) {
+            mtdoffset += erasesize_blockalign;
+            skipfirstblk = 0;
+            continue;
+        }
+
+        readlen = meminfo->oobblock;
+        if (opts->pad && (imglen < readlen)) {
+            readlen = imglen;
+            memset(data_buf + readlen, 0xff,
+                   meminfo->oobblock - readlen);
+        }
+
+        /* read page data from input memory buffer */
+        memcpy(data_buf, buffer, readlen);
+        buffer += readlen;
+
+        if (opts->writeoob) {
+            /* read OOB data from input memory block, exit
+             * on failure */
+            memcpy(oob_buf, buffer, meminfo->oobsize);
+            buffer += meminfo->oobsize;
+
+            /* write OOB data first, as ecc will be placed
+             * in there*/
+            result = meminfo->write_oob(meminfo,
+                            mtdoffset,
+                            meminfo->oobsize,
+                            &written,
+                            (unsigned char *)
+                            &oob_buf);
+
+            if (result != 0) {
+                printf("\nMTD writeoob failure: %d\n",
+                       result);
+                goto restoreoob;
+            }
+            imglen -= meminfo->oobsize;
+        }
+
+        /* write out the page data */
+        result = meminfo->write(meminfo,
+                    mtdoffset,
+                    meminfo->oobblock,
+                    &written,
+                    (unsigned char *) &data_buf);
+
+        if (result != 0) {
+            printf("writing NAND page at offset 0x%lx failed\n",
+                   mtdoffset);
+            goto restoreoob;
+        }
+        imglen -= readlen;
+
+        if (!opts->quiet) {
+            int percent = (int)
+                ((unsigned long long)
+                 (opts->length-imglen) * 100
+                 / opts->length);
+            /* output progress message only at whole percent
+             * steps to reduce the number of messages printed
+             * on (slow) serial consoles
+             */
+            if (percent != percent_complete) {
+                printf("\rWriting data at 0x%x "
+                       "-- %3d%% complete.",
+                       mtdoffset, percent);
+                percent_complete = percent;
+            }
+        }
 
-		mtdoffset += meminfo->oobblock;
-	}
+        mtdoffset += meminfo->oobblock;
+    }
 
-	if (!opts->quiet)
-		printf("\n");
+    if (!opts->quiet)
+        printf("\n");
 
 restoreoob:
-	if (oobinfochanged) {
-		memcpy(&meminfo->oobinfo, &old_oobinfo,
-		       sizeof(meminfo->oobinfo));
-	}
-
-	if (imglen > 0) {
-		printf("Data did not fit into device, due to bad blocks\n");
-		return -1;
-	}
+    if (oobinfochanged) {
+        memcpy(&meminfo->oobinfo, &old_oobinfo,
+               sizeof(meminfo->oobinfo));
+    }
+
+    if (imglen > 0) {
+        printf("Data did not fit into device, due to bad blocks\n");
+        return -1;
+    }
 
-	/* return happy */
-	return 0;
+    /* return happy */
+    return 0;
 }
 
 /**
  * nand_read_opts: - read image from NAND flash with support for various options
  *
- * @param meminfo	NAND device to erase
- * @param opts		read options (@see struct nand_read_options)
- * @return		0 in case of success
+ * @param meminfo   NAND device to erase
+ * @param opts      read options (@see struct nand_read_options)
+ * @return      0 in case of success
  *
  */
 int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)
 {
-	int imglen = opts->length;
-	int pagelen;
-	int baderaseblock;
-	int blockstart = -1;
-	int percent_complete = -1;
-	loff_t offs;
-	size_t readlen;
-	ulong mtdoffset = opts->offset;
-	u_char *buffer = opts->buffer;
-	int result;
-
-	/* make sure device page sizes are valid */
-	if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
-	    && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
-	    && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
-		printf("Unknown flash (not normal NAND)\n");
-		return -1;
-	}
-
-	pagelen = meminfo->oobblock
-		+ ((opts->readoob != 0) ? meminfo->oobsize : 0);
-
-	/* check, if length is not larger than device */
-	if (((imglen / pagelen) * meminfo->oobblock)
-	     > (meminfo->size - opts->offset)) {
-		printf("Image %d bytes, NAND page %d bytes, "
-		       "OOB area %u bytes, device size %u bytes\n",
-		       imglen, pagelen, meminfo->oobblock, meminfo->size);
-		printf("Input block is larger than device\n");
-		return -1;
-	}
-
-	if (!opts->quiet)
-		printf("\n");
-
-	/* get data from input and write to the device */
-	while (imglen && (mtdoffset < meminfo->size)) {
-
-		WATCHDOG_RESET ();
-
-		/*
-		 * new eraseblock, check for bad block(s). Stay in the
-		 * loop to be sure if the offset changes because of
-		 * a bad block, that the next block that will be
-		 * written to is also checked. Thus avoiding errors if
-		 * the block(s) after the skipped block(s) is also bad
-		 * (number of blocks depending on the blockalign
-		 */
-		while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) {
-			blockstart = mtdoffset & (~meminfo->erasesize+1);
-			offs = blockstart;
-			baderaseblock = 0;
-
-			/* check all the blocks in an erase block for
-			 * bad blocks */
-			do {
-				int ret = meminfo->block_isbad(meminfo, offs);
-
-				if (ret < 0) {
-					printf("Bad block check failed\n");
-					return -1;
-				}
-				if (ret == 1) {
-					baderaseblock = 1;
-					if (!opts->quiet)
-						printf("\rBad block at 0x%lx "
-						       "in erase block from "
-						       "0x%x will be skipped\n",
-						       (long) offs,
-						       blockstart);
-				}
-
-				if (baderaseblock) {
-					mtdoffset = blockstart
-						+ meminfo->erasesize;
-				}
-				offs +=	 meminfo->erasesize;
-
-			} while (offs < blockstart + meminfo->erasesize);
-		}
-
-
-		/* read page data to memory buffer */
-		result = meminfo->read(meminfo,
-				       mtdoffset,
-				       meminfo->oobblock,
-				       &readlen,
-				       (unsigned char *) &data_buf);
-
-		if (result != 0) {
-			printf("reading NAND page at offset 0x%lx failed\n",
-			       mtdoffset);
-			return -1;
-		}
-
-		if (imglen < readlen) {
-			readlen = imglen;
-		}
-
-		memcpy(buffer, data_buf, readlen);
-		buffer += readlen;
-		imglen -= readlen;
-
-		if (opts->readoob) {
-			result = meminfo->read_oob(meminfo,
-						   mtdoffset,
-						   meminfo->oobsize,
-						   &readlen,
-						   (unsigned char *)
-						   &oob_buf);
-
-			if (result != 0) {
-				printf("\nMTD readoob failure: %d\n",
-				       result);
-				return -1;
-			}
-
-
-			if (imglen < readlen) {
-				readlen = imglen;
-			}
-
-			memcpy(buffer, oob_buf, readlen);
-
-			buffer += readlen;
-			imglen -= readlen;
-		}
-
-		if (!opts->quiet) {
-			int percent = (int)
-				((unsigned long long)
-				 (opts->length-imglen) * 100
-				 / opts->length);
-			/* output progress message only at whole percent
-			 * steps to reduce the number of messages printed
-			 * on (slow) serial consoles
-			 */
-			if (percent != percent_complete) {
-			if (!opts->quiet)
-				printf("\rReading data from 0x%x "
-				       "-- %3d%% complete.",
-				       mtdoffset, percent);
-				percent_complete = percent;
-			}
-		}
-
-		mtdoffset += meminfo->oobblock;
-	}
-
-	if (!opts->quiet)
-		printf("\n");
-
-	if (imglen > 0) {
-		printf("Could not read entire image due to bad blocks\n");
-		return -1;
-	}
+    int imglen = opts->length;
+    int pagelen;
+    int baderaseblock;
+    int blockstart = -1;
+    int percent_complete = -1;
+    loff_t offs;
+    size_t readlen;
+    ulong mtdoffset = opts->offset;
+    u_char *buffer = opts->buffer;
+    int result;
+    struct nand_oobinfo old_oobinfo;
+    int oobinfochanged = 0;
+
+    /* make sure device page sizes are valid */
+    if (!(meminfo->oobsize == 16 && meminfo->oobblock == 512)
+        && !(meminfo->oobsize == 8 && meminfo->oobblock == 256)
+        && !(meminfo->oobsize == 64 && meminfo->oobblock == 2048)) {
+        printf("Unknown flash (not normal NAND)\n");
+        return -1;
+    }
+
+    pagelen = meminfo->oobblock
+        + ((opts->readoob != 0) ? meminfo->oobsize : 0);
+
+    /* check, if length is not larger than device */
+    if (((imglen / pagelen) * meminfo->oobblock)
+         > (meminfo->size - opts->offset)) {
+        printf("Image %d bytes, NAND page %d bytes, "
+               "OOB area %u bytes, device size %u bytes\n",
+               imglen, pagelen, meminfo->oobblock, meminfo->size);
+        printf("Input block is larger than device\n");
+        return -1;
+    }
+
+    if (!opts->quiet)
+        printf("\n");
+
+    /* read the current oob info */
+    memcpy(&old_oobinfo, &meminfo->oobinfo, sizeof(old_oobinfo));
+
+    /* write without ecc? */
+    if (opts->noecc) {
+        memcpy(&meminfo->oobinfo, &none_oobinfo,
+               sizeof(meminfo->oobinfo));
+        oobinfochanged = 1;
+    }
+
+    /* get data from input and write to the device */
+    while (imglen && (mtdoffset < meminfo->size)) {
+
+        WATCHDOG_RESET ();
+
+        /*
+         * new eraseblock, check for bad block(s). Stay in the
+         * loop to be sure if the offset changes because of
+         * a bad block, that the next block that will be
+         * written to is also checked. Thus avoiding errors if
+         * the block(s) after the skipped block(s) is also bad
+         * (number of blocks depending on the blockalign
+         */
+        while (blockstart != (mtdoffset & (~meminfo->erasesize+1))) {
+            blockstart = mtdoffset & (~meminfo->erasesize+1);
+            offs = blockstart;
+            baderaseblock = 0;
+
+            /* check all the blocks in an erase block for
+             * bad blocks */
+            if (!opts->nocheckbadblk) {
+                do {
+                    int ret = meminfo->block_isbad(meminfo, offs);
+
+                    if (ret < 0) {
+                        printf("Bad block check failed\n");
+                        goto restoreoob;
+                    }
+                    if (ret == 1) {
+                        baderaseblock = 1;
+                        if (!opts->quiet)
+                            printf("\rBad block at 0x%lx "
+                                   "in erase block from "
+                                   "0x%x will be skipped\n",
+                                   (long) offs,
+                                   blockstart);
+                    }
+
+                    if (baderaseblock) {
+                        mtdoffset = blockstart
+                            + meminfo->erasesize;
+                    }
+                    offs +=  meminfo->erasesize;
+
+                } while (offs < blockstart + meminfo->erasesize);
+            }
+        }
+
+
+        /* read page data to memory buffer */
+        result = meminfo->read(meminfo,
+                       mtdoffset,
+                       meminfo->oobblock,
+                       &readlen,
+                       (unsigned char *) &data_buf);
+
+        if (result != 0) {
+            printf("reading NAND page at offset 0x%lx failed\n",
+                   mtdoffset);
+            goto restoreoob;
+        }
+
+        if (imglen < readlen) {
+            readlen = imglen;
+        }
+
+        memcpy(buffer, data_buf, readlen);
+        buffer += readlen;
+        imglen -= readlen;
+
+        if (opts->readoob) {
+            result = meminfo->read_oob(meminfo,
+                           mtdoffset,
+                           meminfo->oobsize,
+                           &readlen,
+                           (unsigned char *)
+                           &oob_buf);
+
+            if (result != 0) {
+                printf("\nMTD readoob failure: %d\n",
+                       result);
+                goto restoreoob;
+            }
+
+
+            if (imglen < readlen) {
+                readlen = imglen;
+            }
+
+            memcpy(buffer, oob_buf, readlen);
+
+            buffer += readlen;
+            imglen -= readlen;
+        }
+
+        if (!opts->quiet) {
+            int percent = (int)
+                ((unsigned long long)
+                 (opts->length-imglen) * 100
+                 / opts->length);
+            /* output progress message only at whole percent
+             * steps to reduce the number of messages printed
+             * on (slow) serial consoles
+             */
+            if (percent != percent_complete) {
+            if (!opts->quiet)
+                printf("\rReading data from 0x%x "
+                       "-- %3d%% complete.",
+                       mtdoffset, percent);
+                percent_complete = percent;
+            }
+        }
 
-	/* return happy */
-	return 0;
+        mtdoffset += meminfo->oobblock;
+    }
+
+    if (!opts->quiet)
+        printf("\n");
+
+restoreoob:
+    if (oobinfochanged) {
+        memcpy(&meminfo->oobinfo, &old_oobinfo,
+               sizeof(meminfo->oobinfo));
+    }
+
+    if (imglen > 0) {
+        printf("Could not read entire image due to bad blocks\n");
+        return -1;
+    }
+
+    /* return happy */
+    return 0;
 }
 
 /******************************************************************************
  * Support for locking / unlocking operations of some NAND devices
  *****************************************************************************/
 
-#define NAND_CMD_LOCK		0x2a
-#define NAND_CMD_LOCK_TIGHT	0x2c
-#define NAND_CMD_UNLOCK1	0x23
-#define NAND_CMD_UNLOCK2	0x24
-#define NAND_CMD_LOCK_STATUS	0x7a
+#define NAND_CMD_LOCK       0x2a
+#define NAND_CMD_LOCK_TIGHT 0x2c
+#define NAND_CMD_UNLOCK1    0x23
+#define NAND_CMD_UNLOCK2    0x24
+#define NAND_CMD_LOCK_STATUS    0x7a
 
 /**
  * nand_lock: Set all pages of NAND flash chip to the LOCK or LOCK-TIGHT
- *	      state
+ *        state
  *
- * @param meminfo	nand mtd instance
- * @param tight		bring device in lock tight mode
+ * @param meminfo   nand mtd instance
+ * @param tight     bring device in lock tight mode
  *
- * @return		0 on success, -1 in case of error
+ * @return      0 on success, -1 in case of error
  *
  * The lock / lock-tight command only applies to the whole chip. To get some
  * parts of the chip lock and others unlocked use the following sequence:
@@ -716,147 +747,147 @@
  */
 int nand_lock(nand_info_t *meminfo, int tight)
 {
-	int ret = 0;
-	int status;
-	struct nand_chip *this = meminfo->priv;
-
-	/* select the NAND device */
-	this->select_chip(meminfo, 0);
-
-	this->cmdfunc(meminfo,
-		      (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),
-		      -1, -1);
-
-	/* call wait ready function */
-	status = this->waitfunc(meminfo, this, FL_WRITING);
-
-	/* see if device thinks it succeeded */
-	if (status & 0x01) {
-		ret = -1;
-	}
-
-	/* de-select the NAND device */
-	this->select_chip(meminfo, -1);
-	return ret;
+    int ret = 0;
+    int status;
+    struct nand_chip *this = meminfo->priv;
+
+    /* select the NAND device */
+    this->select_chip(meminfo, 0);
+
+    this->cmdfunc(meminfo,
+              (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK),
+              -1, -1);
+
+    /* call wait ready function */
+    status = this->waitfunc(meminfo, this, FL_WRITING);
+
+    /* see if device thinks it succeeded */
+    if (status & 0x01) {
+        ret = -1;
+    }
+
+    /* de-select the NAND device */
+    this->select_chip(meminfo, -1);
+    return ret;
 }
 
 /**
  * nand_get_lock_status: - query current lock state from one page of NAND
- *			   flash
+ *             flash
  *
- * @param meminfo	nand mtd instance
- * @param offset	page address to query (muss be page aligned!)
+ * @param meminfo   nand mtd instance
+ * @param offset    page address to query (muss be page aligned!)
  *
- * @return		-1 in case of error
- *			>0 lock status:
- *			  bitfield with the following combinations:
- *			  NAND_LOCK_STATUS_TIGHT: page in tight state
- *			  NAND_LOCK_STATUS_LOCK:  page locked
- *			  NAND_LOCK_STATUS_UNLOCK: page unlocked
+ * @return      -1 in case of error
+ *          >0 lock status:
+ *            bitfield with the following combinations:
+ *            NAND_LOCK_STATUS_TIGHT: page in tight state
+ *            NAND_LOCK_STATUS_LOCK:  page locked
+ *            NAND_LOCK_STATUS_UNLOCK: page unlocked
  *
  */
 int nand_get_lock_status(nand_info_t *meminfo, ulong offset)
 {
-	int ret = 0;
-	int chipnr;
-	int page;
-	struct nand_chip *this = meminfo->priv;
-
-	/* select the NAND device */
-	chipnr = (int)(offset >> this->chip_shift);
-	this->select_chip(meminfo, chipnr);
-
-
-	if ((offset & (meminfo->oobblock - 1)) != 0) {
-		printf ("nand_get_lock_status: "
-			"Start address must be beginning of "
-			"nand page!\n");
-		ret = -1;
-		goto out;
-	}
-
-	/* check the Lock Status */
-	page = (int)(offset >> this->page_shift);
-	this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask);
-
-	ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT
-					  | NAND_LOCK_STATUS_LOCK
-					  | NAND_LOCK_STATUS_UNLOCK);
+    int ret = 0;
+    int chipnr;
+    int page;
+    struct nand_chip *this = meminfo->priv;
+
+    /* select the NAND device */
+    chipnr = (int)(offset >> this->chip_shift);
+    this->select_chip(meminfo, chipnr);
+
+
+    if ((offset & (meminfo->oobblock - 1)) != 0) {
+        printf ("nand_get_lock_status: "
+            "Start address must be beginning of "
+            "nand page!\n");
+        ret = -1;
+        goto out;
+    }
+
+    /* check the Lock Status */
+    page = (int)(offset >> this->page_shift);
+    this->cmdfunc(meminfo, NAND_CMD_LOCK_STATUS, -1, page & this->pagemask);
+
+    ret = this->read_byte(meminfo) & (NAND_LOCK_STATUS_TIGHT
+                      | NAND_LOCK_STATUS_LOCK
+                      | NAND_LOCK_STATUS_UNLOCK);
 
  out:
-	/* de-select the NAND device */
-	this->select_chip(meminfo, -1);
-	return ret;
+    /* de-select the NAND device */
+    this->select_chip(meminfo, -1);
+    return ret;
 }
 
 /**
  * nand_unlock: - Unlock area of NAND pages
- *		  only one consecutive area can be unlocked at one time!
+ *        only one consecutive area can be unlocked at one time!
  *
- * @param meminfo	nand mtd instance
- * @param start		start byte address
- * @param length	number of bytes to unlock (must be a multiple of
- *			page size nand->oobblock)
+ * @param meminfo   nand mtd instance
+ * @param start     start byte address
+ * @param length    number of bytes to unlock (must be a multiple of
+ *          page size nand->oobblock)
  *
- * @return		0 on success, -1 in case of error
+ * @return      0 on success, -1 in case of error
  */
 int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)
 {
-	int ret = 0;
-	int chipnr;
-	int status;
-	int page;
-	struct nand_chip *this = meminfo->priv;
-	printf ("nand_unlock: start: %08x, length: %d!\n",
-		(int)start, (int)length);
-
-	/* select the NAND device */
-	chipnr = (int)(start >> this->chip_shift);
-	this->select_chip(meminfo, chipnr);
-
-	/* check the WP bit */
-	this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1);
-	if ((this->read_byte(meminfo) & 0x80) == 0) {
-		printf ("nand_unlock: Device is write protected!\n");
-		ret = -1;
-		goto out;
-	}
-
-	if ((start & (meminfo->oobblock - 1)) != 0) {
-		printf ("nand_unlock: Start address must be beginning of "
-			"nand page!\n");
-		ret = -1;
-		goto out;
-	}
-
-	if (length == 0 || (length & (meminfo->oobblock - 1)) != 0) {
-		printf ("nand_unlock: Length must be a multiple of nand page "
-			"size!\n");
-		ret = -1;
-		goto out;
-	}
-
-	/* submit address of first page to unlock */
-	page = (int)(start >> this->page_shift);
-	this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask);
-
-	/* submit ADDRESS of LAST page to unlock */
-	page += (int)(length >> this->page_shift) - 1;
-	this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask);
-
-	/* call wait ready function */
-	status = this->waitfunc(meminfo, this, FL_WRITING);
-	/* see if device thinks it succeeded */
-	if (status & 0x01) {
-		/* there was an error */
-		ret = -1;
-		goto out;
-	}
+    int ret = 0;
+    int chipnr;
+    int status;
+    int page;
+    struct nand_chip *this = meminfo->priv;
+    printf ("nand_unlock: start: %08x, length: %d!\n",
+        (int)start, (int)length);
+
+    /* select the NAND device */
+    chipnr = (int)(start >> this->chip_shift);
+    this->select_chip(meminfo, chipnr);
+
+    /* check the WP bit */
+    this->cmdfunc(meminfo, NAND_CMD_STATUS, -1, -1);
+    if ((this->read_byte(meminfo) & 0x80) == 0) {
+        printf ("nand_unlock: Device is write protected!\n");
+        ret = -1;
+        goto out;
+    }
+
+    if ((start & (meminfo->oobblock - 1)) != 0) {
+        printf ("nand_unlock: Start address must be beginning of "
+            "nand page!\n");
+        ret = -1;
+        goto out;
+    }
+
+    if (length == 0 || (length & (meminfo->oobblock - 1)) != 0) {
+        printf ("nand_unlock: Length must be a multiple of nand page "
+            "size!\n");
+        ret = -1;
+        goto out;
+    }
+
+    /* submit address of first page to unlock */
+    page = (int)(start >> this->page_shift);
+    this->cmdfunc(meminfo, NAND_CMD_UNLOCK1, -1, page & this->pagemask);
+
+    /* submit ADDRESS of LAST page to unlock */
+    page += (int)(length >> this->page_shift) - 1;
+    this->cmdfunc(meminfo, NAND_CMD_UNLOCK2, -1, page & this->pagemask);
+
+    /* call wait ready function */
+    status = this->waitfunc(meminfo, this, FL_WRITING);
+    /* see if device thinks it succeeded */
+    if (status & 0x01) {
+        /* there was an error */
+        ret = -1;
+        goto out;
+    }
 
  out:
-	/* de-select the NAND device */
-	this->select_chip(meminfo, -1);
-	return ret;
+    /* de-select the NAND device */
+    this->select_chip(meminfo, -1);
+    return ret;
 }
 
 #endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) */
diff -urN u-boot-1.1.6/drivers/nand_legacy/nand_legacy.c u-boot-1.1.6_jz2440/drivers/nand_legacy/nand_legacy.c
--- u-boot-1.1.6/drivers/nand_legacy/nand_legacy.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/drivers/nand_legacy/nand_legacy.c	2010-11-26 12:54:38.414220270 +0800
@@ -60,6 +60,7 @@
 #define NANDRW_WRITE	0x00
 #define NANDRW_JFFS2	0x02
 #define NANDRW_JFFS2_SKIP	0x04
+#define NANDRW_YAFFS	0x08    /* to write yaffs image, www.100ask.net */
 
 
 /*
@@ -185,6 +186,31 @@
 	 */
 	unsigned long eblk = ~0;	/* force mismatch on first pass */
 	unsigned long erasesize = nand->erasesize;
+    int bfirstyaffsblk = 1;
+    int page;
+    unsigned long badblk=0, prgmblk=0;
+    unsigned long badblks=0, prgmblks = 0;
+    unsigned long allblks;
+
+    allblks = (erasesize/nand->oobblock)*(nand->oobblock+nand->oobsize);
+    allblks = (len + allblks - 1) / allblks;
+    
+	if ((cmd & NANDRW_YAFFS) && (len % (nand->oobblock + nand->oobsize))) {
+        printf("Length of the yaffs image should be times of (%d +%d), now it is %d\n", nand->oobblock, nand->oobsize, len);
+        return -1;
+    }
+
+    if ((cmd & NANDRW_YAFFS) && (start % erasesize)) {
+        printf("Start address of the flash should be %d align\n", erasesize);
+        return -1;
+    }
+
+	if (cmd & (NANDRW_WRITE | NANDRW_YAFFS)) {
+        printf("Flash params: oobblock = %d, oobsize = %d, erasesize = %d\n", nand->oobblock, nand->oobsize, nand->erasesize);
+    	printf("Programming NAND with yaffs image, length = %d\n", len);
+        printf(" Block Programming(addr/count) --- Block bad(addr/count) --- Block programed/All(%%)\n");
+        printf("------------------------------------------------------------------------------------\n");
+	}
 
 	while (len) {
 		if ((start & (-erasesize)) != eblk) {
@@ -193,6 +219,8 @@
 			 */
 			eblk = start & (-erasesize); /* start of block */
 			if (check_block(nand, eblk)) {
+                badblk = eblk;
+                badblks++;
 				if (cmd == (NANDRW_READ | NANDRW_JFFS2)) {
 					while (len > 0 &&
 					       start - eblk < erasesize) {
@@ -209,6 +237,12 @@
 					/* skip bad block */
 					start += erasesize;
 					continue;
+				} else if (cmd == (NANDRW_WRITE | NANDRW_YAFFS)) {
+				    /* by www.100ask.net */
+                    printf("       0x%08x/%05d               0x%08x/%05d          %05d/%05d=%02d%%\r", prgmblk, prgmblks, badblk, badblks, prgmblks, allblks, prgmblks*100/allblks);
+					/* skip bad block */
+					start += erasesize;
+					continue;
 				} else {
 					ret = 1;
 					break;
@@ -221,7 +255,33 @@
 		if((start != ROUND_DOWN(start, 0x200)) || (len < 0x200))
 			printf("Warning block writes should be at least 512 bytes and start on a 512 byte boundry\n");
 
-		if (cmd & NANDRW_READ) {
+        /* for yaffs, by www.100ask.net */
+		if (cmd & (NANDRW_WRITE | NANDRW_YAFFS)) {
+			/* Do some programming, but not in the first block */			
+            if (!bfirstyaffsblk) {
+                prgmblk = start;
+                prgmblks++;
+                printf("       0x%08x/%05d               0x%08x/%05d          %05d/%05d=%02d%%\r", prgmblk, prgmblks, badblk, badblks, prgmblks, allblks, prgmblks*100/allblks);
+                for (page = 0; (page < erasesize/nand->oobblock) && (len - page*(nand->oobblock+nand->oobsize) > 0); page++) {
+        			ret = nand_write_ecc(nand, start+page*nand->oobblock,
+        					    nand->oobblock, (size_t *)&n,
+        					    (u_char*)buf+page*(nand->oobblock+nand->oobsize), (u_char *)0); /* without ecc */
+                    if (!ret) 
+                        ret = nand_write_oob(nand, start+page*nand->oobblock,
+    						     nand->oobsize, (size_t *)&n,
+    						     (u_char*)buf+page*(nand->oobblock+nand->oobsize)+nand->oobblock);
+                    if (ret)
+                        break;
+                }
+                n = page * (nand->oobblock+nand->oobsize);
+            } else {
+                bfirstyaffsblk = 0;
+                n = 0;
+                start += erasesize;     /* skip first block */
+                ret = 0;
+                page = 0;
+            }
+		} else if (cmd & NANDRW_READ) {
 			ret = nand_read_ecc(nand, start,
 					   min(len, eblk + erasesize - start),
 					   (size_t *)&n, (u_char*)buf, (u_char *)eccbuf);
@@ -234,14 +294,18 @@
 		if (ret)
 			break;
 
-		start  += n;
+		if (cmd & (NANDRW_WRITE | NANDRW_YAFFS))
+    		start  += page * nand->oobblock;
+        else
+    		start  += n;
+        
 		buf   += n;
 		total += n;
 		len   -= n;
 	}
 	if (retlen)
 		*retlen = total;
-
+    printf("\n");
 	return ret;
 }
 
@@ -759,6 +823,7 @@
 
 /*
  *	Nand_page_program function is used for write and writev !
+ *  Change By www.100ask.net, if ecc_code is null, write without ECC
  */
 static int nand_write_page (struct nand_chip *nand,
 			    int page, int col, int last, u_char * ecc_code)
@@ -766,6 +831,7 @@
 
 	int i;
 	unsigned long nandptr = nand->IO_ADDR;
+    int writecnt;
 
 #ifdef CONFIG_MTD_NAND_ECC
 #ifdef CONFIG_MTD_NAND_VERIFY_WRITE
@@ -778,8 +844,9 @@
 
 #ifdef CONFIG_MTD_NAND_ECC
 	/* Zero out the ECC array */
-	for (i = 0; i < 6; i++)
-		ecc_code[i] = 0x00;
+    if (ecc_code)   /* www.100ask.net */
+    	for (i = 0; i < 6; i++)
+    		ecc_code[i] = 0x00;
 
 	/* Read back previous written data, if col > 0 */
 	if (col) {
@@ -807,7 +874,9 @@
 	}
 
 	/* Calculate and write the ECC if we have enough data */
-	if ((col < nand->eccsize) && (last >= nand->eccsize)) {
+	//if ((col < nand->eccsize) && (last >= nand->eccsize)) {
+    /* if ecc_code is null, write without ecc, www.100ask.net */
+	if (ecc_code && (col < nand->eccsize) && (last >= nand->eccsize)) {
 		nand_calculate_ecc (&nand->data_buf[0], &(ecc_code[0]));
 		for (i = 0; i < 3; i++) {
 			nand->data_buf[(nand->oobblock +
@@ -820,7 +889,9 @@
 	}
 
 	/* Calculate and write the second ECC if we have enough data */
-	if ((nand->oobblock == 512) && (last == nand->oobblock)) {
+	//if ((nand->oobblock == 512) && (last == nand->oobblock)) {
+    /* if ecc_code is null, write without ecc, www.100ask.net */
+	if (ecc_code && (nand->oobblock == 512) && (last == nand->oobblock)) {
 		nand_calculate_ecc (&nand->data_buf[256], &(ecc_code[3]));
 		for (i = 3; i < 6; i++) {
 			nand->data_buf[(nand->oobblock +
@@ -851,15 +922,21 @@
 			      (page << nand->page_shift) + col);
 	}
 
+    /* if ecc_code is null, write without ecc, www.100ask.net */
+    if (ecc_code)
+        writecnt = nand->oobblock + nand->oobsize;
+    else
+        writecnt = nand->oobblock;
+
 	/* Write out complete page of data */
 	if (nand->bus16) {
-		for (i = 0; i < (nand->oobblock + nand->oobsize); i += 2) {
+		for (i = 0; i < writecnt; i += 2) {
 			WRITE_NAND (nand->data_buf[i] +
 				    (nand->data_buf[i + 1] << 8),
 				    nand->IO_ADDR);
 		}
 	} else {
-		for (i = 0; i < (nand->oobblock + nand->oobsize); i++)
+		for (i = 0; i < writecnt; i++)
 			WRITE_NAND (nand->data_buf[i], nand->IO_ADDR);
 	}
 
@@ -933,35 +1010,38 @@
 	 * We also want to check that the ECC bytes wrote
 	 * correctly for the same reasons stated above.
 	 */
-	NanD_Command (nand, NAND_CMD_READOOB);
-	if (nand->bus16) {
-		NanD_Address (nand, ADDR_COLUMN_PAGE,
-			      (page << nand->page_shift) + (col >> 1));
-	} else {
-		NanD_Address (nand, ADDR_COLUMN_PAGE,
-			      (page << nand->page_shift) + col);
-	}
-	if (nand->bus16) {
-		for (i = 0; i < nand->oobsize; i += 2) {
-			u16 val;
-
-			val = READ_NAND (nand->IO_ADDR);
-			nand->data_buf[i] = val & 0xff;
-			nand->data_buf[i + 1] = val >> 8;
-		}
-	} else {
-		for (i = 0; i < nand->oobsize; i++) {
-			nand->data_buf[i] = READ_NAND (nand->IO_ADDR);
-		}
-	}
-	for (i = 0; i < ecc_bytes; i++) {
-		if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) {
-			printf ("%s: Failed ECC write "
-				"verify, page 0x%08x, "
-				"%6i bytes were succesful\n",
-				__FUNCTION__, page, i);
-			return -1;
-		}
+    /* if ecc_code is null, write without ecc, www.100ask.net */
+	if (ecc_code) {
+    	NanD_Command (nand, NAND_CMD_READOOB);
+    	if (nand->bus16) {
+    		NanD_Address (nand, ADDR_COLUMN_PAGE,
+    			      (page << nand->page_shift) + (col >> 1));
+    	} else {
+    		NanD_Address (nand, ADDR_COLUMN_PAGE,
+    			      (page << nand->page_shift) + col);
+    	}
+    	if (nand->bus16) {
+    		for (i = 0; i < nand->oobsize; i += 2) {
+    			u16 val;
+
+    			val = READ_NAND (nand->IO_ADDR);
+    			nand->data_buf[i] = val & 0xff;
+    			nand->data_buf[i + 1] = val >> 8;
+    		}
+    	} else {
+    		for (i = 0; i < nand->oobsize; i++) {
+    			nand->data_buf[i] = READ_NAND (nand->IO_ADDR);
+    		}
+    	}
+    	for (i = 0; i < ecc_bytes; i++) {
+    		if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) {
+    			printf ("%s: Failed ECC write "
+    				"verify, page 0x%08x, "
+    				"%6i bytes were succesful\n",
+    				__FUNCTION__, page, i);
+    			return -1;
+    		}
+    	}
 	}
 #endif	/* CONFIG_MTD_NAND_ECC */
 #endif	/* CONFIG_MTD_NAND_VERIFY_WRITE */
@@ -1053,6 +1133,7 @@
 	return ret;
 }
 
+
 /* read from the 16 bytes of oob data that correspond to a 512 byte
  * page or 2 256-byte pages.
  */
@@ -1132,6 +1213,17 @@
 
 	/* issue the Read2 command to set the pointer to the Spare Data Area. */
 	NanD_Command(nand, NAND_CMD_READOOB);
+
+/* bug fixed by www.100ask.net
+ * write oob sequence: 
+ *  1. NAND_CMD_READOOB
+ *  2. NAND_CMD_SEQIN
+ *  3. Address
+ *  4. Data
+ *  5. NAND_CMD_PAGEPROG
+ *  6. NAND_CMD_STATUS
+ */
+#if 0   
 	if (nand->bus16) {
  		NanD_Address(nand, ADDR_COLUMN_PAGE,
 			     ((ofs >> nand->page_shift) << nand->page_shift) +
@@ -1139,7 +1231,7 @@
 	} else {
  		NanD_Address(nand, ADDR_COLUMN_PAGE, ofs);
 	}
-
+#endif
 	/* update address for 2M x 8bit devices. OOB starts on the second */
 	/* page to maintain compatibility with nand_read_ecc. */
 	if (nand->page256) {
diff -urN u-boot-1.1.6/drivers/usb/2440usb.h u-boot-1.1.6_jz2440/drivers/usb/2440usb.h
--- u-boot-1.1.6/drivers/usb/2440usb.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/2440usb.h	2010-11-26 12:54:38.322059054 +0800
@@ -0,0 +1,117 @@
+/*********************************************
+  NAME: 2440usb.h
+  DESC: 
+  HISTORY:
+  03.23.2002:purnnamu: first release for 2410
+ *********************************************/
+#ifndef __24XUSB_H__
+#define __24XUSB_H__
+
+//*************************************************************************
+// USB definitons
+//*************************************************************************
+
+/* Power Management Register */
+#define DISABLE_SUSPEND          0x00   
+#define ENABLE_SUSPEND           0x01
+#define SUSPEND_MODE		 0x02
+#define MCU_RESUME               0x04
+#define ISO_UPDATE		 (1<<7)
+
+/* MAXP Register */
+#define FIFO_SIZE_0              0x00  /* 0x00 * 8 = 0  */
+#define FIFO_SIZE_8              0x01  /* 0x01 * 8 = 8  */
+#define FIFO_SIZE_16             0x02  /* 0x02 * 8 = 16 */
+#define FIFO_SIZE_32             0x04  /* 0x04 * 8 = 32 */
+#define FIFO_SIZE_64             0x08  /* 0x08 * 8 = 64 */
+
+/* ENDPOINT0 CSR (Control Status Register) : Mapped to IN CSR1 */
+#define EP0_OUT_PKT_READY        0x01  /* USB sets, MCU clears by setting SERVICED_OUT_PKT_RDY */
+#define EP0_IN_PKT_READY         0x02  /* MCU sets, USB clears after sending FIFO */
+#define EP0_SENT_STALL           0x04  /* USB sets */       
+#define EP0_DATA_END             0x08  /* MCU sets */
+#define EP0_SETUP_END            0x10  /* USB sets, MCU clears by setting SERVICED_SETUP_END */
+#define EP0_SEND_STALL           0x20  /* MCU sets */
+#define EP0_SERVICED_OUT_PKT_RDY 0x40  /* MCU writes 1 to clear OUT_PKT_READY */
+#define EP0_SERVICED_SETUP_END   0x80  /* MCU writes 1 to clear SETUP_END        */
+
+#define EP0_WR_BITS              0xc0  
+
+//EP_INT_REG / EP_INT_EN_REG
+#define EP0_INT                	 0x01  // Endpoint 0, Control   
+#define EP1_INT                  0x02  // Endpoint 1, (Bulk-In) 
+#define EP2_INT                  0x04  // Endpoint 2 
+#define EP3_INT			 0x08  // Endpoint 3, (Bulk-Out)   
+#define EP4_INT			 0x10  // Endpoint 4
+
+//USB_INT_REG / USB_INT_EN_REG
+#define SUSPEND_INT            	 0x01  
+#define RESUME_INT               0x02  
+#define RESET_INT                0x04  
+
+//IN_CSR1
+#define EPI_IN_PKT_READY         0x01  
+#define EPI_UNDER_RUN		 0x04
+#define EPI_FIFO_FLUSH		 0x08
+#define EPI_SEND_STALL           0x10  
+#define EPI_SENT_STALL           0x20  
+#define EPI_CDT			 0x40	
+#define EPI_WR_BITS              (EPI_FIFO_FLUSH|EPI_IN_PKT_READY|EPI_CDT) 
+					//(EPI_FIFO_FLUSH) is preferred  (???)
+//IN_CSR2
+#define EPI_IN_DMA_INT_MASK	(1<<4)
+#define EPI_MODE_IN		(1<<5)
+#define EPI_MODE_OUT		(0<<5)
+#define EPI_ISO			(1<<6)
+#define EPI_BULK		(0<<6)
+#define EPI_AUTO_SET		(1<<7)
+
+//OUT_CSR1
+#define EPO_OUT_PKT_READY        0x01  
+#define EPO_OVER_RUN		 0x04  
+#define EPO_DATA_ERROR		 0x08  
+#define EPO_FIFO_FLUSH		 0x10
+#define EPO_SEND_STALL           0x20  
+#define EPO_SENT_STALL           0x40
+#define EPO_CDT			 0x80	
+#define EPO_WR_BITS              (EPO_FIFO_FLUSH|EPO_SEND_STALL|EPO_CDT)
+					//(EPO_FIFO_FLUSH) is preferred (???)
+
+//OUT_CSR2
+#define EPO_OUT_DMA_INT_MASK	(1<<5)
+#define EPO_ISO		 	(1<<6)
+#define EPO_BULK	 	(0<<6)
+#define EPO_AUTO_CLR		(1<<7)
+
+//USB DMA control register
+#define UDMA_IN_RUN_OB		(1<<7)
+#define UDMA_IGNORE_TTC		(1<<7)
+#define UDMA_DEMAND_MODE	(1<<3)
+#define UDMA_OUT_RUN_OB		(1<<2)
+#define UDMA_OUT_DMA_RUN	(1<<2)
+#define UDMA_IN_DMA_RUN		(1<<1)
+#define UDMA_DMA_MODE_EN	(1<<0)
+
+#define rEP1_DMA_TTC	(rEP1_DMA_TTC_L+(rEP1_DMA_TTC_M<<8)+(rEP1_DMA_TTC_H<<16))
+#define rEP2_DMA_TTC	(rEP2_DMA_TTC_L+(rEP2_DMA_TTC_M<<8)+(rEP2_DMA_TTC_H<<16))
+#define rEP3_DMA_TTC	(rEP3_DMA_TTC_L+(rEP3_DMA_TTC_M<<8)+(rEP3_DMA_TTC_H<<16))
+#define rEP4_DMA_TTC	(rEP4_DMA_TTC_L+(rEP4_DMA_TTC_M<<8)+(rEP4_DMA_TTC_H<<16))
+
+#define ADDR_EP0_FIFO 		(0x520001c0) //Endpoint 0 FIFO
+#define ADDR_EP1_FIFO		(0x520001c4) //Endpoint 1 FIFO
+#define ADDR_EP2_FIFO		(0x520001c8) //Endpoint 2 FIFO
+#define ADDR_EP3_FIFO		(0x520001cc) //Endpoint 3 FIFO
+#define ADDR_EP4_FIFO		(0x520001d0) //Endpoint 4 FIFO
+
+//If you chane the packet size, the source code should be changed!!!
+//USB Device Options
+#define USBDMA		TRUE
+//#define USBDMA		FALSE
+#define USBDMA_DEMAND 	FALSE	//the downloadFileSize should be (64*n)
+#define BULK_PKT_SIZE	32
+
+#define EP0_PKT_SIZE             8	
+#define EP1_PKT_SIZE             BULK_PKT_SIZE
+#define EP3_PKT_SIZE             BULK_PKT_SIZE
+
+#endif //__24XUSB_H__
diff -urN u-boot-1.1.6/drivers/usb/Makefile u-boot-1.1.6_jz2440/drivers/usb/Makefile
--- u-boot-1.1.6/drivers/usb/Makefile	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/Makefile	2010-11-26 12:54:38.326057824 +0800
@@ -0,0 +1,45 @@
+#
+# (C) Copyright 2006
+# 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
+
+LIB 	:= $(obj)libusb.a
+
+COBJS 	:= usbin.o  usblib.o  usbmain.o  usbout.o  usbsetup.o usbinit.o
+
+SRCS 	:= $(COBJS:.o=.c)
+OBJS 	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff -urN u-boot-1.1.6/drivers/usb/mrgtmp0 u-boot-1.1.6_jz2440/drivers/usb/mrgtmp0
--- u-boot-1.1.6/drivers/usb/mrgtmp0	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/mrgtmp0	2010-11-26 12:54:38.322059054 +0800
@@ -0,0 +1,537 @@
+/****************************************************************
+ NAME: u2440mon.c
+ DESC: u2440mon entry point,menu,download
+ HISTORY:
+ Mar.25.2002:purnnamu: S3C2400X profile.c is ported for S3C2410X.
+ Mar.27.2002:purnnamu: DMA is enabled.
+ Apr.01.2002:purnnamu: isDownloadReady flag is added.
+ Apr.10.2002:purnnamu: - Selecting menu is available in the waiting loop. 
+                         So, isDownloadReady flag gets not needed
+                       - UART ch.1 can be selected for the console.
+ Aug.20.2002:purnnamu: revision number change 0.2 -> R1.1       
+ Sep.03.2002:purnnamu: To remove the power noise in the USB signal, the unused CLKOUT0,1 is disabled.
+ ****************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "def.h"
+#include "option.h"
+#include "2440addr.h"
+#include "2440lib.h"
+#include "2440slib.h"
+#include "mmu.h"
+#include "profile.h"
+#include "memtest.h"
+
+#include "usbmain.h"
+#include "usbout.h"
+#include "usblib.h"
+#include "2440usb.h"
+#include "printk.h"
+#include "types.h"
+
+
+#include "platform/smdk2440.h"
+
+
+void Isr_Init(void);
+void HaltUndef(void);
+void HaltSwi(void);
+void HaltPabort(void);
+void HaltDabort(void);
+void Lcd_Off(void);
+void WaitDownload(void);
+void Menu(void);
+void ClearMemory(void);
+
+
+void Clk0_Enable(int clock_sel);	
+void Clk1_Enable(int clock_sel);
+void Clk0_Disable(void);
+void Clk1_Disable(void);
+
+//#define DOWNLOAD_ADDRESS _RAM_STARTADDRESS
+volatile U32 downloadAddress;
+
+void (*restart)(void)=(void (*)(void))0x0;
+void (*run)(void);
+
+
+volatile unsigned char *downPt;
+volatile U32 downloadFileSize;
+volatile U16 checkSum;
+volatile unsigned int err=0;
+volatile U32 totalDmaCount;
+
+volatile int isUsbdSetConfiguration;
+
+int download_run=0;
+U32 tempDownloadAddress;
+int menuUsed=0;
+
+extern char Image$$RW$$Limit[];
+U32 *pMagicNum=(U32 *)Image$$RW$$Limit;
+int consoleNum;
+
+void usb_init(void)
+{
+	char *mode;
+	int i;
+	U8 key;
+	U32 mpll_val, divn_upll=0;
+    
+	#if ADS10   
+	__rt_lib_init(); //for ADS 1.0
+	#endif
+
+	Port_Init();
+	// USB device detection control
+	rGPGCON &= ~(3<<24);
+	rGPGCON |=  (1<<24); // output
+	rGPGUP  |=  (1<<12); // pullup disable
+	rGPGDAT |=  (1<<12); // output	
+	
+
+	//ChangeUPllValue(60,4,2);		// 48MHz
+	//for(i=0; i<7; i++);
+	//ChangeClockDivider(13,12);
+	//ChangeMPllValue(97,1,2);		//296Mhz
+
+	Isr_Init();
+
+	consoleNum=1;		// Uart 1 select for debug.
+	Uart_Init(0,115200);
+	Uart_Select(consoleNum);
+
+	rMISCCR=rMISCCR&~(1<<3); // USBD is selected instead of USBH1 
+	rMISCCR=rMISCCR&~(1<<13); // USB port 1 is enabled.
+
+
+//
+//  USBD should be initialized first of all.
+//
+	isUsbdSetConfiguration=0;
+
+#if 0
+	UsbdMain(); 
+	MMU_Init(); //MMU should be reconfigured or turned off for the debugger, 
+	//After downloading, MMU should be turned off for the MMU based program,such as WinCE.	
+#else
+	MMU_EnableICache();  
+	UsbdMain(); 
+#endif
+	Delay(0);  //calibrate Delay()
+	
+	pISR_SWI=(_ISR_STARTADDRESS+0xf0);	//for pSOS
+
+	Led_Display(0x6);
+
+#if USBDMA
+	mode="DMA";
+#else
+	mode="Int";
+#endif
+
+	// CLKOUT0/1 select.
+	//Uart_Printf("CLKOUT0:MPLL in, CLKOUT1:RTC clock.\n");
+	//Clk0_Enable(0);	// 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
+	//Clk1_Enable(2);	// 0:MPLLout, 1:UPLL, 2:RTC, 3:HCLK, 4:PCLK, 5:DCLK1	
+	Clk0_Disable();
+	Clk1_Disable();
+	
+	mpll_val = rMPLLCON;
+	Uart_Printf("DIVN_UPLL%x\n", divn_upll);
+	Uart_Printf("MPLLVal [M:%xh,P:%xh,S:%xh]\n", (mpll_val&(0xff<<12))>>12,(mpll_val&(0x3f<<4))>>4,(mpll_val&0x3));
+	Uart_Printf("CLKDIVN:%xh\n", rCLKDIVN);
+
+	Uart_Printf("\n\n");
+	Uart_Printf("+---------------------------------------------+\n");
+	Uart_Printf("| S3C2440A USB Downloader ver R0.03 2004 Jan  |\n");
+	Uart_Printf("+---------------------------------------------+\n");
+	Uart_Printf("FCLK=%4.1fMHz,%s mode\n",FCLK/1000000.,mode); 
+	Uart_Printf("USB: IN_ENDPOINT:1 OUT_ENDPOINT:3\n"); 
+	Uart_Printf("FORMAT: <ADDR(DATA):4>+<SIZE(n+10):4>+<DATA:n>+<CS:2>\n");
+	Uart_Printf("NOTE: 1. Power off/on or press the reset button for 1 sec\n");
+	Uart_Printf("		 in order to get a valid USB device address.\n");
+	Uart_Printf("	  2. For additional menu, Press any key. \n");
+	Uart_Printf("\n");
+
+	download_run=1; //The default menu is the Download & Run mode.
+
+	while(1)
+	{
+		if(menuUsed==1)Menu();
+		WaitDownload();	
+	}
+
+}
+
+
+
+void Menu(void)
+{
+	int i;
+	U8 key;
+	menuUsed=1;
+	while(1)
+	{
+		Uart_Printf("\n###### Select Menu ######\n");
+		Uart_Printf(" [0] Download & Run\n");
+		Uart_Printf(" [1] Download Only\n");
+		Uart_Printf(" [2] Test SDRAM \n");
+		Uart_Printf(" [3] Change The Console UART Ch.\n");
+		Uart_Printf(" [4] Clear unused area in SDRAM \n");		
+		key=Uart_Getch();
+		
+		switch(key)
+		{
+		case '0':
+			Uart_Printf("\nDownload&Run is selected.\n\n");
+			download_run=1;
+			return;
+		case '1':
+			Uart_Printf("\nDownload Only is selected.\n");
+			Uart_Printf("Enter a new temporary download address(0x3...):");
+			tempDownloadAddress=Uart_GetIntNum();
+			download_run=0;
+			Uart_Printf("The temporary download address is 0x%x.\n\n",tempDownloadAddress);
+			return;
+		case '2':
+			Uart_Printf("\nMemory Test is selected.\n");
+		MemoryTest();
+		Menu();
+		return;
+			break;
+		case '3':
+			Uart_Printf("\nWhich UART channel do you want to use for the console?[0/1]\n");
+			if(Uart_Getch()!='1')
+			{
+			*pMagicNum=0x0;
+		Uart_Printf("UART ch.0 will be used for console at next boot.\n");					
+		}
+		else
+		{
+			*pMagicNum=0x12345678;
+ 		Uart_Printf("UART ch.1 will be used for console at next boot.\n");		
+				Uart_Printf("UART ch.0 will be used after long power-off.\n");
+		}
+			Uart_Printf("System is waiting for a reset. Please, Reboot!!!\n");
+			while(1);
+			break;
+		case '4':
+			Uart_Printf("\nMemory clear is selected.\n");
+			ClearMemory();
+		break;
+		default:
+			break;
+	}	
+	}		
+
+}
+
+
+
+void WaitDownload(void)
+{
+	U32 i;
+	U32 j;
+	U16 cs;
+	U32 temp;
+	U16 dnCS;
+	int first=1;
+	float time;
+	U8 tempMem[16];
+	U8 key;
+	
+	checkSum=0;
+	downloadAddress=(U32)tempMem; //_RAM_STARTADDRESS; 
+	downPt=(unsigned char *)downloadAddress;
+	//This address is used for receiving first 8 byte.
+	downloadFileSize=0;
+	
+#if 0
+	MMU_DisableICache(); 
+		//For multi-ICE. 
+		//If ICache is not turned-off, debugging is started with ICache-on.
+#endif
+
+	/*******************************/
+	/*	Test program download	*/
+	/*******************************/
+	j=0;
+
+	if(isUsbdSetConfiguration==0)
+	{
+	Uart_Printf("USB host is not connected yet.\n");
+	}
+
+	while(downloadFileSize==0)
+	{
+		if(first==1 && isUsbdSetConfiguration!=0)
+		{
+			Uart_Printf("USB host is connected. Waiting a download.\n");
+			first=0;
+		}
+
+	if(j%0x50000==0)Led_Display(0x6);
+	if(j%0x50000==0x28000)Led_Display(0x9);
+	j++;
+
+	key=Uart_GetKey();
+	if(key!=0)
+	{
+		Menu();
+			first=1; //To display the message,"USB host ...."
+	}
+
+	}
+
+	Timer_InitEx();	  
+	Timer_StartEx();  
+
+#if USBDMA	
+
+	rINTMSK&=~(BIT_DMA2);  
+
+	ClearEp3OutPktReady(); 
+		// indicate the first packit is processed.
+		// has been delayed for DMA2 cofiguration.
+
+	if(downloadFileSize>EP3_PKT_SIZE)
+	{
+		if(downloadFileSize<=(0x80000))
+		{
+	  		ConfigEp3DmaMode(downloadAddress+EP3_PKT_SIZE-8,downloadFileSize-EP3_PKT_SIZE);	
+ 
+	  		//will not be used.
+/*	   rDIDST2=(downloadAddress+downloadFileSize-EP3_PKT_SIZE);  
+		   rDIDSTC2=(0<<1)|(0<<0);  
+		rDCON2=rDCON2&~(0xfffff)|(0);				
+*/
+		}
+	  	else
+	  	{
+	  		ConfigEp3DmaMode(downloadAddress+EP3_PKT_SIZE-8,0x80000-EP3_PKT_SIZE);
+	   		
+			if(downloadFileSize>(0x80000*2))//for 1st autoreload
+			{
+				rDIDST2=(downloadAddress+0x80000-8);  //for 1st autoreload.
+			 rDIDSTC2=(1<<2)|(0<<1)|(0<<0);  
+				rDCON2=rDCON2&~(0xfffff)|(0x80000);			  
+
+  		while(rEP3_DMA_TTC<0xfffff)
+  		{
+  			rEP3_DMA_TTC_L=0xff; 
+  			rEP3_DMA_TTC_M=0xff;
+  			rEP3_DMA_TTC_H=0xf;
+  		}
+			}	
+ 		else
+ 		{
+ 			rDIDST2=(downloadAddress+0x80000-8);  //for 1st autoreload.
+	  			rDIDSTC2=(1<<2)|(0<<1)|(0<<0);  
+ 			rDCON2=rDCON2&~(0xfffff)|(downloadFileSize-0x80000); 		
+
+  		while(rEP3_DMA_TTC<0xfffff)
+  		{
+  			rEP3_DMA_TTC_L=0xff; 
+  			rEP3_DMA_TTC_M=0xff;
+  			rEP3_DMA_TTC_H=0xf;
+  		}
+		}
+	}
+ 	totalDmaCount=0;
+	}
+	else
+	{
+	totalDmaCount=downloadFileSize;
+	}
+#endif
+
+	Uart_Printf("\nNow, Downloading [ADDRESS:%xh,TOTAL:%d]\n",
+			downloadAddress,downloadFileSize);
+	Uart_Printf("RECEIVED FILE SIZE:%8d",0);
+   
+#if USBDMA	
+	j=0x10000;
+
+	while(1)
+	{
+		if( (rDCDST2-(U32)downloadAddress+8)>=j)
+	{
+		Uart_Printf("\b\b\b\b\b\b\b\b%8d",j);
+   		j+=0x10000;
+		}
+	if(totalDmaCount>=downloadFileSize)break;
+	}
+
+#else
+	j=0x10000;
+
+	while(((U32)downPt-downloadAddress)<(downloadFileSize-8))
+	{
+	if( ((U32)downPt-downloadAddress)>=j)
+	{
+		Uart_Printf("\b\b\b\b\b\b\b\b%8d",j);
+   		j+=0x10000;
+	}
+	}
+#endif
+
+	time=Timer_StopEx();
+	
+	Uart_Printf("\b\b\b\b\b\b\b\b%8d",downloadFileSize);	
+	Uart_Printf("\n(%5.1fKB/S,%3.1fS)\n",(float)(downloadFileSize/time/1000.),time);
+	
+#if USBDMA	
+	/*******************************/
+	/*	 Verify check sum		*/
+	/*******************************/
+
+	Uart_Printf("Now, Checksum calculation\n");
+
+	cs=0;	
+	i=(downloadAddress);
+	j=(downloadAddress+downloadFileSize-10)&0xfffffffc;
+	while(i<j)
+	{
+		temp=*((U32 *)i);
+		i+=4;
+		cs+=(U16)(temp&0xff);
+		cs+=(U16)((temp&0xff00)>>8);
+		cs+=(U16)((temp&0xff0000)>>16);
+		cs+=(U16)((temp&0xff000000)>>24);
+	}
+
+	i=(downloadAddress+downloadFileSize-10)&0xfffffffc;
+	j=(downloadAddress+downloadFileSize-10);
+	while(i<j)
+	{
+  	cs+=*((U8 *)i++);
+	}
+	
+	checkSum=cs;
+#else
+	//checkSum was calculated including dnCS. So, dnCS should be subtracted.
+	checkSum=checkSum - *((unsigned char *)(downloadAddress+downloadFileSize-8-2))
+		 - *( (unsigned char *)(downloadAddress+downloadFileSize-8-1) );	
+#endif	  
+
+	dnCS=*((unsigned char *)(downloadAddress+downloadFileSize-8-2))+
+	(*( (unsigned char *)(downloadAddress+downloadFileSize-8-1) )<<8);
+
+	if(checkSum!=dnCS)
+	{
+	Uart_Printf("Checksum Error!!! MEM:%x DN:%x\n",checkSum,dnCS);
+	return;
+	}
+
+	Uart_Printf("Download O.K.\n\n");
+	Uart_TxEmpty(consoleNum);
+
+
+	if(download_run==1)
+	{
+		rINTMSK=BIT_ALLMSK;
+		run=(void (*)(void))downloadAddress;
+	run();
+	}
+}
+
+
+
+
+void Isr_Init(void)
+{
+	pISR_UNDEF=(unsigned)HaltUndef;
+	pISR_SWI  =(unsigned)HaltSwi;
+	pISR_PABORT=(unsigned)HaltPabort;
+	pISR_DABORT=(unsigned)HaltDabort;
+	rINTMOD=0x0;	  // All=IRQ mode
+	rINTMSK=BIT_ALLMSK;	  // All interrupt is masked.
+
+	//pISR_URXD0=(unsigned)Uart0_RxInt;	
+	//rINTMSK=~(BIT_URXD0);   //enable UART0 RX Default value=0xffffffff
+
+#if 1
+	pISR_USBD =(unsigned)IsrUsbd;
+	pISR_DMA2 =(unsigned)IsrDma2;
+#else
+	pISR_IRQ =(unsigned)IsrUsbd;	
+		//Why doesn't it receive the big file if use this. (???)
+		//It always stops when 327680 bytes are received.
+#endif	
+	ClearPending(BIT_DMA2);
+	ClearPending(BIT_USBD);
+	//rINTMSK&=~(BIT_USBD);  
+   
+	//pISR_FIQ,pISR_IRQ must be initialized
+}
+
+
+void HaltUndef(void)
+{
+	Uart_Printf("Undefined instruction exception!!!\n");
+	while(1);
+}
+
+void HaltSwi(void)
+{
+	Uart_Printf("SWI exception!!!\n");
+	while(1);
+}
+
+void HaltPabort(void)
+{
+	Uart_Printf("Pabort exception!!!\n");
+	while(1);
+}
+
+void HaltDabort(void)
+{
+	Uart_Printf("Dabort exception!!!\n");
+	while(1);
+}
+
+
+void ClearMemory(void)
+{
+	int i;
+	U32 data;
+	int memError=0;
+	U32 *pt;
+	
+	//
+	// memory clear
+	//
+	Uart_Printf("Clear Memory (%xh-%xh):WR",_RAM_STARTADDRESS,HEAPEND);
+
+	pt=(U32 *)_RAM_STARTADDRESS;
+	while((U32)pt < HEAPEND)
+	{
+		*pt=(U32)0x0;
+		pt++;
+	}
+	
+	if(memError==0)Uart_Printf("\b\bO.K.\n");
+}
+
+void Clk0_Enable(int clock_sel)	
+{	// 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
+	rMISCCR = rMISCCR&~(7<<4) | (clock_sel<<4);
+	rGPHCON = rGPHCON&~(3<<18) | (2<<18);
+}
+void Clk1_Enable(int clock_sel)
+{	// 0:MPLLout, 1:UPLL, 2:RTC, 3:HCLK, 4:PCLK, 5:DCLK1	
+	rMISCCR = rMISCCR&~(7<<8) | (clock_sel<<8);
+	rGPHCON = rGPHCON&~(3<<20) | (2<<20);
+}
+void Clk0_Disable(void)
+{
+	rGPHCON = rGPHCON&~(3<<18);	// GPH9 Input
+}
+void Clk1_Disable(void)
+{
+	rGPHCON = rGPHCON&~(3<<20);	// GPH10 Input
+}
+
diff -urN u-boot-1.1.6/drivers/usb/usb.h u-boot-1.1.6_jz2440/drivers/usb/usb.h
--- u-boot-1.1.6/drivers/usb/usb.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usb.h	2010-11-26 12:54:38.330048254 +0800
@@ -0,0 +1,169 @@
+/****************************************************************
+ NAME: usb.h
+ DESC: definitions(USB data structure) for USB setup operation.
+       Because It's h/w independent file, it may be used without any change in future.
+       Reuse the source of S3C2400X u24xmon 
+ HISTORY:
+ Apr.07.2000:purnnamu: first release. 
+ ****************************************************************/
+#ifndef __USB_H__
+#define __USB_H__
+
+//************************
+//       Endpoint 0      
+//************************
+
+// Standard bmRequestTyje (Direction) 
+#define HOST_TO_DEVICE              (0x00)
+#define DEVICE_TO_HOST              (0x80)    
+
+// Standard bmRequestType (Type) 
+#define STANDARD_TYPE               (0x00)
+#define CLASS_TYPE                  (0x20)
+#define VENDOR_TYPE                 (0x40)
+#define RESERVED_TYPE               (0x60)
+
+// Standard bmRequestType (Recipient) 
+#define DEVICE_RECIPIENT            (0)
+#define INTERFACE_RECIPIENT         (1)
+#define ENDPOINT_RECIPIENT          (2)
+#define OTHER_RECIPIENT             (3)
+
+// Feature Selectors 
+#define DEVICE_REMOTE_WAKEUP        (1)
+#define EP_STALL                    (0)
+
+// Standard Request Codes 
+#define GET_STATUS                  (0)
+#define CLEAR_FEATURE               (1)
+#define SET_FEATURE                 (3)
+#define SET_ADDRESS                 (5)
+#define GET_DESCRIPTOR              (6)
+#define SET_DESCRIPTOR              (7)
+#define GET_CONFIGURATION           (8)
+#define SET_CONFIGURATION           (9)
+#define GET_INTERFACE               (10)
+#define SET_INTERFACE               (11)
+#define SYNCH_FRAME                 (12)
+
+// Class-specific Request Codes 
+#define GET_DEVICE_ID               (0)
+#define GET_PORT_STATUS             (1)
+#define SOFT_RESET                  (2)
+
+// Descriptor Types
+#define DEVICE_TYPE                 (1)
+#define CONFIGURATION_TYPE          (2)
+#define STRING_TYPE                 (3)
+#define INTERFACE_TYPE              (4)
+#define ENDPOINT_TYPE               (5)
+
+//configuration descriptor: bmAttributes 
+#define CONF_ATTR_DEFAULT	    (0x80) //Spec 1.0 it was BUSPOWERED bit.
+#define CONF_ATTR_REMOTE_WAKEUP     (0x20)
+#define CONF_ATTR_SELFPOWERED       (0x40)
+
+//endpoint descriptor
+#define EP_ADDR_IN		    (0x80)	
+#define EP_ADDR_OUT		    (0x00)
+
+#define EP_ATTR_CONTROL		    (0x0)	
+#define EP_ATTR_ISOCHRONOUS	    (0x1)
+#define EP_ATTR_BULK		    (0x2)
+#define EP_ATTR_INTERRUPT	    (0x3)	
+
+
+//string descriptor
+#define LANGID_US_L 		    (0x09)  
+#define LANGID_US_H 		    (0x04)
+
+
+struct USB_SETUP_DATA{
+    U8 bmRequestType;    
+    U8 bRequest;         
+    U8 bValueL;          
+    U8 bValueH;          
+    U8 bIndexL;          
+    U8 bIndexH;          
+    U8 bLengthL;         
+    U8 bLengthH;         
+};
+
+
+struct USB_DEVICE_DESCRIPTOR{
+    U8 bLength;    
+    U8 bDescriptorType;         
+    U8 bcdUSBL;
+    U8 bcdUSBH;
+    U8 bDeviceClass;          
+    U8 bDeviceSubClass;          
+    U8 bDeviceProtocol;          
+    U8 bMaxPacketSize0;         
+    U8 idVendorL;
+    U8 idVendorH;
+    U8 idProductL;
+    U8 idProductH;
+    U8 bcdDeviceL;
+    U8 bcdDeviceH;
+    U8 iManufacturer;
+    U8 iProduct;
+    U8 iSerialNumber;
+    U8 bNumConfigurations;
+};
+
+
+struct USB_CONFIGURATION_DESCRIPTOR{
+    U8 bLength;    
+    U8 bDescriptorType;         
+    U8 wTotalLengthL;
+    U8 wTotalLengthH;
+    U8 bNumInterfaces;
+    U8 bConfigurationValue;
+    U8 iConfiguration;
+    U8 bmAttributes;
+    U8 maxPower;          
+};
+    
+
+struct USB_INTERFACE_DESCRIPTOR{
+    U8 bLength;    
+    U8 bDescriptorType;         
+    U8 bInterfaceNumber;
+    U8 bAlternateSetting;
+    U8 bNumEndpoints;
+    U8 bInterfaceClass;
+    U8 bInterfaceSubClass;
+    U8 bInterfaceProtocol;
+    U8 iInterface;
+};
+
+
+struct USB_ENDPOINT_DESCRIPTOR{
+    U8 bLength;    
+    U8 bDescriptorType;         
+    U8 bEndpointAddress;
+    U8 bmAttributes;
+    U8 wMaxPacketSizeL;
+    U8 wMaxPacketSizeH;
+    U8 bInterval;
+};
+
+ struct USB_CONFIGURATION_SET{
+     U8 ConfigurationValue;
+ };
+
+ struct USB_GET_STATUS{
+     U8 Device;
+     U8 Interface;
+     U8 Endpoint0;
+     U8 Endpoint1;
+     U8 Endpoint3;
+ };
+
+ struct USB_INTERFACE_GET{
+     U8 AlternateSetting;
+ };
+
+
+ 
+#endif /*__USB_H__*/                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
diff -urN u-boot-1.1.6/drivers/usb/usbin.c u-boot-1.1.6_jz2440/drivers/usb/usbin.c
--- u-boot-1.1.6/drivers/usb/usbin.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbin.c	2010-11-26 12:54:38.326057824 +0800
@@ -0,0 +1,111 @@
+/****************************************************************
+ NAME: usbin.c
+ DESC: usb bulk-IN operation
+ HISTORY:
+ Mar.25.2002:purnnamu: ported for S3C2410X.
+ ****************************************************************/
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include <def.h>
+
+#include "2440usb.h"
+#include "usbmain.h"
+#include "usb.h"
+#include "usblib.h"
+#include "usbsetup.h"
+#include "usbin.h"
+
+extern S3C24X0_USB_DEVICE * usbdevregs;
+extern S3C24X0_DMAS * dmaregs;
+
+static void PrintEpiPkt(U8 *pt,int cnt);
+
+
+// ===================================================================
+// All following commands will operate in case 
+// - in_csr1 is valid.
+// ===================================================================
+
+#define SET_EP1_IN_PKT_READY()  usbdevregs->EP0_CSR_IN_CSR1_REG= ( in_csr1 &(~ EPI_WR_BITS)\
+					| EPI_IN_PKT_READY )	 
+#define SET_EP1_SEND_STALL()	usbdevregs->EP0_CSR_IN_CSR1_REG= ( in_csr1 & (~EPI_WR_BITS)\
+					| EPI_SEND_STALL) )
+#define CLR_EP1_SENT_STALL()	usbdevregs->EP0_CSR_IN_CSR1_REG= ( in_csr1 & (~EPI_WR_BITS)\
+					&(~EPI_SENT_STALL) )
+#define FLUSH_EP1_FIFO() 	usbdevregs->EP0_CSR_IN_CSR1_REG= ( in_csr1 & (~EPI_WR_BITS)\
+					| EPI_FIFO_FLUSH) )
+
+
+// ***************************
+// *** VERY IMPORTANT NOTE ***
+// ***************************
+// Prepare the code for the packit size constraint!!!
+
+// EP1 = IN end point. 
+
+U8 ep1Buf[EP1_PKT_SIZE];
+int transferIndex=0;
+
+
+
+void PrepareEp1Fifo(void) 
+{
+    int i;
+    U8 in_csr1;
+    usbdevregs->INDEX_REG=1;
+    in_csr1=usbdevregs->EP0_CSR_IN_CSR1_REG;
+    
+    for(i=0;i<EP1_PKT_SIZE;i++)ep1Buf[i]=(U8)(transferIndex+i);
+    WrPktEp1(ep1Buf,EP1_PKT_SIZE);
+    SET_EP1_IN_PKT_READY(); 
+}
+
+
+void Ep1Handler(void)
+{
+    U8 in_csr1;
+    int i;
+    usbdevregs->INDEX_REG=1;
+    in_csr1=usbdevregs->EP0_CSR_IN_CSR1_REG;
+    
+    DbgPrintf("<1:%x]",in_csr1);
+
+    //I think that EPI_SENT_STALL will not be set to 1.
+    if(in_csr1 & EPI_SENT_STALL)
+    {   
+   	DbgPrintf("[STALL]");
+   	CLR_EP1_SENT_STALL();
+   	return;
+    }	
+
+    //IN_PKT_READY is cleared
+    
+    //The data transfered was ep1Buf[] which was already configured 
+
+    PrintEpiPkt(ep1Buf,EP1_PKT_SIZE); 
+    
+    transferIndex++;
+
+    PrepareEp1Fifo(); 
+    	//IN_PKT_READY is set   
+    	//This packit will be used for next IN packit.	
+
+    return;
+}
+
+
+    
+void PrintEpiPkt(U8 *pt,int cnt)
+{
+    int i;
+    DbgPrintf("[B_IN:%d:",cnt);
+    for(i=0;i<cnt;i++)
+    	DbgPrintf("%x,",pt[i]);
+    DbgPrintf("]");
+}
+
diff -urN u-boot-1.1.6/drivers/usb/usbin.h u-boot-1.1.6_jz2440/drivers/usb/usbin.h
--- u-boot-1.1.6/drivers/usb/usbin.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbin.h	2010-11-26 12:54:38.326057824 +0800
@@ -0,0 +1,13 @@
+/****************************************************************
+ NAME: usbin.h
+ DESC: 
+ HISTORY:
+ Mar.25.2002:purnnamu: reuse the source of S3C2400X u24xmon 
+ ****************************************************************/
+#ifndef __USBIN_H__
+#define __USBIN_H__
+
+void Ep1Handler(void);
+void PrepareEp1Fifo(void);
+
+#endif /*__USBIN_H__*/
diff -urN u-boot-1.1.6/drivers/usb/usbinit.c u-boot-1.1.6_jz2440/drivers/usb/usbinit.c
--- u-boot-1.1.6/drivers/usb/usbinit.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbinit.c	2010-11-26 12:54:38.322059054 +0800
@@ -0,0 +1,476 @@
+/****************************************************************
+ NAME: u2440mon.c
+ DESC: u2440mon entry point,menu,download
+ HISTORY:
+ Mar.25.2002:purnnamu: S3C2400X profile.c is ported for S3C2410X.
+ Mar.27.2002:purnnamu: DMA is enabled.
+ Apr.01.2002:purnnamu: isDownloadReady flag is added.
+ Apr.10.2002:purnnamu: - Selecting menu is available in the waiting loop. 
+                         So, isDownloadReady flag gets not needed
+                       - UART ch.1 can be selected for the console.
+ Aug.20.2002:purnnamu: revision number change 0.2 -> R1.1       
+ Sep.03.2002:purnnamu: To remove the power noise in the USB signal, the unused CLKOUT0,1 is disabled.
+ ****************************************************************/
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include "usbmain.h"
+#include "usbout.h"
+#include "usblib.h"
+#include "2440usb.h"
+
+extern S3C24X0_INTERRUPT * intregs;
+S3C24X0_USB_DEVICE * usbdevregs;
+S3C24X0_DMAS * dmaregs;
+S3C24X0_CLOCK_POWER * clk_powerregs;
+S3C24X0_GPIO * gpioregs;
+
+void Isr_Init(void);
+void HaltUndef(void);
+void HaltSwi(void);
+void HaltPabort(void);
+void HaltDabort(void);
+void Lcd_Off(void);
+//void WaitDownload(void);
+__u32 usb_receive(char *buf, size_t len, U32 wait);
+void Menu(void);
+
+extern void Timer_InitEx(void);
+extern void Timer_StartEx(void);
+extern unsigned int Timer_StopEx(void);
+
+extern void (*isr_handle_array[])(void);
+
+/*
+ * Reads and returns a character from the serial port
+ *   - Times out after delay iterations checking for presence of character
+ *   - Sets *error_p to UART error bits or - on timeout
+ *   - On timeout, sets *error_p to -1 and returns 0
+ */
+char awaitkey(unsigned long delay, int* error_p)
+{
+    int i;
+    char c;
+
+    if (delay == -1) {
+        while (1) {
+            if (tstc()) /* we got a key press	*/
+                return getc();
+        }
+    }
+    else {        
+        for (i = 0; i < delay; i++) {
+    		if (tstc()) /* we got a key press	*/
+    			return getc();
+            udelay (10*1000);
+        }
+    }
+    
+    if (error_p)
+        *error_p = -1;
+    return 0;
+}
+
+#define CTRL(x)   (x & 0x1f)
+#define INTR      CTRL('C')
+
+void Clk0_Enable(int clock_sel);	
+void Clk1_Enable(int clock_sel);
+void Clk0_Disable(void);
+void Clk1_Disable(void);
+
+//#define DOWNLOAD_ADDRESS _RAM_STARTADDRESS
+volatile U32 downloadAddress;
+
+void (*restart)(void)=(void (*)(void))0x0;
+void (*run)(void);
+
+
+volatile unsigned char *downPt;
+volatile U32 downloadFileSize;
+volatile U16 checkSum;
+volatile unsigned int err=0;
+volatile U32 totalDmaCount;
+
+volatile int isUsbdSetConfiguration;
+
+int download_run=0;
+volatile U32 tempDownloadAddress;
+int menuUsed=0;
+
+volatile U32 dwUSBBufReadPtr;
+volatile U32 dwUSBBufWritePtr;
+volatile U32 dwWillDMACnt;
+volatile U32 bDMAPending;
+volatile U32 dwUSBBufBase;
+volatile U32 dwUSBBufSize;
+
+int consoleNum;
+
+
+//***************************[ PORTS ]****************************************************
+void Port_Init(void)
+{    
+    gpioregs = S3C24X0_GetBase_GPIO();
+    //CAUTION:Follow the configuration order for setting the ports. 
+    // 1) setting value(GPnDAT) 
+    // 2) setting control register  (GPnCON)
+    // 3) configure pull-up resistor(GPnUP)  
+
+    //32bit data bus configuration  
+    //*** PORT A GROUP
+    //Ports  : GPA22 GPA21  GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12  
+    //Signal : nFCE nRSTOUT nFRE   nFWE  ALE   CLE  nGCS5 nGCS4 nGCS3 nGCS2 nGCS1 
+    //Binary :  1     1      1  , 1   1   1    1   ,  1     1     1     1
+    //Ports  : GPA11   GPA10  GPA9   GPA8   GPA7   GPA6   GPA5   GPA4   GPA3   GPA2   GPA1  GPA0
+    //Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0 
+    //Binary :  1       1      1      1   , 1       1      1      1   ,  1       1     1      1         
+    gpioregs->GPACON = 0x7fffff; 
+
+    //**** PORT B GROUP
+    //Ports  : GPB10    GPB9    GPB8    GPB7    GPB6     GPB5    GPB4   GPB3   GPB2     GPB1      GPB0
+    //Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard
+    //Setting: INPUT  OUTPUT   INPUT  OUTPUT   INPUT   OUTPUT   OUTPUT OUTPUT OUTPUT   OUTPUT    OUTPUT 
+    //Binary :   00  ,  01       00  ,   01      00   ,  01       01  ,   01     01   ,  01        01  
+    gpioregs->GPBCON = 0x044555;
+    gpioregs->GPBUP  = 0x7ff;     // The pull up function is disabled GPB[10:0]
+	gpioregs->GPBDAT &= ~(1<<0);	/* 禁止蜂鸣器 */
+	gpioregs->GPBDAT &= ~(1<<9);	/* disable USB Device, enable later, thisway.diy */
+
+    //*** PORT C GROUP
+    //Ports  : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8  GPC7    GPC6     GPC5     GPC4 GPC3     GPC2  GPC1 GPC0
+    //Signal : VD7    VD6    VD5     VD4     VD3     VD2     VD1  VD0    LCDVF2 LCDVF1 OUTPUT VM    VFRAME VLINE VCLK LEND  
+    //Binary :  10     10  ,    10       10  ,     10       10  ,    10     10  ,   10         10  ,      01          10 ,   10         10 ,     10     10
+    gpioregs->GPCCON = 0xaaaaa6aa;       
+    gpioregs->GPCUP  = 0xffff;     // The pull up function is disabled GPC[15:0] 
+	gpioregs->GPCDAT &= ~(1<<5);	/* disable USB Device, enable later, thisway.diy */
+
+    //*** PORT D GROUP
+    //Ports  : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
+    //Signal : VD23  VD22  VD21  VD20  VD19  VD18  VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9  VD8
+    //Binary : 10    10  , 10    10  , 10    10  , 10   10 , 10   10 , 10   10 , 10   10 ,10   10
+    gpioregs->GPDCON = 0xaaaaaaaa;       
+    gpioregs->GPDUP  = 0xffff;     // The pull up function is disabled GPD[15:0]
+
+    //*** PORT E GROUP
+    //Ports  : GPE15  GPE14 GPE13   GPE12   GPE11   GPE10   GPE9    GPE8     GPE7  GPE6  GPE5   GPE4  
+    //Signal : IICSDA IICSCL SPICLK SPIMOSI SPIMISO SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK IN 
+    //Binary :  10     10  ,  10      10  ,  10      10   ,  10      10   ,   10    10  , 10     00  ,     
+    //-------------------------------------------------------------------------------------------------------
+    //Ports  :  GPE3   GPE2  GPE1    GPE0    
+    //Signal :  IN     IN    IN      IN  
+    //Binary :  00     00  ,  00      00 
+    //rGPECON = 0xaaaaaaaa;       
+    //rGPEUP  = 0xffff;     // The pull up function is disabled GPE[15:0]
+	gpioregs->GPECON = 0xaaaaa800; // For added AC97 setting      
+    gpioregs->GPEUP  = 0xffff;     
+
+     //*** PORT F GROUP
+    //Ports  : GPF7   GPF6   GPF5   GPF4      GPF3     GPF2  GPF1   GPF0
+    //Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0
+    //Setting: Output Output Output Output    EINT3    EINT2 EINT1  EINT0
+    //Binary :  01      01 ,  01     01  ,     10       10  , 10     10
+    gpioregs->GPFCON = 0x55aa;
+    gpioregs->GPFUP  = 0xff;     // The pull up function is disabled GPF[7:0]
+
+    //*** PORT G GROUP
+    //Ports  : GPG15 GPG14 GPG13 GPG12 GPG11    GPG10    GPG9     GPG8     GPG7      GPG6    
+    //Signal : nYPON  YMON nXPON XMON  EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI
+    //Setting: nYPON  YMON nXPON Output EINT19  Output   Output   Output   SPICLK1    SPIMOSI1
+    //Binary :   11    11 , 11    01  , 10      01    ,   01       01   ,    11         11
+    //-----------------------------------------------------------------------------------------
+    //Ports  :    GPG5       GPG4    GPG3    GPG2    GPG1    GPG0    
+    //Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA
+    //Setting:  SPIMISO1  LCD_PWRDN EINT11   nSS0   EINT9    EINT8
+    //Binary :     11         11   ,  10      11  ,  10        10
+    //rGPGCON = 0xff95ffba;
+    gpioregs->GPGCON = 0xfd95ffba;	/* thisway.diy, GPG12-->OUTPUT, GPG9-->OUTPUT for FS2410, as USB Device enable */
+    gpioregs->GPGUP  = 0xffff;    // The pull up function is disabled GPG[15:0]
+	gpioregs->GPGDAT &= ~((1<<9) | (1<<12));	/* disable USB Device, enable later, thisway.diy */
+
+    //*** PORT H GROUP
+    //Ports  :  GPH10    GPH9  GPH8 GPH7  GPH6  GPH5 GPH4 GPH3 GPH2 GPH1  GPH0 
+    //Signal : CLKOUT1 CLKOUT0 UCLK nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
+    //Binary :   10   ,  10     10 , 11    11  , 10   10 , 10   10 , 10    10
+    gpioregs->GPHCON = 0x2afaaa;
+    gpioregs->GPHUP  = 0x7ff;    // The pull up function is disabled GPH[10:0]
+
+	// Added for S3C2440X, DonGo
+	//*** PORT J GROUP
+    //Ports  : GPJ12   GPJ11       GPJ10    GPJ9    GPJ8      GPJ7      GPJ6      GPJ5      GPJ4      GPJ3      GPJ2      GPJ1     GPJ0 
+    //Signal : CAMRESET CAMPCLKOUT CAMHREF CAMVSYNC CAMPCLKIN CAMDAT[7] CAMDAT[6] CAMDAT[5] CAMDAT[4] CAMDAT[3] CAMDAT[2] CAMDAT[1] CAMDAT[0] 
+    //Binary :   10      10       10        10       10        10        10        10       10         10        10        10      10
+    gpioregs->GPJCON = 0x02aaaaaa;
+    gpioregs->GPJUP  = 0x1fff;    // The pull up function is disabled GPH[10:0]
+    
+    //External interrupt will be falling edge triggered. 
+    gpioregs->EXTINT0 = 0x22222222;    // EINT[7:0]
+    gpioregs->EXTINT1 = 0x22222222;    // EINT[15:8]
+    gpioregs->EXTINT2 = 0x22222222;    // EINT[23:16]
+}
+
+
+void usb_init(void)
+{
+	char *mode;
+	int i;
+	U8 key;
+	U32 mpll_val, upll_val, divn_upll=0;
+    extern int bBootFrmNORFlash(void);
+
+    clk_powerregs = S3C24X0_GetBase_CLOCK_POWER();
+
+    usbdevregs = S3C24X0_GetBase_USB_DEVICE();
+    dmaregs = S3C24X0_GetBase_DMAS();
+
+    udelay(100000);
+#if 0	
+	// USB device detection control
+	rGPGCON &= ~(3<<24);
+	rGPGCON |=  (1<<24); // output
+	rGPGUP  |=  (1<<12); // pullup disable
+	rGPGDAT |=  (1<<12); // output	
+#endif
+
+	//ChangeUPllValue(60,4,2);		// 48MHz
+	//for(i=0; i<7; i++);
+	//ChangeClockDivider(13,12);
+	//ChangeMPllValue(97,1,2);		//296Mhz
+
+	isUsbdSetConfiguration=0;
+
+	Isr_Init();
+
+	gpioregs->MISCCR=gpioregs->MISCCR&~(1<<3); // USBD is selected instead of USBH1 
+	gpioregs->MISCCR=gpioregs->MISCCR&~(1<<13); // USB port 1 is enabled.
+
+//
+//  USBD should be initialized first of all.
+//
+
+#if 0
+	UsbdMain(); 
+	MMU_Init(); //MMU should be reconfigured or turned off for the debugger, 
+	//After downloading, MMU should be turned off for the MMU based program,such as WinCE.	
+#else
+//thisway.diy    MMU_EnableICache();  
+	UsbdMain(); 
+    udelay(100000);
+    gpioregs->GPGDAT |= ((1<<9) | (1<<12));  /* enable USB Device, thisway.diy */
+    gpioregs->GPBDAT |= (1<<9);   /* enable USB Device, thisway.diy */
+    gpioregs->GPCDAT |= (1<<5);   /* enable USB Device, thisway.diy */
+#endif
+
+#if USBDMA
+	mode="DMA";
+#else
+	mode="Int";
+#endif
+
+	// CLKOUT0/1 select.
+	//printf("CLKOUT0:MPLL in, CLKOUT1:RTC clock.\n");
+	//Clk0_Enable(0);	// 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
+	//Clk1_Enable(2);	// 0:MPLLout, 1:UPLL, 2:RTC, 3:HCLK, 4:PCLK, 5:DCLK1	
+//	Clk0_Disable();
+//	Clk1_Disable();
+	
+	mpll_val = clk_powerregs->MPLLCON;
+	upll_val = clk_powerregs->UPLLCON; 
+
+
+    if (1) //(!bBootFrmNORFlash())
+    {
+    	printf("UPLLVal [M:%xh,P:%xh,S:%xh]\n", (upll_val&(0xff<<12))>>12,(upll_val&(0x3f<<4))>>4,(upll_val&0x3));
+    	printf("MPLLVal [M:%xh,P:%xh,S:%xh]\n", (mpll_val&(0xff<<12))>>12,(mpll_val&(0x3f<<4))>>4,(mpll_val&0x3));
+    	printf("CLKDIVN:%xh\n", clk_powerregs->CLKDIVN);
+
+    	printf("\n\n");
+    	printf("+---------------------------------------------+\n");
+    	printf("| S3C2440A USB Downloader ver R0.03 2004 Jan  |\n");
+    	printf("+---------------------------------------------+\n");
+    //	printf("FCLK=%4.1fMHz,%s mode\n",FCLK/1000000.,mode); 
+    	printf("USB: IN_ENDPOINT:1 OUT_ENDPOINT:3\n"); 
+    	printf("FORMAT: <ADDR(DATA):4>+<SIZE(n+10):4>+<DATA:n>+<CS:2>\n");
+    	printf("NOTE: Power off/on or press the reset button for 1 sec\n");
+    	printf("      in order to get a valid USB device address.\n");
+    	printf("\n");
+    }
+	download_run=0; //The default menu is the Download & Run mode.
+
+//	WaitDownload();    
+
+}
+
+
+//void WaitDownload(void)
+__u32 usb_receive(char *buf, size_t len, U32 wait)
+{
+    int first=1;
+    U8 tempMem[16];
+    U32 j;
+    unsigned int dwRecvTimeSec = 0;
+	char c;
+
+    dwUSBBufReadPtr = dwUSBBufBase; // USB_BUF_BASE; thiswa.diy, 2006.06.21
+    dwUSBBufWritePtr = dwUSBBufBase; // USB_BUF_BASE; thiswa.diy, 2006.06.21
+    bDMAPending = 0;
+
+    /* add by thisway.diy */
+    tempDownloadAddress = dwUSBBufBase; // USB_BUF_BASE; thiswa.diy, 2006.06.21 // RAM_BASE, changed by thisway.diy for wince, 2006.06.18
+
+    downloadAddress=(U32)tempMem; //_RAM_STARTADDRESS; 
+    downPt=(unsigned char *)downloadAddress;
+	//This address is used for receiving first 8 byte.
+    downloadFileSize=0;
+    
+
+    /*******************************/
+    /*    File download    */
+    /*******************************/
+    if(isUsbdSetConfiguration==0)
+    {
+	    printf("USB host is not connected yet.\n");
+    }
+
+    while(downloadFileSize==0) /* wait until send a file */
+    {
+        if(first==1 && isUsbdSetConfiguration!=0)
+        {
+            printf("USB host is connected. Waiting a download.\n");
+            first=0;
+        }
+		c = awaitkey(1, 0);
+		if ((c & 0x7f) == INTR)
+		{
+			printf("Cancelled by user\n");
+			return 0;
+		}
+    }
+
+    /* add by thisway.diy */
+    if (downloadFileSize - 10 > len)
+    {
+        printf("Length of file is too big : %d > %d\n", downloadFileSize - 10, len);
+        return 0;
+    }
+    
+    Timer_InitEx();
+    Timer_StartEx();
+        
+#if USBDMA    
+
+    intregs->INTMSK&=~(BIT_DMA2);  
+
+    ClearEp3OutPktReady(); 
+    	// indicate the first packit is processed.
+    	// has been delayed for DMA2 cofiguration.
+
+    if(downloadFileSize>EP3_PKT_SIZE)
+    {
+        if(downloadFileSize - EP3_PKT_SIZE<=(0x80000))
+        {
+            /* set the source and length */
+            dwUSBBufWritePtr = downloadAddress + EP3_PKT_SIZE-8;
+            dwWillDMACnt = downloadFileSize - EP3_PKT_SIZE;
+	    }
+      	else
+      	{
+            dwUSBBufWritePtr = downloadAddress + EP3_PKT_SIZE - 8;
+            // dwWillDMACnt = 0x80000 - EP3_PKT_SIZE;
+            
+            /* Changed by thisway.diy, 2006.06.22
+             * We want When the first DMA interrupt happened, 
+             * it has received (0x80000 + 8) bytes data from PC
+             * The format of data PC send out is: <ADDR(DATA):4>+<SIZE(n+10):4>+<DATA:n>+<CS:2>
+             * So, the first 8 bytes isn't the real data we want
+             * We want the dwUSBBufWritePtr is always 0x80000 aligin
+             */
+            dwWillDMACnt = 0x80000 + 8 - EP3_PKT_SIZE;
+    	}
+     	totalDmaCount = 0;
+  	    ConfigEp3DmaMode(dwUSBBufWritePtr, dwWillDMACnt);
+    }
+    else
+    {
+        dwUSBBufWritePtr = downloadAddress + downloadFileSize - 8;
+	    totalDmaCount = downloadFileSize;
+    }
+#endif
+
+    printf("\nNow, Downloading [ADDRESS:%xh,TOTAL:%d]\n",
+    		downloadAddress,downloadFileSize);
+
+    if (wait)
+    {
+        printf("RECEIVED FILE SIZE:%8d",0);
+
+        j = totalDmaCount + 0x10000;
+        while (totalDmaCount != downloadFileSize)
+        {
+            if (totalDmaCount > j)
+            {
+        	    printf("\b\b\b\b\b\b\b\b%8d", j);
+                j = totalDmaCount + 0x10000;
+            }
+        }
+	    printf("\b\b\b\b\b\b\b\b%8d ", totalDmaCount);
+        dwRecvTimeSec = Timer_StopEx();
+        if (dwRecvTimeSec == 0)
+        {
+            dwRecvTimeSec = 1;
+        }
+        printf("(%dKB/S, %dS)\n", (downloadFileSize/dwRecvTimeSec/1024), dwRecvTimeSec);
+    }
+
+    return downloadFileSize - 10;
+
+}
+
+
+void HaltUndef(void)
+{
+	printf("Undefined instruction exception!!!\n");
+	while(1);
+}
+
+void HaltSwi(void)
+{
+	printf("SWI exception!!!\n");
+	while(1);
+}
+
+void HaltPabort(void)
+{
+	printf("Pabort exception!!!\n");
+	while(1);
+}
+
+void HaltDabort(void)
+{
+	printf("Dabort exception!!!\n");
+	while(1);
+}
+
+void Clk0_Enable(int clock_sel)	
+{	// 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
+	gpioregs->MISCCR = gpioregs->MISCCR&~(7<<4) | (clock_sel<<4);
+	gpioregs->GPHCON = gpioregs->GPHCON&~(3<<18) | (2<<18);
+}
+void Clk1_Enable(int clock_sel)
+{	// 0:MPLLout, 1:UPLL, 2:RTC, 3:HCLK, 4:PCLK, 5:DCLK1	
+	gpioregs->MISCCR = gpioregs->MISCCR&~(7<<8) | (clock_sel<<8);
+	gpioregs->GPHCON = gpioregs->GPHCON&~(3<<20) | (2<<20);
+}
+void Clk0_Disable(void)
+{
+	gpioregs->GPHCON = gpioregs->GPHCON&~(3<<18);	// GPH9 Input
+}
+void Clk1_Disable(void)
+{
+	gpioregs->GPHCON = gpioregs->GPHCON&~(3<<20);	// GPH10 Input
+}
+
diff -urN u-boot-1.1.6/drivers/usb/usbinit.h u-boot-1.1.6_jz2440/drivers/usb/usbinit.h
--- u-boot-1.1.6/drivers/usb/usbinit.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbinit.h	2010-11-26 12:54:38.330048254 +0800
@@ -0,0 +1,20 @@
+/****************************************************************
+ NAME: u2440mon.h
+ DESC: 
+ HISTORY:
+ Mar.29.2002:purnnamu: created first
+ ****************************************************************/
+ 
+#ifndef __U241MON_H__
+#define __U241MON_H__
+
+extern volatile unsigned char *downPt;
+extern volatile U32 totalDmaCount;
+extern volatile U32 downloadFileSize;
+extern volatile U32 downloadAddress;
+extern volatile U16 checkSum;
+
+extern int download_run;
+extern U32 tempDownloadAddress;
+
+#endif /*__U241MON_H__*/
diff -urN u-boot-1.1.6/drivers/usb/usblib.c u-boot-1.1.6_jz2440/drivers/usb/usblib.c
--- u-boot-1.1.6/drivers/usb/usblib.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usblib.c	2010-11-26 12:54:38.330048254 +0800
@@ -0,0 +1,241 @@
+/****************************************************************
+ NAME: usblib.c
+ DESC: S3C2440X USB library functions
+ HISTORY:
+ Mar.25.2002:purnnamu: ported for S3C2410X.
+ Mar.27.2002:purnnamu: DMA is enabled.
+ ****************************************************************/
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include "2440usb.h"
+#include "usbmain.h"
+#include "usblib.h"
+#include "usbsetup.h"
+#include "usbmain.h"
+
+extern volatile U32 dwUSBBufReadPtr;
+extern volatile U32 dwUSBBufWritePtr;
+extern volatile U32 dwPreDMACnt;
+extern volatile U32 dwNextDMACnt;
+
+extern S3C24X0_INTERRUPT * intregs;
+extern S3C24X0_USB_DEVICE * usbdevregs;
+extern S3C24X0_DMAS * dmaregs;
+
+void ConfigUsbd(void)
+{
+
+    ReconfigUsbd();
+/*
+    pISR_USBD =(unsigned)IsrUsbd;
+    ClearPending(BIT_USBD);
+    rINTMSK&=~(BIT_USBD);  
+*/   
+    intregs->INTMSK&=~(BIT_USBD);  
+}
+
+
+void ReconfigUsbd(void)
+{
+// *** End point information ***
+//   EP0: control
+//   EP1: bulk in end point
+//   EP2: not used
+//   EP3: bulk out end point
+//   EP4: not used
+    
+    usbdevregs->PWR_REG=PWR_REG_DEFAULT_VALUE;	//disable suspend mode
+
+    usbdevregs->INDEX_REG=0;	
+    usbdevregs->MAXP_REG=FIFO_SIZE_8;   	//EP0 max packit size = 8 
+    usbdevregs->EP0_CSR_IN_CSR1_REG=EP0_SERVICED_OUT_PKT_RDY|EP0_SERVICED_SETUP_END;	
+ 				//EP0:clear OUT_PKT_RDY & SETUP_END
+    usbdevregs->INDEX_REG=1;
+    #if (EP1_PKT_SIZE==32)
+        usbdevregs->MAXP_REG=FIFO_SIZE_32;	//EP1:max packit size = 32
+    #else
+	usbdevregs->MAXP_REG=FIFO_SIZE_64;	//EP1:max packit size = 64
+    #endif	
+    usbdevregs->EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;	
+    usbdevregs->IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK|EPI_BULK; //IN mode, IN_DMA_INT=masked    
+    usbdevregs->OUT_CSR1_REG=EPO_CDT;   	
+    usbdevregs->OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;   	
+
+    usbdevregs->INDEX_REG=2;
+    usbdevregs->MAXP_REG=FIFO_SIZE_64;	//EP2:max packit size = 64
+    usbdevregs->EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
+    usbdevregs->IN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK; //IN mode, IN_DMA_INT=masked    
+    usbdevregs->OUT_CSR1_REG=EPO_CDT;   	
+    usbdevregs->OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;   	
+
+    usbdevregs->INDEX_REG=3;
+    #if (EP3_PKT_SIZE==32)
+        usbdevregs->MAXP_REG=FIFO_SIZE_32;	//EP3:max packit size = 32
+    #else
+	usbdevregs->MAXP_REG=FIFO_SIZE_64;	//EP3:max packit size = 64
+    #endif	
+    usbdevregs->EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
+    usbdevregs->IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT mode, IN_DMA_INT=masked    
+    usbdevregs->OUT_CSR1_REG=EPO_CDT;   	
+    	//clear OUT_PKT_RDY, data_toggle_bit.
+	//The data toggle bit should be cleared when initialization.
+    usbdevregs->OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;   	
+
+    usbdevregs->INDEX_REG=4;
+    usbdevregs->MAXP_REG=FIFO_SIZE_64;	//EP4:max packit size = 64
+    usbdevregs->EP0_CSR_IN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;
+    usbdevregs->IN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK; //OUT mode, IN_DMA_INT=masked    
+    usbdevregs->OUT_CSR1_REG=EPO_CDT;   	
+    	//clear OUT_PKT_RDY, data_toggle_bit.
+	//The data toggle bit should be cleared when initialization.
+    usbdevregs->OUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;   	
+    
+    usbdevregs->EP_INT_REG=EP0_INT|EP1_INT|EP2_INT|EP3_INT|EP4_INT;
+    usbdevregs->USB_INT_REG=RESET_INT|SUSPEND_INT|RESUME_INT; 
+    	//Clear all usbd pending bits
+    	
+    //EP0,1,3 & reset interrupt are enabled
+    usbdevregs->EP_INT_EN_REG=EP0_INT|EP1_INT|EP3_INT;
+    usbdevregs->USB_INT_EN_REG=RESET_INT;
+    ep0State=EP0_STATE_INIT;
+    
+}
+
+
+void RdPktEp0(U8 *buf,int num)
+{
+    int i;
+    	
+    for(i=0;i<num;i++)
+    {
+        buf[i]=(U8)usbdevregs->fifo[0].EP_FIFO_REG;
+    }
+}
+    
+
+void WrPktEp0(U8 *buf,int num)
+{
+    int i;
+    	
+    for(i=0;i<num;i++)
+    {
+        usbdevregs->fifo[0].EP_FIFO_REG=buf[i];	
+    }
+}
+
+
+void WrPktEp1(U8 *buf,int num)
+{
+    int i;
+    	
+    for(i=0;i<num;i++)
+    {
+        usbdevregs->fifo[1].EP_FIFO_REG=buf[i];	
+    }
+}
+
+
+void WrPktEp2(U8 *buf,int num)
+{
+    int i;
+    	
+    for(i=0;i<num;i++)
+    {
+        usbdevregs->fifo[2].EP_FIFO_REG=buf[i];	
+    }
+}
+
+
+void RdPktEp3(U8 *buf,int num)
+{
+    int i;
+    	
+    for(i=0;i<num;i++)
+    {
+        buf[i]=(U8)usbdevregs->fifo[3].EP_FIFO_REG;	
+    }
+}
+
+
+void RdPktEp4(U8 *buf,int num)
+{
+    int i;
+    	
+    for(i=0;i<num;i++)
+    {
+        buf[i]=(U8)usbdevregs->fifo[4].EP_FIFO_REG;	
+    }
+}
+
+
+void ConfigEp3DmaMode(U32 bufAddr,U32 count)
+{
+    int i;
+
+    usbdevregs->INDEX_REG=3;
+    count=count&0xfffff; //transfer size should be <1MB
+    
+    dmaregs->dma[2].DISRCC=(1<<1)|(1<<0);
+    dmaregs->dma[2].DISRC=ADDR_EP3_FIFO; //src=APB,fixed,src=EP3_FIFO
+    dmaregs->dma[2].DIDSTC=(0<<1)|(0<<0);  
+    dmaregs->dma[2].DIDST=bufAddr;       //dst=AHB,increase,dst=bufAddr
+#if USBDMA_DEMAND
+    dmaregs->dma[2].DCON=(count)|(0<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(4<<24)|(1<<23)|(0<<22)|(0<<20); 
+        //demand,requestor=APB,CURR_TC int enable,unit transfer,
+        //single service,src=USBD,H/W request,autoreload,byte,CURR_TC
+#else
+//    rDCON2=(count)|(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(4<<24)|(1<<23)|(0<<22)|(0<<20); 
+    /* changed by thisway.diy to disable autoreload */
+    dmaregs->dma[2].DCON=(count)|(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(4<<24)|(1<<23)|(1<<22)|(0<<20); 
+        //handshake,requestor=APB,CURR_TC int enable,unit transfer,
+        //single service,src=USBD,H/W request,autoreload,byte,CURR_TC
+#endif        
+    dmaregs->dma[2].DMASKTRIG= (1<<1); 
+        //DMA 2 on
+
+    //rEP3_DMA_FIFO=0x40; //not needed for OUT operation. 	
+
+    usbdevregs->ep3.EP_DMA_TTC_L=0xff;
+    usbdevregs->ep3.EP_DMA_TTC_M=0xff;
+    usbdevregs->ep3.EP_DMA_TTC_H=0x0f;
+
+    usbdevregs->OUT_CSR2_REG=usbdevregs->OUT_CSR2_REG|EPO_AUTO_CLR|EPO_OUT_DMA_INT_MASK; 
+    	//AUTO_CLR(OUT_PKT_READY is cleared automatically), interrupt_masking.
+#if USBDMA_DEMAND
+    usbdevregs->ep3.EP_DMA_UNIT=EP3_PKT_SIZE; //DMA transfer unit=64 bytes
+    usbdevregs->ep3.EP_DMA_CON=UDMA_DEMAND_MODE|UDMA_OUT_DMA_RUN|UDMA_DMA_MODE_EN; 
+        // deamnd enable,out_dma_run=run,in_dma_run=stop,DMA mode enable
+#else        
+    usbdevregs->ep3.EP_DMA_UNIT=0x01; //DMA transfer unit=1byte
+    usbdevregs->ep3.EP_DMA_CON=UDMA_OUT_DMA_RUN|UDMA_DMA_MODE_EN;
+        // deamnd disable,out_dma_run=run,in_dma_run=stop,DMA mode enable
+#endif  
+    //wait until DMA_CON is effective.
+    usbdevregs->ep3.EP_DMA_CON;
+    for(i=0;i<10;i++);    	
+
+    /* add by thisway.diy for non-autoreload */
+    dmaregs->dma[3].DMASKTRIG = (1<<1);
+}
+
+
+void ConfigEp3IntMode(void)
+{
+    usbdevregs->INDEX_REG=3;
+    
+    dmaregs->dma[2].DMASKTRIG= (0<<1);  // EP3=DMA ch 2
+        //DMA channel off
+    usbdevregs->OUT_CSR2_REG=usbdevregs->OUT_CSR2_REG&~(EPO_AUTO_CLR/*|EPO_OUT_DMA_INT_MASK*/); 
+    	//AUTOCLEAR off,interrupt_enabled (???)
+    usbdevregs->ep3.EP_DMA_UNIT=1;	
+    usbdevregs->ep3.EP_DMA_CON=0; 
+    	// deamnd disable,out_dma_run=stop,in_dma_run=stop,DMA mode disable
+    //wait until DMA_CON is effective.
+    usbdevregs->ep3.EP_DMA_CON;
+    
+}
diff -urN u-boot-1.1.6/drivers/usb/usblib.h u-boot-1.1.6_jz2440/drivers/usb/usblib.h
--- u-boot-1.1.6/drivers/usb/usblib.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usblib.h	2010-11-26 12:54:38.326057824 +0800
@@ -0,0 +1,29 @@
+/****************************************************************
+ NAME: usblib.h
+ DESC: 
+ HISTORY:
+ Mar.25.2002:purnnamu: ported for S3C2410X.
+ ****************************************************************/
+#ifndef __USBLIB_H__
+#define __USBLIB_H__
+
+#include "2440usb.h"
+#include <def.h>
+
+#define PWR_REG_DEFAULT_VALUE (DISABLE_SUSPEND)
+
+void ConfigUsbd(void);
+void ReconfigUsbd(void);
+
+void RdPktEp0(U8 *buf,int num);
+void WrPktEp0(U8 *buf,int num);
+void WrPktEp1(U8 *buf,int num);
+void WrPktEp2(U8 *buf,int num);
+void RdPktEp3(U8 *buf,int num);
+void RdPktEp4(U8 *buf,int num);
+
+void ConfigEp3IntMode(void);
+void ConfigEp3DmaMode(U32 bufAddr,U32 count);
+
+#endif /*__USBLIB_H__*/
+
diff -urN u-boot-1.1.6/drivers/usb/usbmain.c u-boot-1.1.6_jz2440/drivers/usb/usbmain.c
--- u-boot-1.1.6/drivers/usb/usbmain.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbmain.c	2010-11-26 12:54:38.330048254 +0800
@@ -0,0 +1,169 @@
+/****************************************************************
+ NAME: usbmain.c
+ DESC: endpoint interrupt handler
+       USB init jobs
+ HISTORY:
+ Mar.25.2002:purnnamu: ported for S3C2410X.
+ Mar.27.2002:purnnamu: DMA is enabled.
+ ****************************************************************/
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include "2440usb.h"
+#include "usbmain.h"
+#include "usblib.h"
+#include "usbsetup.h"
+#include "usbout.h"
+#include "usbin.h"
+
+extern S3C24X0_USB_DEVICE * usbdevregs;
+extern S3C24X0_DMAS * dmaregs;
+    
+/**************************
+    Some PrepareEp1Fifo() should be deleted
+ **************************/   
+
+void UsbdMain(void)
+{
+    int i;
+    U8 tmp1;
+    U8 oldTmp1=0xff;
+    
+    //ChangeUPllValue(0x38,2,1);	// UCLK=96Mhz     
+    //ChangeUPllValue(0x38,2,2);	// UCLK=48Mhz     
+    InitDescriptorTable();
+    //ResetUsbd();
+    
+    ConfigUsbd(); 
+
+    //DetectVbus(); //not used in S3C2400X
+
+    PrepareEp1Fifo(); 
+#if 0    
+    while(1)
+    {
+    	if(DbgPrintfLoop())continue;
+    	
+    	Delay(5000);
+    	if((i++%2)==0)Led_Display(0x8);
+    	else Led_Display(0x0);
+    }
+#endif    
+}
+
+
+void IsrUsbd(void)
+{
+    U8 usbdIntpnd,epIntpnd;
+    U8 saveIndexReg=usbdevregs->INDEX_REG;
+    usbdIntpnd=usbdevregs->USB_INT_REG;
+    epIntpnd=usbdevregs->EP_INT_REG;
+    //DbgPrintf( "[INT:EP_I=%x,USBI=%x]",epIntpnd,usbIntpnd );
+
+    if(usbdIntpnd&SUSPEND_INT)
+    {
+    	usbdevregs->USB_INT_REG=SUSPEND_INT;
+    	DbgPrintf( "<SUS]");
+    }
+    if(usbdIntpnd&RESUME_INT)
+    {
+    	usbdevregs->USB_INT_REG=RESUME_INT;
+    	DbgPrintf("<RSM]");
+    }
+    if(usbdIntpnd&RESET_INT)
+    {
+    	DbgPrintf( "<RST]");  
+    	
+    	//ResetUsbd();
+    	ReconfigUsbd();
+
+    	usbdevregs->USB_INT_REG=RESET_INT;  //RESET_INT should be cleared after ResetUsbd().   	
+
+        PrepareEp1Fifo(); 
+    }
+
+    if(epIntpnd&EP0_INT)
+    {
+	    usbdevregs->EP_INT_REG=EP0_INT;  
+    	Ep0Handler();
+    }
+    if(epIntpnd&EP1_INT)
+    {
+    	usbdevregs->EP_INT_REG=EP1_INT;  
+    	Ep1Handler();
+    }
+
+    if(epIntpnd&EP2_INT)
+    {
+    	usbdevregs->EP_INT_REG=EP2_INT;  
+    	DbgPrintf("<2:TBD]");   //not implemented yet	
+    	//Ep2Handler();
+    }
+
+    if(epIntpnd&EP3_INT)
+    {
+    	usbdevregs->EP_INT_REG=EP3_INT;
+    	Ep3Handler();
+    }
+
+    if(epIntpnd&EP4_INT)
+    {
+    	usbdevregs->EP_INT_REG=EP4_INT;
+    	DbgPrintf("<4:TBD]");   //not implemented yet	
+    	//Ep4Handler();
+    }
+
+    ClearPending(BIT_USBD);	 
+    
+    usbdevregs->INDEX_REG=saveIndexReg;
+}
+
+
+
+
+/******************* Consol printf for debug *********************/
+
+#define DBGSTR_LENGTH (0x1000)
+U8 dbgStrFifo[DBGSTR_LENGTH];
+volatile U32 dbgStrRdPt=0;
+volatile U32 dbgStrWrPt=0;
+
+
+
+void _WrDbgStrFifo(U8 c)
+{
+    dbgStrFifo[dbgStrWrPt++]=c;
+    if(dbgStrWrPt==DBGSTR_LENGTH)dbgStrWrPt=0;
+
+}
+
+
+#if 0
+void DbgPrintf(char *fmt,...)
+{
+    int i,slen;
+    va_list ap;
+    char string[256];
+
+    va_start(ap,fmt);
+    vsprintf(string,fmt,ap);
+    
+//    slen=strlen(string);
+    
+//    for(i=0;i<slen;i++)
+//    	_WrDbgStrFifo(string[i]);
+    
+    va_end(ap);
+    puts(string);
+}
+#else
+void DbgPrintf(char *fmt,...)
+{
+}
+#endif
+
+
diff -urN u-boot-1.1.6/drivers/usb/usbmain.h u-boot-1.1.6_jz2440/drivers/usb/usbmain.h
--- u-boot-1.1.6/drivers/usb/usbmain.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbmain.h	2010-11-26 12:54:38.330048254 +0800
@@ -0,0 +1,17 @@
+/****************************************************************
+ NAME: usbmain.h
+ DESC: 
+ HISTORY:
+ Mar.25.2002:purnnamu: reuse the source of S3C2400X u24xmon 
+ ****************************************************************/
+ 
+#ifndef __USBMAIN_H__
+#define __USBMAIN_H__
+
+void UsbdMain(void);
+void IsrUsbd(void);
+
+void DbgPrintf(char *fmt,...);
+
+
+#endif /*__USBMAIN_H__*/
diff -urN u-boot-1.1.6/drivers/usb/usbout.c u-boot-1.1.6_jz2440/drivers/usb/usbout.c
--- u-boot-1.1.6/drivers/usb/usbout.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbout.c	2010-11-26 12:54:38.322059054 +0800
@@ -0,0 +1,246 @@
+/****************************************************************
+ NAME: usbout.c
+ DESC: USB bulk-OUT operation related functions
+ HISTORY:
+ Mar.25.2002:purnnamu: ported for S3C2410X.
+ Mar.27.2002:purnnamu: DMA is enabled.
+ ****************************************************************/
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include <def.h>
+ 
+#include "2440usb.h"
+#include "usbmain.h"
+#include "usb.h"
+#include "usblib.h"
+#include "usbsetup.h"
+#include "usbout.h"
+
+#include "usbinit.h"
+
+extern volatile U32 dwUSBBufReadPtr;
+extern volatile U32 dwUSBBufWritePtr;
+extern volatile U32 dwWillDMACnt;
+extern volatile U32 bDMAPending;
+extern volatile U32 dwUSBBufBase;
+extern volatile U32 dwUSBBufSize;
+
+extern S3C24X0_INTERRUPT * intregs;
+extern S3C24X0_USB_DEVICE * usbdevregs;
+extern S3C24X0_DMAS * dmaregs;
+
+static void PrintEpoPkt(U8 *pt,int cnt);
+static void RdPktEp3_CheckSum(U8 *buf,int num);
+
+
+
+// ===================================================================
+// All following commands will operate in case 
+// - out_csr3 is valid.
+// ===================================================================
+
+ 
+
+#define CLR_EP3_OUT_PKT_READY() usbdevregs->OUT_CSR1_REG= ( out_csr3 &(~ EPO_WR_BITS)\
+					&(~EPO_OUT_PKT_READY) ) 
+#define SET_EP3_SEND_STALL()	usbdevregs->OUT_CSR1_REG= ( out_csr3 & (~EPO_WR_BITS)\
+					| EPO_SEND_STALL) )
+#define CLR_EP3_SENT_STALL()	usbdevregs->OUT_CSR1_REG= ( out_csr3 & (~EPO_WR_BITS)\
+					&(~EPO_SENT_STALL) )
+#define FLUSH_EP3_FIFO() 	usbdevregs->OUT_CSR1_REG= ( out_csr3 & (~EPO_WR_BITS)\
+					|EPO_FIFO_FLUSH) )
+
+// ***************************
+// *** VERY IMPORTANT NOTE ***
+// ***************************
+// Prepare for the packit size constraint!!!
+
+// EP3 = OUT end point. 
+
+U8 ep3Buf[EP3_PKT_SIZE];
+static U8 tempBuf[64+1];
+
+void Ep3Handler(void)
+{
+    U8 out_csr3;
+    int fifoCnt;
+    usbdevregs->INDEX_REG=3;
+
+    out_csr3=usbdevregs->OUT_CSR1_REG;
+    
+    DbgPrintf("<3:%x]",out_csr3);
+
+    if(out_csr3 & EPO_OUT_PKT_READY)
+    {   
+	fifoCnt=usbdevregs->OUT_FIFO_CNT1_REG; 
+#if 0
+	RdPktEp3(ep3Buf,fifoCnt);
+	PrintEpoPkt(ep3Buf,fifoCnt);
+#else
+
+	if(downloadFileSize==0)
+	{
+   	    RdPktEp3((U8 *)downPt,8); 	
+   	    
+   	    if(download_run==0)
+   	    {
+		    downloadAddress=tempDownloadAddress;
+	    }
+	    else
+	    {
+	    	downloadAddress=
+	    		*((U8 *)(downPt+0))+
+			(*((U8 *)(downPt+1))<<8)+
+			(*((U8 *)(downPt+2))<<16)+
+			(*((U8 *)(downPt+3))<<24);
+            
+            dwUSBBufReadPtr = downloadAddress;
+            dwUSBBufWritePtr = downloadAddress;
+	    }
+	    downloadFileSize=
+	    	*((U8 *)(downPt+4))+
+		(*((U8 *)(downPt+5))<<8)+
+		(*((U8 *)(downPt+6))<<16)+
+		(*((U8 *)(downPt+7))<<24);
+	    checkSum=0;
+	    downPt=(U8 *)downloadAddress;
+
+  	    RdPktEp3_CheckSum((U8 *)downPt,fifoCnt-8); //The first 8-bytes are deleted.	    
+  	    downPt+=fifoCnt-8;  
+  	    
+  	#if USBDMA
+     	    //CLR_EP3_OUT_PKT_READY() is not executed. 
+     	    //So, USBD may generate NAK until DMA2 is configured for USB_EP3;
+     	    intregs->INTMSK|=BIT_USBD; //for debug
+      	    return;	
+  	#endif	
+	}
+	else
+	{
+	#if USBDMA    	
+	    printf("<ERROR>");
+	#endif    
+	    RdPktEp3_CheckSum((U8 *)downPt,fifoCnt); 	    
+	    downPt+=fifoCnt;  //fifoCnt=64
+	}
+#endif
+   	CLR_EP3_OUT_PKT_READY();
+#if 0
+       if(((rOUT_CSR1_REG&0x1)==1) && ((rEP_INT_REG & 0x8)==0))
+  		{
+  		fifoCnt=rOUT_FIFO_CNT1_REG; 
+		RdPktEp3_CheckSum((U8 *)downPt,fifoCnt); 	    
+	       downPt+=fifoCnt;  //fifoCnt=64
+	       CLR_EP3_OUT_PKT_READY();
+		}
+#endif
+  	return;
+    }
+
+    
+    //I think that EPO_SENT_STALL will not be set to 1.
+    if(out_csr3 & EPO_SENT_STALL)
+    {   
+   	DbgPrintf("[STALL]");
+   	CLR_EP3_SENT_STALL();
+   	return;
+    }	
+}
+
+
+
+void PrintEpoPkt(U8 *pt,int cnt)
+{
+    int i;
+    DbgPrintf("[BOUT:%d:",cnt);
+    for(i=0;i<cnt;i++)
+    	DbgPrintf("%x,",pt[i]);
+    DbgPrintf("]");
+}
+
+
+void RdPktEp3_CheckSum(U8 *buf,int num)
+{
+    int i;
+    	
+    for(i=0;i<num;i++)
+    {
+        buf[i]=(U8)usbdevregs->fifo[3].EP_FIFO_REG;
+        checkSum+=buf[i];
+    }
+}
+
+
+
+void IsrDma2(void)
+{
+    U8 out_csr3;
+    U32 dwEmptyCnt;
+    U8 saveIndexReg=usbdevregs->INDEX_REG;
+    usbdevregs->INDEX_REG=3;
+    out_csr3=usbdevregs->OUT_CSR1_REG;
+
+    ClearPending(BIT_DMA2);	    
+
+    /* thisway.diy, 2006.06.22 
+     * When the first DMA interrupt happened, it has received max (0x80000 + EP3_PKT_SIZE) bytes data from PC
+     */
+    if (!totalDmaCount) 
+        totalDmaCount = dwWillDMACnt + EP3_PKT_SIZE;
+    else
+        totalDmaCount+=dwWillDMACnt;
+
+//    dwUSBBufWritePtr = ((dwUSBBufWritePtr + dwWillDMACnt - USB_BUF_BASE) % USB_BUF_SIZE) + USB_BUF_BASE; /* thisway.diy, 2006.06.21 */
+    dwUSBBufWritePtr = ((dwUSBBufWritePtr + dwWillDMACnt - dwUSBBufBase) % dwUSBBufSize) + dwUSBBufBase;
+
+    if(totalDmaCount>=downloadFileSize)// is last?
+    {
+    	totalDmaCount=downloadFileSize;
+	
+    	ConfigEp3IntMode();	
+
+    	if(out_csr3& EPO_OUT_PKT_READY)
+    	{
+       	    CLR_EP3_OUT_PKT_READY();
+	    }
+        intregs->INTMSK|=BIT_DMA2;  
+        intregs->INTMSK&=~(BIT_USBD);  
+    }
+    else
+    {
+    	if((totalDmaCount+0x80000)<downloadFileSize)	
+    	{
+    	    dwWillDMACnt = 0x80000;
+	    }
+    	else
+    	{
+    	    dwWillDMACnt = downloadFileSize - totalDmaCount;
+    	}
+
+        // dwEmptyCnt = (dwUSBBufReadPtr - dwUSBBufWritePtr - 1 + USB_BUF_SIZE) % USB_BUF_SIZE; /* thisway.diy, 2006.06.21 */
+        dwEmptyCnt = (dwUSBBufReadPtr - dwUSBBufWritePtr - 1 + dwUSBBufSize) % dwUSBBufSize;
+        if (dwEmptyCnt >= dwWillDMACnt)
+        {
+    	    ConfigEp3DmaMode(dwUSBBufWritePtr, dwWillDMACnt);
+        }
+        else
+        {
+            bDMAPending = 1;
+        }
+    }
+    usbdevregs->INDEX_REG = saveIndexReg;
+}
+
+
+void ClearEp3OutPktReady(void)
+{
+    U8 out_csr3;
+    usbdevregs->INDEX_REG=3;
+    out_csr3=usbdevregs->OUT_CSR1_REG;
+    CLR_EP3_OUT_PKT_READY();
+}
diff -urN u-boot-1.1.6/drivers/usb/usbout.h u-boot-1.1.6_jz2440/drivers/usb/usbout.h
--- u-boot-1.1.6/drivers/usb/usbout.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbout.h	2010-11-26 12:54:38.330048254 +0800
@@ -0,0 +1,17 @@
+/****************************************************************
+ NAME: usbout.h
+ DESC: 
+ HISTORY:
+ Mar.25.2002:purnnamu: reuse the source of S3C2400X u24xmon 
+ ****************************************************************/
+ 
+#ifndef __USBOUT_H__
+#define __USBOUT_H__
+
+void Ep3Handler(void);
+void Ep3HandlerOptimized(void);
+
+void IsrDma2(void);
+void ClearEp3OutPktReady(void);
+
+#endif /*__USBOUT_H__*/
diff -urN u-boot-1.1.6/drivers/usb/usbsetup.c u-boot-1.1.6_jz2440/drivers/usb/usbsetup.c
--- u-boot-1.1.6/drivers/usb/usbsetup.c	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbsetup.c	2010-11-26 12:54:38.322059054 +0800
@@ -0,0 +1,692 @@
+/**************************************************************
+ NAME: usbsetup.c
+ DESC: process the USB setup stage operations.
+ HISTORY:
+ MAR.25.2002:purnnamu: S3C2400X usbsetup.c is ported for S3C2410X.
+ AUG.20.2002:purnnamu: rEP0_CSR should be used instead of rOUT_CSR1_REG for EP0 macros.
+ **************************************************************/
+#include <common.h>
+#if defined(CONFIG_S3C2400)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+#include <def.h>
+
+#include "2440usb.h"
+#include "usbmain.h"
+#include "usb.h"
+#include "usblib.h"
+#include "usbsetup.h"
+
+extern S3C24X0_INTERRUPT * intregs;
+extern S3C24X0_USB_DEVICE * usbdevregs;
+extern S3C24X0_DMAS * dmaregs;
+
+// *** End point information ***
+//   EP0: control
+//   EP1: bulk in end point
+//   EP2: not used
+//   EP3: bulk out end point
+//   EP4: not used
+
+// *** VERY IMPORTANT NOTE ***
+// Every descriptor size of EP0 should be 8n+m(m=1~7).
+// Otherwise, USB will not operate normally because the program
+// doesn't prepare the case that the descriptor size is 8n+0.
+// If the size of a descriptor is 8n, the 0 length packit should be sent. 
+// Special thanks to E.S.Choi for reminding me of this USB specification.
+
+
+// ===================================================================
+// All following commands will operate only in case 
+// - ep0_csr is valid.
+// ===================================================================
+#define CLR_EP0_OUT_PKT_RDY() 		usbdevregs->EP0_CSR_IN_CSR1_REG=( ep0_csr & (~EP0_WR_BITS)| \
+						EP0_SERVICED_OUT_PKT_RDY )	 
+#define CLR_EP0_OUTPKTRDY_DATAEND() 	usbdevregs->EP0_CSR_IN_CSR1_REG=( ep0_csr & (~EP0_WR_BITS)| \
+						(EP0_SERVICED_OUT_PKT_RDY|EP0_DATA_END) )	 
+					
+#define SET_EP0_IN_PKT_RDY() 		usbdevregs->EP0_CSR_IN_CSR1_REG=( ep0_csr & (~EP0_WR_BITS)| \
+						(EP0_IN_PKT_READY) )	 
+#define SET_EP0_INPKTRDY_DATAEND() 	usbdevregs->EP0_CSR_IN_CSR1_REG=( ep0_csr & (~EP0_WR_BITS)| \
+						(EP0_IN_PKT_READY|EP0_DATA_END) )	 
+					
+#define CLR_EP0_SETUP_END() 		usbdevregs->EP0_CSR_IN_CSR1_REG=( ep0_csr & (~EP0_WR_BITS)| \
+						(EP0_SERVICED_SETUP_END) )
+
+#define CLR_EP0_SENT_STALL() 		usbdevregs->EP0_CSR_IN_CSR1_REG=( ep0_csr & (~EP0_WR_BITS)& \
+						(~EP0_SENT_STALL) )
+
+#define FLUSH_EP0_FIFO() 		{while(usbdevregs->OUT_FIFO_CNT1_REG)usbdevregs->fifo[0].EP_FIFO_REG;}
+
+U32 ep0State;
+U32 ep0SubState;
+
+extern volatile int isUsbdSetConfiguration;
+volatile U8 Rwuen;
+volatile U8 Configuration=1;
+volatile U8 AlterSetting;
+volatile U8 Selfpwr=TRUE;
+volatile U8 device_status;
+volatile U8 interface_status;
+volatile U8 endpoint0_status;
+volatile U8 endpoint1_status;
+volatile U8 endpoint3_status;
+
+struct USB_SETUP_DATA descSetup;
+struct USB_DEVICE_DESCRIPTOR descDev;
+struct USB_CONFIGURATION_DESCRIPTOR descConf;
+struct USB_INTERFACE_DESCRIPTOR descIf;
+struct USB_ENDPOINT_DESCRIPTOR descEndpt0;
+struct USB_ENDPOINT_DESCRIPTOR descEndpt1;
+struct USB_CONFIGURATION_SET ConfigSet;
+struct USB_INTERFACE_GET InterfaceGet;
+struct USB_GET_STATUS StatusGet;   //={0,0,0,0,0};
+
+
+static const U8 descStr0[]={
+	4,STRING_TYPE,LANGID_US_L,LANGID_US_H,  //codes representing languages
+    };
+
+static const U8 descStr1[]={  //Manufacturer  
+        (0x14+2),STRING_TYPE, 
+        'S',0x0,'y',0x0,'s',0x0,'t',0x0,'e',0x0,'m',0x0,' ',0x0,'M',0x0,
+        'C',0x0,'U',0x0,
+    };
+    
+static const U8 descStr2[]={  //Product  
+        (0x2a+2),STRING_TYPE, 
+        'S',0x0,'E',0x0,'C',0x0,' ',0x0,'S',0x0,'3',0x0,'C',0x0,'2',0x0,
+        '4',0x0,'1',0x0,'0',0x0,'X',0x0,' ',0x0,'T',0x0,'e',0x0,'s',0x0,
+        't',0x0,' ',0x0,'B',0x0,'/',0x0,'D',0x0
+    };
+
+
+void Ep0Handler(void)
+{
+    static int ep0SubState;
+    int i;
+    U8 ep0_csr;
+
+    usbdevregs->INDEX_REG=0;
+    ep0_csr=usbdevregs->EP0_CSR_IN_CSR1_REG;
+    
+    DbgPrintf("<0:%x]",ep0_csr);
+
+    //DATAEND interrupt(ep0_csr==0x0) will be ignored 
+    //because ep0State==EP0_STATE_INIT when the DATAEND interrupt is issued.
+
+    
+    if(ep0_csr & EP0_SETUP_END)
+    {   
+    	 // Host may end GET_DESCRIPTOR operation without completing the IN data stage.
+    	 // If host does that, SETUP_END bit will be set.
+    	 // OUT_PKT_RDY has to be also cleared because status stage sets OUT_PKT_RDY to 1.
+   	DbgPrintf("[SETUPEND]");
+	CLR_EP0_SETUP_END();
+	if(ep0_csr & EP0_OUT_PKT_READY) 
+	{
+	    FLUSH_EP0_FIFO(); //(???)
+	    	//I think this isn't needed because EP0 flush is done automatically.   
+	    CLR_EP0_OUT_PKT_RDY();
+	}
+	
+	ep0State=EP0_STATE_INIT;
+	return;
+    }	
+
+    //I think that EP0_SENT_STALL will not be set to 1.
+    if(ep0_csr & EP0_SENT_STALL)
+    {   
+   	DbgPrintf("[STALL]");
+   	CLR_EP0_SENT_STALL();
+	if(ep0_csr & EP0_OUT_PKT_READY) 
+	{
+	    CLR_EP0_OUT_PKT_RDY();
+	}
+	
+	ep0State=EP0_STATE_INIT;
+	return;
+    }	
+
+
+
+    if((ep0_csr & EP0_OUT_PKT_READY)) // && (ep0State==EP0_STATE_INIT))
+    {	
+	RdPktEp0((U8 *)&descSetup,EP0_PKT_SIZE);
+
+	PrintEp0Pkt((U8 *)(&descSetup)); //DEBUG
+    
+	switch(descSetup.bRequest)
+    	{
+    	case GET_DESCRIPTOR:
+            switch(descSetup.bValueH)        
+            {
+            case DEVICE_TYPE:
+ 	    	DbgPrintf("[GDD]");
+ 	    	CLR_EP0_OUT_PKT_RDY();
+	    	ep0State=EP0_STATE_GD_DEV_0;	        
+	    	break;	
+	    case CONFIGURATION_TYPE:
+ 	    	DbgPrintf("[GDC]");
+ 	    	CLR_EP0_OUT_PKT_RDY();
+ 	    	if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x9)
+ 	    	  //bLengthH should be used for bLength=0x209 at WIN2K.    	
+	    	   ep0State=EP0_STATE_GD_CFG_0; //for WIN98,WIN2K
+               else	    	    
+  		    ep0State=EP0_STATE_GD_CFG_ONLY_0; //for WIN2K
+	    	break;
+   	    case STRING_TYPE:
+ 	    	DbgPrintf("[GDS]");
+ 	    	CLR_EP0_OUT_PKT_RDY();
+	    	switch(descSetup.bValueL)
+	    	{
+	    	    case 0:
+	    	    	ep0State=EP0_STATE_GD_STR_I0;
+	    	    	break;
+	    	    case 1:
+       	    	    	ep0State=EP0_STATE_GD_STR_I1;
+	    	    	break;
+	    	    case 2:	
+	    	    	ep0State=EP0_STATE_GD_STR_I2;
+	    	    	break;
+	    	    default:
+	    		DbgPrintf("[UE:STRI?]");
+	    		break;
+	    	}
+	    	ep0SubState=0;
+	    	break;
+	    case INTERFACE_TYPE:
+ 	    	DbgPrintf("[GDI]");
+ 	    	CLR_EP0_OUT_PKT_RDY();
+	    	ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98
+	    	break;
+	    case ENDPOINT_TYPE:	    	
+ 	    	DbgPrintf("[GDE]");
+ 	    	CLR_EP0_OUT_PKT_RDY();
+ 	    	switch(descSetup.bValueL&0xf)
+	    	{
+	    	case 0:
+	    	    ep0State=EP0_STATE_GD_EP0_ONLY_0;
+	    	    break;
+	    	case 1:
+       	    	    ep0State=EP0_STATE_GD_EP1_ONLY_0;
+	    	    break;
+	    	default:
+	    	    DbgPrintf("[UE:GDE?]");
+	    	    break;
+	    	}
+	    	break;
+	    default:
+	    	DbgPrintf("[UE:GD?]");
+	    	break;
+	    }	
+    	    break;
+
+    	case SET_ADDRESS:
+            DbgPrintf("[SA:%d]",descSetup.bValueL);
+            usbdevregs->FUNC_ADDR_REG=descSetup.bValueL | 0x80;
+	    CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
+            ep0State=EP0_STATE_INIT;
+            break;
+    	
+	case SET_CONFIGURATION:
+            DbgPrintf("[SC]");
+            ConfigSet.ConfigurationValue=descSetup.bValueL;
+            CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
+            ep0State=EP0_STATE_INIT;
+
+            isUsbdSetConfiguration=1; 
+            break;
+
+    	    //////////////////////// For chapter 9 test ////////////////////
+
+    	  case CLEAR_FEATURE:
+    	  	
+    	  	switch (descSetup.bmRequestType)
+    	  	{
+    	  	  case DEVICE_RECIPIENT:
+    	  	  	if (descSetup.bValueL == 1)
+    	  	  		Rwuen = FALSE;
+    	  	  	
+    	  	  	break;
+
+    	  	  case ENDPOINT_RECIPIENT:
+    	  	  	 if (descSetup.bValueL == 0)
+    	  	  	 {
+	                       if((descSetup.bIndexL & 0x7f) == 0x00){
+	                        StatusGet.Endpoint0= 0;    
+	                       }
+	                       if((descSetup.bIndexL & 0x8f) == 0x81){           // IN  Endpoint 1
+	                         StatusGet.Endpoint1= 0;           
+	                        }
+	                       if((descSetup.bIndexL & 0x8f) == 0x03){          // OUT Endpoint 3
+	                         StatusGet.Endpoint3= 0;      
+	                         }
+                       }
+    	  	  	 
+    	  	  	 break;
+
+    	  	  default:
+    	  	  	break;
+    	  	}
+    	  	CLR_EP0_OUTPKTRDY_DATAEND();
+    	  	ep0State=EP0_STATE_INIT;
+    	  	break;
+
+    	  case GET_CONFIGURATION:
+
+                CLR_EP0_OUT_PKT_RDY();
+	    	  ep0State=EP0_CONFIG_SET;
+    	  	   
+    	         break;
+
+
+    	  case GET_INTERFACE:
+    	  	
+    	  	  CLR_EP0_OUT_PKT_RDY();
+	    	  ep0State=EP0_INTERFACE_GET;
+    	  	  
+    	  	  break;
+
+    	  case GET_STATUS:
+
+    	  	switch(descSetup.bmRequestType)
+    	  	{
+    	  	      case  (0x80):
+
+    	  	 		CLR_EP0_OUT_PKT_RDY();
+    	  	 		StatusGet.Device=((U8)Rwuen<<1)|(U8)Selfpwr;
+    	  	 		ep0State=EP0_GET_STATUS0;
+    	  	 		    	  	 		
+                          break;
+
+                     case  (0x81):
+                           	CLR_EP0_OUT_PKT_RDY();
+    	  	 		StatusGet.Interface=0;
+    	  	 		ep0State=EP0_GET_STATUS1;
+                          break;
+
+                     case  (0x82):
+
+                     	CLR_EP0_OUT_PKT_RDY();
+    	  	 		if((descSetup.bIndexL & 0x7f) == 0x00){
+	                          ep0State=EP0_GET_STATUS2;
+    	  	 		  }
+    	  	 		
+	                       if((descSetup.bIndexL & 0x8f) == 0x81){
+	                          ep0State=EP0_GET_STATUS3;
+	                       }
+	                       
+	                       if((descSetup.bIndexL & 0x8f) == 0x03){
+                                ep0State=EP0_GET_STATUS4;
+	                       }
+                          break;
+
+                      default:
+                          	break;
+    	  	}
+    	  	      
+    	  	break;
+
+
+    	  case SET_DESCRIPTOR:
+    	  	       CLR_EP0_OUTPKTRDY_DATAEND();
+    	  	       ep0State=EP0_STATE_INIT;
+    	  	break;
+
+
+    	  case SET_FEATURE:
+    	  	 
+    	  	switch (descSetup.bmRequestType)
+    	  	{
+    	  	  case DEVICE_RECIPIENT:
+    	  	  	if (descSetup.bValueL == 1)
+    	  	  		Rwuen = TRUE;
+    	  	  	
+    	  	  	break;
+
+    	  	  case ENDPOINT_RECIPIENT:
+    	  	  	 if (descSetup.bValueL == 0)
+    	  	  	 {
+	                       if((descSetup.bIndexL & 0x7f) == 0x00){
+	                        StatusGet.Endpoint0= 1;
+	                       }
+	                       if((descSetup.bIndexL & 0x8f) == 0x81){
+	                         StatusGet.Endpoint1= 1;
+	                       }
+	                       if((descSetup.bIndexL & 0x8f) == 0x03){
+	                         StatusGet.Endpoint3= 1;
+	                       }
+                       }
+    	  	  	break;
+
+    	  	  default:
+    	  	  	break;
+    	  	}
+    	  	CLR_EP0_OUTPKTRDY_DATAEND();
+    	  	ep0State=EP0_STATE_INIT;
+    	  
+    	  	break;
+
+
+    	  case SET_INTERFACE:
+    	  	   InterfaceGet.AlternateSetting= descSetup.bValueL;
+    	  	   CLR_EP0_OUTPKTRDY_DATAEND(); 
+                 ep0State=EP0_STATE_INIT;
+    	  	break;
+
+    	  case SYNCH_FRAME:
+    	  	ep0State=EP0_STATE_INIT;
+    	  	break;
+
+    	  //////////////////////////////////////////////////////////////
+
+  	default:
+	    DbgPrintf("[UE:SETUP=%x]",descSetup.bRequest);
+    	    CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
+	    ep0State=EP0_STATE_INIT;
+	    break;
+    
+        }
+    }
+    
+    switch(ep0State)
+    {	
+	case EP0_STATE_INIT:
+	    break; 
+
+	//=== GET_DESCRIPTOR:DEVICE ===
+    	case EP0_STATE_GD_DEV_0:
+            DbgPrintf("[GDD0]");
+            WrPktEp0((U8 *)&descDev+0,8); //EP0_PKT_SIZE
+            SET_EP0_IN_PKT_RDY();
+            ep0State=EP0_STATE_GD_DEV_1;
+            break;
+            
+    	case EP0_STATE_GD_DEV_1:
+            DbgPrintf("[GDD1]");
+            WrPktEp0((U8 *)&descDev+0x8,8); 
+            SET_EP0_IN_PKT_RDY();
+            
+            ep0State=EP0_STATE_GD_DEV_2;
+            break;
+
+    	case EP0_STATE_GD_DEV_2:
+            DbgPrintf("[GDD2]");
+            WrPktEp0((U8 *)&descDev+0x10,2);   //8+8+2=0x12
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;
+            break;
+    
+
+        //=== GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 ===
+        //Windows98 gets these 4 descriptors all together by issuing only a request.
+        //Windows2000 gets each descriptor seperately.
+    	case EP0_STATE_GD_CFG_0:
+            DbgPrintf("[GDC0]");
+            WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE
+            SET_EP0_IN_PKT_RDY();
+            ep0State=EP0_STATE_GD_CFG_1;
+            break;
+    
+    	case EP0_STATE_GD_CFG_1:
+            DbgPrintf("[GDC1]");
+            WrPktEp0((U8 *)&descConf+8,1); 
+            WrPktEp0((U8 *)&descIf+0,7); 
+            SET_EP0_IN_PKT_RDY();
+            ep0State=EP0_STATE_GD_CFG_2;
+            break;
+
+    	case EP0_STATE_GD_CFG_2:
+            DbgPrintf("[GDC2]");
+            WrPktEp0((U8 *)&descIf+7,2); 
+            WrPktEp0((U8 *)&descEndpt0+0,6); 
+            SET_EP0_IN_PKT_RDY();
+            ep0State=EP0_STATE_GD_CFG_3;
+            break;
+
+    	case EP0_STATE_GD_CFG_3:
+            DbgPrintf("[GDC3]");
+            WrPktEp0((U8 *)&descEndpt0+6,1); 
+            WrPktEp0((U8 *)&descEndpt1+0,7); 
+            SET_EP0_IN_PKT_RDY();
+            ep0State=EP0_STATE_GD_CFG_4;            
+            break;
+
+    	case EP0_STATE_GD_CFG_4:
+            DbgPrintf("[GDC4]");
+             //zero length data packit 
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;            
+            break;
+
+        //=== GET_DESCRIPTOR:CONFIGURATION ONLY===
+    	case EP0_STATE_GD_CFG_ONLY_0:
+            DbgPrintf("[GDCO0]");
+            WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE
+            SET_EP0_IN_PKT_RDY();
+            ep0State=EP0_STATE_GD_CFG_ONLY_1;
+            break;
+    
+    	case EP0_STATE_GD_CFG_ONLY_1:
+            DbgPrintf("[GDCO1]");
+            WrPktEp0((U8 *)&descConf+8,1); 
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;            
+            break;
+
+        //=== GET_DESCRIPTOR:INTERFACE ONLY===
+    	case EP0_STATE_GD_IF_ONLY_0:
+            DbgPrintf("[GDI0]");
+            WrPktEp0((U8 *)&descIf+0,8); 
+            SET_EP0_IN_PKT_RDY();
+            ep0State=EP0_STATE_GD_IF_ONLY_1;
+            break;
+    	case EP0_STATE_GD_IF_ONLY_1:
+            DbgPrintf("[GDI1]");
+            WrPktEp0((U8 *)&descIf+8,1); 
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;            
+            break;
+
+        //=== GET_DESCRIPTOR:ENDPOINT 0 ONLY===
+    	case EP0_STATE_GD_EP0_ONLY_0:
+            DbgPrintf("[GDE00]");
+            WrPktEp0((U8 *)&descEndpt0+0,7); 
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;            
+            break;
+            
+        //=== GET_DESCRIPTOR:ENDPOINT 1 ONLY===
+    	case EP0_STATE_GD_EP1_ONLY_0:
+            DbgPrintf("[GDE10]");
+            WrPktEp0((U8 *)&descEndpt1+0,7); 
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;            
+            break;
+            
+////////////////////////////////////////////
+
+         case EP0_INTERFACE_GET:
+            WrPktEp0((U8 *)&InterfaceGet+0,1);
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;      
+         break;
+
+ 
+        //=== GET_DESCRIPTOR:STRING ===
+
+    	case EP0_STATE_GD_STR_I0:
+            DbgPrintf("[GDS0_0]");
+           WrPktEp0((U8 *)descStr0, 4 );  
+	    SET_EP0_INPKTRDY_DATAEND();
+	    ep0State=EP0_STATE_INIT;     
+	    ep0SubState=0;
+	    break;
+
+	case EP0_STATE_GD_STR_I1:
+            DbgPrintf("[GDS1_%d]",ep0SubState);
+             if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr1) )
+            {
+            	WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); 
+            	SET_EP0_IN_PKT_RDY();
+            	ep0State=EP0_STATE_GD_STR_I1;
+            	ep0SubState++;
+            }
+	    else
+	    {
+	    	WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE),
+	    		 sizeof(descStr1)-(ep0SubState*EP0_PKT_SIZE)); 
+		SET_EP0_INPKTRDY_DATAEND();
+		ep0State=EP0_STATE_INIT;     
+		ep0SubState=0;
+	    }
+	    break;
+
+	case EP0_STATE_GD_STR_I2:
+            DbgPrintf("[GDS2_%d]",ep0SubState);
+             if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr2) )
+            {
+            	WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); 
+            	SET_EP0_IN_PKT_RDY();
+            	ep0State=EP0_STATE_GD_STR_I2;
+            	ep0SubState++;
+            }
+	    else
+	    {
+                DbgPrintf("[E]");
+	    	WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),
+	    		 sizeof(descStr2)-(ep0SubState*EP0_PKT_SIZE)); 
+		SET_EP0_INPKTRDY_DATAEND();
+		ep0State=EP0_STATE_INIT;     
+		ep0SubState=0;
+	    }
+	    break;
+
+	 case EP0_CONFIG_SET:
+	 	WrPktEp0((U8 *)&ConfigSet+0,1); 
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;      
+            break;
+
+        case EP0_GET_STATUS0:
+	     WrPktEp0((U8 *)&StatusGet+0,1);
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;      
+         break;
+
+         case EP0_GET_STATUS1:
+	     WrPktEp0((U8 *)&StatusGet+1,1);
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;      
+         break;
+
+         case EP0_GET_STATUS2:
+	     WrPktEp0((U8 *)&StatusGet+2,1);
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;      
+         break;
+
+         case EP0_GET_STATUS3:
+	     WrPktEp0((U8 *)&StatusGet+3,1);
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;      
+         break;
+
+         case EP0_GET_STATUS4:
+	     WrPktEp0((U8 *)&StatusGet+4,1);
+            SET_EP0_INPKTRDY_DATAEND();
+            ep0State=EP0_STATE_INIT;      
+         break;
+
+         
+	 	
+     	default:
+	    DbgPrintf("UE:G?D");
+
+     	    break;
+    }
+}
+
+
+   
+    
+void PrintEp0Pkt(U8 *pt)
+{
+    int i;
+    DbgPrintf("[RCV:");
+    for(i=0;i<EP0_PKT_SIZE;i++)
+        DbgPrintf("%x,",pt[i]);
+    DbgPrintf("]");
+}
+
+
+
+
+void InitDescriptorTable(void)
+{	
+    //Standard device descriptor
+    descDev.bLength=0x12;	//EP0_DEV_DESC_SIZE=0x12 bytes    
+    descDev.bDescriptorType=DEVICE_TYPE;         
+    descDev.bcdUSBL=0x10;
+    descDev.bcdUSBH=0x01; 	//Ver 1.10
+    descDev.bDeviceClass=0xFF; //0x0          
+    descDev.bDeviceSubClass=0x0;          
+    descDev.bDeviceProtocol=0x0;          
+    descDev.bMaxPacketSize0=0x8;         
+    descDev.idVendorL=0x45;
+    descDev.idVendorH=0x53;
+    descDev.idProductL=0x34;
+    descDev.idProductH=0x12;
+    descDev.bcdDeviceL=0x00;
+    descDev.bcdDeviceH=0x01;
+    descDev.iManufacturer=0x1;  //index of string descriptor
+    descDev.iProduct=0x2;	//index of string descriptor 
+    descDev.iSerialNumber=0x0;
+    descDev.bNumConfigurations=0x1;
+
+    //Standard configuration descriptor
+    descConf.bLength=0x9;    
+    descConf.bDescriptorType=CONFIGURATION_TYPE;         
+    descConf.wTotalLengthL=0x20; //<cfg desc>+<if desc>+<endp0 desc>+<endp1 desc>
+    descConf.wTotalLengthH=0;
+    descConf.bNumInterfaces=1;
+//dbg    descConf.bConfigurationValue=2;  //why 2? There's no reason.
+    descConf.bConfigurationValue=1;  
+    descConf.iConfiguration=0;
+    descConf.bmAttributes=CONF_ATTR_DEFAULT|CONF_ATTR_SELFPOWERED;  //bus powered only.
+    descConf.maxPower=25; //draws 50mA current from the USB bus.          
+
+    //Standard interface descriptor
+    descIf.bLength=0x9;    
+    descIf.bDescriptorType=INTERFACE_TYPE;         
+    descIf.bInterfaceNumber=0x0;
+    descIf.bAlternateSetting=0x0; //?
+    descIf.bNumEndpoints=2;	//# of endpoints except EP0
+    descIf.bInterfaceClass=0xff; //0x0 ?
+    descIf.bInterfaceSubClass=0x0;  
+    descIf.bInterfaceProtocol=0x0;
+    descIf.iInterface=0x0;
+
+    //Standard endpoint0 descriptor
+    descEndpt0.bLength=0x7;    
+    descEndpt0.bDescriptorType=ENDPOINT_TYPE;         
+    descEndpt0.bEndpointAddress=1|EP_ADDR_IN;   // 2400Xendpoint 1 is IN endpoint.
+    descEndpt0.bmAttributes=EP_ATTR_BULK;
+    descEndpt0.wMaxPacketSizeL=EP1_PKT_SIZE; //64
+    descEndpt0.wMaxPacketSizeH=0x0;
+    descEndpt0.bInterval=0x0; //not used
+
+    //Standard endpoint1 descriptor
+    descEndpt1.bLength=0x7;    
+    descEndpt1.bDescriptorType=ENDPOINT_TYPE;         
+    descEndpt1.bEndpointAddress=3|EP_ADDR_OUT;   // 2400X endpoint 3 is OUT endpoint.
+    descEndpt1.bmAttributes=EP_ATTR_BULK;
+    descEndpt1.wMaxPacketSizeL=EP3_PKT_SIZE; //64
+    descEndpt1.wMaxPacketSizeH=0x0;
+    descEndpt1.bInterval=0x0; //not used 
+}
+
diff -urN u-boot-1.1.6/drivers/usb/usbsetup.h u-boot-1.1.6_jz2440/drivers/usb/usbsetup.h
--- u-boot-1.1.6/drivers/usb/usbsetup.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/drivers/usb/usbsetup.h	2010-11-26 12:54:38.330048254 +0800
@@ -0,0 +1,55 @@
+/****************************************************************
+ NAME: usbsetup.h
+ DESC: usb setup
+ HISTORY:
+ Mar.25.2002:purnnamu: reuse the source of S3C2400X u24xmon 
+ ****************************************************************/
+ 
+#ifndef __USBSETUP_H__
+#define __USBSETUP_H__
+
+void Ep0Handler(void);
+void InitDescriptorTable(void);
+void PrintEp0Pkt(U8 *pt);
+
+
+#define EP0_STATE_INIT 			(0)  
+
+//NOTE: The ep0State value in a same group should be added by 1.
+#define EP0_STATE_GD_DEV_0	 	(10)  //10-10=0 
+#define EP0_STATE_GD_DEV_1 		(11)  //11-10=1
+#define EP0_STATE_GD_DEV_2 		(12)  //12-10=2
+
+#define EP0_STATE_GD_CFG_0	 	(20)
+#define EP0_STATE_GD_CFG_1 		(21)
+#define EP0_STATE_GD_CFG_2 		(22)
+#define EP0_STATE_GD_CFG_3 		(23)
+#define EP0_STATE_GD_CFG_4 		(24)
+
+#define EP0_STATE_GD_CFG_ONLY_0		(40)
+#define EP0_STATE_GD_CFG_ONLY_1		(41)
+#define EP0_STATE_GD_IF_ONLY_0 		(42)
+#define EP0_STATE_GD_IF_ONLY_1 		(43)
+#define EP0_STATE_GD_EP0_ONLY_0		(44)
+#define EP0_STATE_GD_EP1_ONLY_0		(45)
+#define EP0_INTERFACE_GET                        (46)
+
+
+#define EP0_STATE_GD_STR_I0	 	(30)  
+#define EP0_STATE_GD_STR_I1	 	(31)  
+#define EP0_STATE_GD_STR_I2	 	(32)  
+
+#define EP0_CONFIG_SET    (33)
+#define EP0_GET_STATUS0  (35)
+#define EP0_GET_STATUS1  (36)
+#define EP0_GET_STATUS2  (37)
+#define EP0_GET_STATUS3  (38)
+#define EP0_GET_STATUS4  (39)
+
+
+
+
+extern U32 ep0State;
+
+
+#endif /*__USBSETUP_H__*/
diff -urN u-boot-1.1.6/include/asm-arm/mach-types.h u-boot-1.1.6_jz2440/include/asm-arm/mach-types.h
--- u-boot-1.1.6/include/asm-arm/mach-types.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/asm-arm/mach-types.h	2010-11-26 12:54:38.046150949 +0800
@@ -737,6 +737,7 @@
 #define MACH_TYPE_CB3RUFC              726
 #define MACH_TYPE_MP2USB               727
 #define MACH_TYPE_PDNB3               1002
+#define MACH_TYPE_SMDKS3C2440          782 
 
 #ifdef CONFIG_ARCH_EBSA110
 # ifdef machine_arch_type
diff -urN u-boot-1.1.6/include/asm-arm/types.h u-boot-1.1.6_jz2440/include/asm-arm/types.h
--- u-boot-1.1.6/include/asm-arm/types.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/asm-arm/types.h	2010-11-26 12:54:38.042056315 +0800
@@ -45,6 +45,9 @@
 
 typedef u32 dma_addr_t;
 
+typedef unsigned long phys_addr_t;
+typedef unsigned long phys_size_t;
+
 #endif /* __KERNEL__ */
 
 #endif
diff -urN u-boot-1.1.6/include/asm-arm/u-boot-arm.h u-boot-1.1.6_jz2440/include/asm-arm/u-boot-arm.h
--- u-boot-1.1.6/include/asm-arm/u-boot-arm.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/asm-arm/u-boot-arm.h	2010-11-26 12:54:38.038158106 +0800
@@ -35,6 +35,9 @@
 extern ulong _bss_end;		/* BSS end */
 extern ulong IRQ_STACK_START;	/* top of IRQ stack */
 extern ulong FIQ_STACK_START;	/* top of FIQ stack */
+extern ulong FREE_RAM_END;	/* top of free ram */
+extern ulong FREE_RAM_SIZE;	/* size of free ram */
+extern ulong PreLoadedONRAM;
 
 /* cpu/.../cpu.c */
 int	cpu_init(void);
diff -urN u-boot-1.1.6/include/configs/100ask24x0.h u-boot-1.1.6_jz2440/include/configs/100ask24x0.h
--- u-boot-1.1.6/include/configs/100ask24x0.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/include/configs/100ask24x0.h	2010-11-26 12:54:37.958266315 +0800
@@ -0,0 +1,237 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ * Gary Jennejohn <gj@denx.de>
+ * David Mueller <d.mueller@elsoft.ch>
+ *
+ * Configuation settings for the SAMSUNG SMDK2410 board.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_ARM920T		1	/* This is an ARM920T Core	*/
+#define	CONFIG_S3C2410		1	/* in a SAMSUNG S3C2410 SoC     */
+#define CONFIG_SMDK2410		1	/* on a SAMSUNG SMDK2410 Board  */
+
+/* input clock of PLL */
+#define CONFIG_SYS_CLK_FREQ	12000000 /* the SMDK2410 has 12MHz input clock */
+//#define CONFIG_SYS_CLK_FREQ	16934400 /* the SMDK2410 has 12MHz input clock */
+
+
+#define USE_920T_MMU		1
+
+#define CONFIG_USB_DEVICE   1
+
+#ifdef CONFIG_USB_DEVICE
+#define CONFIG_USE_IRQ		1
+#endif
+
+#define CONFIG_JFFS2_CMDLINE 1
+#define CONFIG_JFFS2_NAND    1
+
+#define MTDIDS_DEFAULT "nand0=nandflash0"
+#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," \
+                            "128k(params)," \
+                            "2m(kernel)," \
+                            "-(root)"
+
+/*
+ * Size of malloc() pool
+ */
+#define CFG_MALLOC_LEN		(CFG_ENV_SIZE + 128*1024)
+#define CFG_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
+
+/*
+ * Hardware drivers
+ */
+#if 1
+#if 0
+#define CONFIG_DRIVER_CS8900	1	/* we have a CS8900 on-board */
+#define CS8900_BASE		0x19000300
+#define CS8900_BUS16		1 /* the Linux driver does accesses as shorts */
+#endif
+
+#if !defined(CONFIG_DRIVER_CS8900)
+#define CONFIG_DRIVER_DM9000		1
+#define CONFIG_DM9000_USE_16BIT 	1
+#define CONFIG_DM9000_BASE			0x20000000
+#define DM9000_IO					0x20000000  
+#define DM9000_DATA					0x20000004
+#endif
+#endif
+/*
+ * select serial console configuration
+ */
+#define CONFIG_SERIAL1          1	/* we use SERIAL 1 on SMDK2410 */
+
+/************************************************************
+ * RTC
+ ************************************************************/
+#define	CONFIG_RTC_S3C24X0	1
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_BAUDRATE		115200
+
+/* for tag(s) to transfer message to kernel, www.100ask.net */
+#define CONFIG_SETUP_MEMORY_TAGS    1
+#define CONFIG_CMDLINE_TAG          1
+
+/***********************************************************
+ * Command definition
+ ***********************************************************/
+#define CONFIG_COMMANDS \
+                        ((CONFIG_CMD_DFL | \
+                        CFG_CMD_CACHE    | \
+                    /* Start: by www.100ask.net */ \
+                        CFG_CMD_PING     | \
+                        CFG_CMD_JFFS2    | \
+                        CFG_CMD_NAND     | \
+                    /* End: by www.100ask.net */ \
+                        /*CFG_CMD_EEPROM |*/ \
+                        /*CFG_CMD_I2C    |*/ \
+                        /*CFG_CMD_USB    |*/ \
+                        CFG_CMD_REGINFO  | \
+                        CFG_CMD_DATE     | \
+                        CFG_CMD_ELF))
+
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#define CONFIG_BOOTDELAY	2
+#define CONFIG_BOOTARGS    	"noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
+#define CONFIG_ETHADDR	    08:00:3e:26:0a:5b
+#define CONFIG_NETMASK      255.255.255.0
+#define CONFIG_IPADDR		192.168.7.17
+#define CONFIG_SERVERIP		192.168.7.11
+/*#define CONFIG_BOOTFILE	"elinos-lart" */
+#define CONFIG_BOOTCOMMAND	"nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0"
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE	115200		/* speed to run kgdb serial port */
+/* what's this ? it's not used anywhere */
+#define CONFIG_KGDB_SER_INDEX	1		/* which serial port to use */
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define	CFG_LONGHELP				/* undef to save memory		*/
+#define	CFG_PROMPT		"OpenJTAG> "	/* Monitor Command Prompt	*/
+#define	CFG_CBSIZE		256		/* Console I/O Buffer Size	*/
+#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define	CFG_MAXARGS		16		/* max number of command args	*/
+#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CFG_MEMTEST_START	0x30000000	/* memtest works on	*/
+#define CFG_MEMTEST_END		0x33F00000	/* 63 MB in DRAM	*/
+
+#undef  CFG_CLKS_IN_HZ		/* everything, incl board info, in Hz */
+
+#define	CFG_LOAD_ADDR		0x33000000	/* default load address	*/
+
+/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */
+/* it to wrap 100 times (total 1562500) to get 1 sec. */
+#define	CFG_HZ			1562500
+
+/* valid baudrates */
+#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE	(128*1024)	/* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ	(4*1024)	/* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ	(4*1024)	/* FIQ stack */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS	1	   /* we have 1 bank of DRAM */
+#define PHYS_SDRAM_1		0x30000000 /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE	0x04000000 /* 64 MB */
+
+#define PHYS_FLASH_1		0x00000000 /* Flash Bank #1 */
+
+#define CFG_FLASH_BASE		PHYS_FLASH_1
+#define CFG_MONITOR_BASE	PHYS_FLASH_1
+
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+
+#if 0
+#define CONFIG_AMD_LV400	1	/* uncomment this if you have a LV400 flash */
+#endif
+//#define CONFIG_AMD_LV800	1	/* uncomment this if you have a LV800 flash */
+
+#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks */
+#ifdef CONFIG_AMD_LV800
+#define PHYS_FLASH_SIZE		0x00100000 /* 1MB */
+#define CFG_MAX_FLASH_SECT	(19)	/* max number of sectors on one chip */
+#define CFG_ENV_ADDR		(CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
+#endif
+#ifdef CONFIG_AMD_LV400
+#define PHYS_FLASH_SIZE		0x00080000 /* 512KB */
+#define CFG_MAX_FLASH_SECT	(11)	/* max number of sectors on one chip */
+#define CFG_ENV_ADDR		(CFG_FLASH_BASE + 0x070000) /* addr of environment */
+#endif
+
+#define CFG_FLASH_CFI				1
+#define CFG_FLASH_CFI_DRIVER 		1
+#define CFG_FLASH_USE_BUFFER_WRITE	1
+#define CONFIG_FLASH_CFI_LEGACY		1
+
+#ifdef CFG_FLASH_CFI_DRIVER
+#define CFG_MAX_FLASH_SECT	 512   /* max number of sectors on one chip */
+#define CFG_FLASH_CFI_WIDTH  0x02  /* FLASH_CFI_16BIT */
+#endif
+
+/* timeout values are in ticks */
+#define CFG_FLASH_ERASE_TOUT	(5*CFG_HZ) /* Timeout for Flash Erase */
+#define CFG_FLASH_WRITE_TOUT	(5*CFG_HZ) /* Timeout for Flash Write */
+
+//#define	CFG_ENV_IS_IN_FLASH	1
+#define CFG_ENV_IS_IN_NAND  1
+#define CFG_ENV_OFFSET      0x40000
+#define CFG_ENV_SIZE		0x20000	/* Total Size of Environment Sector */
+
+/*-----------------------------------------------------------------------
+ * NAND flash settings
+ */
+#define CFG_NAND_BASE           0
+#define CFG_MAX_NAND_DEVICE     1
+#define NAND_MAX_CHIPS          1
+
+#endif	/* __CONFIG_H */
diff -urN u-boot-1.1.6/include/configs/SBC8560.h u-boot-1.1.6_jz2440/include/configs/SBC8560.h
--- u-boot-1.1.6/include/configs/SBC8560.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/configs/SBC8560.h	1970-01-01 07:00:00.000000000 +0700
@@ -1,410 +0,0 @@
-/*
- * (C) Copyright 2002,2003 Motorola,Inc.
- * Xianghua Xiao <X.Xiao@motorola.com>
- *
- * (C) Copyright 2004 Wind River Systems Inc <www.windriver.com>.
- * Added support for Wind River SBC8560 board
- *
- * 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
- */
-
-/* mpc8560ads board configuration file */
-/* please refer to doc/README.mpc85xx for more info */
-/* make sure you change the MAC address and other network params first,
- * search for CONFIG_ETHADDR,CONFIG_SERVERIP,etc in this file
- */
-
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-#if XXX
-#define DEBUG		      /* General debug */
-#define ET_DEBUG
-#endif
-#define TSEC_DEBUG
-
-/* High Level Configuration Options */
-#define CONFIG_BOOKE		1	/* BOOKE			*/
-#define CONFIG_E500		1	/* BOOKE e500 family		*/
-#define CONFIG_MPC85xx		1	/* MPC8540/MPC8560		*/
-#define CONFIG_MPC85xx_REV1	1	/* MPC85xx Rev 1.0 chip		*/
-
-
-#define CONFIG_CPM2		1	/* has CPM2 */
-#define CONFIG_SBC8560      	1   	/* configuration for SBC8560 board */
-
-#define CONFIG_MPC8560ADS	1	/* MPC8560ADS board specific (supplement)	*/
-
-#define CONFIG_TSEC_ENET		/* tsec ethernet support	*/
-#undef	CONFIG_PCI			/* pci ethernet support		*/
-#undef  CONFIG_ETHER_ON_FCC		/* cpm FCC ethernet support	*/
-
-
-#define CONFIG_ENV_OVERWRITE
-
-/* Using Localbus SDRAM to emulate flash before we can program the flash,
- * normally you need a flash-boot image(u-boot.bin), if so undef this.
- */
-#undef CONFIG_RAM_AS_FLASH
-
-#if defined(CONFIG_PCI_66)		/* some PCI card is 33Mhz only	*/
-  #define CONFIG_SYS_CLK_FREQ	66000000/* sysclk for MPC85xx		*/
-#else
-  #define CONFIG_SYS_CLK_FREQ	33000000/* most pci cards are 33Mhz	*/
-#endif
-
-/* below can be toggled for performance analysis. otherwise use default */
-#define CONFIG_L2_CACHE			    /* toggle L2 cache		*/
-#undef	CONFIG_BTB			    /* toggle branch predition	*/
-#undef	CONFIG_ADDR_STREAMING		    /* toggle addr streaming	*/
-
-#define CONFIG_BOARD_EARLY_INIT_F 1	    /* Call board_early_init_f	*/
-
-#undef	CFG_DRAM_TEST			    /* memory test, takes time	*/
-#define CFG_MEMTEST_START	0x00200000  /* memtest region */
-#define CFG_MEMTEST_END		0x00400000
-
-#if (defined(CONFIG_PCI) && defined(CONFIG_TSEC_ENET) || \
-     defined(CONFIG_PCI) && defined(CONFIG_ETHER_ON_FCC) || \
-     defined(CONFIG_TSEC_ENET) && defined(CONFIG_ETHER_ON_FCC))
-#error "You can only use ONE of PCI Ethernet Card or TSEC Ethernet or CPM FCC."
-#endif
-
-/*
- * Base addresses -- Note these are effective addresses where the
- * actual resources get mapped (not physical addresses)
- */
-#define CFG_CCSRBAR_DEFAULT	0xff700000	/* CCSRBAR Default	*/
-
-#if XXX
-  #define CFG_CCSRBAR		0xfdf00000	/* relocated CCSRBAR	*/
-#else
-  #define CFG_CCSRBAR		0xff700000	/* default CCSRBAR	*/
-#endif
-#define CFG_IMMR		CFG_CCSRBAR	/* PQII uses CFG_IMMR	*/
-
-#define CFG_DDR_SDRAM_BASE	0x00000000	/* DDR is system memory	 */
-#define CFG_SDRAM_BASE		CFG_DDR_SDRAM_BASE
-#define CFG_SDRAM_SIZE		512		/* DDR is 512MB */
-#define SPD_EEPROM_ADDRESS	0x55		/*  DDR DIMM */
-
-#undef  CONFIG_DDR_ECC				/* only for ECC DDR module	*/
-#undef  CONFIG_SPD_EEPROM			/* Use SPD EEPROM for DDR setup */
-
-#if defined(CONFIG_MPC85xx_REV1)
-  #define CONFIG_DDR_DLL			/* possible DLL fix needed	*/
-#endif
-
-#undef CONFIG_CLOCKS_IN_MHZ
-
-#if defined(CONFIG_RAM_AS_FLASH)
-  #define CFG_LBC_SDRAM_BASE	0xfc000000	/* Localbus SDRAM */
-  #define CFG_FLASH_BASE	0xf8000000      /* start of FLASH 8M  */
-  #define CFG_BR0_PRELIM	0xf8000801      /* port size 8bit */
-  #define CFG_OR0_PRELIM	0xf8000ff7	/* 8MB Flash		*/
-#else /* Boot from real Flash */
-  #define CFG_LBC_SDRAM_BASE	0xf8000000	/* Localbus SDRAM */
-  #define CFG_FLASH_BASE	0xff800000      /* start of FLASH 8M    */
-  #define CFG_BR0_PRELIM	0xff800801      /* port size 8bit      */
-  #define CFG_OR0_PRELIM	0xff800ff7	/* 8MB Flash		*/
-#endif
-#define CFG_LBC_SDRAM_SIZE	64		/* LBC SDRAM is 64MB	*/
-
-/* local bus definitions */
-#define CFG_BR1_PRELIM		0xe4001801	/* 64M, 32-bit flash */
-#define CFG_OR1_PRELIM		0xfc000ff7
-
-#define CFG_BR2_PRELIM		0x00000000	/* CS2 not used */
-#define CFG_OR2_PRELIM		0x00000000
-
-#define CFG_BR3_PRELIM		0xf0001861	/* 64MB localbus SDRAM	*/
-#define CFG_OR3_PRELIM		0xfc000cc1
-
-#if defined(CONFIG_RAM_AS_FLASH)
-  #define CFG_BR4_PRELIM	0xf4001861	/* 64M localbus SDRAM */
-#else
-  #define CFG_BR4_PRELIM	0xf8001861	/* 64M localbus SDRAM */
-#endif
-#define CFG_OR4_PRELIM		0xfc000cc1
-
-#define CFG_BR5_PRELIM		0xfc000801	/* 16M CS5 misc devices */
-#if 1
-  #define CFG_OR5_PRELIM	0xff000ff7
-#else
-  #define CFG_OR5_PRELIM	0xff0000f0
-#endif
-
-#define CFG_BR6_PRELIM		0xe0001801	/* 64M, 32-bit flash */
-#define CFG_OR6_PRELIM		0xfc000ff7
-#define CFG_LBC_LCRR		0x00030002	/* local bus freq	*/
-#define CFG_LBC_LBCR		0x00000000
-#define CFG_LBC_LSRT		0x20000000
-#define CFG_LBC_MRTPR		0x20000000
-#define CFG_LBC_LSDMR_1		0x2861b723
-#define CFG_LBC_LSDMR_2		0x0861b723
-#define CFG_LBC_LSDMR_3		0x0861b723
-#define CFG_LBC_LSDMR_4		0x1861b723
-#define CFG_LBC_LSDMR_5		0x4061b723
-
-/* just hijack the MOT BCSR def for SBC8560 misc devices */
-#define CFG_BCSR		((CFG_BR5_PRELIM & 0xff000000)|0x00400000)
-/* the size of CS5 needs to be >= 16M for TLB and LAW setups */
-
-#define CONFIG_L1_INIT_RAM
-#define CFG_INIT_RAM_LOCK	1
-#define CFG_INIT_RAM_ADDR	0x70000000	/* Initial RAM address	*/
-#define CFG_INIT_RAM_END	0x4000		/* End of used area in RAM */
-
-#define CFG_GBL_DATA_SIZE	128		/* num bytes initial data */
-#define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
-#define CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET
-
-#define CFG_MONITOR_LEN		(256 * 1024)	/* Reserve 256 kB for Mon */
-#define CFG_MALLOC_LEN		(128 * 1024)	/* Reserved for malloc */
-
-/* Serial Port */
-#undef  CONFIG_CONS_ON_SCC			/* define if console on SCC */
-#undef	CONFIG_CONS_NONE			/* define if console on something else */
-
-#define CONFIG_CONS_INDEX     1
-#undef	CONFIG_SERIAL_SOFTWARE_FIFO
-#define CFG_NS16550
-#define CFG_NS16550_SERIAL
-#define CFG_NS16550_REG_SIZE	1
-#define CFG_NS16550_CLK		1843200 /* get_bus_freq(0) */
-#define CONFIG_BAUDRATE		9600
-
-#define CFG_BAUDRATE_TABLE  \
-	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400,115200}
-
-#define CFG_NS16550_COM1	((CFG_BR5_PRELIM & 0xff000000)+0x00700000)
-#define CFG_NS16550_COM2	((CFG_BR5_PRELIM & 0xff000000)+0x00800000)
-
-/* Use the HUSH parser */
-#define CFG_HUSH_PARSER
-#ifdef	CFG_HUSH_PARSER
-#define CFG_PROMPT_HUSH_PS2 "> "
-#endif
-
-/* I2C */
-#define	 CONFIG_HARD_I2C		/* I2C with hardware support*/
-#undef	CONFIG_SOFT_I2C			/* I2C bit-banged */
-#define CFG_I2C_SPEED		400000	/* I2C speed and slave address	*/
-#define CFG_I2C_SLAVE		0x7F
-#define CFG_I2C_NOPROBES	{0x69}	/* Don't probe these addrs */
-
-#define CFG_PCI_MEM_BASE	0xC0000000
-#define CFG_PCI_MEM_PHYS	0xC0000000
-#define CFG_PCI_MEM_SIZE	0x10000000
-
-#if defined(CONFIG_TSEC_ENET)		/* TSEC Ethernet port */
-
-#  define CONFIG_NET_MULTI	1
-#  define CONFIG_MII		1	/* MII PHY management		*/
-#  define CONFIG_MPC85xx_TSEC1
-#  define CONFIG_MPC85xx_TSEC1_NAME	"TSEC0"
-#  define TSEC1_PHY_ADDR	25
-#  define TSEC1_PHYIDX		0
-/* Options are: TSEC0 */
-#  define CONFIG_ETHPRIME		"TSEC0"
-
-
-#elif defined(CONFIG_ETHER_ON_FCC)	/* CPM FCC Ethernet */
-
-  #undef  CONFIG_ETHER_NONE		/* define if ether on something else */
-  #define CONFIG_ETHER_ON_FCC2		/* cpm FCC ethernet support	*/
-  #define CONFIG_ETHER_INDEX	2	/* which channel for ether  */
-
-  #if (CONFIG_ETHER_INDEX == 2)
-    /*
-     * - Rx-CLK is CLK13
-     * - Tx-CLK is CLK14
-     * - Select bus for bd/buffers
-     * - Full duplex
-     */
-    #define CFG_CMXFCR_MASK	(CMXFCR_FC2 | CMXFCR_RF2CS_MSK | CMXFCR_TF2CS_MSK)
-    #define CFG_CMXFCR_VALUE	(CMXFCR_RF2CS_CLK13 | CMXFCR_TF2CS_CLK14)
-    #define CFG_CPMFCR_RAMTYPE	0
-    #define CFG_FCC_PSMR	(FCC_PSMR_FDE)
-
-  #elif (CONFIG_ETHER_INDEX == 3)
-    /* need more definitions here for FE3 */
-  #endif				/* CONFIG_ETHER_INDEX */
-
-  #define CONFIG_MII			/* MII PHY management */
-  #define CONFIG_BITBANGMII		/* bit-bang MII PHY management	*/
-  /*
-   * GPIO pins used for bit-banged MII communications
-   */
-  #define MDIO_PORT	2		/* Port C */
-  #define MDIO_ACTIVE	(iop->pdir |=  0x00400000)
-  #define MDIO_TRISTATE	(iop->pdir &= ~0x00400000)
-  #define MDIO_READ	((iop->pdat &  0x00400000) != 0)
-
-  #define MDIO(bit)	if(bit) iop->pdat |=  0x00400000; \
-			else	iop->pdat &= ~0x00400000
-
-  #define MDC(bit)	if(bit) iop->pdat |=  0x00200000; \
-			else	iop->pdat &= ~0x00200000
-
-  #define MIIDELAY	udelay(1)
-
-#endif
-
-/*-----------------------------------------------------------------------
- * FLASH and environment organization
- */
-
-#define CFG_FLASH_CFI		1	/* Flash is CFI conformant		*/
-#define CFG_FLASH_CFI_DRIVER	1	/* Use the common driver		*/
-#if 0
-#define CFG_FLASH_USE_BUFFER_WRITE 1    /* use buffered writes (20x faster)     */
-#define CFG_FLASH_PROTECTION		/* use hardware protection		*/
-#endif
-#define CFG_MAX_FLASH_SECT	64	/* max number of sectors on one chip	*/
-#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks		*/
-
-#undef	CFG_FLASH_CHECKSUM
-#define CFG_FLASH_ERASE_TOUT	200000		/* Timeout for Flash Erase (in ms)	*/
-#define CFG_FLASH_WRITE_TOUT	50000		/* Timeout for Flash Write (in ms)	*/
-
-#define CFG_MONITOR_BASE	TEXT_BASE	/* start of monitor	*/
-
-#if 0
-/* XXX This doesn't work and I don't want to fix it */
-#if (CFG_MONITOR_BASE < CFG_FLASH_BASE)
-  #define CFG_RAMBOOT
-#else
-  #undef  CFG_RAMBOOT
-#endif
-#endif
-
-/* Environment */
-#if !defined(CFG_RAMBOOT)
-  #if defined(CONFIG_RAM_AS_FLASH)
-    #define CFG_ENV_IS_NOWHERE
-    #define CFG_ENV_ADDR	(CFG_FLASH_BASE + 0x100000)
-    #define CFG_ENV_SIZE	0x2000
-  #else
-    #define CFG_ENV_IS_IN_FLASH	1
-    #define CFG_ENV_SECT_SIZE	0x20000 /* 128K(one sector) for env */
-    #define CFG_ENV_ADDR	(CFG_MONITOR_BASE - CFG_ENV_SECT_SIZE)
-    #define CFG_ENV_SIZE	0x2000 /* CFG_ENV_SECT_SIZE */
-  #endif
-#else
-  #define CFG_NO_FLASH		1	/* Flash is not usable now	*/
-  #define CFG_ENV_IS_NOWHERE	1	/* Store ENV in memory only	*/
-  #define CFG_ENV_ADDR		(CFG_MONITOR_BASE - 0x1000)
-  #define CFG_ENV_SIZE		0x2000
-#endif
-
-#define CONFIG_BOOTARGS "root=/dev/nfs rw nfsroot=192.168.0.251:/tftpboot ip=192.168.0.105:192.168.0.251::255.255.255.0:sbc8560:eth0:off console=ttyS0,9600"
-/*#define CONFIG_BOOTARGS      "root=/dev/ram rw console=ttyS0,115200"*/
-#define CONFIG_BOOTCOMMAND	"bootm 0xff800000 0xffa00000"
-#define CONFIG_BOOTDELAY	5	/* -1 disable autoboot */
-
-#define CONFIG_LOADS_ECHO	1	/* echo on for serial download	*/
-#define CFG_LOADS_BAUD_CHANGE	1	/* allow baudrate change	*/
-
-#if defined(CFG_RAMBOOT) || defined(CONFIG_RAM_AS_FLASH)
-  #if defined(CONFIG_PCI)
-    #define  CONFIG_COMMANDS	((CONFIG_CMD_DFL | CFG_CMD_PCI | \
-				CFG_CMD_PING | CFG_CMD_I2C) & \
-				 ~(CFG_CMD_ENV | \
-				  CFG_CMD_LOADS ))
-  #elif (defined(CONFIG_TSEC_ENET) || defined(CONFIG_ETHER_ON_FCC))
-    #define  CONFIG_COMMANDS	((CONFIG_CMD_DFL | CFG_CMD_MII | \
-				CFG_CMD_PING | CFG_CMD_I2C) & \
-				~(CFG_CMD_ENV))
-  #endif
-#else
-  #if defined(CONFIG_PCI)
-    #define  CONFIG_COMMANDS	(CONFIG_CMD_DFL | CFG_CMD_PCI | \
-				CFG_CMD_PING | CFG_CMD_I2C)
-  #elif (defined(CONFIG_TSEC_ENET) || defined(CONFIG_ETHER_ON_FCC))
-    #define  CONFIG_COMMANDS	(CONFIG_CMD_DFL | CFG_CMD_MII | \
-				CFG_CMD_PING | CFG_CMD_I2C)
-  #endif
-#endif
-
-#include <cmd_confdefs.h>
-
-#undef CONFIG_WATCHDOG			/* watchdog disabled		*/
-
-/*
- * Miscellaneous configurable options
- */
-#define CFG_LONGHELP			/* undef to save memory		*/
-#define CFG_PROMPT	"SBC8560=> " /* Monitor Command Prompt	*/
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
-  #define CFG_CBSIZE	1024		/* Console I/O Buffer Size	*/
-#else
-  #define CFG_CBSIZE	256		/* Console I/O Buffer Size	*/
-#endif
-#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
-#define CFG_MAXARGS	16		/* max number of command args	*/
-#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size	*/
-#define CFG_LOAD_ADDR	0x1000000	/* default load address */
-#define CFG_HZ		1000		/* decrementer freq: 1 ms ticks */
-
-/*
- * For booting Linux, the board info and command line data
- * have to be in the first 8 MB of memory, since this is
- * the maximum mapped by the Linux kernel during initialization.
- */
-#define CFG_BOOTMAPSZ		(8 << 20) /* Initial Memory map for Linux */
-
-/* Cache Configuration */
-#define CFG_DCACHE_SIZE		32768
-#define CFG_CACHELINE_SIZE	32
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
-  #define CFG_CACHELINE_SHIFT	5	/* log base 2 of the above value */
-#endif
-
-/*
- * Internal Definitions
- *
- * Boot Flags
- */
-#define BOOTFLAG_COLD	0x01		/* Normal Power-On: Boot from FLASH */
-#define BOOTFLAG_WARM	0x02		/* Software reboot		*/
-
-#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
-  #define CONFIG_KGDB_BAUDRATE	230400	/* speed to run kgdb serial port */
-  #define CONFIG_KGDB_SER_INDEX	2	/* which serial port to use */
-#endif
-
-/*Note: change below for your network setting!!! */
-#if defined(CONFIG_TSEC_ENET) || defined(CONFIG_ETHER_ON_FCC)
-#  define CONFIG_ETHADDR	00:vv:ww:xx:yy:8a
-#  define CONFIG_HAS_ETH1
-#  define CONFIG_ETH1ADDR	00:vv:ww:xx:yy:8b
-#  define CONFIG_HAS_ETH2
-#  define CONFIG_ETH2ADDR	00:vv:ww:xx:yy:8c
-#endif
-
-#define CONFIG_SERVERIP		YourServerIP
-#define CONFIG_IPADDR		YourTargetIP
-#define CONFIG_GATEWAYIP	YourGatewayIP
-#define CONFIG_NETMASK		255.255.255.0
-#define CONFIG_HOSTNAME		SBC8560
-#define CONFIG_ROOTPATH		YourRootPath
-#define CONFIG_BOOTFILE		YourImageName
-
-#endif	/* __CONFIG_H */
diff -urN u-boot-1.1.6/include/def.h u-boot-1.1.6_jz2440/include/def.h
--- u-boot-1.1.6/include/def.h	1970-01-01 07:00:00.000000000 +0700
+++ u-boot-1.1.6_jz2440/include/def.h	2010-11-26 12:54:38.010185389 +0800
@@ -0,0 +1,74 @@
+//
+// Copyright (c) Microsoft Corporation.  All rights reserved.
+//
+//
+// Use of this source code is subject to the terms of the Microsoft end-user
+// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
+// If you did not accept the terms of the EULA, you are not authorized to use
+// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
+// install media.
+//
+/*++
+THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+PARTICULAR PURPOSE.
+--*/
+#ifndef __DEF_H__
+#define __DEF_H__
+#ifndef U32
+#define U32 unsigned int
+#endif
+
+#ifndef U16
+#define U16 unsigned short
+#endif
+
+#ifndef S32
+#define S32 int
+#endif
+
+#ifndef S16
+#define S16 short int
+#endif
+
+#ifndef U8
+#define U8  unsigned char
+#endif
+
+#ifndef S8
+#define	S8  char
+#endif
+
+typedef unsigned char BOOL;
+typedef unsigned char UCHAR;
+typedef UCHAR *PUCHAR;
+typedef unsigned long DWORD;
+typedef DWORD *PDWORD;
+typedef unsigned long LDWORD;
+typedef DWORD *LPDWORD;
+typedef unsigned char   BYTE;
+typedef unsigned short  WORD;
+
+typedef unsigned long ULONG;
+typedef ULONG *PULONG;
+typedef unsigned short USHORT;
+typedef USHORT *PUSHORT;
+
+typedef BYTE *LPBYTE;
+
+typedef void *PVOID;
+
+typedef  char*          LPSTR;
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define TRUE 	1   
+#define FALSE 	0
+
+#endif /*__DEF_H__*/
+
+
diff -urN u-boot-1.1.6/include/flash.h u-boot-1.1.6_jz2440/include/flash.h
--- u-boot-1.1.6/include/flash.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/flash.h	2010-11-26 12:54:37.882083977 +0800
@@ -43,9 +43,18 @@
 	ulong	write_tout;		/* maximum write timeout		*/
 	ulong	buffer_write_tout;	/* maximum buffer write timeout		*/
 	ushort	vendor;			/* the primary vendor id		*/
-	ushort	cmd_reset;		/* Vendor specific reset command	*/
+	ushort	cmd_reset;		/* vendor specific reset command	*/
 	ushort	interface;		/* used for x8/x16 adjustments		*/
 	ushort	legacy_unlock;		/* support Intel legacy (un)locking	*/
+	uchar	manufacturer_id;	/* manufacturer id			*/
+	ushort	device_id;		/* device id				*/
+	ushort	device_id2;		/* extended device id			*/
+	ushort	ext_addr;		/* extended query table address		*/
+	ushort	cfi_version;		/* cfi version				*/
+	ushort	cfi_offset;		/* offset for cfi query			*/
+	ulong   addr_unlock1;		/* unlock address 1 for AMD flash roms  */
+	ulong   addr_unlock2;		/* unlock address 2 for AMD flash roms  */
+	const char *name;		/* human-readable name	                */
 #endif
 } flash_info_t;
 
@@ -71,6 +80,7 @@
 #define FLASH_CFI_X8		0x00
 #define FLASH_CFI_X16		0x01
 #define FLASH_CFI_X8X16		0x02
+#define FLASH_CFI_X16X32	0x05
 
 /* convert between bit value and numeric value */
 #define CFI_FLASH_SHIFT_WIDTH	3
@@ -95,6 +105,13 @@
 extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int offset, int len);
 #endif	/* CFG_FLASH_PROTECTION */
 
+#ifdef CONFIG_FLASH_CFI_LEGACY
+extern ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info);
+extern int jedec_flash_match(flash_info_t *info, ulong base);
+#define CFI_CMDSET_AMD_LEGACY		0xFFF0
+#endif
+
+
 /*-----------------------------------------------------------------------
  * return codes from flash_write():
  */
@@ -113,6 +130,11 @@
  */
 #define FLAG_PROTECT_SET	0x01
 #define FLAG_PROTECT_CLEAR	0x02
+#define	FLAG_PROTECT_INVALID	0x03
+/*-----------------------------------------------------------------------
+ * Set Environment according to label:
+ */
+#define	FLAG_SETENV		0x80
 
 /*-----------------------------------------------------------------------
  * Device IDs
@@ -246,6 +268,8 @@
 #define STM_ID_x800AB	0x005B005B	/* M29W800AB ID (8M = 512K x 16 )	*/
 #define STM_ID_29W320DT 0x22CA22CA	/* M29W320DT ID (32 M, top boot sector) */
 #define STM_ID_29W320DB 0x22CB22CB	/* M29W320DB ID (32 M, bottom boot sect)	*/
+#define STM_ID_29W320ET 0x22562256	/* M29W320ET ID (32 M, top boot sector) */
+#define STM_ID_29W320EB 0x22572257	/* M29W320EB ID (32 M, bottom boot sect)*/
 #define STM_ID_29W040B	0x00E300E3	/* M29W040B ID (4M = 512K x 8)	*/
 #define FLASH_PSD4256GV 0x00E9		/* PSD4256 Flash and CPLD combination	*/
 
@@ -298,6 +322,7 @@
 
 #define TOSH_ID_FVT160	0xC2		/* TC58FVT160 ID (16 M, top )		*/
 #define TOSH_ID_FVB160	0x43		/* TC58FVT160 ID (16 M, bottom )	*/
+#define PHILIPS_LPC2292 0x0401FF13  /* LPC2292 internal FLASH			*/
 
 /*-----------------------------------------------------------------------
  * Internal FLASH identification codes
@@ -439,6 +464,7 @@
 #define FLASH_MAN_MT	0x00400000
 #define FLASH_MAN_SHARP 0x00500000
 #define FLASH_MAN_ATM	0x00600000
+#define FLASH_MAN_CFI	0x01000000
 
 
 #define FLASH_TYPEMASK	0x0000FFFF	/* extract FLASH type	information	*/
diff -urN u-boot-1.1.6/include/nand.h u-boot-1.1.6_jz2440/include/nand.h
--- u-boot-1.1.6/include/nand.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/nand.h	2010-11-26 12:54:38.062126185 +0800
@@ -78,6 +78,14 @@
 	int pad;		/* pad to page size */
 	int blockalign;		/* 1|2|4 set multiple of eraseblocks
 				 * to align to */
+    int skipfirstblk;   /* if true, skip the first good block,  
+                         * set true when write the yaffs image, 
+                         * add by www.100ask.net
+                         */                    
+    int nocheckbadblk;  /* if true, don't check bad blockes,
+                         * use them as good blockes
+                         * add by www.100ask.net
+                         */                    
 };
 
 typedef struct nand_write_options nand_write_options_t;
@@ -88,6 +96,11 @@
 	ulong offset;		/* start address in NAND */
 	int quiet;		/* don't display progress messages */
 	int readoob;		/* put oob data in image */
+	int noecc;		/* read without ecc */
+    int nocheckbadblk;  /* if true, don't check bad blockes,
+                         * use them as good blockes
+                         * add by www.100ask.net
+                         */                    
 };
 
 typedef struct nand_read_options nand_read_options_t;
diff -urN u-boot-1.1.6/include/s3c2410.h u-boot-1.1.6_jz2440/include/s3c2410.h
--- u-boot-1.1.6/include/s3c2410.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/s3c2410.h	2010-11-26 12:54:37.994099919 +0800
@@ -22,7 +22,7 @@
  */
 
 /************************************************
- * NAME	    : s3c2410.h
+ * NAME     : s3c2410.h
  * Version  : 31.3.2003
  *
  * Based on S3C2410X User's manual Rev 1.1
@@ -31,38 +31,38 @@
 #ifndef __S3C2410_H__
 #define __S3C2410_H__
 
-#define S3C24X0_UART_CHANNELS	3
-#define S3C24X0_SPI_CHANNELS	2
+#define S3C24X0_UART_CHANNELS   3
+#define S3C24X0_SPI_CHANNELS    2
 
 /* S3C2410 only supports 512 Byte HW ECC */
-#define S3C2410_ECCSIZE		512
-#define S3C2410_ECCBYTES	3
+#define S3C2410_ECCSIZE     512
+#define S3C2410_ECCBYTES    3
 
 typedef enum {
-	S3C24X0_UART0,
-	S3C24X0_UART1,
-	S3C24X0_UART2
+    S3C24X0_UART0,
+    S3C24X0_UART1,
+    S3C24X0_UART2
 } S3C24X0_UARTS_NR;
 
 /* S3C2410 device base addresses */
-#define S3C24X0_MEMCTL_BASE		0x48000000
-#define S3C24X0_USB_HOST_BASE		0x49000000
-#define S3C24X0_INTERRUPT_BASE		0x4A000000
-#define S3C24X0_DMA_BASE		0x4B000000
-#define S3C24X0_CLOCK_POWER_BASE	0x4C000000
-#define S3C24X0_LCD_BASE		0x4D000000
-#define S3C2410_NAND_BASE		0x4E000000
-#define S3C24X0_UART_BASE		0x50000000
-#define S3C24X0_TIMER_BASE		0x51000000
-#define S3C24X0_USB_DEVICE_BASE		0x52000140
-#define S3C24X0_WATCHDOG_BASE		0x53000000
-#define S3C24X0_I2C_BASE		0x54000000
-#define S3C24X0_I2S_BASE		0x55000000
-#define S3C24X0_GPIO_BASE		0x56000000
-#define S3C24X0_RTC_BASE		0x57000000
-#define S3C2410_ADC_BASE		0x58000000
-#define S3C24X0_SPI_BASE		0x59000000
-#define S3C2410_SDI_BASE		0x5A000000
+#define S3C24X0_MEMCTL_BASE     0x48000000
+#define S3C24X0_USB_HOST_BASE       0x49000000
+#define S3C24X0_INTERRUPT_BASE      0x4A000000
+#define S3C24X0_DMA_BASE        0x4B000000
+#define S3C24X0_CLOCK_POWER_BASE    0x4C000000
+#define S3C24X0_LCD_BASE        0x4D000000
+#define S3C2410_NAND_BASE       0x4E000000
+#define S3C24X0_UART_BASE       0x50000000
+#define S3C24X0_TIMER_BASE      0x51000000
+#define S3C24X0_USB_DEVICE_BASE     0x52000140
+#define S3C24X0_WATCHDOG_BASE       0x53000000
+#define S3C24X0_I2C_BASE        0x54000000
+#define S3C24X0_I2S_BASE        0x55000000
+#define S3C24X0_GPIO_BASE       0x56000000
+#define S3C24X0_RTC_BASE        0x57000000
+#define S3C2410_ADC_BASE        0x58000000
+#define S3C24X0_SPI_BASE        0x59000000
+#define S3C2410_SDI_BASE        0x5A000000
 
 
 /* include common stuff */
@@ -71,130 +71,172 @@
 
 static inline S3C24X0_MEMCTL * const S3C24X0_GetBase_MEMCTL(void)
 {
-	return (S3C24X0_MEMCTL * const)S3C24X0_MEMCTL_BASE;
+    return (S3C24X0_MEMCTL * const)S3C24X0_MEMCTL_BASE;
 }
 static inline S3C24X0_USB_HOST * const S3C24X0_GetBase_USB_HOST(void)
 {
-	return (S3C24X0_USB_HOST * const)S3C24X0_USB_HOST_BASE;
+    return (S3C24X0_USB_HOST * const)S3C24X0_USB_HOST_BASE;
 }
 static inline S3C24X0_INTERRUPT * const S3C24X0_GetBase_INTERRUPT(void)
 {
-	return (S3C24X0_INTERRUPT * const)S3C24X0_INTERRUPT_BASE;
+    return (S3C24X0_INTERRUPT * const)S3C24X0_INTERRUPT_BASE;
 }
 static inline S3C24X0_DMAS * const S3C24X0_GetBase_DMAS(void)
 {
-	return (S3C24X0_DMAS * const)S3C24X0_DMA_BASE;
+    return (S3C24X0_DMAS * const)S3C24X0_DMA_BASE;
 }
 static inline S3C24X0_CLOCK_POWER * const S3C24X0_GetBase_CLOCK_POWER(void)
 {
-	return (S3C24X0_CLOCK_POWER * const)S3C24X0_CLOCK_POWER_BASE;
+    return (S3C24X0_CLOCK_POWER * const)S3C24X0_CLOCK_POWER_BASE;
 }
 static inline S3C24X0_LCD * const S3C24X0_GetBase_LCD(void)
 {
-	return (S3C24X0_LCD * const)S3C24X0_LCD_BASE;
+    return (S3C24X0_LCD * const)S3C24X0_LCD_BASE;
 }
 static inline S3C2410_NAND * const S3C2410_GetBase_NAND(void)
 {
-	return (S3C2410_NAND * const)S3C2410_NAND_BASE;
+    return (S3C2410_NAND * const)S3C2410_NAND_BASE;
+}
+
+/* for s3c2440, www.100ask.net */
+static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
+{
+    return (S3C2440_NAND * const)S3C2410_NAND_BASE;
 }
 static inline S3C24X0_UART * const S3C24X0_GetBase_UART(S3C24X0_UARTS_NR nr)
 {
-	return (S3C24X0_UART * const)(S3C24X0_UART_BASE + (nr * 0x4000));
+    return (S3C24X0_UART * const)(S3C24X0_UART_BASE + (nr * 0x4000));
 }
 static inline S3C24X0_TIMERS * const S3C24X0_GetBase_TIMERS(void)
 {
-	return (S3C24X0_TIMERS * const)S3C24X0_TIMER_BASE;
+    return (S3C24X0_TIMERS * const)S3C24X0_TIMER_BASE;
 }
 static inline S3C24X0_USB_DEVICE * const S3C24X0_GetBase_USB_DEVICE(void)
 {
-	return (S3C24X0_USB_DEVICE * const)S3C24X0_USB_DEVICE_BASE;
+    return (S3C24X0_USB_DEVICE * const)S3C24X0_USB_DEVICE_BASE;
 }
 static inline S3C24X0_WATCHDOG * const S3C24X0_GetBase_WATCHDOG(void)
 {
-	return (S3C24X0_WATCHDOG * const)S3C24X0_WATCHDOG_BASE;
+    return (S3C24X0_WATCHDOG * const)S3C24X0_WATCHDOG_BASE;
 }
 static inline S3C24X0_I2C * const S3C24X0_GetBase_I2C(void)
 {
-	return (S3C24X0_I2C * const)S3C24X0_I2C_BASE;
+    return (S3C24X0_I2C * const)S3C24X0_I2C_BASE;
 }
 static inline S3C24X0_I2S * const S3C24X0_GetBase_I2S(void)
 {
-	return (S3C24X0_I2S * const)S3C24X0_I2S_BASE;
+    return (S3C24X0_I2S * const)S3C24X0_I2S_BASE;
 }
 static inline S3C24X0_GPIO * const S3C24X0_GetBase_GPIO(void)
 {
-	return (S3C24X0_GPIO * const)S3C24X0_GPIO_BASE;
+    return (S3C24X0_GPIO * const)S3C24X0_GPIO_BASE;
 }
 static inline S3C24X0_RTC * const S3C24X0_GetBase_RTC(void)
 {
-	return (S3C24X0_RTC * const)S3C24X0_RTC_BASE;
+    return (S3C24X0_RTC * const)S3C24X0_RTC_BASE;
 }
 static inline S3C2410_ADC * const S3C2410_GetBase_ADC(void)
 {
-	return (S3C2410_ADC * const)S3C2410_ADC_BASE;
+    return (S3C2410_ADC * const)S3C2410_ADC_BASE;
 }
 static inline S3C24X0_SPI * const S3C24X0_GetBase_SPI(void)
 {
-	return (S3C24X0_SPI * const)S3C24X0_SPI_BASE;
+    return (S3C24X0_SPI * const)S3C24X0_SPI_BASE;
 }
 static inline S3C2410_SDI * const S3C2410_GetBase_SDI(void)
 {
-	return (S3C2410_SDI * const)S3C2410_SDI_BASE;
+    return (S3C2410_SDI * const)S3C2410_SDI_BASE;
 }
 
+/* add by thisway.diy */             
+#define _ISR_STARTADDRESS   ((unsigned)isr_handle_array)
+
+#define ISR_EINT0_OFT     0
+#define ISR_EINT1_OFT     1
+#define ISR_EINT2_OFT     2
+#define ISR_EINT3_OFT     3
+#define ISR_EINT4_7_OFT   4
+#define ISR_EINT8_23_OFT  5
+#define ISR_NOTUSED6_OFT  6
+#define ISR_BAT_FLT_OFT   7
+#define ISR_TICK_OFT      8
+#define ISR_WDT_OFT       9
+#define ISR_TIMER0_OFT    10
+#define ISR_TIMER1_OFT    11
+#define ISR_TIMER2_OFT    12
+#define ISR_TIMER3_OFT    13
+#define ISR_TIMER4_OFT    14
+#define ISR_UART2_OFT     15
+#define ISR_LCD_OFT       16
+#define ISR_DMA0_OFT      17
+#define ISR_DMA1_OFT      18
+#define ISR_DMA2_OFT      19
+#define ISR_DMA3_OFT      20
+#define ISR_SDI_OFT       21
+#define ISR_SPI0_OFT      22
+#define ISR_UART1_OFT     23
+#define ISR_NOTUSED24_OFT 24
+#define ISR_USBD_OFT      25
+#define ISR_USBH_OFT      26
+#define ISR_IIC_OFT       27
+#define ISR_UART0_OFT     28
+#define ISR_SPI1_OFT      29
+#define ISR_RTC_OFT       30
+#define ISR_ADC_OFT       31
 
 /* ISR */
-#define pISR_RESET		(*(unsigned *)(_ISR_STARTADDRESS+0x0))
-#define pISR_UNDEF		(*(unsigned *)(_ISR_STARTADDRESS+0x4))
-#define pISR_SWI		(*(unsigned *)(_ISR_STARTADDRESS+0x8))
-#define pISR_PABORT		(*(unsigned *)(_ISR_STARTADDRESS+0xC))
-#define pISR_DABORT		(*(unsigned *)(_ISR_STARTADDRESS+0x10))
-#define pISR_RESERVED		(*(unsigned *)(_ISR_STARTADDRESS+0x14))
-#define pISR_IRQ		(*(unsigned *)(_ISR_STARTADDRESS+0x18))
-#define pISR_FIQ		(*(unsigned *)(_ISR_STARTADDRESS+0x1C))
-
-#define pISR_EINT0		(*(unsigned *)(_ISR_STARTADDRESS+0x20))
-#define pISR_EINT1		(*(unsigned *)(_ISR_STARTADDRESS+0x24))
-#define pISR_EINT2		(*(unsigned *)(_ISR_STARTADDRESS+0x28))
-#define pISR_EINT3		(*(unsigned *)(_ISR_STARTADDRESS+0x2C))
-#define pISR_EINT4_7		(*(unsigned *)(_ISR_STARTADDRESS+0x30))
-#define pISR_EINT8_23		(*(unsigned *)(_ISR_STARTADDRESS+0x34))
-#define pISR_BAT_FLT		(*(unsigned *)(_ISR_STARTADDRESS+0x3C))
-#define pISR_TICK		(*(unsigned *)(_ISR_STARTADDRESS+0x40))
-#define pISR_WDT		(*(unsigned *)(_ISR_STARTADDRESS+0x44))
-#define pISR_TIMER0		(*(unsigned *)(_ISR_STARTADDRESS+0x48))
-#define pISR_TIMER1		(*(unsigned *)(_ISR_STARTADDRESS+0x4C))
-#define pISR_TIMER2		(*(unsigned *)(_ISR_STARTADDRESS+0x50))
-#define pISR_TIMER3		(*(unsigned *)(_ISR_STARTADDRESS+0x54))
-#define pISR_TIMER4		(*(unsigned *)(_ISR_STARTADDRESS+0x58))
-#define pISR_UART2		(*(unsigned *)(_ISR_STARTADDRESS+0x5C))
-#define pISR_NOTUSED		(*(unsigned *)(_ISR_STARTADDRESS+0x60))
-#define pISR_DMA0		(*(unsigned *)(_ISR_STARTADDRESS+0x64))
-#define pISR_DMA1		(*(unsigned *)(_ISR_STARTADDRESS+0x68))
-#define pISR_DMA2		(*(unsigned *)(_ISR_STARTADDRESS+0x6C))
-#define pISR_DMA3		(*(unsigned *)(_ISR_STARTADDRESS+0x70))
-#define pISR_SDI		(*(unsigned *)(_ISR_STARTADDRESS+0x74))
-#define pISR_SPI0		(*(unsigned *)(_ISR_STARTADDRESS+0x78))
-#define pISR_UART1		(*(unsigned *)(_ISR_STARTADDRESS+0x7C))
-#define pISR_USBD		(*(unsigned *)(_ISR_STARTADDRESS+0x84))
-#define pISR_USBH		(*(unsigned *)(_ISR_STARTADDRESS+0x88))
-#define pISR_IIC		(*(unsigned *)(_ISR_STARTADDRESS+0x8C))
-#define pISR_UART0		(*(unsigned *)(_ISR_STARTADDRESS+0x90))
-#define pISR_SPI1		(*(unsigned *)(_ISR_STARTADDRESS+0x94))
-#define pISR_RTC		(*(unsigned *)(_ISR_STARTADDRESS+0x98))
-#define pISR_ADC		(*(unsigned *)(_ISR_STARTADDRESS+0xA0))
+#define pISR_RESET      (*(unsigned *)(_ISR_STARTADDRESS+0x0))
+#define pISR_UNDEF      (*(unsigned *)(_ISR_STARTADDRESS+0x4))
+#define pISR_SWI        (*(unsigned *)(_ISR_STARTADDRESS+0x8))
+#define pISR_PABORT     (*(unsigned *)(_ISR_STARTADDRESS+0xC))
+#define pISR_DABORT     (*(unsigned *)(_ISR_STARTADDRESS+0x10))
+#define pISR_RESERVED       (*(unsigned *)(_ISR_STARTADDRESS+0x14))
+#define pISR_IRQ        (*(unsigned *)(_ISR_STARTADDRESS+0x18))
+#define pISR_FIQ        (*(unsigned *)(_ISR_STARTADDRESS+0x1C))
+
+#define pISR_EINT0      (*(unsigned *)(_ISR_STARTADDRESS+0x20))
+#define pISR_EINT1      (*(unsigned *)(_ISR_STARTADDRESS+0x24))
+#define pISR_EINT2      (*(unsigned *)(_ISR_STARTADDRESS+0x28))
+#define pISR_EINT3      (*(unsigned *)(_ISR_STARTADDRESS+0x2C))
+#define pISR_EINT4_7        (*(unsigned *)(_ISR_STARTADDRESS+0x30))
+#define pISR_EINT8_23       (*(unsigned *)(_ISR_STARTADDRESS+0x34))
+#define pISR_BAT_FLT        (*(unsigned *)(_ISR_STARTADDRESS+0x3C))
+#define pISR_TICK       (*(unsigned *)(_ISR_STARTADDRESS+0x40))
+#define pISR_WDT        (*(unsigned *)(_ISR_STARTADDRESS+0x44))
+#define pISR_TIMER0     (*(unsigned *)(_ISR_STARTADDRESS+0x48))
+#define pISR_TIMER1     (*(unsigned *)(_ISR_STARTADDRESS+0x4C))
+#define pISR_TIMER2     (*(unsigned *)(_ISR_STARTADDRESS+0x50))
+#define pISR_TIMER3     (*(unsigned *)(_ISR_STARTADDRESS+0x54))
+#define pISR_TIMER4     (*(unsigned *)(_ISR_STARTADDRESS+0x58))
+#define pISR_UART2      (*(unsigned *)(_ISR_STARTADDRESS+0x5C))
+#define pISR_NOTUSED        (*(unsigned *)(_ISR_STARTADDRESS+0x60))
+#define pISR_DMA0       (*(unsigned *)(_ISR_STARTADDRESS+0x64))
+#define pISR_DMA1       (*(unsigned *)(_ISR_STARTADDRESS+0x68))
+#define pISR_DMA2       (*(unsigned *)(_ISR_STARTADDRESS+0x6C))
+#define pISR_DMA3       (*(unsigned *)(_ISR_STARTADDRESS+0x70))
+#define pISR_SDI        (*(unsigned *)(_ISR_STARTADDRESS+0x74))
+#define pISR_SPI0       (*(unsigned *)(_ISR_STARTADDRESS+0x78))
+#define pISR_UART1      (*(unsigned *)(_ISR_STARTADDRESS+0x7C))
+#define pISR_USBD       (*(unsigned *)(_ISR_STARTADDRESS+0x84))
+#define pISR_USBH       (*(unsigned *)(_ISR_STARTADDRESS+0x88))
+#define pISR_IIC        (*(unsigned *)(_ISR_STARTADDRESS+0x8C))
+#define pISR_UART0      (*(unsigned *)(_ISR_STARTADDRESS+0x90))
+#define pISR_SPI1       (*(unsigned *)(_ISR_STARTADDRESS+0x94))
+#define pISR_RTC        (*(unsigned *)(_ISR_STARTADDRESS+0x98))
+#define pISR_ADC        (*(unsigned *)(_ISR_STARTADDRESS+0xA0))
 
 
-/* PENDING BIT */
+// PENDING BIT
 #define BIT_EINT0		(0x1)
 #define BIT_EINT1		(0x1<<1)
 #define BIT_EINT2		(0x1<<2)
 #define BIT_EINT3		(0x1<<3)
 #define BIT_EINT4_7		(0x1<<4)
-#define BIT_EINT8_23		(0x1<<5)
+#define BIT_EINT8_23	(0x1<<5)
+#define BIT_CAM			(0x1<<6)		// Added for 2440.
 #define BIT_BAT_FLT		(0x1<<7)
-#define BIT_TICK		(0x1<<8)
-#define BIT_WDT			(0x1<<9)
+#define BIT_TICK			(0x1<<8)
+#define BIT_WDT_AC97	(0x1<<9)
 #define BIT_TIMER0		(0x1<<10)
 #define BIT_TIMER1		(0x1<<11)
 #define BIT_TIMER2		(0x1<<12)
@@ -207,21 +249,33 @@
 #define BIT_DMA2		(0x1<<19)
 #define BIT_DMA3		(0x1<<20)
 #define BIT_SDI			(0x1<<21)
-#define BIT_SPI0		(0x1<<22)
+#define BIT_SPI0			(0x1<<22)
 #define BIT_UART1		(0x1<<23)
+#define BIT_NFCON		(0x1<<24)		// Added for 2440.
 #define BIT_USBD		(0x1<<25)
 #define BIT_USBH		(0x1<<26)
 #define BIT_IIC			(0x1<<27)
 #define BIT_UART0		(0x1<<28)
-#define BIT_SPI1		(0x1<<29)
+#define BIT_SPI1			(0x1<<29)
 #define BIT_RTC			(0x1<<30)
 #define BIT_ADC			(0x1<<31)
-#define BIT_ALLMSK		(0xFFFFFFFF)
+#define BIT_ALLMSK		(0xffffffff)
+
+#define BIT_SUB_ALLMSK	(0x7fff)
+#define BIT_SUB_AC97 	(0x1<<14)
+#define BIT_SUB_WDT 	(0x1<<13)
+#define BIT_SUB_CAM_S	(0x1<<12)		// Added for 2440.
+#define BIT_SUB_CAM_C	(0x1<<11)		// Added for 2440.
+#define BIT_SUB_ADC		(0x1<<10)
+#define BIT_SUB_TC		(0x1<<9)
+#define BIT_SUB_ERR2	(0x1<<8)
+#define BIT_SUB_TXD2	(0x1<<7)
+#define BIT_SUB_RXD2	(0x1<<6)
+#define BIT_SUB_ERR1	(0x1<<5)
+#define BIT_SUB_TXD1	(0x1<<4)
+#define BIT_SUB_RXD1	(0x1<<3)
+#define BIT_SUB_ERR0	(0x1<<2)
+#define BIT_SUB_TXD0	(0x1<<1)
+#define BIT_SUB_RXD0	(0x1<<0)
 
-#define ClearPending(bit) {\
-		 rSRCPND = bit;\
-		 rINTPND = bit;\
-		 rINTPND;\
-		 }
-/* Wait until rINTPND is changed for the case that the ISR is very short. */
 #endif /*__S3C2410_H__*/
diff -urN u-boot-1.1.6/include/s3c24x0.h u-boot-1.1.6_jz2440/include/s3c24x0.h
--- u-boot-1.1.6/include/s3c24x0.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/s3c24x0.h	2010-11-26 12:54:37.882083977 +0800
@@ -22,7 +22,7 @@
  */
 
 /************************************************
- * NAME	    : s3c24x0.h
+ * NAME     : s3c24x0.h
  * Version  : 31.3.2003
  *
  * common stuff for SAMSUNG S3C24X0 SoC
@@ -31,337 +31,363 @@
 #ifndef __S3C24X0_H__
 #define __S3C24X0_H__
 
-typedef volatile u8	S3C24X0_REG8;
-typedef volatile u16	S3C24X0_REG16;
-typedef volatile u32	S3C24X0_REG32;
+typedef volatile u8 S3C24X0_REG8;
+typedef volatile u16    S3C24X0_REG16;
+typedef volatile u32    S3C24X0_REG32;
 
 /* Memory controller (see manual chapter 5) */
 typedef struct {
-	S3C24X0_REG32	BWSCON;
-	S3C24X0_REG32	BANKCON[8];
-	S3C24X0_REG32	REFRESH;
-	S3C24X0_REG32	BANKSIZE;
-	S3C24X0_REG32	MRSRB6;
-	S3C24X0_REG32	MRSRB7;
+    S3C24X0_REG32   BWSCON;
+    S3C24X0_REG32   BANKCON[8];
+    S3C24X0_REG32   REFRESH;
+    S3C24X0_REG32   BANKSIZE;
+    S3C24X0_REG32   MRSRB6;
+    S3C24X0_REG32   MRSRB7;
 } /*__attribute__((__packed__))*/ S3C24X0_MEMCTL;
 
 
 /* USB HOST (see manual chapter 12) */
 typedef struct {
-	S3C24X0_REG32	HcRevision;
-	S3C24X0_REG32	HcControl;
-	S3C24X0_REG32	HcCommonStatus;
-	S3C24X0_REG32	HcInterruptStatus;
-	S3C24X0_REG32	HcInterruptEnable;
-	S3C24X0_REG32	HcInterruptDisable;
-	S3C24X0_REG32	HcHCCA;
-	S3C24X0_REG32	HcPeriodCuttendED;
-	S3C24X0_REG32	HcControlHeadED;
-	S3C24X0_REG32	HcControlCurrentED;
-	S3C24X0_REG32	HcBulkHeadED;
-	S3C24X0_REG32	HcBuldCurrentED;
-	S3C24X0_REG32	HcDoneHead;
-	S3C24X0_REG32	HcRmInterval;
-	S3C24X0_REG32	HcFmRemaining;
-	S3C24X0_REG32	HcFmNumber;
-	S3C24X0_REG32	HcPeriodicStart;
-	S3C24X0_REG32	HcLSThreshold;
-	S3C24X0_REG32	HcRhDescriptorA;
-	S3C24X0_REG32	HcRhDescriptorB;
-	S3C24X0_REG32	HcRhStatus;
-	S3C24X0_REG32	HcRhPortStatus1;
-	S3C24X0_REG32	HcRhPortStatus2;
+    S3C24X0_REG32   HcRevision;
+    S3C24X0_REG32   HcControl;
+    S3C24X0_REG32   HcCommonStatus;
+    S3C24X0_REG32   HcInterruptStatus;
+    S3C24X0_REG32   HcInterruptEnable;
+    S3C24X0_REG32   HcInterruptDisable;
+    S3C24X0_REG32   HcHCCA;
+    S3C24X0_REG32   HcPeriodCuttendED;
+    S3C24X0_REG32   HcControlHeadED;
+    S3C24X0_REG32   HcControlCurrentED;
+    S3C24X0_REG32   HcBulkHeadED;
+    S3C24X0_REG32   HcBuldCurrentED;
+    S3C24X0_REG32   HcDoneHead;
+    S3C24X0_REG32   HcRmInterval;
+    S3C24X0_REG32   HcFmRemaining;
+    S3C24X0_REG32   HcFmNumber;
+    S3C24X0_REG32   HcPeriodicStart;
+    S3C24X0_REG32   HcLSThreshold;
+    S3C24X0_REG32   HcRhDescriptorA;
+    S3C24X0_REG32   HcRhDescriptorB;
+    S3C24X0_REG32   HcRhStatus;
+    S3C24X0_REG32   HcRhPortStatus1;
+    S3C24X0_REG32   HcRhPortStatus2;
 } /*__attribute__((__packed__))*/ S3C24X0_USB_HOST;
 
 
 /* INTERRUPT (see manual chapter 14) */
 typedef struct {
-	S3C24X0_REG32	SRCPND;
-	S3C24X0_REG32	INTMOD;
-	S3C24X0_REG32	INTMSK;
-	S3C24X0_REG32	PRIORITY;
-	S3C24X0_REG32	INTPND;
-	S3C24X0_REG32	INTOFFSET;
+    S3C24X0_REG32   SRCPND;
+    S3C24X0_REG32   INTMOD;
+    S3C24X0_REG32   INTMSK;
+    S3C24X0_REG32   PRIORITY;
+    S3C24X0_REG32   INTPND;
+    S3C24X0_REG32   INTOFFSET;
 #ifdef CONFIG_S3C2410
-	S3C24X0_REG32	SUBSRCPND;
-	S3C24X0_REG32	INTSUBMSK;
+    S3C24X0_REG32   SUBSRCPND;
+    S3C24X0_REG32   INTSUBMSK;
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_INTERRUPT;
 
 
 /* DMAS (see manual chapter 8) */
 typedef struct {
-	S3C24X0_REG32	DISRC;
+    S3C24X0_REG32   DISRC;
 #ifdef CONFIG_S3C2410
-	S3C24X0_REG32	DISRCC;
+    S3C24X0_REG32   DISRCC;
 #endif
-	S3C24X0_REG32	DIDST;
+    S3C24X0_REG32   DIDST;
 #ifdef CONFIG_S3C2410
-	S3C24X0_REG32	DIDSTC;
+    S3C24X0_REG32   DIDSTC;
 #endif
-	S3C24X0_REG32	DCON;
-	S3C24X0_REG32	DSTAT;
-	S3C24X0_REG32	DCSRC;
-	S3C24X0_REG32	DCDST;
-	S3C24X0_REG32	DMASKTRIG;
+    S3C24X0_REG32   DCON;
+    S3C24X0_REG32   DSTAT;
+    S3C24X0_REG32   DCSRC;
+    S3C24X0_REG32   DCDST;
+    S3C24X0_REG32   DMASKTRIG;
 #ifdef CONFIG_S3C2400
-	S3C24X0_REG32	res[1];
+    S3C24X0_REG32   res[1];
 #endif
 #ifdef CONFIG_S3C2410
-	S3C24X0_REG32	res[7];
+    S3C24X0_REG32   res[7];
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_DMA;
 
 typedef struct {
-	S3C24X0_DMA	dma[4];
+    S3C24X0_DMA dma[4];
 } /*__attribute__((__packed__))*/ S3C24X0_DMAS;
 
 
 /* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */
 /*                          (see S3C2410 manual chapter 7) */
 typedef struct {
-	S3C24X0_REG32	LOCKTIME;
-	S3C24X0_REG32	MPLLCON;
-	S3C24X0_REG32	UPLLCON;
-	S3C24X0_REG32	CLKCON;
-	S3C24X0_REG32	CLKSLOW;
-	S3C24X0_REG32	CLKDIVN;
+    S3C24X0_REG32   LOCKTIME;
+    S3C24X0_REG32   MPLLCON;
+    S3C24X0_REG32   UPLLCON;
+    S3C24X0_REG32   CLKCON;
+    S3C24X0_REG32   CLKSLOW;
+    S3C24X0_REG32   CLKDIVN;
+    S3C24X0_REG32   CAMDIVN;    /* for s3c2440, by www.100ask.net */
 } /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;
 
 
 /* LCD CONTROLLER (see manual chapter 15) */
 typedef struct {
-	S3C24X0_REG32	LCDCON1;
-	S3C24X0_REG32	LCDCON2;
-	S3C24X0_REG32	LCDCON3;
-	S3C24X0_REG32	LCDCON4;
-	S3C24X0_REG32	LCDCON5;
-	S3C24X0_REG32	LCDSADDR1;
-	S3C24X0_REG32	LCDSADDR2;
-	S3C24X0_REG32	LCDSADDR3;
-	S3C24X0_REG32	REDLUT;
-	S3C24X0_REG32	GREENLUT;
-	S3C24X0_REG32	BLUELUT;
-	S3C24X0_REG32	res[8];
-	S3C24X0_REG32	DITHMODE;
-	S3C24X0_REG32	TPAL;
+    S3C24X0_REG32   LCDCON1;
+    S3C24X0_REG32   LCDCON2;
+    S3C24X0_REG32   LCDCON3;
+    S3C24X0_REG32   LCDCON4;
+    S3C24X0_REG32   LCDCON5;
+    S3C24X0_REG32   LCDSADDR1;
+    S3C24X0_REG32   LCDSADDR2;
+    S3C24X0_REG32   LCDSADDR3;
+    S3C24X0_REG32   REDLUT;
+    S3C24X0_REG32   GREENLUT;
+    S3C24X0_REG32   BLUELUT;
+    S3C24X0_REG32   res[8];
+    S3C24X0_REG32   DITHMODE;
+    S3C24X0_REG32   TPAL;
 #ifdef CONFIG_S3C2410
-	S3C24X0_REG32	LCDINTPND;
-	S3C24X0_REG32	LCDSRCPND;
-	S3C24X0_REG32	LCDINTMSK;
-	S3C24X0_REG32	LPCSEL;
+    S3C24X0_REG32   LCDINTPND;
+    S3C24X0_REG32   LCDSRCPND;
+    S3C24X0_REG32   LCDINTMSK;
+    S3C24X0_REG32   LPCSEL;
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_LCD;
 
 
 /* NAND FLASH (see S3C2410 manual chapter 6) */
 typedef struct {
-	S3C24X0_REG32	NFCONF;
-	S3C24X0_REG32	NFCMD;
-	S3C24X0_REG32	NFADDR;
-	S3C24X0_REG32	NFDATA;
-	S3C24X0_REG32	NFSTAT;
-	S3C24X0_REG32	NFECC;
+    S3C24X0_REG32   NFCONF;
+    S3C24X0_REG32   NFCMD;
+    S3C24X0_REG32   NFADDR;
+    S3C24X0_REG32   NFDATA;
+    S3C24X0_REG32   NFSTAT;
+    S3C24X0_REG32   NFECC;
 } /*__attribute__((__packed__))*/ S3C2410_NAND;
 
+/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */
+typedef struct {
+    S3C24X0_REG32   NFCONF;
+    S3C24X0_REG32   NFCONT;
+    S3C24X0_REG32   NFCMD;
+    S3C24X0_REG32   NFADDR;
+    S3C24X0_REG32   NFDATA;
+    S3C24X0_REG32   NFMECCD0;
+    S3C24X0_REG32   NFMECCD1;
+    S3C24X0_REG32   NFSECCD;
+    S3C24X0_REG32   NFSTAT;
+    S3C24X0_REG32   NFESTAT0;
+    S3C24X0_REG32   NFESTAT1;
+    S3C24X0_REG32   NFMECC0;
+    S3C24X0_REG32   NFMECC1;
+    S3C24X0_REG32   NFSECC;
+    S3C24X0_REG32   NFSBLK;
+    S3C24X0_REG32   NFEBLK;
+} /*__attribute__((__packed__))*/ S3C2440_NAND;
 
 /* UART (see manual chapter 11) */
 typedef struct {
-	S3C24X0_REG32	ULCON;
-	S3C24X0_REG32	UCON;
-	S3C24X0_REG32	UFCON;
-	S3C24X0_REG32	UMCON;
-	S3C24X0_REG32	UTRSTAT;
-	S3C24X0_REG32	UERSTAT;
-	S3C24X0_REG32	UFSTAT;
-	S3C24X0_REG32	UMSTAT;
+    S3C24X0_REG32   ULCON;
+    S3C24X0_REG32   UCON;
+    S3C24X0_REG32   UFCON;
+    S3C24X0_REG32   UMCON;
+    S3C24X0_REG32   UTRSTAT;
+    S3C24X0_REG32   UERSTAT;
+    S3C24X0_REG32   UFSTAT;
+    S3C24X0_REG32   UMSTAT;
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	UTXH;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	URXH;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    UTXH;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    URXH;
 #else /* Little Endian */
-	S3C24X0_REG8	UTXH;
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	URXH;
-	S3C24X0_REG8	res2[3];
+    S3C24X0_REG8    UTXH;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    URXH;
+    S3C24X0_REG8    res2[3];
 #endif
-	S3C24X0_REG32	UBRDIV;
+    S3C24X0_REG32   UBRDIV;
 } /*__attribute__((__packed__))*/ S3C24X0_UART;
 
 
 /* PWM TIMER (see manual chapter 10) */
 typedef struct {
-	S3C24X0_REG32	TCNTB;
-	S3C24X0_REG32	TCMPB;
-	S3C24X0_REG32	TCNTO;
+    S3C24X0_REG32   TCNTB;
+    S3C24X0_REG32   TCMPB;
+    S3C24X0_REG32   TCNTO;
 } /*__attribute__((__packed__))*/ S3C24X0_TIMER;
 
 typedef struct {
-	S3C24X0_REG32	TCFG0;
-	S3C24X0_REG32	TCFG1;
-	S3C24X0_REG32	TCON;
-	S3C24X0_TIMER	ch[4];
-	S3C24X0_REG32	TCNTB4;
-	S3C24X0_REG32	TCNTO4;
+    S3C24X0_REG32   TCFG0;
+    S3C24X0_REG32   TCFG1;
+    S3C24X0_REG32   TCON;
+    S3C24X0_TIMER   ch[4];
+    S3C24X0_REG32   TCNTB4;
+    S3C24X0_REG32   TCNTO4;
 } /*__attribute__((__packed__))*/ S3C24X0_TIMERS;
 
 
 /* USB DEVICE (see manual chapter 13) */
 typedef struct {
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG8	res[3];
-	S3C24X0_REG8	EP_FIFO_REG;
+    S3C24X0_REG8    res[3];
+    S3C24X0_REG8    EP_FIFO_REG;
 #else /*  little endian */
-	S3C24X0_REG8	EP_FIFO_REG;
-	S3C24X0_REG8	res[3];
+    S3C24X0_REG8    EP_FIFO_REG;
+    S3C24X0_REG8    res[3];
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_USB_DEV_FIFOS;
 
 typedef struct {
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	EP_DMA_CON;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	EP_DMA_UNIT;
-	S3C24X0_REG8	res3[3];
-	S3C24X0_REG8	EP_DMA_FIFO;
-	S3C24X0_REG8	res4[3];
-	S3C24X0_REG8	EP_DMA_TTC_L;
-	S3C24X0_REG8	res5[3];
-	S3C24X0_REG8	EP_DMA_TTC_M;
-	S3C24X0_REG8	res6[3];
-	S3C24X0_REG8	EP_DMA_TTC_H;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    EP_DMA_CON;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    EP_DMA_UNIT;
+    S3C24X0_REG8    res3[3];
+    S3C24X0_REG8    EP_DMA_FIFO;
+    S3C24X0_REG8    res4[3];
+    S3C24X0_REG8    EP_DMA_TTC_L;
+    S3C24X0_REG8    res5[3];
+    S3C24X0_REG8    EP_DMA_TTC_M;
+    S3C24X0_REG8    res6[3];
+    S3C24X0_REG8    EP_DMA_TTC_H;
 #else /*  little endian */
-	S3C24X0_REG8	EP_DMA_CON;
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	EP_DMA_UNIT;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	EP_DMA_FIFO;
-	S3C24X0_REG8	res3[3];
-	S3C24X0_REG8	EP_DMA_TTC_L;
-	S3C24X0_REG8	res4[3];
-	S3C24X0_REG8	EP_DMA_TTC_M;
-	S3C24X0_REG8	res5[3];
-	S3C24X0_REG8	EP_DMA_TTC_H;
-	S3C24X0_REG8	res6[3];
+    S3C24X0_REG8    EP_DMA_CON;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    EP_DMA_UNIT;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    EP_DMA_FIFO;
+    S3C24X0_REG8    res3[3];
+    S3C24X0_REG8    EP_DMA_TTC_L;
+    S3C24X0_REG8    res4[3];
+    S3C24X0_REG8    EP_DMA_TTC_M;
+    S3C24X0_REG8    res5[3];
+    S3C24X0_REG8    EP_DMA_TTC_H;
+    S3C24X0_REG8    res6[3];
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_USB_DEV_DMAS;
 
 typedef struct {
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	FUNC_ADDR_REG;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	PWR_REG;
-	S3C24X0_REG8	res3[3];
-	S3C24X0_REG8	EP_INT_REG;
-	S3C24X0_REG8	res4[15];
-	S3C24X0_REG8	USB_INT_REG;
-	S3C24X0_REG8	res5[3];
-	S3C24X0_REG8	EP_INT_EN_REG;
-	S3C24X0_REG8	res6[15];
-	S3C24X0_REG8	USB_INT_EN_REG;
-	S3C24X0_REG8	res7[3];
-	S3C24X0_REG8	FRAME_NUM1_REG;
-	S3C24X0_REG8	res8[3];
-	S3C24X0_REG8	FRAME_NUM2_REG;
-	S3C24X0_REG8	res9[3];
-	S3C24X0_REG8	INDEX_REG;
-	S3C24X0_REG8	res10[7];
-	S3C24X0_REG8	MAXP_REG;
-	S3C24X0_REG8	res11[3];
-	S3C24X0_REG8	EP0_CSR_IN_CSR1_REG;
-	S3C24X0_REG8	res12[3];
-	S3C24X0_REG8	IN_CSR2_REG;
-	S3C24X0_REG8	res13[7];
-	S3C24X0_REG8	OUT_CSR1_REG;
-	S3C24X0_REG8	res14[3];
-	S3C24X0_REG8	OUT_CSR2_REG;
-	S3C24X0_REG8	res15[3];
-	S3C24X0_REG8	OUT_FIFO_CNT1_REG;
-	S3C24X0_REG8	res16[3];
-	S3C24X0_REG8	OUT_FIFO_CNT2_REG;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    FUNC_ADDR_REG;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    PWR_REG;
+    S3C24X0_REG8    res3[3];
+    S3C24X0_REG8    EP_INT_REG;
+    S3C24X0_REG8    res4[15];
+    S3C24X0_REG8    USB_INT_REG;
+    S3C24X0_REG8    res5[3];
+    S3C24X0_REG8    EP_INT_EN_REG;
+    S3C24X0_REG8    res6[15];
+    S3C24X0_REG8    USB_INT_EN_REG;
+    S3C24X0_REG8    res7[3];
+    S3C24X0_REG8    FRAME_NUM1_REG;
+    S3C24X0_REG8    res8[3];
+    S3C24X0_REG8    FRAME_NUM2_REG;
+    S3C24X0_REG8    res9[3];
+    S3C24X0_REG8    INDEX_REG;
+    S3C24X0_REG8    res10[7];
+    S3C24X0_REG8    MAXP_REG;
+    S3C24X0_REG8    res11[3];
+    S3C24X0_REG8    EP0_CSR_IN_CSR1_REG;
+    S3C24X0_REG8    res12[3];
+    S3C24X0_REG8    IN_CSR2_REG;
+    S3C24X0_REG8    res13[7];
+    S3C24X0_REG8    OUT_CSR1_REG;
+    S3C24X0_REG8    res14[3];
+    S3C24X0_REG8    OUT_CSR2_REG;
+    S3C24X0_REG8    res15[3];
+    S3C24X0_REG8    OUT_FIFO_CNT1_REG;
+    S3C24X0_REG8    res16[3];
+    S3C24X0_REG8    OUT_FIFO_CNT2_REG;
 #else /*  little endian */
-	S3C24X0_REG8	FUNC_ADDR_REG;
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	PWR_REG;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	EP_INT_REG;
-	S3C24X0_REG8	res3[15];
-	S3C24X0_REG8	USB_INT_REG;
-	S3C24X0_REG8	res4[3];
-	S3C24X0_REG8	EP_INT_EN_REG;
-	S3C24X0_REG8	res5[15];
-	S3C24X0_REG8	USB_INT_EN_REG;
-	S3C24X0_REG8	res6[3];
-	S3C24X0_REG8	FRAME_NUM1_REG;
-	S3C24X0_REG8	res7[3];
-	S3C24X0_REG8	FRAME_NUM2_REG;
-	S3C24X0_REG8	res8[3];
-	S3C24X0_REG8	INDEX_REG;
-	S3C24X0_REG8	res9[7];
-	S3C24X0_REG8	MAXP_REG;
-	S3C24X0_REG8	res10[7];
-	S3C24X0_REG8	EP0_CSR_IN_CSR1_REG;
-	S3C24X0_REG8	res11[3];
-	S3C24X0_REG8	IN_CSR2_REG;
-	S3C24X0_REG8	res12[3];
-	S3C24X0_REG8	OUT_CSR1_REG;
-	S3C24X0_REG8	res13[7];
-	S3C24X0_REG8	OUT_CSR2_REG;
-	S3C24X0_REG8	res14[3];
-	S3C24X0_REG8	OUT_FIFO_CNT1_REG;
-	S3C24X0_REG8	res15[3];
-	S3C24X0_REG8	OUT_FIFO_CNT2_REG;
-	S3C24X0_REG8	res16[3];
+    S3C24X0_REG8    FUNC_ADDR_REG;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    PWR_REG;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    EP_INT_REG;
+    S3C24X0_REG8    res3[15];
+    S3C24X0_REG8    USB_INT_REG;
+    S3C24X0_REG8    res4[3];
+    S3C24X0_REG8    EP_INT_EN_REG;
+    S3C24X0_REG8    res5[15];
+    S3C24X0_REG8    USB_INT_EN_REG;
+    S3C24X0_REG8    res6[3];
+    S3C24X0_REG8    FRAME_NUM1_REG;
+    S3C24X0_REG8    res7[3];
+    S3C24X0_REG8    FRAME_NUM2_REG;
+    S3C24X0_REG8    res8[3];
+    S3C24X0_REG8    INDEX_REG;
+    S3C24X0_REG8    res9[7];
+    S3C24X0_REG8    MAXP_REG;
+    S3C24X0_REG8    res10[3];
+    S3C24X0_REG8    EP0_CSR_IN_CSR1_REG;
+    S3C24X0_REG8    res11[3];
+    S3C24X0_REG8    IN_CSR2_REG;
+    S3C24X0_REG8    res12[7];
+    S3C24X0_REG8    OUT_CSR1_REG;
+    S3C24X0_REG8    res13[3];
+    S3C24X0_REG8    OUT_CSR2_REG;
+    S3C24X0_REG8    res14[3];
+    S3C24X0_REG8    OUT_FIFO_CNT1_REG;
+    S3C24X0_REG8    res15[3];
+    S3C24X0_REG8    OUT_FIFO_CNT2_REG;
+    S3C24X0_REG8    res16[3];
 #endif /*  __BIG_ENDIAN */
-	S3C24X0_USB_DEV_FIFOS	fifo[5];
-	S3C24X0_USB_DEV_DMAS	dma[5];
+    S3C24X0_REG32   res17[8];
+    S3C24X0_USB_DEV_FIFOS   fifo[5];
+    S3C24X0_REG32   res18[11];
+    S3C24X0_USB_DEV_DMAS    ep1;
+    S3C24X0_USB_DEV_DMAS    ep2;
+    S3C24X0_REG8    res19[16];
+    S3C24X0_USB_DEV_DMAS    ep3;
+    S3C24X0_USB_DEV_DMAS    ep4;
 } /*__attribute__((__packed__))*/ S3C24X0_USB_DEVICE;
 
 
 /* WATCH DOG TIMER (see manual chapter 18) */
 typedef struct {
-	S3C24X0_REG32	WTCON;
-	S3C24X0_REG32	WTDAT;
-	S3C24X0_REG32	WTCNT;
+    S3C24X0_REG32   WTCON;
+    S3C24X0_REG32   WTDAT;
+    S3C24X0_REG32   WTCNT;
 } /*__attribute__((__packed__))*/ S3C24X0_WATCHDOG;
 
 
 /* IIC (see manual chapter 20) */
 typedef struct {
-	S3C24X0_REG32	IICCON;
-	S3C24X0_REG32	IICSTAT;
-	S3C24X0_REG32	IICADD;
-	S3C24X0_REG32	IICDS;
+    S3C24X0_REG32   IICCON;
+    S3C24X0_REG32   IICSTAT;
+    S3C24X0_REG32   IICADD;
+    S3C24X0_REG32   IICDS;
 } /*__attribute__((__packed__))*/ S3C24X0_I2C;
 
 
 /* IIS (see manual chapter 21) */
 typedef struct {
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG16	res1;
-	S3C24X0_REG16	IISCON;
-	S3C24X0_REG16	res2;
-	S3C24X0_REG16	IISMOD;
-	S3C24X0_REG16	res3;
-	S3C24X0_REG16	IISPSR;
-	S3C24X0_REG16	res4;
-	S3C24X0_REG16	IISFCON;
-	S3C24X0_REG16	res5;
-	S3C24X0_REG16	IISFIFO;
+    S3C24X0_REG16   res1;
+    S3C24X0_REG16   IISCON;
+    S3C24X0_REG16   res2;
+    S3C24X0_REG16   IISMOD;
+    S3C24X0_REG16   res3;
+    S3C24X0_REG16   IISPSR;
+    S3C24X0_REG16   res4;
+    S3C24X0_REG16   IISFCON;
+    S3C24X0_REG16   res5;
+    S3C24X0_REG16   IISFIFO;
 #else /*  little endian */
-	S3C24X0_REG16	IISCON;
-	S3C24X0_REG16	res1;
-	S3C24X0_REG16	IISMOD;
-	S3C24X0_REG16	res2;
-	S3C24X0_REG16	IISPSR;
-	S3C24X0_REG16	res3;
-	S3C24X0_REG16	IISFCON;
-	S3C24X0_REG16	res4;
-	S3C24X0_REG16	IISFIFO;
-	S3C24X0_REG16	res5;
+    S3C24X0_REG16   IISCON;
+    S3C24X0_REG16   res1;
+    S3C24X0_REG16   IISMOD;
+    S3C24X0_REG16   res2;
+    S3C24X0_REG16   IISPSR;
+    S3C24X0_REG16   res3;
+    S3C24X0_REG16   IISFCON;
+    S3C24X0_REG16   res4;
+    S3C24X0_REG16   IISFIFO;
+    S3C24X0_REG16   res5;
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_I2S;
 
@@ -369,87 +395,93 @@
 /* I/O PORT (see manual chapter 9) */
 typedef struct {
 #ifdef CONFIG_S3C2400
-	S3C24X0_REG32	PACON;
-	S3C24X0_REG32	PADAT;
+    S3C24X0_REG32   PACON;
+    S3C24X0_REG32   PADAT;
 
-	S3C24X0_REG32	PBCON;
-	S3C24X0_REG32	PBDAT;
-	S3C24X0_REG32	PBUP;
+    S3C24X0_REG32   PBCON;
+    S3C24X0_REG32   PBDAT;
+    S3C24X0_REG32   PBUP;
 
-	S3C24X0_REG32	PCCON;
-	S3C24X0_REG32	PCDAT;
-	S3C24X0_REG32	PCUP;
+    S3C24X0_REG32   PCCON;
+    S3C24X0_REG32   PCDAT;
+    S3C24X0_REG32   PCUP;
 
-	S3C24X0_REG32	PDCON;
-	S3C24X0_REG32	PDDAT;
-	S3C24X0_REG32	PDUP;
+    S3C24X0_REG32   PDCON;
+    S3C24X0_REG32   PDDAT;
+    S3C24X0_REG32   PDUP;
 
-	S3C24X0_REG32	PECON;
-	S3C24X0_REG32	PEDAT;
-	S3C24X0_REG32	PEUP;
+    S3C24X0_REG32   PECON;
+    S3C24X0_REG32   PEDAT;
+    S3C24X0_REG32   PEUP;
 
-	S3C24X0_REG32	PFCON;
-	S3C24X0_REG32	PFDAT;
-	S3C24X0_REG32	PFUP;
+    S3C24X0_REG32   PFCON;
+    S3C24X0_REG32   PFDAT;
+    S3C24X0_REG32   PFUP;
 
-	S3C24X0_REG32	PGCON;
-	S3C24X0_REG32	PGDAT;
-	S3C24X0_REG32	PGUP;
+    S3C24X0_REG32   PGCON;
+    S3C24X0_REG32   PGDAT;
+    S3C24X0_REG32   PGUP;
 
-	S3C24X0_REG32	OPENCR;
+    S3C24X0_REG32   OPENCR;
 
-	S3C24X0_REG32	MISCCR;
-	S3C24X0_REG32	EXTINT;
+    S3C24X0_REG32   MISCCR;
+    S3C24X0_REG32   EXTINT;
 #endif
 #ifdef CONFIG_S3C2410
-	S3C24X0_REG32	GPACON;
-	S3C24X0_REG32	GPADAT;
-	S3C24X0_REG32	res1[2];
-	S3C24X0_REG32	GPBCON;
-	S3C24X0_REG32	GPBDAT;
-	S3C24X0_REG32	GPBUP;
-	S3C24X0_REG32	res2;
-	S3C24X0_REG32	GPCCON;
-	S3C24X0_REG32	GPCDAT;
-	S3C24X0_REG32	GPCUP;
-	S3C24X0_REG32	res3;
-	S3C24X0_REG32	GPDCON;
-	S3C24X0_REG32	GPDDAT;
-	S3C24X0_REG32	GPDUP;
-	S3C24X0_REG32	res4;
-	S3C24X0_REG32	GPECON;
-	S3C24X0_REG32	GPEDAT;
-	S3C24X0_REG32	GPEUP;
-	S3C24X0_REG32	res5;
-	S3C24X0_REG32	GPFCON;
-	S3C24X0_REG32	GPFDAT;
-	S3C24X0_REG32	GPFUP;
-	S3C24X0_REG32	res6;
-	S3C24X0_REG32	GPGCON;
-	S3C24X0_REG32	GPGDAT;
-	S3C24X0_REG32	GPGUP;
-	S3C24X0_REG32	res7;
-	S3C24X0_REG32	GPHCON;
-	S3C24X0_REG32	GPHDAT;
-	S3C24X0_REG32	GPHUP;
-	S3C24X0_REG32	res8;
-
-	S3C24X0_REG32	MISCCR;
-	S3C24X0_REG32	DCLKCON;
-	S3C24X0_REG32	EXTINT0;
-	S3C24X0_REG32	EXTINT1;
-	S3C24X0_REG32	EXTINT2;
-	S3C24X0_REG32	EINTFLT0;
-	S3C24X0_REG32	EINTFLT1;
-	S3C24X0_REG32	EINTFLT2;
-	S3C24X0_REG32	EINTFLT3;
-	S3C24X0_REG32	EINTMASK;
-	S3C24X0_REG32	EINTPEND;
-	S3C24X0_REG32	GSTATUS0;
-	S3C24X0_REG32	GSTATUS1;
-	S3C24X0_REG32	GSTATUS2;
-	S3C24X0_REG32	GSTATUS3;
-	S3C24X0_REG32	GSTATUS4;
+    S3C24X0_REG32   GPACON;
+    S3C24X0_REG32   GPADAT;
+    S3C24X0_REG32   res1[2];
+    S3C24X0_REG32   GPBCON;
+    S3C24X0_REG32   GPBDAT;
+    S3C24X0_REG32   GPBUP;
+    S3C24X0_REG32   res2;
+    S3C24X0_REG32   GPCCON;
+    S3C24X0_REG32   GPCDAT;
+    S3C24X0_REG32   GPCUP;
+    S3C24X0_REG32   res3;
+    S3C24X0_REG32   GPDCON;
+    S3C24X0_REG32   GPDDAT;
+    S3C24X0_REG32   GPDUP;
+    S3C24X0_REG32   res4;
+    S3C24X0_REG32   GPECON;
+    S3C24X0_REG32   GPEDAT;
+    S3C24X0_REG32   GPEUP;
+    S3C24X0_REG32   res5;
+    S3C24X0_REG32   GPFCON;
+    S3C24X0_REG32   GPFDAT;
+    S3C24X0_REG32   GPFUP;
+    S3C24X0_REG32   res6;
+    S3C24X0_REG32   GPGCON;
+    S3C24X0_REG32   GPGDAT;
+    S3C24X0_REG32   GPGUP;
+    S3C24X0_REG32   res7;
+    S3C24X0_REG32   GPHCON;
+    S3C24X0_REG32   GPHDAT;
+    S3C24X0_REG32   GPHUP;
+    S3C24X0_REG32   res8;
+
+    S3C24X0_REG32   MISCCR;
+    S3C24X0_REG32   DCLKCON;
+    S3C24X0_REG32   EXTINT0;
+    S3C24X0_REG32   EXTINT1;
+    S3C24X0_REG32   EXTINT2;
+    S3C24X0_REG32   EINTFLT0;
+    S3C24X0_REG32   EINTFLT1;
+    S3C24X0_REG32   EINTFLT2;
+    S3C24X0_REG32   EINTFLT3;
+    S3C24X0_REG32   EINTMASK;
+    S3C24X0_REG32   EINTPEND;
+    S3C24X0_REG32   GSTATUS0;
+    S3C24X0_REG32   GSTATUS1;
+    S3C24X0_REG32   GSTATUS2;
+    S3C24X0_REG32   GSTATUS3;
+    S3C24X0_REG32   GSTATUS4;
+
+    /* s3c2440 */
+    S3C24X0_REG32   res9[4];
+    S3C24X0_REG32   GPJCON;
+    S3C24X0_REG32   GPJDAT;
+    S3C24X0_REG32   GPJUP;
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_GPIO;
 
@@ -457,679 +489,682 @@
 /* RTC (see manual chapter 17) */
 typedef struct {
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG8	res1[67];
-	S3C24X0_REG8	RTCCON;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	TICNT;
-	S3C24X0_REG8	res3[11];
-	S3C24X0_REG8	RTCALM;
-	S3C24X0_REG8	res4[3];
-	S3C24X0_REG8	ALMSEC;
-	S3C24X0_REG8	res5[3];
-	S3C24X0_REG8	ALMMIN;
-	S3C24X0_REG8	res6[3];
-	S3C24X0_REG8	ALMHOUR;
-	S3C24X0_REG8	res7[3];
-	S3C24X0_REG8	ALMDATE;
-	S3C24X0_REG8	res8[3];
-	S3C24X0_REG8	ALMMON;
-	S3C24X0_REG8	res9[3];
-	S3C24X0_REG8	ALMYEAR;
-	S3C24X0_REG8	res10[3];
-	S3C24X0_REG8	RTCRST;
-	S3C24X0_REG8	res11[3];
-	S3C24X0_REG8	BCDSEC;
-	S3C24X0_REG8	res12[3];
-	S3C24X0_REG8	BCDMIN;
-	S3C24X0_REG8	res13[3];
-	S3C24X0_REG8	BCDHOUR;
-	S3C24X0_REG8	res14[3];
-	S3C24X0_REG8	BCDDATE;
-	S3C24X0_REG8	res15[3];
-	S3C24X0_REG8	BCDDAY;
-	S3C24X0_REG8	res16[3];
-	S3C24X0_REG8	BCDMON;
-	S3C24X0_REG8	res17[3];
-	S3C24X0_REG8	BCDYEAR;
+    S3C24X0_REG8    res1[67];
+    S3C24X0_REG8    RTCCON;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    TICNT;
+    S3C24X0_REG8    res3[11];
+    S3C24X0_REG8    RTCALM;
+    S3C24X0_REG8    res4[3];
+    S3C24X0_REG8    ALMSEC;
+    S3C24X0_REG8    res5[3];
+    S3C24X0_REG8    ALMMIN;
+    S3C24X0_REG8    res6[3];
+    S3C24X0_REG8    ALMHOUR;
+    S3C24X0_REG8    res7[3];
+    S3C24X0_REG8    ALMDATE;
+    S3C24X0_REG8    res8[3];
+    S3C24X0_REG8    ALMMON;
+    S3C24X0_REG8    res9[3];
+    S3C24X0_REG8    ALMYEAR;
+    S3C24X0_REG8    res10[3];
+    S3C24X0_REG8    RTCRST;
+    S3C24X0_REG8    res11[3];
+    S3C24X0_REG8    BCDSEC;
+    S3C24X0_REG8    res12[3];
+    S3C24X0_REG8    BCDMIN;
+    S3C24X0_REG8    res13[3];
+    S3C24X0_REG8    BCDHOUR;
+    S3C24X0_REG8    res14[3];
+    S3C24X0_REG8    BCDDATE;
+    S3C24X0_REG8    res15[3];
+    S3C24X0_REG8    BCDDAY;
+    S3C24X0_REG8    res16[3];
+    S3C24X0_REG8    BCDMON;
+    S3C24X0_REG8    res17[3];
+    S3C24X0_REG8    BCDYEAR;
 #else /*  little endian */
-	S3C24X0_REG8	res0[64];
-	S3C24X0_REG8	RTCCON;
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	TICNT;
-	S3C24X0_REG8	res2[11];
-	S3C24X0_REG8	RTCALM;
-	S3C24X0_REG8	res3[3];
-	S3C24X0_REG8	ALMSEC;
-	S3C24X0_REG8	res4[3];
-	S3C24X0_REG8	ALMMIN;
-	S3C24X0_REG8	res5[3];
-	S3C24X0_REG8	ALMHOUR;
-	S3C24X0_REG8	res6[3];
-	S3C24X0_REG8	ALMDATE;
-	S3C24X0_REG8	res7[3];
-	S3C24X0_REG8	ALMMON;
-	S3C24X0_REG8	res8[3];
-	S3C24X0_REG8	ALMYEAR;
-	S3C24X0_REG8	res9[3];
-	S3C24X0_REG8	RTCRST;
-	S3C24X0_REG8	res10[3];
-	S3C24X0_REG8	BCDSEC;
-	S3C24X0_REG8	res11[3];
-	S3C24X0_REG8	BCDMIN;
-	S3C24X0_REG8	res12[3];
-	S3C24X0_REG8	BCDHOUR;
-	S3C24X0_REG8	res13[3];
-	S3C24X0_REG8	BCDDATE;
-	S3C24X0_REG8	res14[3];
-	S3C24X0_REG8	BCDDAY;
-	S3C24X0_REG8	res15[3];
-	S3C24X0_REG8	BCDMON;
-	S3C24X0_REG8	res16[3];
-	S3C24X0_REG8	BCDYEAR;
-	S3C24X0_REG8	res17[3];
+    S3C24X0_REG8    res0[64];
+    S3C24X0_REG8    RTCCON;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    TICNT;
+    S3C24X0_REG8    res2[11];
+    S3C24X0_REG8    RTCALM;
+    S3C24X0_REG8    res3[3];
+    S3C24X0_REG8    ALMSEC;
+    S3C24X0_REG8    res4[3];
+    S3C24X0_REG8    ALMMIN;
+    S3C24X0_REG8    res5[3];
+    S3C24X0_REG8    ALMHOUR;
+    S3C24X0_REG8    res6[3];
+    S3C24X0_REG8    ALMDATE;
+    S3C24X0_REG8    res7[3];
+    S3C24X0_REG8    ALMMON;
+    S3C24X0_REG8    res8[3];
+    S3C24X0_REG8    ALMYEAR;
+    S3C24X0_REG8    res9[3];
+    S3C24X0_REG8    RTCRST;
+    S3C24X0_REG8    res10[3];
+    S3C24X0_REG8    BCDSEC;
+    S3C24X0_REG8    res11[3];
+    S3C24X0_REG8    BCDMIN;
+    S3C24X0_REG8    res12[3];
+    S3C24X0_REG8    BCDHOUR;
+    S3C24X0_REG8    res13[3];
+    S3C24X0_REG8    BCDDATE;
+    S3C24X0_REG8    res14[3];
+    S3C24X0_REG8    BCDDAY;
+    S3C24X0_REG8    res15[3];
+    S3C24X0_REG8    BCDMON;
+    S3C24X0_REG8    res16[3];
+    S3C24X0_REG8    BCDYEAR;
+    S3C24X0_REG8    res17[3];
 #endif
 } /*__attribute__((__packed__))*/ S3C24X0_RTC;
 
 
 /* ADC (see manual chapter 16) */
 typedef struct {
-	S3C24X0_REG32	ADCCON;
-	S3C24X0_REG32	ADCDAT;
+    S3C24X0_REG32   ADCCON;
+    S3C24X0_REG32   ADCDAT;
 } /*__attribute__((__packed__))*/ S3C2400_ADC;
 
 
 /* ADC (see manual chapter 16) */
 typedef struct {
-	S3C24X0_REG32	ADCCON;
-	S3C24X0_REG32	ADCTSC;
-	S3C24X0_REG32	ADCDLY;
-	S3C24X0_REG32	ADCDAT0;
-	S3C24X0_REG32	ADCDAT1;
+    S3C24X0_REG32   ADCCON;
+    S3C24X0_REG32   ADCTSC;
+    S3C24X0_REG32   ADCDLY;
+    S3C24X0_REG32   ADCDAT0;
+    S3C24X0_REG32   ADCDAT1;
 } /*__attribute__((__packed__))*/ S3C2410_ADC;
 
 
 /* SPI (see manual chapter 22) */
 typedef struct {
-	S3C24X0_REG32	SPCON;
-	S3C24X0_REG32	SPSTA;
-	S3C24X0_REG32	SPPIN;
-	S3C24X0_REG32	SPPRE;
-	S3C24X0_REG32	SPTDAT;
-	S3C24X0_REG32	SPRDAT;
-	S3C24X0_REG32	res[2];
+    S3C24X0_REG32   SPCON;
+    S3C24X0_REG32   SPSTA;
+    S3C24X0_REG32   SPPIN;
+    S3C24X0_REG32   SPPRE;
+    S3C24X0_REG32   SPTDAT;
+    S3C24X0_REG32   SPRDAT;
+    S3C24X0_REG32   res[2];
 } __attribute__((__packed__)) S3C24X0_SPI_CHANNEL;
 
 typedef struct {
-	S3C24X0_SPI_CHANNEL	ch[S3C24X0_SPI_CHANNELS];
+    S3C24X0_SPI_CHANNEL ch[S3C24X0_SPI_CHANNELS];
 } /*__attribute__((__packed__))*/ S3C24X0_SPI;
 
 
 /* MMC INTERFACE (see S3C2400 manual chapter 19) */
 typedef struct {
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	MMCON;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	MMCRR;
-	S3C24X0_REG8	res3[3];
-	S3C24X0_REG8	MMFCON;
-	S3C24X0_REG8	res4[3];
-	S3C24X0_REG8	MMSTA;
-	S3C24X0_REG16	res5;
-	S3C24X0_REG16	MMFSTA;
-	S3C24X0_REG8	res6[3];
-	S3C24X0_REG8	MMPRE;
-	S3C24X0_REG16	res7;
-	S3C24X0_REG16	MMLEN;
-	S3C24X0_REG8	res8[3];
-	S3C24X0_REG8	MMCR7;
-	S3C24X0_REG32	MMRSP[4];
-	S3C24X0_REG8	res9[3];
-	S3C24X0_REG8	MMCMD0;
-	S3C24X0_REG32	MMCMD1;
-	S3C24X0_REG16	res10;
-	S3C24X0_REG16	MMCR16;
-	S3C24X0_REG8	res11[3];
-	S3C24X0_REG8	MMDAT;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    MMCON;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    MMCRR;
+    S3C24X0_REG8    res3[3];
+    S3C24X0_REG8    MMFCON;
+    S3C24X0_REG8    res4[3];
+    S3C24X0_REG8    MMSTA;
+    S3C24X0_REG16   res5;
+    S3C24X0_REG16   MMFSTA;
+    S3C24X0_REG8    res6[3];
+    S3C24X0_REG8    MMPRE;
+    S3C24X0_REG16   res7;
+    S3C24X0_REG16   MMLEN;
+    S3C24X0_REG8    res8[3];
+    S3C24X0_REG8    MMCR7;
+    S3C24X0_REG32   MMRSP[4];
+    S3C24X0_REG8    res9[3];
+    S3C24X0_REG8    MMCMD0;
+    S3C24X0_REG32   MMCMD1;
+    S3C24X0_REG16   res10;
+    S3C24X0_REG16   MMCR16;
+    S3C24X0_REG8    res11[3];
+    S3C24X0_REG8    MMDAT;
 #else
-	S3C24X0_REG8	MMCON;
-	S3C24X0_REG8	res1[3];
-	S3C24X0_REG8	MMCRR;
-	S3C24X0_REG8	res2[3];
-	S3C24X0_REG8	MMFCON;
-	S3C24X0_REG8	res3[3];
-	S3C24X0_REG8	MMSTA;
-	S3C24X0_REG8	res4[3];
-	S3C24X0_REG16	MMFSTA;
-	S3C24X0_REG16	res5;
-	S3C24X0_REG8	MMPRE;
-	S3C24X0_REG8	res6[3];
-	S3C24X0_REG16	MMLEN;
-	S3C24X0_REG16	res7;
-	S3C24X0_REG8	MMCR7;
-	S3C24X0_REG8	res8[3];
-	S3C24X0_REG32	MMRSP[4];
-	S3C24X0_REG8	MMCMD0;
-	S3C24X0_REG8	res9[3];
-	S3C24X0_REG32	MMCMD1;
-	S3C24X0_REG16	MMCR16;
-	S3C24X0_REG16	res10;
-	S3C24X0_REG8	MMDAT;
-	S3C24X0_REG8	res11[3];
+    S3C24X0_REG8    MMCON;
+    S3C24X0_REG8    res1[3];
+    S3C24X0_REG8    MMCRR;
+    S3C24X0_REG8    res2[3];
+    S3C24X0_REG8    MMFCON;
+    S3C24X0_REG8    res3[3];
+    S3C24X0_REG8    MMSTA;
+    S3C24X0_REG8    res4[3];
+    S3C24X0_REG16   MMFSTA;
+    S3C24X0_REG16   res5;
+    S3C24X0_REG8    MMPRE;
+    S3C24X0_REG8    res6[3];
+    S3C24X0_REG16   MMLEN;
+    S3C24X0_REG16   res7;
+    S3C24X0_REG8    MMCR7;
+    S3C24X0_REG8    res8[3];
+    S3C24X0_REG32   MMRSP[4];
+    S3C24X0_REG8    MMCMD0;
+    S3C24X0_REG8    res9[3];
+    S3C24X0_REG32   MMCMD1;
+    S3C24X0_REG16   MMCR16;
+    S3C24X0_REG16   res10;
+    S3C24X0_REG8    MMDAT;
+    S3C24X0_REG8    res11[3];
 #endif
 } /*__attribute__((__packed__))*/ S3C2400_MMC;
 
 
 /* SD INTERFACE (see S3C2410 manual chapter 19) */
 typedef struct {
-	S3C24X0_REG32	SDICON;
-	S3C24X0_REG32	SDIPRE;
-	S3C24X0_REG32	SDICARG;
-	S3C24X0_REG32	SDICCON;
-	S3C24X0_REG32	SDICSTA;
-	S3C24X0_REG32	SDIRSP0;
-	S3C24X0_REG32	SDIRSP1;
-	S3C24X0_REG32	SDIRSP2;
-	S3C24X0_REG32	SDIRSP3;
-	S3C24X0_REG32	SDIDTIMER;
-	S3C24X0_REG32	SDIBSIZE;
-	S3C24X0_REG32	SDIDCON;
-	S3C24X0_REG32	SDIDCNT;
-	S3C24X0_REG32	SDIDSTA;
-	S3C24X0_REG32	SDIFSTA;
+    S3C24X0_REG32   SDICON;
+    S3C24X0_REG32   SDIPRE;
+    S3C24X0_REG32   SDICARG;
+    S3C24X0_REG32   SDICCON;
+    S3C24X0_REG32   SDICSTA;
+    S3C24X0_REG32   SDIRSP0;
+    S3C24X0_REG32   SDIRSP1;
+    S3C24X0_REG32   SDIRSP2;
+    S3C24X0_REG32   SDIRSP3;
+    S3C24X0_REG32   SDIDTIMER;
+    S3C24X0_REG32   SDIBSIZE;
+    S3C24X0_REG32   SDIDCON;
+    S3C24X0_REG32   SDIDCNT;
+    S3C24X0_REG32   SDIDSTA;
+    S3C24X0_REG32   SDIFSTA;
 #ifdef __BIG_ENDIAN
-	S3C24X0_REG8	res[3];
-	S3C24X0_REG8	SDIDAT;
+    S3C24X0_REG8    res[3];
+    S3C24X0_REG8    SDIDAT;
 #else
-	S3C24X0_REG8	SDIDAT;
-	S3C24X0_REG8	res[3];
+    S3C24X0_REG8    SDIDAT;
+    S3C24X0_REG8    res[3];
 #endif
-	S3C24X0_REG32	SDIIMSK;
+    S3C24X0_REG32   SDIIMSK;
 } /*__attribute__((__packed__))*/ S3C2410_SDI;
 
 
 #if 0
 /* Memory control */
-#define rBWSCON			(*(volatile unsigned *)0x48000000)
-#define rBANKCON0		(*(volatile unsigned *)0x48000004)
-#define rBANKCON1		(*(volatile unsigned *)0x48000008)
-#define rBANKCON2		(*(volatile unsigned *)0x4800000C)
-#define rBANKCON3		(*(volatile unsigned *)0x48000010)
-#define rBANKCON4		(*(volatile unsigned *)0x48000014)
-#define rBANKCON5		(*(volatile unsigned *)0x48000018)
-#define rBANKCON6		(*(volatile unsigned *)0x4800001C)
-#define rBANKCON7		(*(volatile unsigned *)0x48000020)
-#define rREFRESH		(*(volatile unsigned *)0x48000024)
-#define rBANKSIZE		(*(volatile unsigned *)0x48000028)
-#define rMRSRB6			(*(volatile unsigned *)0x4800002C)
-#define rMRSRB7			(*(volatile unsigned *)0x48000030)
+#define rBWSCON         (*(volatile unsigned *)0x48000000)
+#define rBANKCON0       (*(volatile unsigned *)0x48000004)
+#define rBANKCON1       (*(volatile unsigned *)0x48000008)
+#define rBANKCON2       (*(volatile unsigned *)0x4800000C)
+#define rBANKCON3       (*(volatile unsigned *)0x48000010)
+#define rBANKCON4       (*(volatile unsigned *)0x48000014)
+#define rBANKCON5       (*(volatile unsigned *)0x48000018)
+#define rBANKCON6       (*(volatile unsigned *)0x4800001C)
+#define rBANKCON7       (*(volatile unsigned *)0x48000020)
+#define rREFRESH        (*(volatile unsigned *)0x48000024)
+#define rBANKSIZE       (*(volatile unsigned *)0x48000028)
+#define rMRSRB6         (*(volatile unsigned *)0x4800002C)
+#define rMRSRB7         (*(volatile unsigned *)0x48000030)
 
 
 /* USB HOST */
-#define rHcRevision		(*(volatile unsigned *)0x49000000)
-#define rHcControl		(*(volatile unsigned *)0x49000004)
-#define rHcCommonStatus		(*(volatile unsigned *)0x49000008)
-#define rHcInterruptStatus	(*(volatile unsigned *)0x4900000C)
-#define rHcInterruptEnable	(*(volatile unsigned *)0x49000010)
-#define rHcInterruptDisable	(*(volatile unsigned *)0x49000014)
-#define rHcHCCA			(*(volatile unsigned *)0x49000018)
-#define rHcPeriodCuttendED	(*(volatile unsigned *)0x4900001C)
-#define rHcControlHeadED	(*(volatile unsigned *)0x49000020)
-#define rHcControlCurrentED	(*(volatile unsigned *)0x49000024)
-#define rHcBulkHeadED		(*(volatile unsigned *)0x49000028)
-#define rHcBuldCurrentED	(*(volatile unsigned *)0x4900002C)
-#define rHcDoneHead		(*(volatile unsigned *)0x49000030)
-#define rHcRmInterval		(*(volatile unsigned *)0x49000034)
-#define rHcFmRemaining		(*(volatile unsigned *)0x49000038)
-#define rHcFmNumber		(*(volatile unsigned *)0x4900003C)
-#define rHcPeriodicStart	(*(volatile unsigned *)0x49000040)
-#define rHcLSThreshold		(*(volatile unsigned *)0x49000044)
-#define rHcRhDescriptorA	(*(volatile unsigned *)0x49000048)
-#define rHcRhDescriptorB	(*(volatile unsigned *)0x4900004C)
-#define rHcRhStatus		(*(volatile unsigned *)0x49000050)
-#define rHcRhPortStatus1	(*(volatile unsigned *)0x49000054)
-#define rHcRhPortStatus2	(*(volatile unsigned *)0x49000058)
+#define rHcRevision     (*(volatile unsigned *)0x49000000)
+#define rHcControl      (*(volatile unsigned *)0x49000004)
+#define rHcCommonStatus     (*(volatile unsigned *)0x49000008)
+#define rHcInterruptStatus  (*(volatile unsigned *)0x4900000C)
+#define rHcInterruptEnable  (*(volatile unsigned *)0x49000010)
+#define rHcInterruptDisable (*(volatile unsigned *)0x49000014)
+#define rHcHCCA         (*(volatile unsigned *)0x49000018)
+#define rHcPeriodCuttendED  (*(volatile unsigned *)0x4900001C)
+#define rHcControlHeadED    (*(volatile unsigned *)0x49000020)
+#define rHcControlCurrentED (*(volatile unsigned *)0x49000024)
+#define rHcBulkHeadED       (*(volatile unsigned *)0x49000028)
+#define rHcBuldCurrentED    (*(volatile unsigned *)0x4900002C)
+#define rHcDoneHead     (*(volatile unsigned *)0x49000030)
+#define rHcRmInterval       (*(volatile unsigned *)0x49000034)
+#define rHcFmRemaining      (*(volatile unsigned *)0x49000038)
+#define rHcFmNumber     (*(volatile unsigned *)0x4900003C)
+#define rHcPeriodicStart    (*(volatile unsigned *)0x49000040)
+#define rHcLSThreshold      (*(volatile unsigned *)0x49000044)
+#define rHcRhDescriptorA    (*(volatile unsigned *)0x49000048)
+#define rHcRhDescriptorB    (*(volatile unsigned *)0x4900004C)
+#define rHcRhStatus     (*(volatile unsigned *)0x49000050)
+#define rHcRhPortStatus1    (*(volatile unsigned *)0x49000054)
+#define rHcRhPortStatus2    (*(volatile unsigned *)0x49000058)
 
 
 /* INTERRUPT */
-#define rSRCPND			(*(volatile unsigned *)0x4A000000)
-#define rINTMOD			(*(volatile unsigned *)0x4A000004)
-#define rINTMSK			(*(volatile unsigned *)0x4A000008)
-#define rPRIORITY		(*(volatile unsigned *)0x4A00000C)
-#define rINTPND			(*(volatile unsigned *)0x4A000010)
-#define rINTOFFSET		(*(volatile unsigned *)0x4A000014)
-#define rSUBSRCPND		(*(volatile unsigned *)0x4A000018)
-#define rINTSUBMSK		(*(volatile unsigned *)0x4A00001C)
+#define rSRCPND         (*(volatile unsigned *)0x4A000000)
+#define rINTMOD         (*(volatile unsigned *)0x4A000004)
+#define rINTMSK         (*(volatile unsigned *)0x4A000008)
+#define rPRIORITY       (*(volatile unsigned *)0x4A00000C)
+#define rINTPND         (*(volatile unsigned *)0x4A000010)
+#define rINTOFFSET      (*(volatile unsigned *)0x4A000014)
+#define rSUBSRCPND      (*(volatile unsigned *)0x4A000018)
+#define rINTSUBMSK      (*(volatile unsigned *)0x4A00001C)
 
 
 /* DMA */
-#define rDISRC0			(*(volatile unsigned *)0x4B000000)
-#define rDISRCC0		(*(volatile unsigned *)0x4B000004)
-#define rDIDST0			(*(volatile unsigned *)0x4B000008)
-#define rDIDSTC0		(*(volatile unsigned *)0x4B00000C)
-#define rDCON0			(*(volatile unsigned *)0x4B000010)
-#define rDSTAT0			(*(volatile unsigned *)0x4B000014)
-#define rDCSRC0			(*(volatile unsigned *)0x4B000018)
-#define rDCDST0			(*(volatile unsigned *)0x4B00001C)
-#define rDMASKTRIG0		(*(volatile unsigned *)0x4B000020)
-#define rDISRC1			(*(volatile unsigned *)0x4B000040)
-#define rDISRCC1		(*(volatile unsigned *)0x4B000044)
-#define rDIDST1			(*(volatile unsigned *)0x4B000048)
-#define rDIDSTC1		(*(volatile unsigned *)0x4B00004C)
-#define rDCON1			(*(volatile unsigned *)0x4B000050)
-#define rDSTAT1			(*(volatile unsigned *)0x4B000054)
-#define rDCSRC1			(*(volatile unsigned *)0x4B000058)
-#define rDCDST1			(*(volatile unsigned *)0x4B00005C)
-#define rDMASKTRIG1		(*(volatile unsigned *)0x4B000060)
-#define rDISRC2			(*(volatile unsigned *)0x4B000080)
-#define rDISRCC2		(*(volatile unsigned *)0x4B000084)
-#define rDIDST2			(*(volatile unsigned *)0x4B000088)
-#define rDIDSTC2		(*(volatile unsigned *)0x4B00008C)
-#define rDCON2			(*(volatile unsigned *)0x4B000090)
-#define rDSTAT2			(*(volatile unsigned *)0x4B000094)
-#define rDCSRC2			(*(volatile unsigned *)0x4B000098)
-#define rDCDST2			(*(volatile unsigned *)0x4B00009C)
-#define rDMASKTRIG2		(*(volatile unsigned *)0x4B0000A0)
-#define rDISRC3			(*(volatile unsigned *)0x4B0000C0)
-#define rDISRCC3		(*(volatile unsigned *)0x4B0000C4)
-#define rDIDST3			(*(volatile unsigned *)0x4B0000C8)
-#define rDIDSTC3		(*(volatile unsigned *)0x4B0000CC)
-#define rDCON3			(*(volatile unsigned *)0x4B0000D0)
-#define rDSTAT3			(*(volatile unsigned *)0x4B0000D4)
-#define rDCSRC3			(*(volatile unsigned *)0x4B0000D8)
-#define rDCDST3			(*(volatile unsigned *)0x4B0000DC)
-#define rDMASKTRIG3		(*(volatile unsigned *)0x4B0000E0)
+#define rDISRC0         (*(volatile unsigned *)0x4B000000)
+#define rDISRCC0        (*(volatile unsigned *)0x4B000004)
+#define rDIDST0         (*(volatile unsigned *)0x4B000008)
+#define rDIDSTC0        (*(volatile unsigned *)0x4B00000C)
+#define rDCON0          (*(volatile unsigned *)0x4B000010)
+#define rDSTAT0         (*(volatile unsigned *)0x4B000014)
+#define rDCSRC0         (*(volatile unsigned *)0x4B000018)
+#define rDCDST0         (*(volatile unsigned *)0x4B00001C)
+#define rDMASKTRIG0     (*(volatile unsigned *)0x4B000020)
+#define rDISRC1         (*(volatile unsigned *)0x4B000040)
+#define rDISRCC1        (*(volatile unsigned *)0x4B000044)
+#define rDIDST1         (*(volatile unsigned *)0x4B000048)
+#define rDIDSTC1        (*(volatile unsigned *)0x4B00004C)
+#define rDCON1          (*(volatile unsigned *)0x4B000050)
+#define rDSTAT1         (*(volatile unsigned *)0x4B000054)
+#define rDCSRC1         (*(volatile unsigned *)0x4B000058)
+#define rDCDST1         (*(volatile unsigned *)0x4B00005C)
+#define rDMASKTRIG1     (*(volatile unsigned *)0x4B000060)
+#define rDISRC2         (*(volatile unsigned *)0x4B000080)
+#define rDISRCC2        (*(volatile unsigned *)0x4B000084)
+#define rDIDST2         (*(volatile unsigned *)0x4B000088)
+#define rDIDSTC2        (*(volatile unsigned *)0x4B00008C)
+#define rDCON2          (*(volatile unsigned *)0x4B000090)
+#define rDSTAT2         (*(volatile unsigned *)0x4B000094)
+#define rDCSRC2         (*(volatile unsigned *)0x4B000098)
+#define rDCDST2         (*(volatile unsigned *)0x4B00009C)
+#define rDMASKTRIG2     (*(volatile unsigned *)0x4B0000A0)
+#define rDISRC3         (*(volatile unsigned *)0x4B0000C0)
+#define rDISRCC3        (*(volatile unsigned *)0x4B0000C4)
+#define rDIDST3         (*(volatile unsigned *)0x4B0000C8)
+#define rDIDSTC3        (*(volatile unsigned *)0x4B0000CC)
+#define rDCON3          (*(volatile unsigned *)0x4B0000D0)
+#define rDSTAT3         (*(volatile unsigned *)0x4B0000D4)
+#define rDCSRC3         (*(volatile unsigned *)0x4B0000D8)
+#define rDCDST3         (*(volatile unsigned *)0x4B0000DC)
+#define rDMASKTRIG3     (*(volatile unsigned *)0x4B0000E0)
 
 
 /* CLOCK & POWER MANAGEMENT */
-#define rLOCKTIME		(*(volatile unsigned *)0x4C000000)
-#define rMPLLCON		(*(volatile unsigned *)0x4C000004)
-#define rUPLLCON		(*(volatile unsigned *)0x4C000008)
-#define rCLKCON			(*(volatile unsigned *)0x4C00000C)
-#define rCLKSLOW		(*(volatile unsigned *)0x4C000010)
-#define rCLKDIVN		(*(volatile unsigned *)0x4C000014)
+#define rLOCKTIME       (*(volatile unsigned *)0x4C000000)
+#define rMPLLCON        (*(volatile unsigned *)0x4C000004)
+#define rUPLLCON        (*(volatile unsigned *)0x4C000008)
+#define rCLKCON         (*(volatile unsigned *)0x4C00000C)
+#define rCLKSLOW        (*(volatile unsigned *)0x4C000010)
+#define rCLKDIVN        (*(volatile unsigned *)0x4C000014)
 
 
 /* LCD CONTROLLER */
-#define rLCDCON1		(*(volatile unsigned *)0x4D000000)
-#define rLCDCON2		(*(volatile unsigned *)0x4D000004)
-#define rLCDCON3		(*(volatile unsigned *)0x4D000008)
-#define rLCDCON4		(*(volatile unsigned *)0x4D00000C)
-#define rLCDCON5		(*(volatile unsigned *)0x4D000010)
-#define rLCDSADDR1		(*(volatile unsigned *)0x4D000014)
-#define rLCDSADDR2		(*(volatile unsigned *)0x4D000018)
-#define rLCDSADDR3		(*(volatile unsigned *)0x4D00001C)
-#define rREDLUT			(*(volatile unsigned *)0x4D000020)
-#define rGREENLUT		(*(volatile unsigned *)0x4D000024)
-#define rBLUELUT		(*(volatile unsigned *)0x4D000028)
-#define rDITHMODE		(*(volatile unsigned *)0x4D00004C)
-#define rTPAL			(*(volatile unsigned *)0x4D000050)
-#define rLCDINTPND		(*(volatile unsigned *)0x4D000054)
-#define rLCDSRCPND		(*(volatile unsigned *)0x4D000058)
-#define rLCDINTMSK		(*(volatile unsigned *)0x4D00005C)
+#define rLCDCON1        (*(volatile unsigned *)0x4D000000)
+#define rLCDCON2        (*(volatile unsigned *)0x4D000004)
+#define rLCDCON3        (*(volatile unsigned *)0x4D000008)
+#define rLCDCON4        (*(volatile unsigned *)0x4D00000C)
+#define rLCDCON5        (*(volatile unsigned *)0x4D000010)
+#define rLCDSADDR1      (*(volatile unsigned *)0x4D000014)
+#define rLCDSADDR2      (*(volatile unsigned *)0x4D000018)
+#define rLCDSADDR3      (*(volatile unsigned *)0x4D00001C)
+#define rREDLUT         (*(volatile unsigned *)0x4D000020)
+#define rGREENLUT       (*(volatile unsigned *)0x4D000024)
+#define rBLUELUT        (*(volatile unsigned *)0x4D000028)
+#define rDITHMODE       (*(volatile unsigned *)0x4D00004C)
+#define rTPAL           (*(volatile unsigned *)0x4D000050)
+#define rLCDINTPND      (*(volatile unsigned *)0x4D000054)
+#define rLCDSRCPND      (*(volatile unsigned *)0x4D000058)
+#define rLCDINTMSK      (*(volatile unsigned *)0x4D00005C)
 
 
 /* NAND FLASH */
-#define rNFCONF			(*(volatile unsigned *)0x4E000000)
-#define rNFCMD			(*(volatile unsigned *)0x4E000004)
-#define rNFADDR			(*(volatile unsigned *)0x4E000008)
-#define rNFDATA			(*(volatile unsigned *)0x4E00000C)
-#define rNFSTAT			(*(volatile unsigned *)0x4E000010)
-#define rNFECC			(*(volatile unsigned *)0x4E000014)
+#define rNFCONF         (*(volatile unsigned *)0x4E000000)
+#define rNFCMD          (*(volatile unsigned *)0x4E000004)
+#define rNFADDR         (*(volatile unsigned *)0x4E000008)
+#define rNFDATA         (*(volatile unsigned *)0x4E00000C)
+#define rNFSTAT         (*(volatile unsigned *)0x4E000010)
+#define rNFECC          (*(volatile unsigned *)0x4E000014)
 
 
 /* UART */
-#define rULCON0			(*(volatile unsigned *)0x50000000)
-#define rUCON0			(*(volatile unsigned *)0x50000004)
-#define rUFCON0			(*(volatile unsigned *)0x50000008)
-#define rUMCON0			(*(volatile unsigned *)0x5000000C)
-#define rUTRSTAT0		(*(volatile unsigned *)0x50000010)
-#define rUERSTAT0		(*(volatile unsigned *)0x50000014)
-#define rUFSTAT0		(*(volatile unsigned *)0x50000018)
-#define rUMSTAT0		(*(volatile unsigned *)0x5000001C)
-#define rUBRDIV0		(*(volatile unsigned *)0x50000028)
-
-#define rULCON1			(*(volatile unsigned *)0x50004000)
-#define rUCON1			(*(volatile unsigned *)0x50004004)
-#define rUFCON1			(*(volatile unsigned *)0x50004008)
-#define rUMCON1			(*(volatile unsigned *)0x5000400C)
-#define rUTRSTAT1		(*(volatile unsigned *)0x50004010)
-#define rUERSTAT1		(*(volatile unsigned *)0x50004014)
-#define rUFSTAT1		(*(volatile unsigned *)0x50004018)
-#define rUMSTAT1		(*(volatile unsigned *)0x5000401C)
-#define rUBRDIV1		(*(volatile unsigned *)0x50004028)
-
-#define rULCON2			(*(volatile unsigned *)0x50008000)
-#define rUCON2			(*(volatile unsigned *)0x50008004)
-#define rUFCON2			(*(volatile unsigned *)0x50008008)
-#define rUTRSTAT2		(*(volatile unsigned *)0x50008010)
-#define rUERSTAT2		(*(volatile unsigned *)0x50008014)
-#define rUFSTAT2		(*(volatile unsigned *)0x50008018)
-#define rUBRDIV2		(*(volatile unsigned *)0x50008028)
+#define rULCON0         (*(volatile unsigned *)0x50000000)
+#define rUCON0          (*(volatile unsigned *)0x50000004)
+#define rUFCON0         (*(volatile unsigned *)0x50000008)
+#define rUMCON0         (*(volatile unsigned *)0x5000000C)
+#define rUTRSTAT0       (*(volatile unsigned *)0x50000010)
+#define rUERSTAT0       (*(volatile unsigned *)0x50000014)
+#define rUFSTAT0        (*(volatile unsigned *)0x50000018)
+#define rUMSTAT0        (*(volatile unsigned *)0x5000001C)
+#define rUBRDIV0        (*(volatile unsigned *)0x50000028)
+
+#define rULCON1         (*(volatile unsigned *)0x50004000)
+#define rUCON1          (*(volatile unsigned *)0x50004004)
+#define rUFCON1         (*(volatile unsigned *)0x50004008)
+#define rUMCON1         (*(volatile unsigned *)0x5000400C)
+#define rUTRSTAT1       (*(volatile unsigned *)0x50004010)
+#define rUERSTAT1       (*(volatile unsigned *)0x50004014)
+#define rUFSTAT1        (*(volatile unsigned *)0x50004018)
+#define rUMSTAT1        (*(volatile unsigned *)0x5000401C)
+#define rUBRDIV1        (*(volatile unsigned *)0x50004028)
+
+#define rULCON2         (*(volatile unsigned *)0x50008000)
+#define rUCON2          (*(volatile unsigned *)0x50008004)
+#define rUFCON2         (*(volatile unsigned *)0x50008008)
+#define rUTRSTAT2       (*(volatile unsigned *)0x50008010)
+#define rUERSTAT2       (*(volatile unsigned *)0x50008014)
+#define rUFSTAT2        (*(volatile unsigned *)0x50008018)
+#define rUBRDIV2        (*(volatile unsigned *)0x50008028)
 
 #ifdef __BIG_ENDIAN
-#define rUTXH0			(*(volatile unsigned char *)0x50000023)
-#define rURXH0			(*(volatile unsigned char *)0x50000027)
-#define rUTXH1			(*(volatile unsigned char *)0x50004023)
-#define rURXH1			(*(volatile unsigned char *)0x50004027)
-#define rUTXH2			(*(volatile unsigned char *)0x50008023)
-#define rURXH2			(*(volatile unsigned char *)0x50008027)
-
-#define WrUTXH0(ch)		(*(volatile unsigned char *)0x50000023)=(unsigned char)(ch)
-#define RdURXH0()		(*(volatile unsigned char *)0x50000027)
-#define WrUTXH1(ch)		(*(volatile unsigned char *)0x50004023)=(unsigned char)(ch)
-#define RdURXH1()		(*(volatile unsigned char *)0x50004027)
-#define WrUTXH2(ch)		(*(volatile unsigned char *)0x50008023)=(unsigned char)(ch)
-#define RdURXH2()		(*(volatile unsigned char *)0x50008027)
-
-#define UTXH0			(0x50000020+3)  /* byte_access address by DMA */
-#define URXH0			(0x50000024+3)
-#define UTXH1			(0x50004020+3)
-#define URXH1			(0x50004024+3)
-#define UTXH2			(0x50008020+3)
-#define URXH2			(0x50008024+3)
+#define rUTXH0          (*(volatile unsigned char *)0x50000023)
+#define rURXH0          (*(volatile unsigned char *)0x50000027)
+#define rUTXH1          (*(volatile unsigned char *)0x50004023)
+#define rURXH1          (*(volatile unsigned char *)0x50004027)
+#define rUTXH2          (*(volatile unsigned char *)0x50008023)
+#define rURXH2          (*(volatile unsigned char *)0x50008027)
+
+#define WrUTXH0(ch)     (*(volatile unsigned char *)0x50000023)=(unsigned char)(ch)
+#define RdURXH0()       (*(volatile unsigned char *)0x50000027)
+#define WrUTXH1(ch)     (*(volatile unsigned char *)0x50004023)=(unsigned char)(ch)
+#define RdURXH1()       (*(volatile unsigned char *)0x50004027)
+#define WrUTXH2(ch)     (*(volatile unsigned char *)0x50008023)=(unsigned char)(ch)
+#define RdURXH2()       (*(volatile unsigned char *)0x50008027)
+
+#define UTXH0           (0x50000020+3)  /* byte_access address by DMA */
+#define URXH0           (0x50000024+3)
+#define UTXH1           (0x50004020+3)
+#define URXH1           (0x50004024+3)
+#define UTXH2           (0x50008020+3)
+#define URXH2           (0x50008024+3)
 
 #else /* Little Endian */
-#define rUTXH0			(*(volatile unsigned char *)0x50000020)
-#define rURXH0			(*(volatile unsigned char *)0x50000024)
-#define rUTXH1			(*(volatile unsigned char *)0x50004020)
-#define rURXH1			(*(volatile unsigned char *)0x50004024)
-#define rUTXH2			(*(volatile unsigned char *)0x50008020)
-#define rURXH2			(*(volatile unsigned char *)0x50008024)
-
-#define WrUTXH0(ch)		(*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
-#define RdURXH0()		(*(volatile unsigned char *)0x50000024)
-#define WrUTXH1(ch)		(*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
-#define RdURXH1()		(*(volatile unsigned char *)0x50004024)
-#define WrUTXH2(ch)		(*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
-#define RdURXH2()		(*(volatile unsigned char *)0x50008024)
-
-#define UTXH0			(0x50000020)    /* byte_access address by DMA */
-#define URXH0			(0x50000024)
-#define UTXH1			(0x50004020)
-#define URXH1			(0x50004024)
-#define UTXH2			(0x50008020)
-#define URXH2			(0x50008024)
+#define rUTXH0          (*(volatile unsigned char *)0x50000020)
+#define rURXH0          (*(volatile unsigned char *)0x50000024)
+#define rUTXH1          (*(volatile unsigned char *)0x50004020)
+#define rURXH1          (*(volatile unsigned char *)0x50004024)
+#define rUTXH2          (*(volatile unsigned char *)0x50008020)
+#define rURXH2          (*(volatile unsigned char *)0x50008024)
+
+#define WrUTXH0(ch)     (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
+#define RdURXH0()       (*(volatile unsigned char *)0x50000024)
+#define WrUTXH1(ch)     (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
+#define RdURXH1()       (*(volatile unsigned char *)0x50004024)
+#define WrUTXH2(ch)     (*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
+#define RdURXH2()       (*(volatile unsigned char *)0x50008024)
+
+#define UTXH0           (0x50000020)    /* byte_access address by DMA */
+#define URXH0           (0x50000024)
+#define UTXH1           (0x50004020)
+#define URXH1           (0x50004024)
+#define UTXH2           (0x50008020)
+#define URXH2           (0x50008024)
 #endif
 
 
 /* PWM TIMER */
-#define rTCFG0			(*(volatile unsigned *)0x51000000)
-#define rTCFG1			(*(volatile unsigned *)0x51000004)
-#define rTCON			(*(volatile unsigned *)0x51000008)
-#define rTCNTB0			(*(volatile unsigned *)0x5100000C)
-#define rTCMPB0			(*(volatile unsigned *)0x51000010)
-#define rTCNTO0			(*(volatile unsigned *)0x51000014)
-#define rTCNTB1			(*(volatile unsigned *)0x51000018)
-#define rTCMPB1			(*(volatile unsigned *)0x5100001C)
-#define rTCNTO1			(*(volatile unsigned *)0x51000020)
-#define rTCNTB2			(*(volatile unsigned *)0x51000024)
-#define rTCMPB2			(*(volatile unsigned *)0x51000028)
-#define rTCNTO2			(*(volatile unsigned *)0x5100002C)
-#define rTCNTB3			(*(volatile unsigned *)0x51000030)
-#define rTCMPB3			(*(volatile unsigned *)0x51000034)
-#define rTCNTO3			(*(volatile unsigned *)0x51000038)
-#define rTCNTB4			(*(volatile unsigned *)0x5100003C)
-#define rTCNTO4			(*(volatile unsigned *)0x51000040)
+#define rTCFG0          (*(volatile unsigned *)0x51000000)
+#define rTCFG1          (*(volatile unsigned *)0x51000004)
+#define rTCON           (*(volatile unsigned *)0x51000008)
+#define rTCNTB0         (*(volatile unsigned *)0x5100000C)
+#define rTCMPB0         (*(volatile unsigned *)0x51000010)
+#define rTCNTO0         (*(volatile unsigned *)0x51000014)
+#define rTCNTB1         (*(volatile unsigned *)0x51000018)
+#define rTCMPB1         (*(volatile unsigned *)0x5100001C)
+#define rTCNTO1         (*(volatile unsigned *)0x51000020)
+#define rTCNTB2         (*(volatile unsigned *)0x51000024)
+#define rTCMPB2         (*(volatile unsigned *)0x51000028)
+#define rTCNTO2         (*(volatile unsigned *)0x5100002C)
+#define rTCNTB3         (*(volatile unsigned *)0x51000030)
+#define rTCMPB3         (*(volatile unsigned *)0x51000034)
+#define rTCNTO3         (*(volatile unsigned *)0x51000038)
+#define rTCNTB4         (*(volatile unsigned *)0x5100003C)
+#define rTCNTO4         (*(volatile unsigned *)0x51000040)
 
 
 /* USB DEVICE */
 #ifdef __BIG_ENDIAN
-#define rFUNC_ADDR_REG		(*(volatile unsigned char *)0x52000143)
-#define rPWR_REG		(*(volatile unsigned char *)0x52000147)
-#define rEP_INT_REG		(*(volatile unsigned char *)0x5200014B)
-#define rUSB_INT_REG		(*(volatile unsigned char *)0x5200015B)
-#define rEP_INT_EN_REG		(*(volatile unsigned char *)0x5200015F)
-#define rUSB_INT_EN_REG		(*(volatile unsigned char *)0x5200016F)
-#define rFRAME_NUM1_REG		(*(volatile unsigned char *)0x52000173)
-#define rFRAME_NUM2_REG		(*(volatile unsigned char *)0x52000177)
-#define rINDEX_REG		(*(volatile unsigned char *)0x5200017B)
-#define rMAXP_REG		(*(volatile unsigned char *)0x52000183)
-#define rEP0_CSR		(*(volatile unsigned char *)0x52000187)
-#define rIN_CSR1_REG		(*(volatile unsigned char *)0x52000187)
-#define rIN_CSR2_REG		(*(volatile unsigned char *)0x5200018B)
-#define rOUT_CSR1_REG		(*(volatile unsigned char *)0x52000193)
-#define rOUT_CSR2_REG		(*(volatile unsigned char *)0x52000197)
-#define rOUT_FIFO_CNT1_REG	(*(volatile unsigned char *)0x5200019B)
-#define rOUT_FIFO_CNT2_REG	(*(volatile unsigned char *)0x5200019F)
-#define rEP0_FIFO		(*(volatile unsigned char *)0x520001C3)
-#define rEP1_FIFO		(*(volatile unsigned char *)0x520001C7)
-#define rEP2_FIFO		(*(volatile unsigned char *)0x520001CB)
-#define rEP3_FIFO		(*(volatile unsigned char *)0x520001CF)
-#define rEP4_FIFO		(*(volatile unsigned char *)0x520001D3)
-#define rEP1_DMA_CON		(*(volatile unsigned char *)0x52000203)
-#define rEP1_DMA_UNIT		(*(volatile unsigned char *)0x52000207)
-#define rEP1_DMA_FIFO		(*(volatile unsigned char *)0x5200020B)
-#define rEP1_DMA_TX_LO		(*(volatile unsigned char *)0x5200020F)
-#define rEP1_DMA_TX_MD		(*(volatile unsigned char *)0x52000213)
-#define rEP1_DMA_TX_HI		(*(volatile unsigned char *)0x52000217)
-#define rEP2_DMA_CON		(*(volatile unsigned char *)0x5200021B)
-#define rEP2_DMA_UNIT		(*(volatile unsigned char *)0x5200021F)
-#define rEP2_DMA_FIFO		(*(volatile unsigned char *)0x52000223)
-#define rEP2_DMA_TX_LO		(*(volatile unsigned char *)0x52000227)
-#define rEP2_DMA_TX_MD		(*(volatile unsigned char *)0x5200022B)
-#define rEP2_DMA_TX_HI		(*(volatile unsigned char *)0x5200022F)
-#define rEP3_DMA_CON		(*(volatile unsigned char *)0x52000243)
-#define rEP3_DMA_UNIT		(*(volatile unsigned char *)0x52000247)
-#define rEP3_DMA_FIFO		(*(volatile unsigned char *)0x5200024B)
-#define rEP3_DMA_TX_LO		(*(volatile unsigned char *)0x5200024F)
-#define rEP3_DMA_TX_MD		(*(volatile unsigned char *)0x52000253)
-#define rEP3_DMA_TX_HI		(*(volatile unsigned char *)0x52000257)
-#define rEP4_DMA_CON		(*(volatile unsigned char *)0x5200025B)
-#define rEP4_DMA_UNIT		(*(volatile unsigned char *)0x5200025F)
-#define rEP4_DMA_FIFO		(*(volatile unsigned char *)0x52000263)
-#define rEP4_DMA_TX_LO		(*(volatile unsigned char *)0x52000267)
-#define rEP4_DMA_TX_MD		(*(volatile unsigned char *)0x5200026B)
-#define rEP4_DMA_TX_HI		(*(volatile unsigned char *)0x5200026F)
+#define rFUNC_ADDR_REG      (*(volatile unsigned char *)0x52000143)
+#define rPWR_REG        (*(volatile unsigned char *)0x52000147)
+#define rEP_INT_REG     (*(volatile unsigned char *)0x5200014B)
+#define rUSB_INT_REG        (*(volatile unsigned char *)0x5200015B)
+#define rEP_INT_EN_REG      (*(volatile unsigned char *)0x5200015F)
+#define rUSB_INT_EN_REG     (*(volatile unsigned char *)0x5200016F)
+#define rFRAME_NUM1_REG     (*(volatile unsigned char *)0x52000173)
+#define rFRAME_NUM2_REG     (*(volatile unsigned char *)0x52000177)
+#define rINDEX_REG      (*(volatile unsigned char *)0x5200017B)
+#define rMAXP_REG       (*(volatile unsigned char *)0x52000183)
+#define rEP0_CSR        (*(volatile unsigned char *)0x52000187)
+#define rIN_CSR1_REG        (*(volatile unsigned char *)0x52000187)
+#define rIN_CSR2_REG        (*(volatile unsigned char *)0x5200018B)
+#define rOUT_CSR1_REG       (*(volatile unsigned char *)0x52000193)
+#define rOUT_CSR2_REG       (*(volatile unsigned char *)0x52000197)
+#define rOUT_FIFO_CNT1_REG  (*(volatile unsigned char *)0x5200019B)
+#define rOUT_FIFO_CNT2_REG  (*(volatile unsigned char *)0x5200019F)
+#define rEP0_FIFO       (*(volatile unsigned char *)0x520001C3)
+#define rEP1_FIFO       (*(volatile unsigned char *)0x520001C7)
+#define rEP2_FIFO       (*(volatile unsigned char *)0x520001CB)
+#define rEP3_FIFO       (*(volatile unsigned char *)0x520001CF)
+#define rEP4_FIFO       (*(volatile unsigned char *)0x520001D3)
+#define rEP1_DMA_CON        (*(volatile unsigned char *)0x52000203)
+#define rEP1_DMA_UNIT       (*(volatile unsigned char *)0x52000207)
+#define rEP1_DMA_FIFO       (*(volatile unsigned char *)0x5200020B)
+#define rEP1_DMA_TX_LO      (*(volatile unsigned char *)0x5200020F)
+#define rEP1_DMA_TX_MD      (*(volatile unsigned char *)0x52000213)
+#define rEP1_DMA_TX_HI      (*(volatile unsigned char *)0x52000217)
+#define rEP2_DMA_CON        (*(volatile unsigned char *)0x5200021B)
+#define rEP2_DMA_UNIT       (*(volatile unsigned char *)0x5200021F)
+#define rEP2_DMA_FIFO       (*(volatile unsigned char *)0x52000223)
+#define rEP2_DMA_TX_LO      (*(volatile unsigned char *)0x52000227)
+#define rEP2_DMA_TX_MD      (*(volatile unsigned char *)0x5200022B)
+#define rEP2_DMA_TX_HI      (*(volatile unsigned char *)0x5200022F)
+#define rEP3_DMA_CON        (*(volatile unsigned char *)0x52000243)
+#define rEP3_DMA_UNIT       (*(volatile unsigned char *)0x52000247)
+#define rEP3_DMA_FIFO       (*(volatile unsigned char *)0x5200024B)
+#define rEP3_DMA_TX_LO      (*(volatile unsigned char *)0x5200024F)
+#define rEP3_DMA_TX_MD      (*(volatile unsigned char *)0x52000253)
+#define rEP3_DMA_TX_HI      (*(volatile unsigned char *)0x52000257)
+#define rEP4_DMA_CON        (*(volatile unsigned char *)0x5200025B)
+#define rEP4_DMA_UNIT       (*(volatile unsigned char *)0x5200025F)
+#define rEP4_DMA_FIFO       (*(volatile unsigned char *)0x52000263)
+#define rEP4_DMA_TX_LO      (*(volatile unsigned char *)0x52000267)
+#define rEP4_DMA_TX_MD      (*(volatile unsigned char *)0x5200026B)
+#define rEP4_DMA_TX_HI      (*(volatile unsigned char *)0x5200026F)
 #else /*  little endian */
-#define rFUNC_ADDR_REG		(*(volatile unsigned char *)0x52000140)
-#define rPWR_REG		(*(volatile unsigned char *)0x52000144)
-#define rEP_INT_REG		(*(volatile unsigned char *)0x52000148)
-#define rUSB_INT_REG		(*(volatile unsigned char *)0x52000158)
-#define rEP_INT_EN_REG		(*(volatile unsigned char *)0x5200015C)
-#define rUSB_INT_EN_REG		(*(volatile unsigned char *)0x5200016C)
-#define rFRAME_NUM1_REG		(*(volatile unsigned char *)0x52000170)
-#define rFRAME_NUM2_REG		(*(volatile unsigned char *)0x52000174)
-#define rINDEX_REG		(*(volatile unsigned char *)0x52000178)
-#define rMAXP_REG		(*(volatile unsigned char *)0x52000180)
-#define rEP0_CSR		(*(volatile unsigned char *)0x52000184)
-#define rIN_CSR1_REG		(*(volatile unsigned char *)0x52000184)
-#define rIN_CSR2_REG		(*(volatile unsigned char *)0x52000188)
-#define rOUT_CSR1_REG		(*(volatile unsigned char *)0x52000190)
-#define rOUT_CSR2_REG		(*(volatile unsigned char *)0x52000194)
-#define rOUT_FIFO_CNT1_REG	(*(volatile unsigned char *)0x52000198)
-#define rOUT_FIFO_CNT2_REG	(*(volatile unsigned char *)0x5200019C)
-#define rEP0_FIFO		(*(volatile unsigned char *)0x520001C0)
-#define rEP1_FIFO		(*(volatile unsigned char *)0x520001C4)
-#define rEP2_FIFO		(*(volatile unsigned char *)0x520001C8)
-#define rEP3_FIFO		(*(volatile unsigned char *)0x520001CC)
-#define rEP4_FIFO		(*(volatile unsigned char *)0x520001D0)
-#define rEP1_DMA_CON		(*(volatile unsigned char *)0x52000200)
-#define rEP1_DMA_UNIT		(*(volatile unsigned char *)0x52000204)
-#define rEP1_DMA_FIFO		(*(volatile unsigned char *)0x52000208)
-#define rEP1_DMA_TX_LO		(*(volatile unsigned char *)0x5200020C)
-#define rEP1_DMA_TX_MD		(*(volatile unsigned char *)0x52000210)
-#define rEP1_DMA_TX_HI		(*(volatile unsigned char *)0x52000214)
-#define rEP2_DMA_CON		(*(volatile unsigned char *)0x52000218)
-#define rEP2_DMA_UNIT		(*(volatile unsigned char *)0x5200021C)
-#define rEP2_DMA_FIFO		(*(volatile unsigned char *)0x52000220)
-#define rEP2_DMA_TX_LO		(*(volatile unsigned char *)0x52000224)
-#define rEP2_DMA_TX_MD		(*(volatile unsigned char *)0x52000228)
-#define rEP2_DMA_TX_HI		(*(volatile unsigned char *)0x5200022C)
-#define rEP3_DMA_CON		(*(volatile unsigned char *)0x52000240)
-#define rEP3_DMA_UNIT		(*(volatile unsigned char *)0x52000244)
-#define rEP3_DMA_FIFO		(*(volatile unsigned char *)0x52000248)
-#define rEP3_DMA_TX_LO		(*(volatile unsigned char *)0x5200024C)
-#define rEP3_DMA_TX_MD		(*(volatile unsigned char *)0x52000250)
-#define rEP3_DMA_TX_HI		(*(volatile unsigned char *)0x52000254)
-#define rEP4_DMA_CON		(*(volatile unsigned char *)0x52000258)
-#define rEP4_DMA_UNIT		(*(volatile unsigned char *)0x5200025C)
-#define rEP4_DMA_FIFO		(*(volatile unsigned char *)0x52000260)
-#define rEP4_DMA_TX_LO		(*(volatile unsigned char *)0x52000264)
-#define rEP4_DMA_TX_MD		(*(volatile unsigned char *)0x52000268)
-#define rEP4_DMA_TX_HI		(*(volatile unsigned char *)0x5200026C)
+#define rFUNC_ADDR_REG      (*(volatile unsigned char *)0x52000140)
+#define rPWR_REG        (*(volatile unsigned char *)0x52000144)
+#define rEP_INT_REG     (*(volatile unsigned char *)0x52000148)
+#define rUSB_INT_REG        (*(volatile unsigned char *)0x52000158)
+#define rEP_INT_EN_REG      (*(volatile unsigned char *)0x5200015C)
+#define rUSB_INT_EN_REG     (*(volatile unsigned char *)0x5200016C)
+#define rFRAME_NUM1_REG     (*(volatile unsigned char *)0x52000170)
+#define rFRAME_NUM2_REG     (*(volatile unsigned char *)0x52000174)
+#define rINDEX_REG      (*(volatile unsigned char *)0x52000178)
+#define rMAXP_REG       (*(volatile unsigned char *)0x52000180)
+#define rEP0_CSR        (*(volatile unsigned char *)0x52000184)
+#define rIN_CSR1_REG        (*(volatile unsigned char *)0x52000184)
+#define rIN_CSR2_REG        (*(volatile unsigned char *)0x52000188)
+#define rOUT_CSR1_REG       (*(volatile unsigned char *)0x52000190)
+#define rOUT_CSR2_REG       (*(volatile unsigned char *)0x52000194)
+#define rOUT_FIFO_CNT1_REG  (*(volatile unsigned char *)0x52000198)
+#define rOUT_FIFO_CNT2_REG  (*(volatile unsigned char *)0x5200019C)
+#define rEP0_FIFO       (*(volatile unsigned char *)0x520001C0)
+#define rEP1_FIFO       (*(volatile unsigned char *)0x520001C4)
+#define rEP2_FIFO       (*(volatile unsigned char *)0x520001C8)
+#define rEP3_FIFO       (*(volatile unsigned char *)0x520001CC)
+#define rEP4_FIFO       (*(volatile unsigned char *)0x520001D0)
+#define rEP1_DMA_CON        (*(volatile unsigned char *)0x52000200)
+#define rEP1_DMA_UNIT       (*(volatile unsigned char *)0x52000204)
+#define rEP1_DMA_FIFO       (*(volatile unsigned char *)0x52000208)
+#define rEP1_DMA_TX_LO      (*(volatile unsigned char *)0x5200020C)
+#define rEP1_DMA_TX_MD      (*(volatile unsigned char *)0x52000210)
+#define rEP1_DMA_TX_HI      (*(volatile unsigned char *)0x52000214)
+#define rEP2_DMA_CON        (*(volatile unsigned char *)0x52000218)
+#define rEP2_DMA_UNIT       (*(volatile unsigned char *)0x5200021C)
+#define rEP2_DMA_FIFO       (*(volatile unsigned char *)0x52000220)
+#define rEP2_DMA_TX_LO      (*(volatile unsigned char *)0x52000224)
+#define rEP2_DMA_TX_MD      (*(volatile unsigned char *)0x52000228)
+#define rEP2_DMA_TX_HI      (*(volatile unsigned char *)0x5200022C)
+#define rEP3_DMA_CON        (*(volatile unsigned char *)0x52000240)
+#define rEP3_DMA_UNIT       (*(volatile unsigned char *)0x52000244)
+#define rEP3_DMA_FIFO       (*(volatile unsigned char *)0x52000248)
+#define rEP3_DMA_TX_LO      (*(volatile unsigned char *)0x5200024C)
+#define rEP3_DMA_TX_MD      (*(volatile unsigned char *)0x52000250)
+#define rEP3_DMA_TX_HI      (*(volatile unsigned char *)0x52000254)
+#define rEP4_DMA_CON        (*(volatile unsigned char *)0x52000258)
+#define rEP4_DMA_UNIT       (*(volatile unsigned char *)0x5200025C)
+#define rEP4_DMA_FIFO       (*(volatile unsigned char *)0x52000260)
+#define rEP4_DMA_TX_LO      (*(volatile unsigned char *)0x52000264)
+#define rEP4_DMA_TX_MD      (*(volatile unsigned char *)0x52000268)
+#define rEP4_DMA_TX_HI      (*(volatile unsigned char *)0x5200026C)
 #endif /*  __BIG_ENDIAN */
 
 
 /* WATCH DOG TIMER */
-#define rWTCON			(*(volatile unsigned *)0x53000000)
-#define rWTDAT			(*(volatile unsigned *)0x53000004)
-#define rWTCNT			(*(volatile unsigned *)0x53000008)
+#define rWTCON          (*(volatile unsigned *)0x53000000)
+#define rWTDAT          (*(volatile unsigned *)0x53000004)
+#define rWTCNT          (*(volatile unsigned *)0x53000008)
 
 
 /* IIC */
-#define rIICCON			(*(volatile unsigned *)0x54000000)
-#define rIICSTAT		(*(volatile unsigned *)0x54000004)
-#define rIICADD			(*(volatile unsigned *)0x54000008)
-#define rIICDS			(*(volatile unsigned *)0x5400000C)
+#define rIICCON         (*(volatile unsigned *)0x54000000)
+#define rIICSTAT        (*(volatile unsigned *)0x54000004)
+#define rIICADD         (*(volatile unsigned *)0x54000008)
+#define rIICDS          (*(volatile unsigned *)0x5400000C)
 
 
 /* IIS */
-#define rIISCON			(*(volatile unsigned *)0x55000000)
-#define rIISMOD			(*(volatile unsigned *)0x55000004)
-#define rIISPSR			(*(volatile unsigned *)0x55000008)
-#define rIISFCON		(*(volatile unsigned *)0x5500000C)
+#define rIISCON         (*(volatile unsigned *)0x55000000)
+#define rIISMOD         (*(volatile unsigned *)0x55000004)
+#define rIISPSR         (*(volatile unsigned *)0x55000008)
+#define rIISFCON        (*(volatile unsigned *)0x5500000C)
 
 #ifdef __BIG_ENDIAN
-#define IISFIF			((volatile unsigned short *)0x55000012)
+#define IISFIF          ((volatile unsigned short *)0x55000012)
 #else /*  little endian */
-#define IISFIF			((volatile unsigned short *)0x55000010)
+#define IISFIF          ((volatile unsigned short *)0x55000010)
 #endif
 
 
 /* I/O PORT */
-#define rGPACON			(*(volatile unsigned *)0x56000000)
-#define rGPADAT			(*(volatile unsigned *)0x56000004)
+#define rGPACON         (*(volatile unsigned *)0x56000000)
+#define rGPADAT         (*(volatile unsigned *)0x56000004)
 
-#define rGPBCON			(*(volatile unsigned *)0x56000010)
-#define rGPBDAT			(*(volatile unsigned *)0x56000014)
-#define rGPBUP			(*(volatile unsigned *)0x56000018)
-
-#define rGPCCON			(*(volatile unsigned *)0x56000020)
-#define rGPCDAT			(*(volatile unsigned *)0x56000024)
-#define rGPCUP			(*(volatile unsigned *)0x56000028)
-
-#define rGPDCON			(*(volatile unsigned *)0x56000030)
-#define rGPDDAT			(*(volatile unsigned *)0x56000034)
-#define rGPDUP			(*(volatile unsigned *)0x56000038)
-
-#define rGPECON			(*(volatile unsigned *)0x56000040)
-#define rGPEDAT			(*(volatile unsigned *)0x56000044)
-#define rGPEUP			(*(volatile unsigned *)0x56000048)
-
-#define rGPFCON			(*(volatile unsigned *)0x56000050)
-#define rGPFDAT			(*(volatile unsigned *)0x56000054)
-#define rGPFUP			(*(volatile unsigned *)0x56000058)
-
-#define rGPGCON			(*(volatile unsigned *)0x56000060)
-#define rGPGDAT			(*(volatile unsigned *)0x56000064)
-#define rGPGUP			(*(volatile unsigned *)0x56000068)
-
-#define rGPHCON			(*(volatile unsigned *)0x56000070)
-#define rGPHDAT			(*(volatile unsigned *)0x56000074)
-#define rGPHUP			(*(volatile unsigned *)0x56000078)
-
-#define rMISCCR			(*(volatile unsigned *)0x56000080)
-#define rDCLKCON		(*(volatile unsigned *)0x56000084)
-#define rEXTINT0		(*(volatile unsigned *)0x56000088)
-#define rEXTINT1		(*(volatile unsigned *)0x5600008C)
-#define rEXTINT2		(*(volatile unsigned *)0x56000090)
-#define rEINTFLT0		(*(volatile unsigned *)0x56000094)
-#define rEINTFLT1		(*(volatile unsigned *)0x56000098)
-#define rEINTFLT2		(*(volatile unsigned *)0x5600009C)
-#define rEINTFLT3		(*(volatile unsigned *)0x560000A0)
-#define rEINTMASK		(*(volatile unsigned *)0x560000A4)
-#define rEINTPEND		(*(volatile unsigned *)0x560000A8)
-#define rGSTATUS0		(*(volatile unsigned *)0x560000AC)
-#define rGSTATUS1		(*(volatile unsigned *)0x560000B0)
+#define rGPBCON         (*(volatile unsigned *)0x56000010)
+#define rGPBDAT         (*(volatile unsigned *)0x56000014)
+#define rGPBUP          (*(volatile unsigned *)0x56000018)
+
+#define rGPCCON         (*(volatile unsigned *)0x56000020)
+#define rGPCDAT         (*(volatile unsigned *)0x56000024)
+#define rGPCUP          (*(volatile unsigned *)0x56000028)
+
+#define rGPDCON         (*(volatile unsigned *)0x56000030)
+#define rGPDDAT         (*(volatile unsigned *)0x56000034)
+#define rGPDUP          (*(volatile unsigned *)0x56000038)
+
+#define rGPECON         (*(volatile unsigned *)0x56000040)
+#define rGPEDAT         (*(volatile unsigned *)0x56000044)
+#define rGPEUP          (*(volatile unsigned *)0x56000048)
+
+#define rGPFCON         (*(volatile unsigned *)0x56000050)
+#define rGPFDAT         (*(volatile unsigned *)0x56000054)
+#define rGPFUP          (*(volatile unsigned *)0x56000058)
+
+#define rGPGCON         (*(volatile unsigned *)0x56000060)
+#define rGPGDAT         (*(volatile unsigned *)0x56000064)
+#define rGPGUP          (*(volatile unsigned *)0x56000068)
+
+#define rGPHCON         (*(volatile unsigned *)0x56000070)
+#define rGPHDAT         (*(volatile unsigned *)0x56000074)
+#define rGPHUP          (*(volatile unsigned *)0x56000078)
+
+#define rMISCCR         (*(volatile unsigned *)0x56000080)
+#define rDCLKCON        (*(volatile unsigned *)0x56000084)
+#define rEXTINT0        (*(volatile unsigned *)0x56000088)
+#define rEXTINT1        (*(volatile unsigned *)0x5600008C)
+#define rEXTINT2        (*(volatile unsigned *)0x56000090)
+#define rEINTFLT0       (*(volatile unsigned *)0x56000094)
+#define rEINTFLT1       (*(volatile unsigned *)0x56000098)
+#define rEINTFLT2       (*(volatile unsigned *)0x5600009C)
+#define rEINTFLT3       (*(volatile unsigned *)0x560000A0)
+#define rEINTMASK       (*(volatile unsigned *)0x560000A4)
+#define rEINTPEND       (*(volatile unsigned *)0x560000A8)
+#define rGSTATUS0       (*(volatile unsigned *)0x560000AC)
+#define rGSTATUS1       (*(volatile unsigned *)0x560000B0)
 
 
 /* RTC */
 #ifdef __BIG_ENDIAN
-#define rRTCCON			(*(volatile unsigned char *)0x57000043)
-#define rTICNT			(*(volatile unsigned char *)0x57000047)
-#define rRTCALM			(*(volatile unsigned char *)0x57000053)
-#define rALMSEC			(*(volatile unsigned char *)0x57000057)
-#define rALMMIN			(*(volatile unsigned char *)0x5700005B)
-#define rALMHOUR		(*(volatile unsigned char *)0x5700005F)
-#define rALMDATE		(*(volatile unsigned char *)0x57000063)
-#define rALMMON			(*(volatile unsigned char *)0x57000067)
-#define rALMYEAR		(*(volatile unsigned char *)0x5700006B)
-#define rRTCRST			(*(volatile unsigned char *)0x5700006F)
-#define rBCDSEC			(*(volatile unsigned char *)0x57000073)
-#define rBCDMIN			(*(volatile unsigned char *)0x57000077)
-#define rBCDHOUR		(*(volatile unsigned char *)0x5700007B)
-#define rBCDDATE		(*(volatile unsigned char *)0x5700007F)
-#define rBCDDAY			(*(volatile unsigned char *)0x57000083)
-#define rBCDMON			(*(volatile unsigned char *)0x57000087)
-#define rBCDYEAR		(*(volatile unsigned char *)0x5700008B)
+#define rRTCCON         (*(volatile unsigned char *)0x57000043)
+#define rTICNT          (*(volatile unsigned char *)0x57000047)
+#define rRTCALM         (*(volatile unsigned char *)0x57000053)
+#define rALMSEC         (*(volatile unsigned char *)0x57000057)
+#define rALMMIN         (*(volatile unsigned char *)0x5700005B)
+#define rALMHOUR        (*(volatile unsigned char *)0x5700005F)
+#define rALMDATE        (*(volatile unsigned char *)0x57000063)
+#define rALMMON         (*(volatile unsigned char *)0x57000067)
+#define rALMYEAR        (*(volatile unsigned char *)0x5700006B)
+#define rRTCRST         (*(volatile unsigned char *)0x5700006F)
+#define rBCDSEC         (*(volatile unsigned char *)0x57000073)
+#define rBCDMIN         (*(volatile unsigned char *)0x57000077)
+#define rBCDHOUR        (*(volatile unsigned char *)0x5700007B)
+#define rBCDDATE        (*(volatile unsigned char *)0x5700007F)
+#define rBCDDAY         (*(volatile unsigned char *)0x57000083)
+#define rBCDMON         (*(volatile unsigned char *)0x57000087)
+#define rBCDYEAR        (*(volatile unsigned char *)0x5700008B)
 #else /*  little endian */
-#define rRTCCON			(*(volatile unsigned char *)0x57000040)
-#define rTICNT			(*(volatile unsigned char *)0x57000044)
-#define rRTCALM			(*(volatile unsigned char *)0x57000050)
-#define rALMSEC			(*(volatile unsigned char *)0x57000054)
-#define rALMMIN			(*(volatile unsigned char *)0x57000058)
-#define rALMHOUR		(*(volatile unsigned char *)0x5700005C)
-#define rALMDATE		(*(volatile unsigned char *)0x57000060)
-#define rALMMON			(*(volatile unsigned char *)0x57000064)
-#define rALMYEAR		(*(volatile unsigned char *)0x57000068)
-#define rRTCRST			(*(volatile unsigned char *)0x5700006C)
-#define rBCDSEC			(*(volatile unsigned char *)0x57000070)
-#define rBCDMIN			(*(volatile unsigned char *)0x57000074)
-#define rBCDHOUR		(*(volatile unsigned char *)0x57000078)
-#define rBCDDATE		(*(volatile unsigned char *)0x5700007C)
-#define rBCDDAY			(*(volatile unsigned char *)0x57000080)
-#define rBCDMON			(*(volatile unsigned char *)0x57000084)
-#define rBCDYEAR		(*(volatile unsigned char *)0x57000088)
+#define rRTCCON         (*(volatile unsigned char *)0x57000040)
+#define rTICNT          (*(volatile unsigned char *)0x57000044)
+#define rRTCALM         (*(volatile unsigned char *)0x57000050)
+#define rALMSEC         (*(volatile unsigned char *)0x57000054)
+#define rALMMIN         (*(volatile unsigned char *)0x57000058)
+#define rALMHOUR        (*(volatile unsigned char *)0x5700005C)
+#define rALMDATE        (*(volatile unsigned char *)0x57000060)
+#define rALMMON         (*(volatile unsigned char *)0x57000064)
+#define rALMYEAR        (*(volatile unsigned char *)0x57000068)
+#define rRTCRST         (*(volatile unsigned char *)0x5700006C)
+#define rBCDSEC         (*(volatile unsigned char *)0x57000070)
+#define rBCDMIN         (*(volatile unsigned char *)0x57000074)
+#define rBCDHOUR        (*(volatile unsigned char *)0x57000078)
+#define rBCDDATE        (*(volatile unsigned char *)0x5700007C)
+#define rBCDDAY         (*(volatile unsigned char *)0x57000080)
+#define rBCDMON         (*(volatile unsigned char *)0x57000084)
+#define rBCDYEAR        (*(volatile unsigned char *)0x57000088)
 #endif
 
 
 /* ADC */
-#define rADCCON			(*(volatile unsigned *)0x58000000)
-#define rADCTSC			(*(volatile unsigned *)0x58000004)
-#define rADCDLY			(*(volatile unsigned *)0x58000008)
-#define rADCDAT0		(*(volatile unsigned *)0x5800000C)
-#define rADCDAT1		(*(volatile unsigned *)0x58000010)
+#define rADCCON         (*(volatile unsigned *)0x58000000)
+#define rADCTSC         (*(volatile unsigned *)0x58000004)
+#define rADCDLY         (*(volatile unsigned *)0x58000008)
+#define rADCDAT0        (*(volatile unsigned *)0x5800000C)
+#define rADCDAT1        (*(volatile unsigned *)0x58000010)
 
 
 /* SPI */
-#define rSPCON0			(*(volatile unsigned *)0x59000000)
-#define rSPSTA0			(*(volatile unsigned *)0x59000004)
-#define rSPPIN0			(*(volatile unsigned *)0x59000008)
-#define rSPPRE0			(*(volatile unsigned *)0x5900000C)
-#define rSPTDAT0		(*(volatile unsigned *)0x59000010)
-#define rSPRDAT0		(*(volatile unsigned *)0x59000014)
-#define rSPCON1			(*(volatile unsigned *)0x59000020)
-#define rSPSTA1			(*(volatile unsigned *)0x59000024)
-#define rSPPIN1			(*(volatile unsigned *)0x59000028)
-#define rSPPRE1			(*(volatile unsigned *)0x5900002C)
-#define rSPTDAT1		(*(volatile unsigned *)0x59000030)
-#define rSPRDAT1		(*(volatile unsigned *)0x59000034)
+#define rSPCON0         (*(volatile unsigned *)0x59000000)
+#define rSPSTA0         (*(volatile unsigned *)0x59000004)
+#define rSPPIN0         (*(volatile unsigned *)0x59000008)
+#define rSPPRE0         (*(volatile unsigned *)0x5900000C)
+#define rSPTDAT0        (*(volatile unsigned *)0x59000010)
+#define rSPRDAT0        (*(volatile unsigned *)0x59000014)
+#define rSPCON1         (*(volatile unsigned *)0x59000020)
+#define rSPSTA1         (*(volatile unsigned *)0x59000024)
+#define rSPPIN1         (*(volatile unsigned *)0x59000028)
+#define rSPPRE1         (*(volatile unsigned *)0x5900002C)
+#define rSPTDAT1        (*(volatile unsigned *)0x59000030)
+#define rSPRDAT1        (*(volatile unsigned *)0x59000034)
 
 
 /* SD INTERFACE */
-#define rSDICON			(*(volatile unsigned *)0x5A000000)
-#define rSDIPRE			(*(volatile unsigned *)0x5A000004)
-#define rSDICmdArg		(*(volatile unsigned *)0x5A000008)
-#define rSDICmdCon		(*(volatile unsigned *)0x5A00000C)
-#define rSDICmdSta		(*(volatile unsigned *)0x5A000010)
-#define rSDIRSP0		(*(volatile unsigned *)0x5A000014)
-#define rSDIRSP1		(*(volatile unsigned *)0x5A000018)
-#define rSDIRSP2		(*(volatile unsigned *)0x5A00001C)
-#define rSDIRSP3		(*(volatile unsigned *)0x5A000020)
-#define rSDIDTimer		(*(volatile unsigned *)0x5A000024)
-#define rSDIBSize		(*(volatile unsigned *)0x5A000028)
-#define rSDIDatCon		(*(volatile unsigned *)0x5A00002C)
-#define rSDIDatCnt		(*(volatile unsigned *)0x5A000030)
-#define rSDIDatSta		(*(volatile unsigned *)0x5A000034)
-#define rSDIFSTA		(*(volatile unsigned *)0x5A000038)
+#define rSDICON         (*(volatile unsigned *)0x5A000000)
+#define rSDIPRE         (*(volatile unsigned *)0x5A000004)
+#define rSDICmdArg      (*(volatile unsigned *)0x5A000008)
+#define rSDICmdCon      (*(volatile unsigned *)0x5A00000C)
+#define rSDICmdSta      (*(volatile unsigned *)0x5A000010)
+#define rSDIRSP0        (*(volatile unsigned *)0x5A000014)
+#define rSDIRSP1        (*(volatile unsigned *)0x5A000018)
+#define rSDIRSP2        (*(volatile unsigned *)0x5A00001C)
+#define rSDIRSP3        (*(volatile unsigned *)0x5A000020)
+#define rSDIDTimer      (*(volatile unsigned *)0x5A000024)
+#define rSDIBSize       (*(volatile unsigned *)0x5A000028)
+#define rSDIDatCon      (*(volatile unsigned *)0x5A00002C)
+#define rSDIDatCnt      (*(volatile unsigned *)0x5A000030)
+#define rSDIDatSta      (*(volatile unsigned *)0x5A000034)
+#define rSDIFSTA        (*(volatile unsigned *)0x5A000038)
 #ifdef __BIG_ENDIAN
-#define rSDIDAT			(*(volatile unsigned char *)0x5A00003F)
+#define rSDIDAT         (*(volatile unsigned char *)0x5A00003F)
 #else
-#define rSDIDAT			(*(volatile unsigned char *)0x5A00003C)
+#define rSDIDAT         (*(volatile unsigned char *)0x5A00003C)
 #endif
-#define rSDIIntMsk		(*(volatile unsigned *)0x5A000040)
+#define rSDIIntMsk      (*(volatile unsigned *)0x5A000040)
 
 #endif
 
+#define rGSTATUS1       (*(volatile unsigned *)0x560000B0)
+#define isS3C2410 		((rGSTATUS1 & 0xffff0000) == 0x32410000)
+
 #endif /*__S3C24X0_H__*/
diff -urN u-boot-1.1.6/include/usb.h u-boot-1.1.6_jz2440/include/usb.h
--- u-boot-1.1.6/include/usb.h	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/include/usb.h	2010-11-26 12:54:38.014070137 +0800
@@ -202,6 +202,7 @@
 
 #endif
 /* routines */
+void Port_Init(void);
 int usb_init(void); /* initialize the USB Controller */
 int usb_stop(void); /* stop the USB Controller */
 
diff -urN u-boot-1.1.6/lib_arm/armlinux.c u-boot-1.1.6_jz2440/lib_arm/armlinux.c
--- u-boot-1.1.6/lib_arm/armlinux.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/lib_arm/armlinux.c	2010-11-26 12:54:37.662096129 +0800
@@ -261,7 +261,83 @@
 #ifdef CONFIG_USB_DEVICE
 	{
 		extern void udc_disconnect (void);
-		udc_disconnect ();
+                //udc_disconnect (); // cancled by www.100ask.net
+	}
+#endif
+
+	cleanup_before_linux ();
+
+	theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
+}
+
+void do_bootm_rawLinux (ulong addr)
+{
+	ulong len = 0, checksum;
+	ulong initrd_start, initrd_end;
+	ulong data;
+	void (*theKernel)(int zero, int arch, uint params);
+	image_header_t *hdr = &header;
+	bd_t *bd = gd->bd;
+
+#ifdef CONFIG_CMDLINE_TAG
+	char *commandline = getenv ("bootargs");
+#endif
+
+	theKernel = (void (*)(int, int, uint))addr;
+
+	{
+		/*
+		 * no initrd image
+		 */
+		SHOW_BOOT_PROGRESS (14);
+
+		len = data = 0;
+	}
+
+
+	{
+		initrd_start = 0;
+		initrd_end = 0;
+	}
+
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG) || \
+    defined (CONFIG_LCD) || \
+    defined (CONFIG_VFD)
+	setup_start_tag (bd);
+#ifdef CONFIG_SERIAL_TAG
+	setup_serial_tag (&params);
+#endif
+#ifdef CONFIG_REVISION_TAG
+	setup_revision_tag (&params);
+#endif
+#ifdef CONFIG_SETUP_MEMORY_TAGS
+	setup_memory_tags (bd);
+#endif
+#ifdef CONFIG_CMDLINE_TAG
+	setup_commandline_tag (bd, commandline);
+#endif
+#ifdef CONFIG_INITRD_TAG
+	if (initrd_start && initrd_end)
+		setup_initrd_tag (bd, initrd_start, initrd_end);
+#endif
+#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
+	setup_videolfb_tag ((gd_t *) gd);
+#endif
+	setup_end_tag (bd);
+#endif
+
+	/* we assume that the kernel is in place */
+	printf ("\nStarting kernel ...\n\n");
+
+#ifdef CONFIG_USB_DEVICE
+	{
+		extern void udc_disconnect (void);
+                //udc_disconnect (); // cancled by www.100ask.net
 	}
 #endif
 
diff -urN u-boot-1.1.6/lib_arm/board.c u-boot-1.1.6_jz2440/lib_arm/board.c
--- u-boot-1.1.6/lib_arm/board.c	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/lib_arm/board.c	2010-11-26 12:54:37.662096129 +0800
@@ -360,10 +360,15 @@
 	misc_init_r ();
 #endif
 
-	/* enable exceptions */
-	enable_interrupts ();
+	Port_Init();
+	if (!PreLoadedONRAM) {
+		/* enable exceptions */
+		enable_interrupts ();
+	    /* add by www.100ask.net */
+	    usb_init();
+	}
 
-	/* Perform network card initialisation if necessary */
+    /* Perform network card initialisation if necessary */
 #ifdef CONFIG_DRIVER_CS8900
 	cs8900_get_enetaddr (gd->bd->bi_enetaddr);
 #endif
diff -urN u-boot-1.1.6/Makefile u-boot-1.1.6_jz2440/Makefile
--- u-boot-1.1.6/Makefile	2006-11-02 22:15:01.000000000 +0800
+++ u-boot-1.1.6_jz2440/Makefile	2010-11-26 12:54:37.830153999 +0800
@@ -206,8 +206,8 @@
 LIBS += drivers/libdrivers.a
 LIBS += drivers/nand/libnand.a
 LIBS += drivers/nand_legacy/libnand_legacy.a
+LIBS += drivers/usb/libusb.a
 LIBS += drivers/sk98lin/libsk98lin.a
-LIBS += post/libpost.a post/cpu/libcpu.a
 LIBS += common/libcommon.a
 LIBS += $(BOARDLIBS)
 
@@ -266,11 +266,15 @@
 			-Map u-boot.map -o u-boot
 
 $(OBJS):
+	echo $(OBJS)	
 		$(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))
 
 $(LIBS):
 		$(MAKE) -C $(dir $(subst $(obj),,$@))
 
+usb:
+	$(MAKE) -C drivers/usb
+
 $(SUBDIRS):
 		$(MAKE) -C $@ all
 
@@ -1879,6 +1883,9 @@
 smdk2410_config	:	unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
 
+100ask24x0_config	:	unconfig
+	@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0
+
 SX1_config :		unconfig
 	@$(MKCONFIG) $(@:_config=) arm arm925t sx1
 
