now that the gemini target is working, get rid of the obsolete and buggy storm target
[openwrt/openwrt.git] / target / linux / storm / patches / 007-mtd.patch
diff --git a/target/linux/storm/patches/007-mtd.patch b/target/linux/storm/patches/007-mtd.patch
deleted file mode 100644 (file)
index a907de3..0000000
+++ /dev/null
@@ -1,4948 +0,0 @@
---- a/drivers/mtd/chips/Kconfig
-+++ b/drivers/mtd/chips/Kconfig
-@@ -220,6 +220,13 @@ config MTD_ROM
-         This option enables basic support for ROM chips accessed through
-         a bus mapping driver.
-+config MTD_SERIAL
-+      tristate "Support for Serial chips in bus mapping"
-+      depends on MTD
-+      help
-+        This option enables basic support for Serial chips accessed through
-+        a bus mapping driver.
-+
- config MTD_ABSENT
-       tristate "Support for absent chips in bus mapping"
-       help
---- a/drivers/mtd/chips/cfi_cmdset_0002.c
-+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -39,10 +39,15 @@
- #include <linux/mtd/cfi.h>
- #include <linux/mtd/xip.h>
-+//****** Storlink SoC ******
- #define AMD_BOOTLOC_BUG
--#define FORCE_WORD_WRITE 0
--
--#define MAX_WORD_RETRIES 3
-+//#define FORCE_WORD_WRITE 0
-+#define FORCE_WORD_WRITE 1
-+#define FORCE_FAST_PROG 0
-+
-+//#define MAX_WORD_RETRIES 3
-+#define MAX_WORD_RETRIES 3 // CONFIG_MTD_CFI_AMDSTD_RETRY
-+//**************************
- #define MANUFACTURER_AMD      0x0001
- #define MANUFACTURER_ATMEL    0x001F
-@@ -322,6 +327,13 @@ struct mtd_info *cfi_cmdset_0002(struct 
- #endif
-               bootloc = extp->TopBottom;
-+//****** Storlink SoC ******
-+              if(bootloc == 5)
-+              {
-+                      bootloc = 3;
-+                      extp->TopBottom = 3;
-+              }
-+//**************************
-               if ((bootloc != 2) && (bootloc != 3)) {
-                       printk(KERN_WARNING "%s: CFI does not contain boot "
-                              "bank location. Assuming top.\n", map->name);
-@@ -340,6 +352,9 @@ struct mtd_info *cfi_cmdset_0002(struct 
-                               cfi->cfiq->EraseRegionInfo[j] = swap;
-                       }
-               }
-+#ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
-+              cfi->device_type = CFI_DEVICETYPE_X8;
-+#endif
-               /* Set the default CFI lock/unlock addresses */
-               cfi->addr_unlock1 = 0x555;
-               cfi->addr_unlock2 = 0x2aa;
-@@ -461,6 +476,7 @@ static int __xipram chip_ready(struct ma
-       map_word d, t;
-       d = map_read(map, addr);
-+      udelay(20);     //Storlink SoC
-       t = map_read(map, addr);
-       return map_word_equal(map, d, t);
-@@ -626,7 +642,9 @@ static void put_chip(struct map_info *ma
-       default:
-               printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate);
-       }
-+//****** Storlink SoC ******
-       wake_up(&chip->wq);
-+//**************************
- }
- #ifdef CONFIG_MTD_XIP
-@@ -940,7 +958,9 @@ static inline int do_read_secsi_onechip(
-       cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+//****** Storlink SoC ******
-       wake_up(&chip->wq);
-+//**************************
-       spin_unlock(chip->mutex);
-       return 0;
-@@ -1005,7 +1025,10 @@ static int __xipram do_write_oneword(str
-        */
-       unsigned long uWriteTimeout = ( HZ / 1000 ) + 1;
-       int ret = 0;
--      map_word oldd;
-+//****** Storlink SoC ******
-+//    map_word oldd;
-+      map_word oldd, tmp;
-+//**************************
-       int retry_cnt = 0;
-       adr += chip->start;
-@@ -1037,9 +1060,15 @@ static int __xipram do_write_oneword(str
-       ENABLE_VPP(map);
-       xip_disable(map, chip, adr);
-  retry:
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG  /* Unlock bypass */
-+      cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+#else
-       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+#endif
-+//**************************
-       map_write(map, datum, adr);
-       chip->state = FL_WRITING;
-@@ -1072,7 +1101,13 @@ static int __xipram do_write_oneword(str
-               }
-               if (chip_ready(map, adr))
--                      break;
-+              {
-+                      tmp = map_read(map, adr);
-+                      if(map_word_equal(map, tmp, datum))
-+//                            goto op_done;
-+                break;
-+
-+              }
-               /* Latency issues. Drop the lock, wait a while and retry */
-               UDELAY(map, chip, adr, 1);
-@@ -1084,8 +1119,17 @@ static int __xipram do_write_oneword(str
-               /* FIXME - should have reset delay before continuing */
-               if (++retry_cnt <= MAX_WORD_RETRIES)
-+              {
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG
-+                      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-+              //udelay(1);
-+#endif
-+                      udelay(1);
-                       goto retry;
--
-+              }
-               ret = -EIO;
-       }
-       xip_enable(map, chip, adr);
-@@ -1171,7 +1215,14 @@ static int cfi_amdstd_write_words(struct
-                               return 0;
-               }
-       }
--
-+//****** Storlink SoC ******
-+      map_write( map, CMD(0xF0), chipstart );
-+#if FORCE_FAST_PROG
-+              cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-+//**************************
-       /* We are now aligned, write as much as possible */
-       while(len >= map_bankwidth(map)) {
-               map_word datum;
-@@ -1181,7 +1232,15 @@ static int cfi_amdstd_write_words(struct
-               ret = do_write_oneword(map, &cfi->chips[chipnum],
-                                      ofs, datum);
-               if (ret)
-+              {
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG
-+                      /* Get out of unlock bypass mode */
-+                      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-                       return ret;
-+              }
-               ofs += map_bankwidth(map);
-               buf += map_bankwidth(map);
-@@ -1189,19 +1248,38 @@ static int cfi_amdstd_write_words(struct
-               len -= map_bankwidth(map);
-               if (ofs >> cfi->chipshift) {
-+//****** Storlink SoC ******
-+#if FORCE_FAST_PROG
-+                      /* Get out of unlock bypass mode */
-+                      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-                       chipnum ++;
-                       ofs = 0;
-                       if (chipnum == cfi->numchips)
-                               return 0;
-                       chipstart = cfi->chips[chipnum].start;
-+#if FORCE_FAST_PROG
-+                      /* Go into unlock bypass mode for next set of chips */
-+                      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
-+                      cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-               }
-       }
-+#if FORCE_FAST_PROG
-+      /* Get out of unlock bypass mode */
-+      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-+
-       /* Write the trailing bytes if any */
-       if (len & (map_bankwidth(map)-1)) {
-               map_word tmp_buf;
-  retry1:
-+
-               spin_lock(cfi->chips[chipnum].mutex);
-               if (cfi->chips[chipnum].state != FL_READY) {
-@@ -1221,7 +1299,11 @@ static int cfi_amdstd_write_words(struct
- #endif
-                       goto retry1;
-               }
--
-+#if FORCE_FAST_PROG
-+              cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-               tmp_buf = map_read(map, ofs + chipstart);
-               spin_unlock(cfi->chips[chipnum].mutex);
-@@ -1231,11 +1313,23 @@ static int cfi_amdstd_write_words(struct
-               ret = do_write_oneword(map, &cfi->chips[chipnum],
-                               ofs, tmp_buf);
-               if (ret)
-+              {
-+#if FORCE_FAST_PROG
-+      /* Get out of unlock bypass mode */
-+      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-                       return ret;
--
-+              }
-+#if FORCE_FAST_PROG
-+      /* Get out of unlock bypass mode */
-+      cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+      cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
-+#endif
-               (*retlen) += len;
-       }
-+      map_write( map, CMD(0xF0), chipstart );
-       return 0;
- }
-@@ -1275,6 +1369,7 @@ static int __xipram do_write_buffer(stru
-       ENABLE_VPP(map);
-       xip_disable(map, chip, cmd_adr);
-+      map_write( map, CMD(0xF0), chip->start );       //Storlink
-       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-       //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
-@@ -1535,6 +1630,9 @@ static int __xipram do_erase_oneblock(st
-       DECLARE_WAITQUEUE(wait, current);
-       int ret = 0;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-       adr += chip->start;
-       spin_lock(chip->mutex);
-@@ -1613,6 +1711,9 @@ static int __xipram do_erase_oneblock(st
-       chip->state = FL_READY;
-       put_chip(map, chip, adr);
-       spin_unlock(chip->mutex);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-       return ret;
- }
---- /dev/null
-+++ b/drivers/mtd/chips/map_serial.c
-@@ -0,0 +1,188 @@
-+/*
-+ * Common code to handle map devices which are simple ROM
-+ * (C) 2000 Red Hat. GPL'd.
-+ * $Id: map_serial.c,v 1.3 2006/06/05 02:34:54 middle Exp $
-+ */
-+
-+#include <linux/version.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+
-+#include <asm/byteorder.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+
-+#include <asm/hardware.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/init.h> //add
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/flash.h>
-+
-+static int mapserial_erase(struct mtd_info *mtd, struct erase_info *instr);
-+static int mapserial_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
-+static int mapserial_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
-+static void mapserial_nop (struct mtd_info *);
-+struct mtd_info *map_serial_probe(struct map_info *map);
-+
-+extern int m25p80_sector_erase(__u32 address, __u32 schip_en);
-+
-+static struct mtd_chip_driver mapserial_chipdrv = {
-+      probe: map_serial_probe,
-+      name: "map_serial",
-+      module: THIS_MODULE
-+};
-+
-+struct mtd_info *map_serial_probe(struct map_info *map)
-+{
-+      struct mtd_info *mtd;
-+
-+      mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
-+      if (!mtd)
-+              return NULL;
-+
-+      memset(mtd, 0, sizeof(*mtd));
-+
-+      map->fldrv = &mapserial_chipdrv;
-+      mtd->priv = map;
-+      mtd->name = map->name;
-+      mtd->type = MTD_OTHER;
-+      mtd->erase = mapserial_erase;
-+      mtd->size = map->size;
-+      mtd->read = mapserial_read;
-+      mtd->write = mapserial_write;
-+      mtd->sync = mapserial_nop;
-+      mtd->flags = (MTD_WRITEABLE|MTD_ERASEABLE);
-+//    mtd->erasesize = 512; // page size;
-+#ifdef CONFIG_MTD_SL2312_SERIAL_ST
-+      mtd->erasesize = M25P80_SECTOR_SIZE; // block size;
-+#else
-+      mtd->erasesize = 0x1000; // block size;
-+#endif
-+
-+      __module_get(THIS_MODULE);
-+      //MOD_INC_USE_COUNT;
-+      return mtd;
-+}
-+
-+#define       FLASH_ACCESS_OFFSET                             0x00000010
-+#define       FLASH_ADDRESS_OFFSET                            0x00000014
-+#define       FLASH_WRITE_DATA_OFFSET                         0x00000018
-+#define       FLASH_READ_DATA_OFFSET                          0x00000018
-+
-+static __u32 readflash_ctrl_reg(__u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    return __raw_readl(base);
-+}
-+
-+static void writeflash_ctrl_reg(__u32 data, __u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    __raw_writel(data, base);
-+}
-+
-+static int mapserial_erase_block(struct map_info *map,unsigned int block)
-+{
-+
-+      __u32 address;
-+#ifdef CONFIG_MTD_SL2312_SERIAL_ST
-+
-+      if(!m25p80_sector_erase(block, 0))
-+              return (MTD_ERASE_DONE);
-+#else
-+      __u32 opcode;
-+      __u32 count=0;
-+//      __u8  status;
-+
-+ //     printk("mapserial_erase_block : erase block %d \n",block);
-+//      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd;
-+      opcode = 0x80000000 | 0x0200 | 0x50;
-+      address = (block << 13);
-+      writeflash_ctrl_reg(address,FLASH_ADDRESS_OFFSET);
-+      writeflash_ctrl_reg(opcode,FLASH_ACCESS_OFFSET);
-+      opcode=readflash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode = readflash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          count++;
-+          if (count > 10000)
-+          {
-+            return (MTD_ERASE_FAILED);
-+          }
-+      }
-+      return (MTD_ERASE_DONE);
-+#endif
-+}
-+
-+static int mapserial_erase(struct mtd_info *mtd, struct erase_info *instr)
-+{
-+      struct map_info *map = (struct map_info *)mtd->priv;
-+    unsigned int    addr;
-+    int             len;
-+    unsigned int    block;
-+    unsigned int    ret=0;
-+
-+      addr = instr->addr;
-+      len = instr->len;
-+    while (len > 0)
-+    {
-+        block = addr / mtd->erasesize;
-+#ifdef CONFIG_MTD_SL2312_SERIAL_ST
-+        ret = mapserial_erase_block(map,addr);
-+#else
-+              ret = mapserial_erase_block(map,block);
-+#endif
-+        addr = addr + mtd->erasesize;
-+        len = len - mtd->erasesize;
-+    }
-+    return (ret);
-+}
-+
-+static int mapserial_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
-+{
-+      struct map_info *map = (struct map_info *)mtd->priv;
-+//        printk("mapserial_read : \n");
-+      map->copy_from(map, buf, from, len);
-+      *retlen = len;
-+      return 0;
-+}
-+
-+static void mapserial_nop(struct mtd_info *mtd)
-+{
-+      /* Nothing to see here */
-+}
-+
-+static int mapserial_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
-+{
-+      struct map_info *map = (struct map_info *)mtd->priv;
-+//    printk("mapserial_write : buf %x to %x len %x \n",(int)buf, (int)to, (int)len);
-+      //map->copy_to(map, buf, to, len);
-+      map->copy_to(map, to, buf, len);
-+      *retlen = len;
-+      return 0;
-+}
-+
-+int __init map_serial_init(void)
-+{
-+      register_mtd_chip_driver(&mapserial_chipdrv);
-+      return 0;
-+}
-+
-+static void __exit map_serial_exit(void)
-+{
-+      unregister_mtd_chip_driver(&mapserial_chipdrv);
-+}
-+
-+module_init(map_serial_init);
-+module_exit(map_serial_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-+MODULE_DESCRIPTION("MTD chip driver for ROM chips");
---- a/drivers/mtd/maps/Kconfig
-+++ b/drivers/mtd/maps/Kconfig
-@@ -614,5 +614,30 @@ config MTD_PLATRAM
-         This selection automatically selects the map_ram driver.
-+#***************************************************************************************
-+# Storlink parallel/Serial Flash configuration
-+#***************************************************************************************
-+config MTD_SL2312_CFI
-+        tristate "CFI Flash device mapped on SL2312"
-+        depends on MTD_CFI
-+        help
-+          Map driver for SL2312 demo board.
-+
-+config MTD_SL2312_SERIAL_ATMEL
-+        tristate "ATMEL Serial Flash device mapped on SL2312"
-+        depends on MTD_PARTITIONS && ARCH_SL2312
-+        help
-+          Map driver for SL2312 demo board.
-+
-+config MTD_SL2312_SERIAL_ST
-+        tristate "ST Serial Flash device mapped on SL2312"
-+        depends on MTD_PARTITIONS && ARCH_SL2312
-+        help
-+          Map driver for SL2312 demo board.
-+
-+config SL2312_SHARE_PIN
-+        tristate "Parallel Flash share pin on SL2312 ASIC"
-+        depends on SL3516_ASIC
-+
- endmenu
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312-flash-atmel.c
-@@ -0,0 +1,554 @@
-+/*
-+ * $Id: sl2312-flash-atmel.c,v 1.2 2006/06/05 02:35:57 middle Exp $
-+ *
-+ * Flash and EPROM on Hitachi Solution Engine and similar boards.
-+ *
-+ * (C) 2001 Red Hat, Inc.
-+ *
-+ * GPL'd
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+#include <asm/hardware.h>
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/flash.h>
-+#include <linux/init.h> //add
-+
-+
-+#define  g_page_addr  AT45DB321_PAGE_SHIFT    //321 : shift 10  ; 642 : shift 11
-+#define  g_chipen     SERIAL_FLASH_CHIP0_EN   //atmel
-+
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+void address_to_page(__u32 address, __u16 *page, __u16 *offset)
-+{
-+    *page = address / SPAGE_SIZE;
-+    *offset = address % SPAGE_SIZE;
-+}
-+
-+static __u32 read_flash_ctrl_reg(__u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    return __raw_readl(base);
-+}
-+
-+static void write_flash_ctrl_reg(__u32 ofs,__u32 data)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    __raw_writel(data, base);
-+}
-+
-+void atmel_read_status(__u8 cmd, __u8 *data)
-+{
-+      __u32 opcode;
-+      __u32 value;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | cmd | g_chipen;
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      *data = value & 0xff;
-+}
-+
-+void main_memory_page_read(__u8 cmd, __u16 page, __u16 offset, __u8 *data)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u32 value;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_4X_DATA | cmd | g_chipen;
-+      address = (page << g_page_addr) + offset;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      *data = value & 0xff;
-+}
-+
-+void buffer_to_main_memory(__u8 cmd, __u16 page)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (page << g_page_addr);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+
-+void atmel_flash_read_page(__u32 address, __u8 *buffer, __u32 len)
-+{
-+    __u8  byte;
-+    __u16 page, offset;
-+    __u16 i;
-+
-+    address_to_page(address, &page, &offset);
-+
-+     for(i=0; i<len; i++,offset++)
-+    {
-+        main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
-+        buffer [i]= byte;
-+    }
-+}
-+
-+void atmel_flash_program_page(__u32 address, __u8 *buffer, __u32 len)
-+{
-+    __u8  pattern;
-+    __u16 page, offset;
-+    __u32 i;
-+
-+    address_to_page(address, &page, &offset);
-+ //   printk("atmel_flash_program_page: offset %x len %x page %x \n", offset, len, page);
-+
-+    if(offset)
-+          main_memory_to_buffer(MAIN_MEMORY_TO_BUFFER1,page);
-+
-+    for(i=0; i<len; i++,offset++)
-+    {
-+        pattern = buffer[i];
-+        atmel_buffer_write(BUFFER1_WRITE,offset,pattern);
-+    }
-+
-+  //  printk("atmel_flash_program_page: offset %x \n", offset);
-+    buffer_to_main_memory(BUFFER1_TO_MAIN_MEMORY, page);
-+  //  printk("atmel_flash_program_page: buffer_to_main_memory %x page\n", page);
-+
-+}
-+
-+
-+void main_memory_to_buffer(__u8 cmd, __u16 page)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (page << g_page_addr);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void main_memory_page_program(__u8 cmd, __u16 page, __u16 offset, __u8 data)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | cmd | g_chipen;
-+      address = (page << g_page_addr) + offset;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, data);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+}
-+
-+void atmel_buffer_write(__u8 cmd, __u16 offset, __u8 data)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | cmd  | g_chipen;
-+      address = offset;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, data);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void atmel_erase_page(__u8 cmd, __u16 page)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (page << g_page_addr);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void atmel_erase_block(__u8 cmd, __u16 block)
-+{
-+      __u32 opcode;
-+      __u32 address;
-+      __u8  status;
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | cmd | g_chipen;
-+      address = (block << 13);
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(opcode&0x80000000)
-+      {
-+          opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      atmel_read_status(READ_STATUS_SPI, &status);
-+      while(!(status&0x80))
-+      {
-+          atmel_read_status(READ_STATUS_SPI, &status);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+}
-+
-+void flash_delay(void)
-+{
-+      int i;
-+
-+      for(i=0; i<50; i++)
-+           i=i;
-+}
-+
-+
-+
-+
-+__u32 sl2312_read32(struct map_info *map, unsigned long ofs)
-+{
-+
-+#if 0
-+    __u16 page, offset;
-+    __u32 pattern;
-+    __u8  byte, i;
-+
-+     pattern = 0;
-+     address_to_page(ofs, &page, &offset);
-+     for(i=0; i<4; i++, offset++)
-+    {
-+        pattern = pattern << 8;
-+        main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
-+//printk("sl2312_read32:: address = %08x  data = %c \n",ofs,byte);
-+        pattern += byte;
-+    }
-+    return pattern;
-+#else
-+      return read_flash_ctrl_reg(ofs);
-+#endif
-+
-+}
-+
-+__u8 sl2312_read8(struct map_info *map, unsigned long ofs)
-+{
-+    __u16 page, offset;
-+    __u8  byte;
-+
-+     address_to_page(ofs, &page, &offset);
-+     main_memory_page_read(MAIN_MEMORY_PAGE_READ_SPI , page, offset, &byte);
-+       //printk("sl2312_read8:: address = %08x  data = %c \n",ofs,byte);
-+     return byte;
-+
-+}
-+
-+void sl2312_write32(struct map_info *map, __u32 d, unsigned long ofs)
-+{
-+#if 0
-+    __u16 page, offset;
-+    __u8  byte, i;
-+
-+     address_to_page(ofs, &page, &offset);
-+     for(i=0; i<4; i++, offset++)
-+    {
-+      byte = d & 0xff;
-+        main_memory_page_program(MAIN_MEMORY_PROGRAM_BUFFER1, page, offset, byte);
-+        d = d >> 8;
-+//printk("sl2312_write32:: address = %08x  data = %c \n",ofs,byte);
-+    }
-+#else
-+      write_flash_ctrl_reg(ofs, d);
-+#endif
-+}
-+
-+void sl2312_write8(struct map_info *map, __u8 d, unsigned long ofs)
-+{
-+     __u16 page, offset;
-+
-+     address_to_page(ofs, &page, &offset);
-+     main_memory_page_program(MAIN_MEMORY_PROGRAM_BUFFER1, page, offset, d);
-+//printk("sl2312_write8:: address = %08x  data = %c \n",ofs,d);
-+
-+}
-+
-+void sl2312_copy_from(struct map_info *map, void *buf, unsigned long ofs, ssize_t len)
-+{
-+     __u32 size;
-+     __u8  *buffer;
-+     __u32 length;//i, j,
-+
-+     //printk("sl2312_copy_from:: address = %08x  datalen = %d \n",ofs,len);
-+
-+     length = len;
-+     buffer = (__u8 *)buf;
-+     while(len)
-+     {
-+        size = SPAGE_SIZE - (ofs%SPAGE_SIZE);
-+        if(size > len)
-+            size = len;
-+        atmel_flash_read_page(ofs, buffer, size);
-+        buffer+=size;
-+        ofs+=size;
-+        len -= size;
-+     }
-+
-+#if 0
-+        buffer = (__u8 *)buf;
-+        for(i=0; i<length; i+=16)
-+       {
-+          for(j=0; j<16; j++,buffer++)
-+         {
-+            if((i*16+j)<length)
-+              printk("%x  ",(int)*buffer);
-+       }
-+          printk("\n");
-+       }
-+
-+       printk("\n");
-+#endif
-+
-+}
-+
-+
-+void sl2312_copy_to(struct map_info *map, unsigned long ofs, void *buf, ssize_t len)
-+{
-+     __u32 size;
-+     __u8  *buffer;
-+
-+     buffer = (__u8 *)buf;
-+     //printk("sl2312_copy_to:offset %x len %x \n", ofs, len);
-+//     printk("sl2312_copy_to:buf is %x \n", (int)buf);
-+
-+     while(len)
-+     {
-+        size = SPAGE_SIZE - (ofs%SPAGE_SIZE);
-+        if(size > len)
-+            size = len;
-+        atmel_flash_program_page(ofs, buffer, size);
-+        buffer+=size;
-+        ofs+=size;
-+      len-=size;
-+    }
-+
-+
-+}
-+
-+
-+static struct mtd_info *serial_mtd;
-+
-+static struct mtd_partition *parsed_parts;
-+
-+static struct map_info sl2312_serial_map = {
-+//    name: "SL2312 serial flash",
-+//    size: 4194304, //0x400000,
-+//            //buswidth: 4,
-+//    bankwidth: 4,
-+//    phys:            SL2312_FLASH_BASE,
-+//#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
-+//    //read32: sl2312_read32,
-+//    //read8: sl2312_read8,
-+//    copy_from: sl2312_copy_from,
-+//    //write8: sl2312_write8,
-+//    //write32: sl2312_write32,
-+//    read: sl2312_read32,
-+//    write: sl2312_write32,
-+//    copy_to: sl2312_copy_to
-+//#endif
-+      .name = "SL2312 serial flash",
-+      .size = 4194304, //0x400000,
-+              //buswidth: 4,
-+      .bankwidth = 4,
-+      .phys =          SL2312_FLASH_BASE,
-+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
-+      //read32: sl2312_read32,
-+      //read8: sl2312_read8,
-+      .copy_from = sl2312_copy_from,
-+      //write8: sl2312_write8,
-+      //write32: sl2312_write32,
-+      .read = sl2312_read32,
-+      .write = sl2312_write32,
-+      .copy_to = sl2312_copy_to
-+#endif
-+};
-+
-+
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+
-+
-+      ///* boot code */
-+      //{ name: "bootloader", offset: 0x00000000, size: 0x20000, },
-+      ///* kernel image */
-+      //{ name: "kerel image", offset: 0x000020000, size: 0x2E0000 },
-+      ///* All else is writable (e.g. JFFS) */
-+      //{ name: "user data", offset: 0x00300000, size: 0x00100000, },
-+      /* boot code */
-+      { .name = "bootloader", .offset = 0x00000000, .size = 0x20000, },
-+      /* kernel image */
-+      { .name = "kerel image", .offset = 0x000020000, .size = 0xE0000 },
-+      /* All else is writable (e.g. JFFS) */
-+      { .name = "user data", .offset = 0x00100000, .size = 0x00300000, },
-+
-+
-+};
-+
-+
-+
-+static int __init init_sl2312_maps(void)
-+{
-+      int nr_parts = 0;
-+      struct mtd_partition *parts;
-+
-+      serial_mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-+      if (!serial_mtd)
-+              return NULL;
-+
-+      memset(serial_mtd, 0, sizeof(struct mtd_info));
-+      //sl2312flash_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
-+    //sl2312_serial_map.map_priv_1 = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)FLASH_VBASE;
-+    sl2312_serial_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)ioremap(FLASH_START, SFLASH_SIZE);
-+    if (!sl2312_serial_map.virt) {
-+              printk(" failed to ioremap \n");
-+              return -EIO;
-+      }
-+      serial_mtd = do_map_probe("map_serial", &sl2312_serial_map);
-+      if (serial_mtd) {
-+              //serial_mtd->module = THIS_MODULE;
-+              serial_mtd->owner = THIS_MODULE;
-+
-+      }
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+      nr_parts = parse_redboot_partitions(serial_mtd, &parsed_parts);
-+      if (nr_parts > 0)
-+              printk(KERN_NOTICE "Found RedBoot partition table.\n");
-+      else if (nr_parts < 0)
-+              printk(KERN_NOTICE "Error looking for RedBoot partitions.\n");
-+#else
-+      parsed_parts = sl2312_partitions;
-+      parts = sl2312_partitions;
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parsed_parts);
-+#endif /* CONFIG_MTD_REDBOOT_PARTS */
-+
-+      if (nr_parts > 0)
-+          add_mtd_partitions(serial_mtd, parsed_parts, nr_parts);
-+      else
-+          add_mtd_device(serial_mtd);
-+
-+      return 0;
-+}
-+
-+static void __exit cleanup_sl2312_maps(void)
-+{
-+      if (parsed_parts)
-+          del_mtd_partitions(serial_mtd);
-+      else
-+          del_mtd_device(serial_mtd);
-+
-+      map_destroy(serial_mtd);
-+
-+
-+}
-+
-+module_init(init_sl2312_maps);
-+module_exit(cleanup_sl2312_maps);
-+
-+
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Plus Chen <plus@storlink.com.tw>");
-+MODULE_DESCRIPTION("MTD map driver for Storlink Sword boards");
-+
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312-flash-cfi.c
-@@ -0,0 +1,370 @@
-+/*======================================================================
-+
-+   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 <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/ioport.h>
-+#include <linux/init.h>
-+#include <linux/string.h>
-+
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+#include <asm/system.h>
-+#include <asm/arch/sl2312.h>
-+#include <linux/mtd/kvctl.h>
-+#include "sl2312_flashmap.h"
-+
-+
-+//extern int parse_afs_partitions(struct mtd_info *, struct mtd_partition **);
-+
-+/* the base address of FLASH control register */
-+#define FLASH_CONTROL_BASE_ADDR           (IO_ADDRESS(SL2312_FLASH_CTRL_BASE))
-+#define SL2312_GLOBAL_BASE_ADDR     (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+
-+/* define read/write register utility */
-+#define FLASH_READ_REG(offset)                        (__raw_readl(offset+FLASH_CONTROL_BASE_ADDR))
-+#define FLASH_WRITE_REG(offset,val)   (__raw_writel(val,offset+FLASH_CONTROL_BASE_ADDR))
-+
-+/* the offset of FLASH control register */
-+enum EMAC_REGISTER {
-+      FLASH_ID        = 0x0000,
-+      FLASH_STATUS    = 0x0008,
-+      FLASH_TYPE      = 0x000c,
-+      FLASH_ACCESS    = 0x0020,
-+      FLASH_ADDRESS   = 0x0024,
-+      FLASH_DATA              = 0x0028,
-+      FLASH_TIMING    = 0x002c,
-+};
-+
-+//#define FLASH_BASE  FLASH_CONTROL_BASE_ADDR
-+//#define FLASH_SIZE  0x00800000 //INTEGRATOR_FLASH_SIZE
-+
-+//#define FLASH_PART_SIZE 8388608
-+
-+static unsigned int flash_indirect_access = 0;
-+
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+static unsigned int chip_en = 0x00000000;
-+
-+void sl2312flash_enable_parallel_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val & 0xfffffffd;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+
-+void sl2312flash_disable_parallel_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val | 0x00000002;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+#endif
-+
-+
-+static struct map_info sl2312flash_map =
-+{
-+      name:           "SL2312 CFI Flash",
-+      size:       FLASH_SIZE,
-+      bankwidth:   2,
-+      //bankwidth:   1, //for 8 bits width
-+    phys:       SL2312_FLASH_BASE,
-+};
-+
-+static struct mtd_info *mtd;
-+#if 0
-+static struct mtd_partition sl2312_partitions[] = {
-+      /* boot code */
-+      {
-+              name: "bootloader",
-+              offset: 0x00000000,
-+              size: 0x20000,
-+//            mask_flags: MTD_WRITEABLE,
-+      },
-+      /* kernel image */
-+      {
-+              name: "kerel image",
-+              offset: 0x00020000,
-+              size: 0x2E0000
-+      },
-+      /* All else is writable (e.g. JFFS) */
-+      {
-+              name: "user data",
-+              offset: 0x00300000,
-+              size: 0x00100000,
-+      }
-+};
-+#endif
-+
-+
-+
-+static int __init sl2312flash_init(void)
-+{
-+      struct mtd_partition *parts;
-+      int nr_parts = 0;
-+      int ret;
-+#ifndef CONFIG_SL2312_SHARE_PIN
-+    unsigned int    reg_val;
-+#endif
-+
-+    printk("SL2312 MTD Driver Init.......\n");
-+
-+#ifndef CONFIG_SL2312_SHARE_PIN
-+      /* enable flash */
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val & 0xfffffffd;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+#else
-+    sl2312flash_enable_parallel_flash();      /* enable Parallel FLASH */
-+#endif
-+    FLASH_WRITE_REG(FLASH_ACCESS,0x00004000); /* parallel flash direct access mode */
-+    ret = FLASH_READ_REG(FLASH_ACCESS);
-+    if (ret == 0x00004000)
-+    {
-+        flash_indirect_access = 0;  /* parallel flash direct access */
-+    }
-+    else
-+    {
-+        flash_indirect_access = 1;  /* parallel flash indirect access */
-+    }
-+
-+      /*
-+       * Also, the CFI layer automatically works out what size
-+       * of chips we have, and does the necessary identification
-+       * for us automatically.
-+       */
-+#ifdef CONFIG_GEMINI_IPI
-+      sl2312flash_map.virt = FLASH_VBASE;//(unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
-+#else
-+      sl2312flash_map.virt = (unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
-+#endif
-+      //printk("sl2312flash_map.virt  = %08x\n",(unsigned int)sl2312flash_map.virt);
-+
-+//    simple_map_init(&sl2312flash_map);
-+
-+      mtd = do_map_probe("cfi_probe", &sl2312flash_map);
-+      if (!mtd)
-+      {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+        sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
-+#endif
-+              return -ENXIO;
-+      }
-+      mtd->owner = THIS_MODULE;
-+//    mtd->erase = flash_erase;
-+//    mtd->read = flash_read;
-+//    mtd->write = flash_write;
-+
-+    parts = sl2312_partitions;
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
-+      ret = add_mtd_partitions(mtd, parts, nr_parts);
-+      /*If we got an error, free all resources.*/
-+      if (ret < 0) {
-+              del_mtd_partitions(mtd);
-+              map_destroy(mtd);
-+      }
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+    sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
-+#endif
-+    printk("SL2312 MTD Driver Init Success ......\n");
-+      return ret;
-+}
-+
-+static void __exit sl2312flash_exit(void)
-+{
-+      if (mtd) {
-+              del_mtd_partitions(mtd);
-+              map_destroy(mtd);
-+      }
-+
-+      if (sl2312flash_map.virt) {
-+          iounmap((void *)sl2312flash_map.virt);
-+          sl2312flash_map.virt = 0;
-+      }
-+}
-+
-+char chrtohex(char c)
-+{
-+  char val;
-+  if ((c >= '0') && (c <= '9'))
-+  {
-+    val = c - '0';
-+    return val;
-+  }
-+  else if ((c >= 'a') && (c <= 'f'))
-+  {
-+    val = 10 + (c - 'a');
-+    return val;
-+  }
-+  else if ((c >= 'A') && (c <= 'F'))
-+  {
-+    val = 10 + (c - 'A');
-+    return val;
-+  }
-+  printk("<1>Error number\n");
-+  return 0;
-+}
-+
-+
-+int get_vlaninfo(vlaninfo* vlan)
-+{
-+      vctl_mheader head;
-+      vctl_entry entry;
-+      struct mtd_info *mymtd=NULL;
-+      int i, j, loc = 0;
-+      char *payload=0, *tmp1, *tmp2, tmp3[9];
-+      size_t retlen;
-+
-+      #ifdef CONFIG_SL2312_SHARE_PIN
-+      sl2312flash_enable_parallel_flash();
-+      #endif
-+      for(i=0;i<MAX_MTD_DEVICES;i++)
-+      {
-+              mymtd=get_mtd_device(NULL,i);
-+              //    printk("mymtd->name: %s\n", mymtd->name);
-+              if(mymtd && !strcmp(mymtd->name,"VCTL"))
-+              {
-+                      //      printk("%s\n", mymtd->name);
-+                      break;
-+              }
-+      }
-+      if( i >= MAX_MTD_DEVICES)
-+      {
-+              printk("Can't find version control\n");
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              return 0;
-+      }
-+
-+      if (!mymtd | !mymtd->read)
-+      {
-+              printk("<1>Can't read Version Configuration\n");
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              return 0;
-+      }
-+
-+      mymtd->read(mymtd, 0, VCTL_HEAD_SIZE, &retlen, (u_char*)&head);
-+      //  printk("entry header: %c%c%c%c\n", head.header[0], head.header[1], head.header[2], head.header[3]);
-+      //  printk("entry number: %x\n", head.entry_num);
-+      if ( strncmp(head.header, "FLFM", 4) )
-+      {
-+              printk("VCTL is a erase block\n");
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              return 0;
-+      }
-+      loc += retlen;
-+      for (i = 0; i < head.entry_num; i++)
-+      {
-+              mymtd->read(mymtd, loc, VCTL_ENTRY_LEN, &retlen, (u_char*)&entry);
-+              //    printk("type: %x\n", entry.type);
-+              //    printk("size: %x\n", entry.size);
-+              strncpy(tmp3, entry.header, 4);
-+              if (entry.type == VCT_VLAN)
-+              {
-+                      for (j = 0; j < 6 ; j++)
-+                      {
-+                              vlan[0].mac[j] = 0;
-+                              vlan[1].mac[j] = 0;
-+                      }
-+                      vlan[0].vlanid = 1;
-+                      vlan[1].vlanid = 2;
-+                      vlan[0].vlanmap = 0x7F;
-+                      vlan[1].vlanmap = 0x80;
-+
-+                      payload = (char *)kmalloc(entry.size - VCTL_ENTRY_LEN, GFP_KERNEL);
-+                      loc += VCTL_ENTRY_LEN;
-+                      mymtd->read(mymtd, loc, entry.size - VCTL_ENTRY_LEN, &retlen, payload);
-+                      //      printk("%s\n", payload);
-+                      tmp1 = strstr(payload, "MAC1:");
-+                      tmp2 = strstr(payload, "MAC2:");
-+                      if(!tmp1||!tmp2){
-+                              kfree(payload);
-+                              #ifdef CONFIG_SL2312_SHARE_PIN
-+                              sl2312flash_disable_parallel_flash();
-+                              #endif
-+                              printk("Error VCTL format!!\n");
-+                              return 0;
-+                      }
-+                      tmp1 += 7;
-+                      tmp2 += 7;
-+
-+
-+                      for (j = 0; j < 6; j++)
-+                      {
-+                              vlan[0].mac[j] = chrtohex(tmp1[2*j])*16 + chrtohex(tmp1[(2*j)+1]);
-+                              vlan[1].mac[j] = chrtohex(tmp2[2*j])*16 + chrtohex(tmp2[(2*j)+1]);
-+                      }
-+                      tmp1 = strstr(payload, "ID1:");
-+                      tmp2 = strstr(payload, "ID2:");
-+                      tmp1 += 4;
-+                      tmp2 += 4;
-+                      vlan[0].vlanid = tmp1[0] - '0';
-+                      vlan[1].vlanid = tmp2[0] - '0';
-+                      tmp1 = strstr(payload, "MAP1:");
-+                      tmp2 = strstr(payload, "MAP2:");
-+                      tmp1 += 7;
-+                      tmp2 += 7;
-+                      vlan[0].vlanmap = chrtohex(tmp1[0]) * 16 + chrtohex(tmp1[1]);
-+                      vlan[1].vlanmap = chrtohex(tmp2[0]) * 16 + chrtohex(tmp2[1]);
-+                      //  printk("Vlan1 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[0].vlanid, vlan[0].vlanmap, vlan[0].mac[0], vlan[0].mac[1], vlan[0].mac[2], vlan[0].mac[3], vlan[0].mac[4], vlan[0].mac[5]);
-+                      //  printk("Vlan2 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[1].vlanid, vlan[1].vlanmap, vlan[1].mac[0], vlan[1].mac[1], vlan[1].mac[2], vlan[1].mac[3], vlan[1].mac[4], vlan[1].mac[5]);
-+                      break;
-+              }
-+              loc += entry.size;
-+      }
-+      if ( entry.type == VCT_VLAN )
-+      {
-+              #ifdef CONFIG_SL2312_SHARE_PIN
-+              sl2312flash_disable_parallel_flash();
-+              #endif
-+              kfree(payload);
-+              return 1;
-+      }
-+      if (i >= head.entry_num)
-+      printk("Can't find vlan information\n");
-+      #ifdef CONFIG_SL2312_SHARE_PIN
-+      sl2312flash_disable_parallel_flash();
-+      #endif
-+      return 0;
-+}
-+
-+EXPORT_SYMBOL(get_vlaninfo);
-+
-+
-+module_init(sl2312flash_init);
-+module_exit(sl2312flash_exit);
-+
-+MODULE_AUTHOR("Storlink Ltd");
-+MODULE_DESCRIPTION("CFI map driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312-flash-m25p80.c
-@@ -0,0 +1,498 @@
-+/*
-+ * $Id: sl2312-flash-m25p80.c,v 1.2 2006/06/02 08:46:02 middle Exp $
-+ *
-+ * Flash and EPROM on Hitachi Solution Engine and similar boards.
-+ *
-+ * (C) 2001 Red Hat, Inc.
-+ *
-+ * GPL'd
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+
-+#include <asm/io.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/partitions.h>
-+#include <asm/hardware.h>
-+
-+#include <asm/arch/sl2312.h>
-+#include <asm/arch/flash.h>
-+#include <linux/init.h> //add
-+#define  g_chipen     SERIAL_FLASH_CHIP0_EN   //ST
-+
-+//static int m25p80_page_program(__u32 address, __u8 data, __u32 schip_en);
-+static void m25p80_write_cmd(__u8 cmd, __u32 schip_en);
-+extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-+
-+
-+static __u32 read_flash_ctrl_reg(__u32 ofs)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    return __raw_readl(base);
-+}
-+
-+static void write_flash_ctrl_reg(__u32 ofs,__u32 data)
-+{
-+    __u32 *base;
-+
-+    base = (__u32 *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE + ofs));
-+    __raw_writel(data, base);
-+}
-+
-+static void m25p80_read(__u32 address, __u8 *data, __u32 schip_en)
-+{
-+      __u32 opcode,status;
-+      __u32 value;
-+
-+      //opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ;
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | M25P80_READ;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      status=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(status&0x80000000)
-+      {
-+          status=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+
-+      value=read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      *data = value & 0xff;
-+}
-+
-+static int m25p80_page_program(__u32 address, __u8 *data, __u32 schip_en)
-+{
-+      __u32 opcode;
-+      __u32  status;
-+        __u32 tmp;
-+        int res = FLASH_ERR_OK;
-+        //volatile FLASH_DATA_T* data_ptr = (volatile FLASH_DATA_T*) data;
-+        opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+
-+                    opcode|=g_chipen;
-+
-+          write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+          //middle delay_ms(130);
-+          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+          if((status&0x02)==0x02)
-+                {
-+                     //middle delay_ms(100);
-+               m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
-+          }
-+
-+
-+      m25p80_write_cmd(M25P80_WRITE_ENABLE, schip_en);
-+      ////middle delay_ms(10);
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS_DATA | M25P80_PAGE_PROGRAM;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      write_flash_ctrl_reg(FLASH_WRITE_DATA_OFFSET, *data);
-+
-+      //status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //while(status!=data)
-+      //{
-+      //    status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //    //middle delay_ms(10);
-+      //}
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+      //opcode=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+
-+              opcode|=g_chipen;
-+
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //while(status&0xfd)
-+      while(status&0x01)
-+      {
-+                //if((status&0x9c)!=0)
-+                //    printf("  m25p80_page_program   Protect Status = %x\n",status);
-+                write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+          flash_delay();
-+          schedule();
-+          //middle delay_ms(50);
-+      }
-+      //printf("status = %x, data = %x\n",status,data);
-+      if((status&0x02)==0x02)
-+      {
-+        //middle delay_ms(100);
-+          m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
-+      }
-+    //};//while (len > 0)
-+    return res;
-+}
-+
-+void m25p80_copy_from(struct map_info *map, void *buf, unsigned long ofs, ssize_t len)
-+{
-+//     __u32 size;
-+     __u8  *buffer;
-+     __u32 length;//i, j,
-+
-+      length = len;
-+     buffer = (__u8 *)buf;
-+     while(len)
-+     {
-+        m25p80_read(ofs, buffer, g_chipen);
-+        buffer++;
-+        ofs++;
-+        len --;
-+     }        ;
-+
-+}
-+
-+__u32 m25p80_read32(struct map_info *map, unsigned long ofs)
-+{
-+
-+      return read_flash_ctrl_reg(ofs);
-+
-+
-+}
-+
-+void m25p80_write32(struct map_info *map, __u32 d, unsigned long ofs)
-+{
-+
-+      write_flash_ctrl_reg(ofs, d);
-+
-+}
-+
-+void m25p80_copy_to(struct map_info *map, unsigned long ofs, void *buf, ssize_t len)
-+{
-+     __u32 size, i, ret;
-+
-+     while(len > 0)
-+     {
-+        if(len >= M25P80_PAGE_SIZE)
-+                      size = M25P80_PAGE_SIZE;
-+              else
-+                      size = len;
-+
-+        for(i=0;i<size;i++)
-+          {
-+              ret = m25p80_page_program( (ofs+i),  (buf+i),  g_chipen);
-+          }
-+        buf+=M25P80_PAGE_SIZE;
-+        ofs+=M25P80_PAGE_SIZE;
-+              len-=M25P80_PAGE_SIZE;
-+
-+    };
-+
-+
-+}
-+
-+static struct mtd_info *serial_mtd;
-+
-+static struct mtd_partition *parsed_parts;
-+
-+static struct map_info m25p80_map = {
-+
-+      .name = "SL2312 serial flash m25p80",
-+      .size = 1048576, //0x100000,
-+              //buswidth: 4,
-+      .bankwidth = 4,
-+      .phys =          SL2312_FLASH_BASE,
-+#ifdef CONFIG_MTD_COMPLEX_MAPPINGS
-+      .copy_from = m25p80_copy_from,
-+      .read = m25p80_read32,
-+      .write = m25p80_write32,
-+      .copy_to = m25p80_copy_to
-+#endif
-+};
-+
-+
-+
-+static struct mtd_partition m25p80_partitions[] = {
-+
-+      /* boot code */
-+      { .name = "bootloader", .offset = 0x00000000, .size = 0x20000, },
-+      /* kernel image */
-+      { .name = "kerel image", .offset = 0x000020000, .size = 0xC0000 },
-+      /* All else is writable (e.g. JFFS) */
-+      { .name = "user data", .offset = 0x000E0000, .size = 0x00010000, },
-+
-+
-+};
-+
-+void flash_delay()
-+{
-+      int i,j;
-+      for(i=0;i<0x100;i++)
-+              j=i*3+5;
-+}
-+
-+int m25p80_sector_erase(__u32 address, __u32 schip_en)
-+{
-+      __u32 opcode;
-+      __u32  status;
-+      __u32 tmp;
-+      int res = FLASH_ERR_OK;
-+      //printf("\n-->m25p80_sector_erase");
-+      if(address >= FLASH_START)
-+              address-=FLASH_START;
-+
-+      m25p80_write_cmd(M25P80_WRITE_ENABLE, schip_en);
-+      //printf("\n     m25p80_sector_erase : after we-en");
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_SHIFT_ADDRESS | M25P80_SECTOR_ERASE;
-+      write_flash_ctrl_reg(FLASH_ADDRESS_OFFSET, address);
-+      #ifdef MIDWAY_DIAG
-+              opcode|=schip_en;
-+      #endif
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+      #ifdef MIDWAY_DIAG
-+              opcode|=schip_en;
-+      #endif
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //while(status&0xfd)
-+      while(status&0x01)
-+      {
-+                //if((status&0x9c)!=0)
-+                //    printf("  m25p80_sector_erase   Protect Status = %x\n",status);
-+                write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+          status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+          flash_delay();
-+          schedule();
-+          //middle delay_ms(50);
-+      }
-+      if((status&0x02)==0x02)
-+      {
-+                //middle delay_ms(100);
-+          m25p80_write_cmd(M25P80_WRITE_DISABLE, schip_en);
-+      }
-+      //printf("\n<--m25p80_sector_erase");
-+      return res;
-+}
-+
-+static void m25p80_write_cmd(__u8 cmd, __u32 schip_en)
-+{
-+      __u32 opcode,tmp;
-+      __u32  status;
-+
-+
-+
-+
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE | cmd;
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(tmp&0x80000000)
-+      {
-+          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      //////
-+      opcode = 0x80000000 | FLASH_ACCESS_ACTION_OPCODE_DATA | M25P80_READ_STATUS;
-+
-+              opcode|=g_chipen;
-+
-+      write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+      tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+      while(tmp&0x80000000)
-+      {
-+          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+          flash_delay();
-+          schedule();
-+      }
-+      //middle delay_ms(130);
-+      status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+      //printf("\ncmd =%x  status = %x",cmd,status);
-+      if(cmd==M25P80_WRITE_ENABLE)
-+      {
-+              //printf("\n**-->enable**  status = %x",status);
-+              //middle delay_ms(100);
-+                 while((status&0x03) != 2)
-+                 {
-+                      //if((status&0x9c)!=0)
-+                      //    printf("  M25P80_WRITE_ENABLE   Protect Status = %x\n",status);
-+
-+                        write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                        tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  //flash_delay();
-+                              }
-+                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+                     //printf("\n**enable**  status = %x",status);
-+                     flash_delay();
-+                     schedule();
-+                     //middle delay_ms(100);
-+                 }
-+      }
-+      else if(cmd==M25P80_WRITE_DISABLE)
-+      {
-+                 //while((status&0x03) == 2)
-+                 //   printf("\n**disable**  status = %x",status);
-+                 //middle delay_ms(100);
-+                 while((status&0x03) != 0)
-+                 {
-+             //m25p80_write_status((status&0xfd),schip_en);
-+                     write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                     tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                      while(tmp&0x80000000)
-+                      {
-+                          tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                          flash_delay();
-+                          schedule();
-+                      }
-+                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+                     //printf("\n**disable**  status = %x",status);
-+                     flash_delay();
-+                     schedule();
-+                     //middle delay_ms(50);
-+                 }
-+      }
-+      else
-+      {
-+                 //while((status&0x01) !=0)
-+                 while((status&0x01) !=0)
-+                 {
-+                        write_flash_ctrl_reg(FLASH_ACCESS_OFFSET, opcode);
-+                        tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                              while(tmp&0x80000000)
-+                              {
-+                                  tmp=read_flash_ctrl_reg(FLASH_ACCESS_OFFSET);
-+                                  flash_delay();
-+                                  schedule();
-+                              }
-+                     status = read_flash_ctrl_reg(FLASH_READ_DATA_OFFSET);
-+                     flash_delay();
-+                     schedule();
-+                     //middle delay_ms(50);
-+                 }
-+      }
-+      //////
-+
-+      //printf("\n<--  status = %x",status);
-+}
-+
-+static int __init init_sl2312_m25p80(void)
-+{
-+      int nr_parts = 0;
-+      struct mtd_partition *parts;
-+
-+      serial_mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-+      if (!serial_mtd)
-+              return NULL;
-+
-+      memset(serial_mtd, 0, sizeof(struct mtd_info));
-+      m25p80_map.virt = (unsigned long)ioremap(SL2312_FLASH_BASE, SFLASH_SIZE);//(unsigned long)ioremap(FLASH_START, SFLASH_SIZE);
-+    if (!m25p80_map.virt) {
-+              printk(" failed to ioremap \n");
-+              return -EIO;
-+      }
-+      serial_mtd = do_map_probe("map_serial", &m25p80_map);
-+      if (serial_mtd) {
-+              serial_mtd->owner = THIS_MODULE;
-+
-+      }
-+
-+#ifdef CONFIG_MTD_REDBOOT_PARTS
-+      nr_parts = parse_redboot_partitions(serial_mtd, &parsed_parts);
-+      if (nr_parts > 0)
-+              printk(KERN_NOTICE "Found RedBoot partition table.\n");
-+      else if (nr_parts < 0)
-+              printk(KERN_NOTICE "Error looking for RedBoot partitions.\n");
-+#else
-+      parsed_parts = m25p80_partitions;
-+      parts = m25p80_partitions;
-+      nr_parts = sizeof(m25p80_partitions)/sizeof(*parts);
-+      nr_parts = sizeof(m25p80_partitions)/sizeof(*parsed_parts);
-+#endif /* CONFIG_MTD_REDBOOT_PARTS */
-+
-+      if (nr_parts > 0)
-+          add_mtd_partitions(serial_mtd, parsed_parts, nr_parts);
-+      else
-+          add_mtd_device(serial_mtd);
-+
-+      return 0;
-+}
-+
-+static void __exit cleanup_sl2312_m25p80(void)
-+{
-+      if (parsed_parts)
-+          del_mtd_partitions(serial_mtd);
-+      else
-+          del_mtd_device(serial_mtd);
-+
-+      map_destroy(serial_mtd);
-+
-+
-+}
-+
-+module_init(init_sl2312_m25p80);
-+module_exit(cleanup_sl2312_m25p80);
-+
-+
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Plus Chen <plus@storlink.com.tw>");
-+MODULE_DESCRIPTION("MTD map driver for Storlink Sword boards");
-+
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312_flashmap.h
-@@ -0,0 +1,20 @@
-+/*
-+ * Please note that the name are used in mkflash script. Therefore
-+ * don't change them.  If you want to add different partitions, you
-+ * will need to modify mkflash script as well so that the end image
-+ * is what you include here!
-+ *
-+ * Also, the 7th item is always the size, so please don't add extra
-+ * spaces in the name or other items.
-+ *
-+ *  - Alan
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
-+      { name: "kernel",        offset: 0x00020000, size: 0x00100000, },
-+      { name: "rootfs",        offset: 0x00120000, size: 0x006A0000, },
-+      { name: "VCTL",          offset: 0x007C0000, size: 0x00010000, },
-+      { name: "cfg",           offset: 0x007D0000, size: 0x00020000, },
-+      { name: "FIS directory", offset: 0x007F0000, size: 0x00010000, }
-+};
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312_flashmap.h.16MB
-@@ -0,0 +1,21 @@
-+/*
-+ * Please note that the name are used in mkflash script. Therefore
-+ * don't change them.  If you want to add different partitions, you
-+ * will need to modify mkflash script as well so that the end image
-+ * is what you include here!
-+ *
-+ * Also, the 7th item is always the size, so please don't add extra
-+ * spaces in the name or other items.
-+ *
-+ *  - Alan
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
-+      { name: "Kernel",        offset: 0x00020000, size: 0x00300000, },
-+      { name: "Ramdisk",       offset: 0x00320000, size: 0x00600000, },
-+      { name: "Application",   offset: 0x00920000, size: 0x00600000, },
-+      { name: "VCTL",          offset: 0x00F20000, size: 0x00020000, },
-+      { name: "CurConf",       offset: 0x00F40000, size: 0x000A0000, },
-+      { name: "FIS directory", offset: 0x00FE0000, size: 0x00020000, }
-+};
---- /dev/null
-+++ b/drivers/mtd/maps/sl2312_flashmap.h.8MB
-@@ -0,0 +1,21 @@
-+/*
-+ * Please note that the name are used in mkflash script. Therefore
-+ * don't change them.  If you want to add different partitions, you
-+ * will need to modify mkflash script as well so that the end image
-+ * is what you include here!
-+ *
-+ * Also, the 7th item is always the size, so please don't add extra
-+ * spaces in the name or other items.
-+ *
-+ *  - Alan
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot",       offset: 0x00000000, size: 0x00020000, },
-+      { name: "Kernel",        offset: 0x00020000, size: 0x00200000, },
-+      { name: "Ramdisk",       offset: 0x00220000, size: 0x00280000, },
-+      { name: "Application",   offset: 0x004A0000, size: 0x00300000, },
-+      { name: "VCTL",          offset: 0x007A0000, size: 0x00020000, },
-+      { name: "CurConf",       offset: 0x007C0000, size: 0x00020000, },
-+      { name: "FIS directory", offset: 0x007E0000, size: 0x00020000, }
-+};
---- a/drivers/mtd/mtdchar.c
-+++ b/drivers/mtd/mtdchar.c
-@@ -59,6 +59,77 @@ struct mtd_file_info {
-       enum mtd_file_modes mode;
- };
-+/***********************************************************************
-+/*             Storlink SoC -- flash
-+/***********************************************************************/
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+unsigned int share_pin_flag=0;                // bit0:FLASH, bit1:UART, bit2:EMAC, bit3-4:IDE
-+unsigned int check_sleep_flag=0;      // bit0:FLASH, bit1:IDE
-+static spinlock_t sl2312_flash_lock = SPIN_LOCK_UNLOCKED;
-+EXPORT_SYMBOL(share_pin_flag);
-+int dbg=0;
-+DECLARE_WAIT_QUEUE_HEAD(wq);
-+extern struct wait_queue_head_t *flash_wait;
-+unsigned int flash_req=0;
-+void mtd_lock()
-+{
-+      struct task_struct *tsk = current;
-+      unsigned int value ;
-+      unsigned long flags;
-+      flash_req = 1;
-+      DECLARE_WAITQUEUE(wait, tsk);
-+      add_wait_queue(&wq, &wait);
-+      for(;;)
-+      {
-+              set_task_state(tsk, TASK_INTERRUPTIBLE);
-+              spin_lock_irqsave(&sl2312_flash_lock,flags);
-+              if((share_pin_flag&0x1E)){//||(check_sleep_flag&0x00000002)) {
-+                      spin_unlock_irqrestore(&sl2312_flash_lock, flags);
-+                      check_sleep_flag |= 0x00000001;
-+                      if(dbg)
-+                              printk("mtd yield %x %x\n",share_pin_flag,check_sleep_flag);
-+                      wake_up_interruptible(&flash_wait);
-+                      schedule();
-+              }
-+              else {
-+                      check_sleep_flag &= ~0x01;
-+                      share_pin_flag |= 0x00000001 ;                  // set share pin flag
-+                      spin_unlock_irqrestore(&sl2312_flash_lock, flags);
-+                      value = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+                      value = value & (~PFLASH_SHARE_BIT) ;
-+                      writel(value,IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+                      if(dbg)
-+                              printk("mtd Go %x %x\n",share_pin_flag,check_sleep_flag);
-+                      tsk->state = TASK_RUNNING;
-+                      remove_wait_queue(&wq, &wait);
-+                      return ;
-+              }
-+      }
-+}
-+
-+void mtd_unlock()
-+{
-+      unsigned int value ;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&sl2312_flash_lock,flags);            // Disable IRQ
-+      value = readl(IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+      value = value | PFLASH_SHARE_BIT ;                              // Disable Flash PADs
-+      writel(value,IO_ADDRESS((SL2312_GLOBAL_BASE+GLOBAL_MISC_REG)));
-+      share_pin_flag &= ~(0x00000001);                        // clear share pin flag
-+      check_sleep_flag &= ~0x00000001;
-+      spin_unlock_irqrestore(&sl2312_flash_lock, flags);      // Restore IRQ
-+      if (check_sleep_flag & 0x00000002)
-+      {
-+              check_sleep_flag &= ~(0x00000002);
-+              wake_up_interruptible(&flash_wait);
-+      }
-+      DEBUG(MTD_DEBUG_LEVEL0, "Flash Unlock...\n");
-+      flash_req = 0;
-+}
-+#endif
-+/***********************************************************************/
-+
- static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
- {
-       struct mtd_file_info *mfi = file->private_data;
-@@ -162,13 +233,21 @@ static ssize_t mtd_read(struct file *fil
-       int len;
-       char *kbuf;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-+
-       DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
-       if (*ppos + count > mtd->size)
-               count = mtd->size - *ppos;
--      if (!count)
-+      if (!count){
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return 0;
-+      }
-       /* FIXME: Use kiovec in 2.5 to lock down the user's buffers
-          and pass them directly to the MTD functions */
-@@ -178,8 +257,12 @@ static ssize_t mtd_read(struct file *fil
-       else
-               kbuf=kmalloc(count, GFP_KERNEL);
--      if (!kbuf)
-+      if (!kbuf) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return -ENOMEM;
-+      }
-       while (count) {
-@@ -224,6 +307,9 @@ static ssize_t mtd_read(struct file *fil
-                       *ppos += retlen;
-                       if (copy_to_user(buf, kbuf, retlen)) {
-                               kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                               return -EFAULT;
-                       }
-                       else
-@@ -235,13 +321,19 @@ static ssize_t mtd_read(struct file *fil
-                               count = 0;
-               }
-               else {
--                      kfree(kbuf);
-+                      kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-               }
-       }
-       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-       return total_retlen;
- } /* mtd_read */
-@@ -255,24 +347,40 @@ static ssize_t mtd_write(struct file *fi
-       int ret=0;
-       int len;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-+
-       DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
--      if (*ppos == mtd->size)
-+      if (*ppos == mtd->size){
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return -ENOSPC;
-+      }
-       if (*ppos + count > mtd->size)
-               count = mtd->size - *ppos;
--      if (!count)
-+      if (!count){
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return 0;
-+      }
-       if (count > MAX_KMALLOC_SIZE)
-               kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
-       else
-               kbuf=kmalloc(count, GFP_KERNEL);
--      if (!kbuf)
-+      if (!kbuf) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-               return -ENOMEM;
-+      }
-       while (count) {
-@@ -283,6 +391,9 @@ static ssize_t mtd_write(struct file *fi
-               if (copy_from_user(kbuf, buf, len)) {
-                       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-               }
-@@ -323,11 +434,17 @@ static ssize_t mtd_write(struct file *fi
-               }
-               else {
-                       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-               }
-       }
-       kfree(kbuf);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-       return total_retlen;
- } /* mtd_write */
-@@ -381,36 +498,67 @@ static int mtd_ioctl(struct inode *inode
-       u_long size;
-       struct mtd_info_user info;
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_lock();                             // sl2312 share pin lock
-+#endif
-+
-       DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
-       size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
-       if (cmd & IOC_IN) {
-               if (!access_ok(VERIFY_READ, argp, size))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-       }
-       if (cmd & IOC_OUT) {
-               if (!access_ok(VERIFY_WRITE, argp, size))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-       }
-       switch (cmd) {
-       case MEMGETREGIONCOUNT:
-               if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               break;
-       case MEMGETREGIONINFO:
-       {
-               struct region_info_user ur;
--              if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
-+              if (copy_from_user(&ur, argp, sizeof(struct region_info_user))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
--              if (ur.regionindex >= mtd->numeraseregions)
-+              if (ur.regionindex >= mtd->numeraseregions) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
-+              }
-               if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
--                              sizeof(struct mtd_erase_region_info)))
-+                              sizeof(struct mtd_erase_region_info))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               break;
-       }
-@@ -433,7 +581,12 @@ static int mtd_ioctl(struct inode *inode
-               struct erase_info *erase;
-               if(!(file->f_mode & 2))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EPERM;
-+              }
-               erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
-               if (!erase)
-@@ -447,6 +600,9 @@ static int mtd_ioctl(struct inode *inode
-                       if (copy_from_user(&erase->addr, argp,
-                                   sizeof(struct erase_info_user))) {
-                               kfree(erase);
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                               return -EFAULT;
-                       }
-                       erase->mtd = mtd;
-@@ -484,14 +640,26 @@ static int mtd_ioctl(struct inode *inode
-               struct mtd_oob_buf buf;
-               struct mtd_oob_ops ops;
--              if(!(file->f_mode & 2))
-+              if(!(file->f_mode & 2)) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EPERM;
-+              }
--              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
-+              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
--              if (buf.length > 4096)
-+              if (buf.length > 4096) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
-+              }
-               if (!mtd->write_oob)
-                       ret = -EOPNOTSUPP;
-@@ -499,8 +667,12 @@ static int mtd_ioctl(struct inode *inode
-                       ret = access_ok(VERIFY_READ, buf.ptr,
-                                       buf.length) ? 0 : EFAULT;
--              if (ret)
-+              if (ret) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-+              }
-               ops.ooblen = buf.length;
-               ops.ooboffs = buf.start & (mtd->oobsize - 1);
-@@ -536,19 +708,35 @@ static int mtd_ioctl(struct inode *inode
-               struct mtd_oob_buf buf;
-               struct mtd_oob_ops ops;
--              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
-+              if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
--              if (buf.length > 4096)
-+              if (buf.length > 4096) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
-+              }
--              if (!mtd->read_oob)
-+              if (!mtd->read_oob) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       ret = -EOPNOTSUPP;
-+              }
-               else
-                       ret = access_ok(VERIFY_WRITE, buf.ptr,
-                                       buf.length) ? 0 : -EFAULT;
--              if (ret)
-+              if (ret) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return ret;
-+              }
-               ops.ooblen = buf.length;
-               ops.ooboffs = buf.start & (mtd->oobsize - 1);
-@@ -580,7 +768,12 @@ static int mtd_ioctl(struct inode *inode
-               struct erase_info_user info;
-               if (copy_from_user(&info, argp, sizeof(info)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->lock)
-                       ret = -EOPNOTSUPP;
-@@ -594,7 +787,12 @@ static int mtd_ioctl(struct inode *inode
-               struct erase_info_user info;
-               if (copy_from_user(&info, argp, sizeof(info)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->unlock)
-                       ret = -EOPNOTSUPP;
-@@ -629,11 +827,21 @@ static int mtd_ioctl(struct inode *inode
-               loff_t offs;
-               if (copy_from_user(&offs, argp, sizeof(loff_t)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->block_isbad)
-                       ret = -EOPNOTSUPP;
-               else
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return mtd->block_isbad(mtd, offs);
-+              }
-               break;
-       }
-@@ -642,11 +850,21 @@ static int mtd_ioctl(struct inode *inode
-               loff_t offs;
-               if (copy_from_user(&offs, argp, sizeof(loff_t)))
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               if (!mtd->block_markbad)
-                       ret = -EOPNOTSUPP;
-               else
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return mtd->block_markbad(mtd, offs);
-+              }
-               break;
-       }
-@@ -654,8 +872,12 @@ static int mtd_ioctl(struct inode *inode
-       case OTPSELECT:
-       {
-               int mode;
--              if (copy_from_user(&mode, argp, sizeof(int)))
-+              if (copy_from_user(&mode, argp, sizeof(int))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
-+              }
-               mfi->mode = MTD_MODE_NORMAL;
-@@ -670,7 +892,12 @@ static int mtd_ioctl(struct inode *inode
-       {
-               struct otp_info *buf = kmalloc(4096, GFP_KERNEL);
-               if (!buf)
-+              {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -ENOMEM;
-+              }
-               ret = -EOPNOTSUPP;
-               switch (mfi->mode) {
-               case MTD_MODE_OTP_FACTORY:
-@@ -701,12 +928,24 @@ static int mtd_ioctl(struct inode *inode
-       {
-               struct otp_info info;
--              if (mfi->mode != MTD_MODE_OTP_USER)
-+              if (mfi->mode != MTD_MODE_OTP_USER) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EINVAL;
--              if (copy_from_user(&info, argp, sizeof(info)))
-+              }
-+              if (copy_from_user(&info, argp, sizeof(info))) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EFAULT;
--              if (!mtd->lock_user_prot_reg)
-+              }
-+              if (!mtd->lock_user_prot_reg) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                       return -EOPNOTSUPP;
-+              }
-               ret = mtd->lock_user_prot_reg(mtd, info.start, info.length);
-               break;
-       }
-@@ -742,8 +981,12 @@ static int mtd_ioctl(struct inode *inode
-                       break;
-               case MTD_MODE_RAW:
--                      if (!mtd->read_oob || !mtd->write_oob)
-+                      if (!mtd->read_oob || !mtd->write_oob) {
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+                              mtd_unlock();                           // sl2312 share pin lock
-+#endif
-                               return -EOPNOTSUPP;
-+                      }
-                       mfi->mode = arg;
-               case MTD_MODE_NORMAL:
-@@ -766,6 +1009,10 @@ static int mtd_ioctl(struct inode *inode
-               ret = -ENOTTY;
-       }
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+      mtd_unlock();                           // sl2312 share pin lock
-+#endif
-+
-       return ret;
- } /* memory_ioctl */
---- a/drivers/mtd/nand/Kconfig
-+++ b/drivers/mtd/nand/Kconfig
-@@ -44,6 +44,13 @@ config MTD_NAND_AUTCPU12
-         This enables the driver for the autronix autcpu12 board to
-         access the SmartMediaCard.
-+config MTD_NAND_SL2312
-+      tristate "NAND Flash device on Storlink board"
-+      depends on ARM && MTD_NAND && ARCH_SL2312
-+      help
-+        This enables the driver for the Storlink board to
-+        access the nand device.
-+
- config MTD_NAND_EDB7312
-       tristate "Support for Cirrus Logic EBD7312 evaluation board"
-       depends on ARCH_EDB7312
---- /dev/null
-+++ b/drivers/mtd/nand/sl2312-flash-nand.c
-@@ -0,0 +1,2287 @@
-+/*
-+ *  drivers/mtd/sl2312.c
-+ *
-+ * $Id: sl2312-flash-nand.c,v 1.5 2006/06/15 07:02:29 middle Exp $
-+ *
-+ * Copyright (C) 2001 Toshiba Corporation
-+ *
-+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
-+ * the terms of the GNU General Public License version 2. This program
-+ * is licensed "as is" without any warranty of any kind, whether express
-+ * or implied.
-+ *
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/nand.h>
-+#include <linux/mtd/nand_ecc.h>
-+#include <linux/mtd/partitions.h>
-+#include <linux/delay.h>
-+#include <asm/io.h>
-+#include <asm/hardware.h>
-+#include <asm/arch/sl2312.h>
-+#include "sl2312-flash-nand.h"
-+
-+
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/types.h>
-+#include <linux/mtd/compatmac.h>
-+#include <linux/interrupt.h>
-+#include <linux/bitops.h>
-+
-+
-+/*
-+ * NAND low-level MTD interface functions
-+ */
-+static void sl2312_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
-+static void sl2312_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
-+static int sl2312_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
-+
-+static int sl2312_nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-+static int sl2312_nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-+static int sl2312_nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-+static int sl2312_nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
-+static int sl2312_nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-+                         size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-+static int sl2312_nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);
-+static int sl2312_nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
-+                      unsigned long count, loff_t to, size_t * retlen);
-+static int sl2312_nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
-+                      unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
-+static int sl2312_nand_erase (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
-+static void sl2312_nand_sync (struct mtd_info *mtd);
-+static int sl2312_nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  struct nand_oobinfo *oobsel);
-+static int sl2312_nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt);
-+static int sl2312_nand_erase_block(struct mtd_info *mtd, int page);
-+
-+/*
-+ * MTD structure for sl2312 NDFMC
-+ */
-+static struct mtd_info *sl2312_mtd = NULL;
-+static int nand_page=0,nand_col=0;
-+
-+/* Define default oob placement schemes for large and small page devices */
-+static struct nand_oobinfo nand_oob_8 = {
-+      .useecc = MTD_NANDECC_AUTOPLACE,
-+      .eccbytes = 3,
-+      .eccpos = {0, 1, 2},
-+      .oobfree = { {3, 2}, {6, 2} }
-+};
-+
-+static struct nand_oobinfo nand_oob_16 = {
-+      .useecc = MTD_NANDECC_AUTOPLACE,
-+      .eccbytes = 6,
-+      .eccpos = {0, 1, 2, 3, 6, 7},
-+      .oobfree = { {8, 8} }
-+};
-+
-+static struct nand_oobinfo nand_oob_64 = {
-+      .useecc = MTD_NANDECC_AUTOPLACE,
-+      .eccbytes = 24,
-+      .eccpos = {
-+              40, 41, 42, 43, 44, 45, 46, 47,
-+              48, 49, 50, 51, 52, 53, 54, 55,
-+              56, 57, 58, 59, 60, 61, 62, 63},
-+      .oobfree = { {2, 38} }
-+};
-+
-+
-+/*
-+ * Define partitions for flash device
-+ */
-+/* the base address of FLASH control register */
-+#define FLASH_CONTROL_BASE_ADDR           (IO_ADDRESS(SL2312_FLASH_CTRL_BASE))
-+#define SL2312_GLOBAL_BASE_ADDR     (IO_ADDRESS(SL2312_GLOBAL_BASE))
-+//#define SL2312_FLASH_BASE_ADDR      (IO_ADDRESS(SL2312_FLASH_BASE))
-+#define SL2312_FLASH_BASE_ADDR       FLASH_VADDR(SL2312_FLASH_BASE)
-+static unsigned int CHIP_EN;
-+/* define read/write register utility */
-+//#define FLASH_READ_REG(offset)                      (__raw_readl(offset+FLASH_CONTROL_BASE_ADDR))
-+//#define FLASH_WRITE_REG(offset,val)         (__raw_writel(val,offset+FLASH_CONTROL_BASE_ADDR))
-+//#define FLASH_READ_DATA(offset)                     (__raw_readb(offset+SL2312_FLASH_BASE_ADDR))
-+//#define FLASH_WRITE_DATA(offset,val)        (__raw_writeb(val,offset+SL2312_FLASH_BASE_ADDR))
-+
-+unsigned int FLASH_READ_REG(unsigned int addr)
-+{
-+    unsigned int *base;
-+    unsigned int data;
-+
-+    base = (unsigned int *)(FLASH_CONTROL_BASE_ADDR + addr);
-+    data = *base;
-+    return (data);
-+}
-+
-+void FLASH_WRITE_REG(unsigned int addr,unsigned int data)
-+{
-+    unsigned int *base;
-+
-+    base = (unsigned int *)(FLASH_CONTROL_BASE_ADDR + addr);
-+    *base = data;
-+    return;
-+}
-+
-+unsigned int FLASH_READ_DATA(unsigned int addr)
-+{
-+    unsigned char *base;
-+    unsigned int data;
-+
-+    base = (unsigned char *)(SL2312_FLASH_BASE_ADDR + addr);
-+    data = *base;
-+    return (data);
-+}
-+
-+void FLASH_WRITE_DATA(unsigned int addr,unsigned int data)
-+{
-+    unsigned char *base;
-+
-+    base = (unsigned char *)(SL2312_FLASH_BASE_ADDR + addr);
-+    *base = data;
-+    return;
-+}
-+
-+/* the offset of FLASH control register */
-+enum NFLASH_REGISTER {
-+      NFLASH_ID                       = 0x0000,
-+      NFLASH_STATUS                   = 0x0008,
-+      NFLASH_TYPE                     = 0x000c,
-+      NFLASH_ACCESS                   = 0x0030,
-+      NFLASH_COUNT                    = 0x0034,
-+      NFLASH_CMD_ADDR                 = 0x0038,
-+      NFLASH_ADDRESS                  = 0x003C,
-+      NFLASH_DATA                             = 0x0040,
-+      NFLASH_TIMING                   = 0x004C,
-+      NFLASH_ECC_STATUS               = 0x0050,
-+      NFLASH_ECC_CONTROL              = 0x0054,
-+      NFLASH_ECC_OOB                  = 0x005c,
-+      NFLASH_ECC_CODE_GEN0    = 0x0060,
-+      NFLASH_ECC_CODE_GEN1    = 0x0064,
-+      NFLASH_ECC_CODE_GEN2    = 0x0068,
-+      NFLASH_ECC_CODE_GEN3    = 0x006C,
-+      NFLASH_FIFO_CONTROL             = 0x0070,
-+      NFLASH_FIFO_STATUS              = 0x0074,
-+      NFLASH_FIFO_ADDRESS             = 0x0078,
-+      NFLASH_FIFO_DATA                = 0x007c,
-+};
-+
-+
-+
-+//#define FLASH_BASE  FLASH_CONTROL_BASE_ADDR
-+//#define FLASH_SIZE  0x00800000 //INTEGRATOR_FLASH_SIZE
-+
-+//#define FLASH_PART_SIZE 8388608
-+
-+//static unsigned int flash_indirect_access = 0;
-+
-+
-+#ifdef CONFIG_SL2312_SHARE_PIN
-+void sl2312flash_enable_nand_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val & 0xfffffffb;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+
-+void sl2312flash_disable_nand_flash(void)
-+{
-+    unsigned int    reg_val;
-+
-+    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    reg_val = reg_val | 0x00000004;
-+    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
-+    return;
-+}
-+#endif
-+
-+extern struct nand_oobinfo jffs2_oobinfo;
-+/*
-+ * Define partitions for flash devices
-+ */
-+
-+static struct mtd_partition sl2312_partitions[] = {
-+      { name: "RedBoot", offset: 0x00000000, size: 0x0020000, },
-+      { name: "Kernel", offset: 0x00020000, size: 0x00200000, },
-+      { name: "Ramdisk", offset: 0x00220000, size: 0x00280000, },
-+      { name: "Application", offset: 0x004A0000, size: 0x00320000, },
-+      { name: "VCTL", offset: 0x007C0000, size: 0x20000, },
-+      { name: "CurConf", offset: 0x007E0000, size: 0x20000, },
-+      { name: "FIS directory", offset: 0x007e0000, size: 0x00020000, }
-+
-+};
-+
-+
-+/*
-+ *    hardware specific access to control-lines
-+*/
-+static void sl2312_hwcontrol(struct mtd_info *mtd, int cmd)
-+{
-+
-+      return ;
-+}
-+
-+static int sl2312_nand_scan_bbt(struct mtd_info *mtd)
-+{
-+      return 0;
-+}
-+
-+/**
-+ * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset relative to mtd start
-+ */
-+static int sl2312_nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
-+{
-+      /* Check for invalid offset */
-+      if (ofs > mtd->size)
-+              return -EINVAL;
-+
-+      return sl2312_nand_block_checkbad (mtd, ofs, 1, 0);
-+}
-+
-+/**
-+ * nand_block_checkbad - [GENERIC] Check if a block is marked bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset from device start
-+ * @getchip:  0, if the chip is already selected
-+ * @allowbbt: 1, if its allowed to access the bbt area
-+ *
-+ * Check, if the block is bad. Either by reading the bad block table or
-+ * calling of the scan function.
-+ */
-+
-+static int sl2312_nand_erase_block(struct mtd_info *mtd, int page)
-+{
-+      int opcode;
-+      /* Send commands to erase a page */
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+
-+              if(mtd->oobblock > 528)
-+                  FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff21);  // 3 address & 2 command
-+              else
-+                  FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff11);  // 2 address & 2 command
-+
-+              FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x0000d060); // write read id command
-+              FLASH_WRITE_REG(NFLASH_ADDRESS, page); //write address 0x00
-+
-+
-+
-+              /* read maker code */
-+              opcode = 0x80003000|DWIDTH|CHIP_EN; //set start bit & 8bits write command
-+              FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+
-+              while(opcode&0x80000000) //polling flash access 31b
-+              {
-+           opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+           //sl2312_flash_delay();
-+           schedule();
-+           //cond_resched();
-+              }
-+}
-+
-+void sl2312_flash_delay(void)
-+{
-+      int i;
-+
-+      for(i=0; i<50; i++)
-+           i=i;
-+}
-+
-+static int sl2312_nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
-+{
-+      struct nand_chip *this = mtd->priv;
-+
-+      if (!this->bbt)
-+              return this->block_bad(mtd, ofs, getchip);
-+
-+      /* Return info from the table */
-+      return nand_isbad_bbt (mtd, ofs, allowbbt);
-+}
-+
-+/**
-+ * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset relative to mtd start
-+ */
-+static int sl2312_nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
-+{
-+      struct nand_chip *this = mtd->priv;
-+      int ret;
-+
-+        if ((ret = sl2312_nand_block_isbad(mtd, ofs))) {
-+              /* If it was bad already, return success and do nothing. */
-+              if (ret > 0)
-+                      return 0;
-+              return ret;
-+        }
-+
-+      return this->block_markbad(mtd, ofs);
-+}
-+
-+/*
-+ *    Get chip for selected access
-+ */
-+static inline void sl2312_nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state, int *erase_state)
-+{
-+
-+      DECLARE_WAITQUEUE (wait, current);
-+
-+      /*
-+       * Grab the lock and see if the device is available
-+       * For erasing, we keep the spinlock until the
-+       * erase command is written.
-+      */
-+retry:
-+      spin_lock_bh (&this->chip_lock);
-+
-+      if (this->state == FL_READY) {
-+              this->state = new_state;
-+              if (new_state != FL_ERASING)
-+                      spin_unlock_bh (&this->chip_lock);
-+              return;
-+      }
-+
-+      if (this->state == FL_ERASING) {
-+              if (new_state != FL_ERASING) {
-+                      this->state = new_state;
-+                      spin_unlock_bh (&this->chip_lock);
-+                      this->select_chip(mtd, 0);      /* select in any case */
-+                      this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-+                      return;
-+              }
-+      }
-+
-+      set_current_state (TASK_UNINTERRUPTIBLE);
-+      add_wait_queue (&this->wq, &wait);
-+      spin_unlock_bh (&this->chip_lock);
-+      schedule ();
-+      remove_wait_queue (&this->wq, &wait);
-+      goto retry;
-+}
-+
-+/*
-+*     read device ready pin
-+*/
-+static int sl2312_device_ready(struct mtd_info *mtd)
-+{
-+      int ready;
-+
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+      FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000070); //set only command no address and two data
-+
-+      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000070); //write read status command
-+
-+
-+      ready = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
-+      FLASH_WRITE_REG(NFLASH_ACCESS, ready);
-+
-+      while(ready&0x80000000) //polling flash access 31b
-+    {
-+        ready=FLASH_READ_REG(NFLASH_ACCESS);
-+        //sl2312_flash_delay();
-+              schedule();
-+    }
-+    FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+              ready=FLASH_READ_REG(NFLASH_DATA)&0xff;
-+      return ready;
-+}
-+void sl2312_enable_hwecc(struct mtd_info *mtd, int mode)
-+{
-+      /* reset first */
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
-+
-+}
-+
-+
-+void sl2312_device_setup(void)
-+{
-+
-+}
-+static u_char sl2312_nand_read_byte(struct mtd_info *mtd)
-+{
-+
-+        unsigned int    data=0, page=0, col=0, tmp, i;
-+
-+        printk ("**************************sl2312_nand_read_byte !! \n");
-+        //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
-+        //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
-+        page = nand_page;
-+        col  = nand_col;
-+        for(i=0;i<(mtd->oobblock+mtd->oobsize);i++)
-+        {
-+              if(i==col)
-+                              data = FLASH_READ_DATA(page*mtd->oobblock +i);
-+                      else
-+                              tmp = FLASH_READ_DATA(page*mtd->oobblock +i);
-+        }
-+        return data&0xff;
-+}
-+
-+static void sl2312_nand_write_byte(struct mtd_info *mtd, u_char byte)
-+{
-+        //struct nand_chip *this = mtd->priv;
-+        unsigned int    page=0, col=0, i;
-+        u_char *databuf,oobbuf[mtd->oobsize];
-+        size_t  retlen;
-+        retlen=0;
-+              printk ("********************sl2312_nand_write_byte !! \n");
-+              page = nand_page;
-+        col  = nand_col;
-+              databuf = kmalloc (mtd->oobsize+mtd->oobblock,GFP_KERNEL);
-+
-+              if (!databuf) {
-+                      printk ("sl2312_nand_write_byte : Unable to allocate SL2312 NAND MTD device structure.\n");
-+
-+              }
-+
-+               for(i=0;i<(mtd->oobblock+mtd->oobsize);i++)
-+              databuf[i] = FLASH_READ_DATA(page*mtd->oobblock +i);
-+
-+        databuf[col] = byte;
-+        sl2312_nand_write_ecc (mtd, page, mtd->oobblock, &retlen, databuf, oobbuf, NULL);
-+
-+}
-+
-+static void sl2312_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
-+{
-+      int i, page=0,col=0;
-+      struct nand_chip *this = mtd->priv;
-+      u_char *databuf, *oobbuf;
-+        size_t  retlen;
-+        retlen=0;
-+
-+
-+              printk ("***********************sl2312_nand_write_buf !! \n");
-+              databuf = &(this->data_buf[0]);
-+              oobbuf = &(this->data_buf[mtd->oobblock]);
-+              for (i = 0; i < mtd->oobsize; i++)
-+                      oobbuf[i] = 0xff;
-+
-+      if(len < mtd->oobblock)
-+      {
-+              //addr = FLASH_READ_REG(NFLASH_ADDRESS);
-+              //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
-+              //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
-+              page = nand_page;
-+        col  = nand_col;
-+
-+              sl2312_nand_read_ecc (mtd, page, mtd->oobblock , &retlen, databuf, oobbuf, NULL);
-+
-+        for(i=col;i<len;i++)
-+              databuf[col+i] = buf[i];
-+
-+        sl2312_nand_write_ecc (mtd, page, mtd->oobblock, &retlen, databuf, oobbuf, NULL);
-+
-+      }
-+
-+}
-+
-+static void sl2312_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
-+{
-+      int i, page=0,col=0,addr=0,tmp=0;
-+      //struct nand_chip *this = mtd->priv;
-+      printk ("********************sl2312_nand_read_buf !! \n");
-+      if(len < mtd->oobblock)
-+      {
-+              //addr = FLASH_READ_REG(NFLASH_ADDRESS);
-+              //page = FLASH_READ_REG(NFLASH_ADDRESS)&0xffffff00;
-+              //col  = FLASH_READ_REG(NFLASH_ADDRESS)&0x000000ff;
-+              page = nand_page;
-+        col  = nand_col;
-+              for (i=col; i<((mtd->oobblock+mtd->oobsize)-col); i++)
-+              {
-+                      if(i<len)
-+                              buf[i] = FLASH_READ_DATA(addr+i);
-+                      else
-+                              tmp = FLASH_READ_DATA(addr+i);
-+              }
-+      }
-+}
-+
-+static int sl2312_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
-+{
-+      int i;
-+      //struct nand_chip *this = mtd->priv;
-+      u_char *datatmp, *oobtmp;
-+      size_t  retlen;
-+      retlen=0;
-+
-+      datatmp = kmalloc (mtd->oobblock,GFP_KERNEL);
-+      oobtmp = kmalloc (mtd->oobsize,GFP_KERNEL);
-+
-+      if ((!datatmp)||(!oobtmp)) {
-+              printk ("sl2312_nand_verify_buf : Unable to allocate SL2312 NAND MTD device structure.\n");
-+
-+      }
-+      //page = nand_page;
-+      for(i=0;i<mtd->oobblock;i++)
-+              datatmp[i] = FLASH_READ_DATA(nand_page*mtd->oobblock +i);
-+      /* read oobdata */
-+      for (i = 0; i <  mtd->oobsize; i++)
-+              oobtmp[i] = FLASH_READ_DATA(nand_page*mtd->oobblock + mtd->oobblock + i);
-+
-+      if(len==mtd->oobblock)
-+      {
-+              for (i=0; i<len; i++)
-+              {
-+                      if (buf[i] != datatmp[i])
-+                      {
-+                              kfree(datatmp);
-+                              kfree(oobtmp);
-+                              printk("Data verify error -> page: %x, byte: %x \n",nand_page,i);
-+                              return i;
-+                      }
-+              }
-+      }
-+      else if(len == mtd->oobsize)
-+      {
-+              for (i=0; i<len; i++)
-+              {
-+                      if (buf[i] != oobtmp[i])
-+                      {
-+                              kfree(datatmp);
-+                              kfree(oobtmp);
-+                              printk("OOB verify error -> page: %x, byte: %x \n",nand_page,i);
-+                              return i;
-+                      }
-+              }
-+      }
-+      else
-+      {
-+              printk (KERN_WARNING "sl2312_nand_verify_buf : verify length not match 0x%08x\n", len);
-+              kfree(datatmp);
-+              kfree(oobtmp);
-+              return -1;
-+      }
-+
-+      kfree(datatmp);
-+      kfree(oobtmp);
-+      return 0;
-+}
-+
-+/*
-+ * Send command to NAND device
-+ */
-+static void sl2312_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
-+{
-+      register struct nand_chip *this = mtd->priv;
-+      int opcode;
-+
-+
-+      /*
-+       * program and erase have their own busy handlers
-+       * status and sequential in needs no delay
-+      */
-+      switch (command) {
-+
-+      case NAND_CMD_PAGEPROG:
-+      case NAND_CMD_ERASE1:
-+      case NAND_CMD_ERASE2:
-+      case NAND_CMD_SEQIN:
-+      case NAND_CMD_STATUS:
-+      case NAND_CMD_READ0:
-+
-+              /*
-+               * Write out the command to the device.
-+               */
-+              if (column != -1 || page_addr != -1) {
-+
-+                      /* Serially input address */
-+                      if (column != -1)
-+                              //FLASH_WRITE_REG(NFLASH_ADDRESS,column);
-+                              nand_col=column;
-+
-+                      opcode = FLASH_READ_REG(NFLASH_ADDRESS);
-+
-+                      if (page_addr != -1)
-+                              //FLASH_WRITE_REG(NFLASH_ADDRESS,opcode|(page_addr<<8));
-+                              nand_page = page_addr;
-+
-+              }
-+              return;
-+
-+      case NAND_CMD_RESET:
-+              if (this->dev_ready)
-+                      break;
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+              FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff70); //set only command and no other data
-+              FLASH_WRITE_REG(NFLASH_CMD_ADDR, NAND_CMD_RESET); //write reset command
-+
-+              opcode = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
-+              FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+
-+              while(opcode&0x80000000) //polling flash access 31b
-+              {
-+           opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+           //sl2312_flash_delay();
-+           schedule();
-+              }
-+              while ( !(sl2312_device_ready(mtd) & 0x40));
-+              {
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+                      //sl2312_flash_delay();
-+                      schedule();
-+                      return;
-+              }
-+      /* This applies to read commands */
-+      default:
-+              /*
-+               * If we don't have access to the busy pin, we apply the given
-+               * command delay
-+              */
-+              if (!this->dev_ready) {
-+                      udelay (this->chip_delay);
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+                      return;
-+              }
-+      }
-+
-+      /* wait until command is processed */
-+      while (!this->dev_ready(mtd));
-+
-+}
-+/*Add function*/
-+static void nand_read_id(int chip_no, unsigned char *id)
-+{
-+      unsigned int opcode, i;
-+
-+      if(chip_no==0)
-+              CHIP_EN = NFLASH_CHIP0_EN;
-+      else
-+              CHIP_EN = NFLASH_CHIP1_EN;
-+
-+      opcode = FLASH_READ_REG(NFLASH_TYPE);
-+
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+      if((opcode&0x00000300)<=0x00000100)
-+          FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000100); //set only command & address and two data
-+      else
-+          FLASH_WRITE_REG(NFLASH_COUNT, 0x7f000300); //set only command & address and 4 data
-+
-+      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000090); //write read id command
-+      FLASH_WRITE_REG(NFLASH_ADDRESS, 0x00000000); //write address 0x00
-+
-+      /* read maker code */
-+      opcode = 0x80002000|DWIDTH|CHIP_EN;//|chip0_en; //set start bit & 8bits read command
-+      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+      opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+              while(opcode&0x80000000) //polling flash access 31b
-+              {
-+           opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+           //sl2312_flash_delay();
-+           schedule();
-+              }
-+
-+    opcode = FLASH_READ_REG(NFLASH_DATA);
-+    if(DWIDTH==NFLASH_WiDTH16)
-+    {
-+                      id[0] = opcode&0xff;
-+                      id[1] = (opcode&0xff00)>>8;
-+    }
-+    else
-+    {
-+          id[0] = opcode&0xff;
-+          opcode = 0x80002000|DWIDTH|CHIP_EN;//|chip0_en; //set start bit & 8bits read command
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+                      opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+                      while(opcode&0x80000000) //polling flash access 31b
-+              {
-+             opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+             //sl2312_flash_delay();
-+             schedule();
-+              }
-+              opcode = FLASH_READ_REG(NFLASH_DATA);
-+                      id[1] = (opcode&0xff00)>>8;
-+
-+                      opcode=FLASH_READ_REG(NFLASH_TYPE);
-+                      if((opcode&0x300)>0x100)
-+                      {
-+                          for(i=0;i<2;i++)
-+                          {
-+                                      //data cycle 3 & 4 ->not use
-+                                      opcode = 0x80002000|DWIDTH|CHIP_EN;//set start bit & 8bits read command
-+                                      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+                                      opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+                                      while(opcode&0x80000000) //polling flash access 31b
-+                                      {
-+                                 opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+                                 //sl2312_flash_delay();
-+                                 schedule();
-+                                      }
-+
-+                                      opcode=FLASH_READ_REG(NFLASH_DATA);
-+                                      id[2+i] = (opcode&(0xff0000<<i*8))>>(8*(2+i));
-+                          }
-+                      }
-+    }
-+    FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+}
-+
-+/*
-+ * NAND erase a block
-+ */
-+static int sl2312_nand_erase (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
-+{
-+      int page, len, status, pages_per_block, ret, chipnr;
-+      struct nand_chip *this = mtd->priv;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3,
-+             "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
-+
-+      /* Start address must align on block boundary */
-+      if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Length must align on block boundary */
-+      if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Do not allow erase past end of device */
-+      if ((instr->len + instr->addr) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
-+              return -EINVAL;
-+      }
-+
-+      instr->fail_addr = 0xffffffff;
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_ERASING, NULL);
-+
-+      /* Shift to get first page */
-+      page = (int) (instr->addr >> this->page_shift);
-+      chipnr = (int) (instr->addr >> this->chip_shift);
-+
-+      /* Calculate pages in each block */
-+      pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
-+
-+      /* Select the NAND device */
-+      //this->select_chip(mtd, chipnr);
-+      this->select_chip(mtd, 0);
-+
-+      /* Check the WP bit */
-+      /* Check, if it is write protected */
-+      status = sl2312_device_ready(mtd);
-+      if (!(status & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
-+              instr->state = MTD_ERASE_FAILED;
-+              goto erase_exit;
-+      }
-+
-+      /* Loop through the pages */
-+      len = instr->len;
-+
-+      instr->state = MTD_ERASING;
-+
-+      while (len) {
-+              /* Check if we have a bad block, we do not erase bad blocks ! */
-+              if (this->block_bad(mtd, ((loff_t) page) << this->page_shift, 0)) {
-+                      printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
-+                      //instr->state = MTD_ERASE_FAILED;
-+                      //goto erase_exit;
-+              }
-+
-+              /* Invalidate the page cache, if we erase the block which contains
-+                 the current cached page */
-+              if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
-+                      this->pagebuf = -1;
-+              /////////
-+
-+              ///* Send commands to erase a page */
-+              //FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+          //
-+              //if(mtd->oobblock > 528)
-+              //    FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff21);  // 3 address & 2 command
-+              //else
-+              //    FLASH_WRITE_REG(NFLASH_COUNT, 0x7f0fff11);  // 2 address & 2 command
-+              //
-+              //FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x0000d060); // write read id command
-+              //FLASH_WRITE_REG(NFLASH_ADDRESS, page); //write address 0x00
-+              //
-+              //
-+              //
-+              ///* read maker code */
-+              //opcode = 0x80003000|DWIDTH|CHIP_EN; //set start bit & 8bits write command
-+              //FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+              //
-+              //while(opcode&0x80000000) //polling flash access 31b
-+              //{
-+        //   opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+        //   //sl2312_flash_delay();
-+        //   schedule();
-+        //   //cond_resched();
-+              //}
-+              sl2312_nand_erase_block(mtd, page);
-+              //////////////
-+              status = this->waitfunc (mtd, this, FL_ERASING);
-+              /* See if block erase succeeded */
-+              if (status & 0x01) {
-+                      DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
-+                      instr->state = MTD_ERASE_FAILED;
-+                      instr->fail_addr = (page << this->page_shift);
-+                      goto erase_exit;
-+              }
-+
-+              /* Increment page address and decrement length */
-+              len -= (1 << this->phys_erase_shift);
-+              page += pages_per_block;
-+
-+              /* Check, if we cross a chip boundary */
-+              if (len && !(page & this->pagemask)) {
-+                      chipnr++;
-+                      this->select_chip(mtd, 0);
-+                      this->select_chip(mtd, 0);
-+              }
-+              //sl2312_flash_delay();
-+           schedule();
-+           //cond_resched();
-+      }
-+      instr->state = MTD_ERASE_DONE;
-+
-+erase_exit:
-+      /* De-select the NAND device */
-+      this->select_chip(mtd, 0);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;;
-+      /* Do call back function */
-+      if (!ret && instr->callback)
-+              instr->callback (instr);
-+
-+      /* The device is ready */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      spin_unlock_bh (&this->chip_lock);
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+      /* Return more or less happy */
-+      return ret;
-+}
-+
-+static void sl2312_nand_select_chip(struct mtd_info *mtd, int chip)
-+{
-+      //struct nand_chip *this = mtd->priv;
-+
-+      switch(chip) {
-+      case -1:
-+              CHIP_EN = NFLASH_CHIP0_EN;
-+              break;
-+      case 0:
-+              CHIP_EN = NFLASH_CHIP0_EN;
-+              break;
-+      case 1:
-+              CHIP_EN = NFLASH_CHIP1_EN;
-+              break;
-+      default:
-+                      CHIP_EN = NFLASH_CHIP0_EN;
-+                      break;
-+      }
-+}
-+
-+/**
-+ * nand_default_block_markbad - [DEFAULT] mark a block bad
-+ * @mtd:      MTD device structure
-+ * @ofs:      offset from device start
-+ *
-+ * This is the default implementation, which can be overridden by
-+ * a hardware specific driver.
-+*/
-+static int sl2312_nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
-+{
-+      struct nand_chip *this = mtd->priv;
-+      u_char buf[2] = {0, 0};
-+      size_t  retlen;
-+      int block;
-+
-+      /* Get block number */
-+      block = ((int) ofs) >> this->bbt_erase_shift;
-+      this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
-+
-+      /* Do we have a flash based bad block table ? */
-+      if (this->options & NAND_USE_FLASH_BBT)
-+              return nand_update_bbt (mtd, ofs);
-+
-+      /* We write two bytes, so we dont have to mess with 16 bit access */
-+      ofs += mtd->oobsize + (this->badblockpos & ~0x01);
-+      return sl2312_nand_write_oob (mtd, ofs , 2, &retlen, buf);
-+}
-+
-+/* Appropriate chip should already be selected */
-+static int sl2312_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)//(struct mtd_info *mtd, unsigned long page, )
-+{
-+      u_char *buf, *oobbuf;
-+      size_t  retlen;
-+      unsigned long page, chipnr;
-+      struct nand_chip *this = mtd->priv;
-+
-+      if (getchip) {
-+              page = (int)(ofs >> this->page_shift);
-+              chipnr = (int)(ofs >> this->chip_shift);
-+
-+              /* Grab the lock and see if the device is available */
-+              sl2312_nand_get_chip (this, mtd, FL_READING, NULL);
-+              /* Select the NAND device */
-+              this->select_chip(mtd, chipnr);
-+      } else
-+              page = (int) ofs;
-+
-+      buf = kmalloc (mtd->oobblock,GFP_KERNEL);
-+      oobbuf = kmalloc (mtd->oobsize,GFP_KERNEL);
-+
-+      if ((!buf)||(!oobbuf)) {
-+              printk ("sl2312_nand_block_bad : Unable to allocate SL2312 NAND MTD device structure.\n");
-+
-+      }
-+
-+      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , &retlen, buf, oobbuf, NULL);
-+
-+
-+      if(((mtd->oobblock < 528)&&(oobbuf[5] != 0xff))||((mtd->oobblock > 528)&&(oobbuf[0] != 0xff)))
-+      {
-+              kfree(buf);
-+              kfree(oobbuf);
-+              return 1;
-+      }
-+
-+      kfree(buf);
-+      kfree(oobbuf);
-+      return 0;
-+}
-+
-+/*
-+*     Use NAND read ECC
-+*/
-+static int sl2312_nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
-+{
-+      return sl2312_nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
-+}
-+
-+/*
-+ * NAND read with ECC
-+ */
-+static int sl2312_nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-+                        size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
-+{
-+      int j, col, page, opcode, i;
-+      int end=0;//, ecc=0;//, end_page=0;
-+      int erase_state = 0;
-+      int read = 0, oob = 0, ecc_failed = 0;//, ecc_status = 0
-+      struct nand_chip *this = mtd->priv;
-+      u_char *data_poi, *oob_data = oob_buf;
-+      //u_char ecc_calc[6];
-+      //u_char ecc_code[6];
-+      int     eccmode;
-+      int     *oob_config;
-+
-+
-+
-+      // use chip default if zero
-+      if (oobsel == NULL)
-+              oobsel = &mtd->oobinfo;
-+
-+      eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-+      oob_config = oobsel->eccpos;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-+
-+      /* Do not allow reads past end of device */
-+      if ((from + len) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
-+              *retlen = 0;
-+              return -EINVAL;
-+      }
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd ,FL_READING, &erase_state);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* First we calculate the starting page */
-+      page = from >> this->page_shift;
-+
-+      //end_page = mtd->oobblock + mtd->oobsize;
-+      end = mtd->oobblock;
-+      //ecc = mtd->eccsize;
-+      /* Get raw starting column */
-+      col = (from & (mtd->oobblock - 1));
-+
-+
-+      /* Send the read command */
-+      //this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
-+
-+      /* Loop until all data read */
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+      while (read < len) {
-+
-+              //udelay(1200);
-+              /* If we have consequent page reads, apply delay or wait for ready/busy pin */
-+              if (read) {
-+                      if (!this->dev_ready)
-+                              udelay (this->chip_delay);
-+                      else
-+                              while (!this->dev_ready(mtd));
-+              }
-+
-+              /*
-+               * If the read is not page aligned, we have to read into data buffer
-+               * due to ecc, else we read into return buffer direct
-+               */
-+              if (!col && (len - read) >= end)
-+                      data_poi = &buf[read];
-+              else
-+                      data_poi = this->data_buf;
-+
-+              /* get oob area, if we have no oob buffer from fs-driver */
-+              if (!oob_buf) {
-+                      oob_data = &this->data_buf[end];
-+                      oob = 0;
-+              }
-+
-+              j = 0;
-+              switch (eccmode) {
-+                      case NAND_ECC_NONE: {   /* No ECC, Read in a page */
-+                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+                              break;
-+                      }
-+
-+                      case NAND_ECC_SOFT:     /* Software ECC 3/256: Read in a page + oob data */
-+                              break;
-+
-+                      case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data: Read in first 256 byte, get ecc, */
-+                              break;
-+
-+                      case NAND_ECC_HW3_512:
-+                      case NAND_ECC_HW6_512: /* Hardware ECC 3/6 byte / 512 byte data : Read in a page  */
-+                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
-+                              break;
-+
-+                      default:
-+                              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
-+                              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0);
-+                              //BUG();
-+              }//end switch
-+
-+                      for(i=0;i<end;i++)
-+                      {
-+                              //udelay(7);
-+                              data_poi[i] = FLASH_READ_DATA(page*mtd->oobblock +i);
-+                      }
-+                      /* read oobdata */
-+                      for (i = 0; i <  mtd->oobsize; i++)
-+                      {
-+                              //udelay(7);
-+                              oob_data[oob + i] = FLASH_READ_DATA(page*mtd->oobblock +end+i);
-+                      }
-+
-+              /* Skip ECC, if not active */
-+                      if (eccmode == NAND_ECC_NONE)
-+                              goto readdata;
-+
-+                      // compare ecc and correct data
-+
-+                              opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                              while(!(opcode&0x80000000)) //polling flash access 31b
-+                              {
-+                                 opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                                 //sl2312_flash_delay();
-+                                 schedule();
-+                              }
-+                              for(j=0;j<(end/512);j++)
-+                              {//for 2k page
-+
-+                                      opcode = 0x00000000|oob_data[mtd->oobsize-3-4*j]<<16|oob_data[mtd->oobsize-2-4*j]<<8|oob_data[mtd->oobsize-1-4*j];
-+
-+                                      //opcode=FLASH_READ_REG(NFLASH_ECC_CODE_GEN0+(j*4));
-+
-+                                      FLASH_WRITE_REG(NFLASH_ECC_OOB, opcode);
-+                                      opcode = 0x00000000|(j<<8); //select ECC code generation 0
-+                                      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, opcode); //???
-+
-+                                      opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                                      if((opcode&0x00000003)==0x03)
-+                                      {
-+                                              printk (KERN_WARNING "\nPageRead Uncorrectable error !!\n");
-+                                              ecc_failed++;
-+                                      }
-+                                      else if((opcode&0x00000003)==0x01)
-+                                      {
-+                                              printk (KERN_WARNING "\nPageRead One bit data error !!");
-+                                              // correct data
-+                                              if((data_poi[(opcode&0xff80)>>7]>>((opcode&0x38)>>3))%1)
-+                                                      data_poi[(opcode&0xff80)>>7] &= ~(1<<((opcode&0x38)>>3));
-+                                              else
-+                                                      data_poi[(opcode&0xff80)>>7] |= (1<<((opcode&0x38)>>3));
-+
-+                                      }
-+                                      else if((opcode&0x00000003)==0x02)
-+                                      {
-+                                              printk (KERN_WARNING "\nPageRead One bit ECC error !!\n");
-+                                      }
-+                                      else if((opcode&0x00000003)==0x00)
-+                                      {
-+
-+                                      }
-+
-+                              }//for 2k page
-+readdata:
-+              if (col || (len - read) < end) {
-+                      for (j = col; j < end && read < len; j++)
-+                              buf[read++] = data_poi[j];
-+              } else
-+                      read += mtd->oobblock;
-+              /* For subsequent reads align to page boundary. */
-+              col = 0;
-+              /* Increment page address */
-+              page++;
-+              schedule();
-+      }
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_INDIRECT);
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      /*
-+       * Return success, if no ECC failures, else -EIO
-+       * fs driver will take care of that, because
-+       * retlen == desired len and result == -EIO
-+       */
-+      *retlen = read;
-+      return ecc_failed ? -EIO : 0;
-+}
-+
-+/*
-+ * Wait for command done. This applies to erase and program only
-+ * Erase can take up to 400ms and program up to 20ms according to
-+ * general NAND and SmartMedia specs
-+ *
-+*/
-+static int sl2312_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state)
-+{
-+      unsigned long   timeo = jiffies;
-+      int     status, opcode;
-+
-+      if (state == FL_ERASING)
-+               timeo += (HZ * 400) / 1000;
-+      else
-+               timeo += (HZ * 20) / 1000;
-+
-+      spin_lock_bh (&this->chip_lock);
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000); //set 31b = 0
-+      FLASH_WRITE_REG(NFLASH_COUNT, 0x007f000070); //set only command no address and two data
-+
-+      FLASH_WRITE_REG(NFLASH_CMD_ADDR, 0x00000070); //write read status command
-+
-+
-+      opcode = 0x80002000|DWIDTH|CHIP_EN; //set start bit & 8bits read command
-+      FLASH_WRITE_REG(NFLASH_ACCESS, opcode);
-+
-+      while(opcode&0x80000000) //polling flash access 31b
-+    {
-+        opcode=FLASH_READ_REG(NFLASH_ACCESS);
-+        //sl2312_flash_delay();
-+        schedule();
-+    }
-+
-+      while (time_before(jiffies, timeo)) {
-+              /* Check, if we were interrupted */
-+              if (this->state != state) {
-+                      spin_unlock_bh (&this->chip_lock);
-+                      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+                      return 0;
-+              }
-+              if (this->dev_ready) {
-+                      if (this->dev_ready(mtd))
-+                              break;
-+              }
-+              if (FLASH_READ_REG(NFLASH_DATA) & 0x40)
-+                      break;
-+
-+              spin_unlock_bh (&this->chip_lock);
-+              yield ();
-+              spin_lock_bh (&this->chip_lock);
-+      }
-+      status = FLASH_READ_REG(NFLASH_DATA)&0xff;
-+      spin_unlock_bh (&this->chip_lock);
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+      return status;
-+}
-+
-+static int sl2312_nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
-+{
-+      int i, col, page, j=0;
-+      //int erase_state = 0;
-+      struct nand_chip *this = mtd->priv;
-+      u_char *databuf, *oobbuf;
-+
-+      databuf = &this->data_buf[0];
-+      oobbuf = &this->data_buf[mtd->oobblock];
-+              for (i = 0; i < mtd->oobsize; i++)
-+                      oobbuf[i] = 0xff;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-+
-+      /* Shift to get page */
-+      page = ((int) from) >> this->page_shift;
-+
-+      /* Mask to get column */
-+      col = from & (mtd->oobsize-1);  //0x0f;
-+
-+      /* Initialize return length value */
-+      *retlen = 0;
-+      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , retlen, databuf, oobbuf, NULL);
-+      for(i=col,j=0;i<mtd->oobsize||i<(col+len);i++,j++)
-+              buf[j] = oobbuf[i];
-+
-+      *retlen = j ;
-+      return 0;
-+}
-+
-+#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
-+/*
-+*     Use NAND write ECC
-+*/
-+static int sl2312_nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
-+{
-+      return (sl2312_nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
-+}
-+
-+/*
-+ * NAND write with ECC
-+ */
-+static int sl2312_nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-+                         size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
-+{
-+      int page, ret = 0, oob = 0, written = 0;
-+      struct nand_chip *this = mtd->priv;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
-+
-+
-+      /* Do not allow write past end of device */
-+      if ((to + len) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
-+              return -EINVAL;
-+      }
-+
-+      /* reject writes, which are not page aligned */
-+      if (NOTALIGNED (to) || NOTALIGNED(len)) {
-+              printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
-+              return -EINVAL;
-+      }
-+
-+      // if oobsel is NULL, use chip defaults
-+      if (oobsel == NULL)
-+              oobsel = &mtd->oobinfo;
-+
-+      /* Shift to get page */
-+      page = ((int) to) >> this->page_shift;
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Check the WP bit */
-+      if (!(sl2312_device_ready(mtd) & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Device is write protected!!!\n");
-+              ret = -EIO;
-+              goto out;
-+      }
-+
-+      /* Loop until all data is written */
-+      while (written < len) {
-+              //udelay(100);
-+              int cnt = mtd->oobblock;
-+              this->data_poi = (u_char*) &buf[written];
-+              /* We use the same function for write and writev */
-+              if (eccbuf) {
-+                      ret = sl2312_nand_write_page (mtd, this, page, &eccbuf[oob], oobsel);
-+                      oob += mtd->oobsize;
-+              } else
-+                      ret = sl2312_nand_write_page (mtd, this, page, NULL, oobsel);
-+
-+              if (ret)
-+                      goto out;
-+
-+              /* Update written bytes count */
-+              written += cnt;
-+              /* Increment page address */
-+              page++;
-+      }
-+
-+out:
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      *retlen = written;
-+      return ret;
-+}
-+
-+/*
-+ *    Nand_page_program function is used for write and writev !
-+ *    This function will always program a full page of data
-+ *    If you call it with a non page aligned buffer, you're lost :)
-+ */
-+static int sl2312_nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  struct nand_oobinfo *oobsel)
-+{
-+      int     i, j, status, opcode;
-+      u_char  ecc_code[16], *oob_data;
-+      int     eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-+      //int   *oob_config = oobsel->eccpos;
-+
-+      /* pad oob area, if we have no oob buffer from fs-driver */
-+      if (!oob_buf) {
-+              oob_data = &this->data_buf[mtd->oobblock];
-+              for (i = 0; i < mtd->oobsize; i++)
-+                      oob_data[i] = 0xff;
-+      } else
-+              oob_data = oob_buf;
-+
-+      /* Send command to begin auto page programming */
-+
-+      memset(oob_data,0xff,mtd->oobsize);
-+      /* Write out complete page of data, take care of eccmode */
-+      switch (eccmode) {
-+      /* No ecc and software ecc 3/256, write all */
-+      case NAND_ECC_NONE:
-+              printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+              break;
-+      case NAND_ECC_SOFT:
-+              break;
-+
-+      /* Hardware ecc 3 byte / 256 data, write first half, get ecc, then second, if 512 byte pagesize */
-+      case NAND_ECC_HW3_256:
-+              break;
-+
-+      /* Hardware ecc 3 byte / 512 byte data, write full page */
-+      case NAND_ECC_HW3_512:
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x80000001); //set 31b = 0
-+
-+      /* Hardware ecc 6 byte / 512 byte data, write full page */
-+      case NAND_ECC_HW6_512:
-+              break;
-+
-+      default:
-+              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+              //BUG();
-+      }
-+
-+      FLASH_WRITE_REG(NFLASH_ACCESS, NFLASH_DIRECT);
-+
-+      for(i=0;i<mtd->oobblock;i++)
-+      {
-+              //udelay(5);
-+              FLASH_WRITE_DATA((page*mtd->oobblock)+i,this->data_poi[i]);
-+      }
-+      ///////////////
-+      if(eccmode!=NAND_ECC_NONE)
-+      {
-+              opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+              while(!(opcode&0x80000000)) //polling flash access 31b
-+      {
-+                 opcode=FLASH_READ_REG(NFLASH_ECC_STATUS);
-+                 //sl2312_flash_delay();
-+                 schedule();
-+      }
-+
-+
-+      for(i=0;i<(mtd->oobblock/512);i++)
-+      {
-+              opcode=FLASH_READ_REG(NFLASH_ECC_CODE_GEN0+(i*4));
-+
-+              for(j=3;j>0;j--)
-+                    oob_data[(mtd->oobsize-j-(i*4))] = (opcode<<((4-j)*8)) >>24;
-+
-+              for(j=0;j<4;j++)
-+              {
-+                      ecc_code[15-i*4] = opcode;
-+                      ecc_code[15-i*4-1] = opcode>>8;
-+                      ecc_code[15-i*4-2] = opcode>>16;
-+              }
-+      }
-+
-+      //disable ecc
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x00000000);
-+
-+      /* Write out OOB data */
-+      for(i=0;i<mtd->oobsize;i++)
-+      {
-+              //udelay(5);
-+                      FLASH_WRITE_DATA((page*mtd->oobblock)+mtd->oobblock+i,oob_data[i]);
-+              }
-+    }
-+    else
-+    {
-+      for(i=0;i<mtd->oobsize;i++)
-+      {
-+              //udelay(5);
-+                      FLASH_WRITE_DATA((page*mtd->oobblock)+mtd->oobblock+i,0xff);
-+              }
-+    }
-+
-+
-+      /* call wait ready function */
-+      status = this->waitfunc (mtd, this, FL_WRITING);
-+      FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+      /* See if device thinks it succeeded */
-+      if (status & 0x01) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
-+              FLASH_WRITE_REG(NFLASH_ECC_CONTROL, 0x0); //set 31b = 0
-+              return -EIO;
-+      }
-+
-+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-+      /*
-+       * The NAND device assumes that it is always writing to
-+       * a cleanly erased page. Hence, it performs its internal
-+       * write verification only on bits that transitioned from
-+       * 1 to 0. The device does NOT verify the whole page on a
-+       * byte by byte basis. It is possible that the page was
-+       * not completely erased or the page is becoming unusable
-+       * due to wear. The read with ECC would catch the error
-+       * later when the ECC page check fails, but we would rather
-+       * catch it early in the page write stage. Better to write
-+       * no data than invalid data.
-+       */
-+
-+      /* Send command to read back the page */
-+      this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
-+      /* Loop through and verify the data */
-+      if (this->verify_buf(mtd, this->data_poi, mtd->oobblock)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-+              return -EIO;
-+      }
-+
-+      /* check, if we have a fs-supplied oob-buffer */
-+      if (oob_buf) {
-+              if (this->verify_buf(mtd, oob_data, mtd->oobsize)) {
-+                      DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-+                      return -EIO;
-+              }
-+      } else {
-+              if (eccmode != NAND_ECC_NONE) {
-+                      int ecc_bytes = 0;
-+
-+                      switch (this->eccmode) {
-+                      case NAND_ECC_SOFT:
-+                      case NAND_ECC_HW3_256: ecc_bytes = (mtd->oobblock == 512) ? 6 : 3; break;
-+                      case NAND_ECC_HW3_512: ecc_bytes = 3; break;
-+                      case NAND_ECC_HW6_512: ecc_bytes = 6; break;
-+                      }
-+
-+
-+
-+                      for(i=0;i < (mtd->oobblock+mtd->oobsize);i++)
-+                      {
-+                              if(i>=mtd->oobblock)
-+                                      oob_data[i-mtd->oobblock] = FLASH_READ_DATA((page*mtd->oobblock) +i);
-+                              else
-+                                      oob_data[0] = FLASH_READ_DATA((page*mtd->oobblock) +i);
-+                      }
-+
-+                      if(this->eccmode == NAND_ECC_HW3_512)
-+                      {
-+                              for(i=0;i<(mtd->oobblock/512);i++)
-+                      {
-+                              for(j=0;j<3;j++)
-+                              {
-+                                  if (oob_data[mtd->oobsize-1-j-4*i] != ecc_code[15-j-4*i]) {
-+                                                      DEBUG (MTD_DEBUG_LEVEL0,
-+                                                             "%s: Failed ECC write "
-+                                                     "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
-+                                                      return -EIO;
-+                                              }
-+                              }
-+                      }
-+                      }
-+              }//eccmode != NAND_ECC_NONE
-+      }
-+      /*
-+       * Terminate the read command. This is faster than sending a reset command or
-+       * applying a 20us delay before issuing the next programm sequence.
-+       * This is not a problem for all chips, but I have found a bunch of them.
-+       */
-+      //this->select_chip(mtd, -1);
-+      //this->select_chip(mtd, 0);
-+#endif
-+
-+      return 0;
-+}
-+
-+/*
-+ * NAND write with iovec
-+ */
-+static int sl2312_nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-+              loff_t to, size_t * retlen)
-+{
-+      return (sl2312_nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, 0));
-+}
-+
-+static int sl2312_nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-+              loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel)
-+{
-+      int i, page, len, total_len, ret = 0, written = 0;
-+      struct nand_chip *this = mtd->priv;
-+
-+      /* Calculate total length of data */
-+      total_len = 0;
-+      for (i = 0; i < count; i++)
-+              total_len += (int) vecs[i].iov_len;
-+
-+      DEBUG (MTD_DEBUG_LEVEL3,
-+             "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
-+
-+      /* Do not allow write past end of page */
-+      if ((to + total_len) > mtd->size) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n");
-+              return -EINVAL;
-+      }
-+
-+      /* reject writes, which are not page aligned */
-+      if (NOTALIGNED (to) || NOTALIGNED(total_len)) {
-+              printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
-+              return -EINVAL;
-+      }
-+
-+      // if oobsel is NULL, use chip defaults
-+      if (oobsel == NULL)
-+              oobsel = &mtd->oobinfo;
-+
-+      /* Shift to get page */
-+      page = ((int) to) >> this->page_shift;
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Check the WP bit */
-+      if (!(sl2312_device_ready(mtd) & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "sl2312_nand_writev_ecc: Device is write protected!!!\n");
-+              ret = -EIO;
-+              goto out;
-+      }
-+
-+      /* Loop until all iovecs' data has been written */
-+      len = 0;
-+      while (count) {
-+              /*
-+               *  Check, if the tuple gives us not enough data for a
-+               *  full page write. Then we can use the iov direct,
-+               *  else we have to copy into data_buf.
-+               */
-+              if ((vecs->iov_len - len) >= mtd->oobblock) {
-+                      this->data_poi = (u_char *) vecs->iov_base;
-+                      this->data_poi += len;
-+                      len += mtd->oobblock;
-+                      /* Check, if we have to switch to the next tuple */
-+                      if (len >= (int) vecs->iov_len) {
-+                              vecs++;
-+                              len = 0;
-+                              count--;
-+                      }
-+              } else {
-+                      /*
-+                       * Read data out of each tuple until we have a full page
-+                       * to write or we've read all the tuples.
-+                      */
-+                      int cnt = 0;
-+                      while ((cnt < mtd->oobblock) && count) {
-+                              if (vecs->iov_base != NULL && vecs->iov_len) {
-+                                      this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
-+                              }
-+                              /* Check, if we have to switch to the next tuple */
-+                              if (len >= (int) vecs->iov_len) {
-+                                      vecs++;
-+                                      len = 0;
-+                                      count--;
-+                              }
-+                      }
-+                      this->data_poi = this->data_buf;
-+              }
-+
-+              /* We use the same function for write and writev !) */
-+              ret = sl2312_nand_write_page (mtd, this, page, NULL, oobsel);
-+              if (ret)
-+                      goto out;
-+
-+              /* Update written bytes count */
-+              written += mtd->oobblock;;
-+
-+              /* Increment page address */
-+              page++;
-+      }
-+
-+out:
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      *retlen = written;
-+      return ret;
-+}
-+
-+/*
-+static u_char ffchars[] = {
-+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-+};
-+*/
-+/*
-+ * NAND write out-of-band
-+ */
-+static int sl2312_nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
-+{
-+      int column, page, status, ret = 0, j=0;
-+      struct nand_chip *this = mtd->priv;
-+      u_char *databuf, *oobbuf;
-+
-+
-+              databuf = &this->data_buf[0];
-+              oobbuf = &this->data_buf[mtd->oobblock];
-+              for (j = 0; j < mtd->oobsize; j++)
-+                      oobbuf[j] = 0xff;
-+//#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-+//    int     i;
-+//#endif
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
-+
-+      /* Shift to get page */
-+      page = ((int) to) >> this->page_shift;
-+
-+      /* Mask to get column */
-+      column = to & 0x1f;
-+
-+      /* Initialize return length value */
-+      *retlen = 0;
-+
-+      /* Do not allow write past end of page */
-+      if ((column + len) > mtd->oobsize) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Grab the lock and see if the device is available */
-+      sl2312_nand_get_chip (this, mtd, FL_WRITING, NULL);
-+
-+      /* Select the NAND device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Reset the chip. Some chips (like the Toshiba TC5832DC found
-+         in one of my DiskOnChip 2000 test units) will clear the whole
-+         data page too if we don't do this. I have no clue why, but
-+         I seem to have 'fixed' it in the doc2000 driver in
-+         August 1999.  dwmw2. */
-+      this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-+
-+      /* Check the WP bit */
-+      if (!(sl2312_device_ready(mtd) & 0x80)) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Device is write protected!!!\n");
-+              ret = -EIO;
-+              goto out;
-+      }
-+      /* Write out desired data */
-+      this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page);
-+
-+      sl2312_nand_read_ecc (mtd, page, mtd->oobblock , retlen, databuf, oobbuf, NULL);
-+
-+    for(j=column;j<(column+len);j++)
-+      oobbuf[j] = buf[j-column];
-+    sl2312_nand_write_ecc (mtd, page, mtd->oobblock, retlen, databuf, oobbuf, NULL);
-+
-+      status = this->waitfunc (mtd, this, FL_WRITING);
-+
-+      /* See if device thinks it succeeded */
-+      if (status & 0x01) {
-+              DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
-+              ret = -EIO;
-+              goto out;
-+      }
-+      /* Return happy */
-+      *retlen = len;
-+
-+
-+out:
-+      /* De-select the NAND device */
-+      //this->select_chip(mtd, -1);
-+
-+      /* Wake up anyone waiting on the device */
-+      spin_lock_bh (&this->chip_lock);
-+      this->state = FL_READY;
-+      wake_up (&this->wq);
-+      spin_unlock_bh (&this->chip_lock);
-+
-+      return ret;
-+}
-+
-+/*
-+ * NAND sync
-+ */
-+static void sl2312_nand_sync (struct mtd_info *mtd)
-+{
-+      struct nand_chip *this = mtd->priv;
-+      DECLARE_WAITQUEUE (wait, current);
-+
-+      DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
-+
-+retry:
-+      /* Grab the spinlock */
-+      spin_lock_bh (&this->chip_lock);
-+
-+      /* See what's going on */
-+      switch (this->state) {
-+      case FL_READY:
-+      case FL_SYNCING:
-+              this->state = FL_SYNCING;
-+              spin_unlock_bh (&this->chip_lock);
-+              break;
-+
-+      default:
-+              /* Not an idle state */
-+              add_wait_queue (&this->wq, &wait);
-+              spin_unlock_bh (&this->chip_lock);
-+              schedule ();
-+
-+              remove_wait_queue (&this->wq, &wait);
-+              goto retry;
-+      }
-+
-+      /* Lock the device */
-+      spin_lock_bh (&this->chip_lock);
-+
-+      /* Set the device to be ready again */
-+      if (this->state == FL_SYNCING) {
-+              this->state = FL_READY;
-+              wake_up (&this->wq);
-+      }
-+
-+      /* Unlock the device */
-+      spin_unlock_bh (&this->chip_lock);
-+}
-+
-+
-+/*
-+ * Scan for the NAND device
-+ */
-+int sl2312_nand_scan (struct mtd_info *mtd, int maxchips)
-+{
-+      int i, j, nand_maf_id, nand_dev_id, busw;
-+      struct nand_chip *this = mtd->priv;
-+      unsigned char id[4];
-+
-+      /* Get buswidth to select the correct functions*/
-+      busw = this->options & NAND_BUSWIDTH_16;
-+
-+      /* check for proper chip_delay setup, set 20us if not */
-+      if (!this->chip_delay)
-+              this->chip_delay = 20;
-+
-+      /* check, if a user supplied command function given */
-+      if (this->cmdfunc == NULL)
-+              this->cmdfunc = sl2312_nand_command;
-+
-+      /* check, if a user supplied wait function given */
-+      if (this->waitfunc == NULL)
-+              this->waitfunc = sl2312_nand_waitfunc;
-+
-+      if (!this->select_chip)
-+              this->select_chip = sl2312_nand_select_chip;
-+      if (!this->write_byte)
-+              this->write_byte = sl2312_nand_write_byte; //busw ? nand_write_byte16 : nand_write_byte;
-+      if (!this->read_byte)
-+              this->read_byte = sl2312_nand_read_byte; //busw ? nand_read_byte16 : nand_read_byte;
-+//    if (!this->write_word)
-+//            this->write_word = nand_write_word;
-+//    if (!this->read_word)
-+//            this->read_word = nand_read_word;
-+//    if (!this->block_bad)
-+              this->block_bad = sl2312_nand_block_bad; //nand_block_bad;
-+      if (!this->block_markbad)
-+              this->block_markbad = sl2312_nand_default_block_markbad;
-+      if (!this->write_buf)
-+              this->write_buf = sl2312_nand_write_buf; //busw ? nand_write_buf16 : nand_write_buf;
-+      if (!this->read_buf)
-+              this->read_buf = sl2312_nand_read_buf; //busw ? nand_read_buf16 : nand_read_buf;
-+      if (!this->verify_buf)
-+              this->verify_buf = sl2312_nand_verify_buf; //busw ? nand_verify_buf16 : nand_verify_buf;
-+      if (!this->scan_bbt)
-+              this->scan_bbt = sl2312_nand_scan_bbt;
-+
-+      /* Select the device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Read manufacturer and device IDs */
-+      nand_read_id(0,id);
-+
-+      nand_maf_id = id[0];
-+      nand_dev_id = id[1];
-+
-+      /* Print and store flash device information */
-+      for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-+
-+              if (nand_dev_id != nand_flash_ids[i].id)
-+                      continue;
-+
-+              if (!mtd->name) mtd->name = nand_flash_ids[i].name;
-+              this->chipsize = nand_flash_ids[i].chipsize << 20;
-+
-+              /* New devices have all the information in additional id bytes */
-+              if (!nand_flash_ids[i].pagesize) {
-+                      int extid;
-+
-+                      /* The 4th id byte is the important one */
-+                      extid = id[3];
-+                      /* Calc pagesize */
-+                      mtd->oobblock = 1024 << (extid & 0x3);
-+                      extid >>= 2;
-+                      /* Calc oobsize */
-+                      mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512);
-+                      extid >>= 2;
-+                      /* Calc blocksize. Blocksize is multiples of 64KiB */
-+                      mtd->erasesize = (64 * 1024)  << (extid & 0x03);
-+                      extid >>= 2;
-+                      /* Get buswidth information */
-+                      busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
-+
-+              } else {
-+                      /* Old devices have this data hardcoded in the
-+                       * device id table */
-+                      mtd->erasesize = nand_flash_ids[i].erasesize;
-+                      mtd->oobblock = nand_flash_ids[i].pagesize;
-+                      mtd->oobsize = mtd->oobblock / 32;
-+                      busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
-+              }
-+
-+              /* Check, if buswidth is correct. Hardware drivers should set
-+               * this correct ! */
-+              if (busw != (this->options & NAND_BUSWIDTH_16)) {
-+                      printk (KERN_INFO "NAND device: Manufacturer ID:"
-+                              " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-+                              nand_manuf_ids[i].name , mtd->name);
-+                      printk (KERN_WARNING
-+                              "NAND bus width %d instead %d bit\n",
-+                                      (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
-+                                      busw ? 16 : 8);
-+                      this->select_chip(mtd, -1);
-+                      return 1;
-+              }
-+
-+              /* Calculate the address shift from the page size */
-+              this->page_shift = ffs(mtd->oobblock) - 1;
-+              this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
-+              this->chip_shift = ffs(this->chipsize) - 1;
-+
-+              /* Set the bad block position */
-+              this->badblockpos = mtd->oobblock > 512 ?
-+                      NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-+
-+              /* Get chip options, preserve non chip based options */
-+              this->options &= ~NAND_CHIPOPTIONS_MSK;
-+              this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
-+              /* Set this as a default. Board drivers can override it, if neccecary */
-+              this->options |= NAND_NO_AUTOINCR;
-+              /* Check if this is a not a samsung device. Do not clear the options
-+               * for chips which are not having an extended id.
-+               */
-+              if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
-+                      this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
-+
-+              /* Check for AND chips with 4 page planes */
-+      //      if (this->options & NAND_4PAGE_ARRAY)
-+      //              this->erase_cmd = multi_erase_cmd;
-+      //      else
-+      //              this->erase_cmd = single_erase_cmd;
-+
-+              /* Do not replace user supplied command function ! */
-+      //      if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
-+      //              this->cmdfunc = nand_command_lp;
-+
-+              /* Try to identify manufacturer */
-+              for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
-+                      if (nand_manuf_ids[j].id == nand_maf_id)
-+                              break;
-+              }
-+              printk (KERN_INFO "NAND device: Manufacturer ID:"
-+                      " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-+                      nand_manuf_ids[j].name , nand_flash_ids[i].name);
-+              break;
-+      }
-+      /////////////////////////////
-+
-+      for (i=1; i < maxchips; i++) {
-+              this->select_chip(mtd, i);
-+
-+              /* Send the command for reading device ID */
-+              nand_read_id(1,id);
-+
-+              /* Read manufacturer and device IDs */
-+              if (nand_maf_id != id[0] ||
-+                  nand_dev_id != id[1])
-+                      break;
-+      }
-+      if (i > 1)
-+              printk(KERN_INFO "%d NAND chips detected\n", i);
-+
-+      /* Allocate buffers, if neccecary */
-+      if (!this->oob_buf) {
-+              size_t len;
-+              len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);
-+              this->oob_buf = kmalloc (len, GFP_KERNEL);
-+              if (!this->oob_buf) {
-+                      printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");
-+                      return -ENOMEM;
-+              }
-+              this->options |= NAND_OOBBUF_ALLOC;
-+      }
-+
-+      if (!this->data_buf) {
-+              size_t len;
-+              len = mtd->oobblock + mtd->oobsize;
-+              this->data_buf = kmalloc (len, GFP_KERNEL);
-+              if (!this->data_buf) {
-+                      if (this->options & NAND_OOBBUF_ALLOC)
-+                              kfree (this->oob_buf);
-+                      printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
-+                      return -ENOMEM;
-+              }
-+              this->options |= NAND_DATABUF_ALLOC;
-+      }
-+
-+      /* Store the number of chips and calc total size for mtd */
-+      this->numchips = i;
-+      mtd->size = i * this->chipsize;
-+      /* Convert chipsize to number of pages per chip -1. */
-+      this->pagemask = (this->chipsize >> this->page_shift) - 1;
-+      /* Preset the internal oob buffer */
-+      memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
-+
-+      /* If no default placement scheme is given, select an
-+       * appropriate one */
-+      if (!this->autooob) {
-+              /* Select the appropriate default oob placement scheme for
-+               * placement agnostic filesystems */
-+              switch (mtd->oobsize) {
-+              case 8:
-+                      this->autooob = &nand_oob_8;
-+                      break;
-+              case 16:
-+                      this->autooob = &nand_oob_16;
-+                      break;
-+              case 64:
-+                      this->autooob = &nand_oob_64;
-+                      break;
-+              default:
-+                      printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
-+                              mtd->oobsize);
-+                      BUG();
-+              }
-+      }
-+
-+      /* The number of bytes available for the filesystem to place fs dependend
-+       * oob data */
-+      if (this->options & NAND_BUSWIDTH_16) {
-+              mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2);
-+              if (this->autooob->eccbytes & 0x01)
-+                      mtd->oobavail--;
-+      } else
-+              mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1);
-+
-+
-+      /*
-+       * check ECC mode, default to software
-+       * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize
-+       * fallback to software ECC
-+      */
-+      this->eccsize = 256;    /* set default eccsize */
-+      this->eccbytes = 3;
-+
-+      switch (this->eccmode) {
-+      case NAND_ECC_HW12_2048:
-+              if (mtd->oobblock < 2048) {
-+                      printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
-+                             mtd->oobblock);
-+                      this->eccmode = NAND_ECC_SOFT;
-+                      this->calculate_ecc = nand_calculate_ecc;
-+                      this->correct_data = nand_correct_data;
-+              } else
-+                      this->eccsize = 2048;
-+              break;
-+
-+      case NAND_ECC_HW3_512:
-+      case NAND_ECC_HW6_512:
-+      case NAND_ECC_HW8_512:
-+              if (mtd->oobblock == 256) {
-+                      printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
-+                      this->eccmode = NAND_ECC_SOFT;
-+                      this->calculate_ecc = nand_calculate_ecc;
-+                      this->correct_data = nand_correct_data;
-+              } else
-+                      this->eccsize = 512; /* set eccsize to 512 */
-+              break;
-+
-+      case NAND_ECC_HW3_256:
-+              break;
-+
-+      case NAND_ECC_NONE:
-+              printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");
-+              this->eccmode = NAND_ECC_NONE;
-+              break;
-+
-+      case NAND_ECC_SOFT:
-+              this->calculate_ecc = nand_calculate_ecc;
-+              this->correct_data = nand_correct_data;
-+              break;
-+
-+      default:
-+              printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
-+              BUG();
-+      }
-+
-+      /* Check hardware ecc function availability and adjust number of ecc bytes per
-+       * calculation step
-+      */
-+      switch (this->eccmode) {
-+      case NAND_ECC_HW12_2048:
-+              this->eccbytes += 4;
-+      case NAND_ECC_HW8_512:
-+              this->eccbytes += 2;
-+      case NAND_ECC_HW6_512:
-+              this->eccbytes += 3;
-+//    case NAND_ECC_HW3_512:
-+      case NAND_ECC_HW3_256:
-+              if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
-+                      break;
-+              printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
-+              BUG();
-+      }
-+
-+      mtd->eccsize = this->eccsize;
-+
-+      /* Set the number of read / write steps for one page to ensure ECC generation */
-+      switch (this->eccmode) {
-+      case NAND_ECC_HW12_2048:
-+              this->eccsteps = mtd->oobblock / 2048;
-+              break;
-+      case NAND_ECC_HW3_512:
-+      case NAND_ECC_HW6_512:
-+      case NAND_ECC_HW8_512:
-+              this->eccsteps = mtd->oobblock / 512;
-+              break;
-+      case NAND_ECC_HW3_256:
-+      case NAND_ECC_SOFT:
-+              this->eccsteps = mtd->oobblock / 256;
-+              break;
-+
-+      case NAND_ECC_NONE:
-+              this->eccsteps = 1;
-+              break;
-+      }
-+
-+      /* Initialize state, waitqueue and spinlock */
-+      this->state = FL_READY;
-+      init_waitqueue_head (&this->wq);
-+      spin_lock_init (&this->chip_lock);
-+
-+      /* De-select the device */
-+      this->select_chip(mtd, 0);
-+
-+      /* Print warning message for no device */
-+      if (!mtd->size) {
-+              printk (KERN_WARNING "No NAND device found!!!\n");
-+              return 1;
-+      }
-+
-+      /* Fill in remaining MTD driver data */
-+      mtd->type = MTD_NANDFLASH;
-+      mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
-+      mtd->ecctype = MTD_ECC_SW;
-+      mtd->erase = sl2312_nand_erase;
-+      mtd->point = NULL;
-+      mtd->unpoint = NULL;
-+      mtd->read = sl2312_nand_read;
-+      mtd->write = sl2312_nand_write;
-+      mtd->read_ecc = sl2312_nand_read_ecc;
-+      mtd->write_ecc = sl2312_nand_write_ecc;
-+      mtd->read_oob = sl2312_nand_read_oob;
-+      mtd->write_oob = sl2312_nand_write_oob;
-+      mtd->readv = NULL;
-+      mtd->writev = sl2312_nand_writev;
-+      mtd->writev_ecc = sl2312_nand_writev_ecc;
-+      mtd->sync = sl2312_nand_sync;
-+      mtd->lock = NULL;
-+      mtd->unlock = NULL;
-+      mtd->suspend = NULL;
-+      mtd->resume = NULL;
-+      mtd->block_isbad = sl2312_nand_block_isbad;
-+      mtd->block_markbad = sl2312_nand_block_markbad;
-+
-+      /* and make the autooob the default one */
-+      memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
-+
-+      mtd->owner = THIS_MODULE;
-+
-+      /* Build bad block table */
-+      return this->scan_bbt (mtd);
-+}
-+
-+/*End Add function*/
-+
-+/*
-+ * Main initialization routine
-+ */
-+extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
-+
-+int __init sl2312_mtd_init (void)
-+{
-+      struct nand_chip *this;
-+      int err = 0;
-+      struct mtd_partition *parts;
-+      int nr_parts = 0;
-+      int ret, data, *base;
-+
-+      printk("NAND MTD Driver Start Init ......\n");
-+
-+      base = (unsigned int *)(IO_ADDRESS(SL2312_GLOBAL_BASE) + 0x30);
-+      data = *base;
-+      data&=0xffffffeb;
-+      data|=0x3; //disable p & s flash
-+        *base = data;
-+
-+      /* Allocate memory for MTD device structure and private data */
-+      sl2312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-+      if (!sl2312_mtd) {
-+              printk ("Unable to allocate SL2312 NAND MTD device structure.\n");
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      //  sl2312_device_setup();
-+
-+      /* io is indirect via a register so don't need to ioremap address */
-+
-+      /* Get pointer to private data */
-+      this = (struct nand_chip *) (&sl2312_mtd[1]);
-+
-+      /* Initialize structures */
-+      memset((char *) sl2312_mtd, 0, sizeof(struct mtd_info));
-+      memset((char *) this, 0, sizeof(struct nand_chip));
-+
-+      /* Link the private data with the MTD structure */
-+      sl2312_mtd->priv = this;
-+      sl2312_mtd->name = "sl2312-nand";
-+
-+      /* Set address of NAND IO lines */
-+      this->IO_ADDR_R = (void __iomem *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE+NFLASH_DATA)); //(unsigned long)&(sl2312_ndfmcptr->dtr);
-+      this->IO_ADDR_W = (void __iomem *)IO_ADDRESS((SL2312_FLASH_CTRL_BASE+NFLASH_DATA)); //(unsigned long)&(sl2312_ndfmcptr->dtr);
-+      this->read_byte = sl2312_nand_read_byte;
-+    this->write_byte = sl2312_nand_write_byte;
-+    this->write_buf = sl2312_nand_write_buf;
-+      this->read_buf = sl2312_nand_read_buf;
-+      this->verify_buf = sl2312_nand_verify_buf;
-+      this->select_chip = sl2312_nand_select_chip;
-+      this->block_bad = sl2312_nand_block_bad;
-+      this->hwcontrol = sl2312_hwcontrol;
-+      this->dev_ready = sl2312_device_ready;
-+      this->cmdfunc = sl2312_nand_command;
-+      this->waitfunc = sl2312_nand_waitfunc;
-+      //this->calculate_ecc = sl2312_readecc;
-+      this->enable_hwecc = sl2312_enable_hwecc;
-+      this->eccmode = NAND_ECC_HW3_512;
-+      /*this->eccsize = 512;  */
-+      /* 20 us command delay time */
-+      this->chip_delay = 20;
-+
-+      this->correct_data = nand_correct_data;
-+//    this->scan_bbt = sl2312_nand_scan_bbt;
-+
-+      /* Allocate memory for internal data buffer */
-+      this->data_buf = kmalloc (sizeof(u_char) * (sl2312_mtd->oobblock + sl2312_mtd->oobsize), GFP_KERNEL);
-+      if (!this->data_buf) {
-+              printk ("Unable to allocate NAND data buffer.\n");
-+              err = -ENOMEM;
-+              goto out_ior;
-+      }
-+
-+      /* Scan to find existance of the device */
-+      if (sl2312_nand_scan(sl2312_mtd, 1)) {
-+              err = -ENXIO;
-+              goto out_ior;
-+      }
-+
-+      /* Register the partitions */
-+      parts = sl2312_partitions;
-+      nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
-+
-+      ret = add_mtd_partitions(sl2312_mtd, sl2312_partitions, nr_parts);
-+      /*If we got an error, free all resources.*/
-+      if (ret < 0) {
-+              del_mtd_partitions(sl2312_mtd);
-+              map_destroy(sl2312_mtd);
-+      }
-+      goto out;
-+
-+//out_buf:
-+//    kfree (this->data_buf);
-+out_ior:
-+out:
-+      printk("NAND MTD Driver Init Success ......\n");
-+      return err;
-+}
-+
-+module_init(sl2312_mtd_init);
-+
-+/*
-+ * Clean up routine
-+ */
-+#ifdef MODULE
-+static void __exit sl2312_cleanup (void)
-+{
-+      struct nand_chip *this = (struct nand_chip *) &sl2312_mtd[1];
-+
-+      /* Unregister partitions */
-+      del_mtd_partitions(sl2312_mtd);
-+
-+      /* Unregister the device */
-+      del_mtd_device (sl2312_mtd);
-+
-+      /* Free internal data buffers */
-+      kfree (this->data_buf);
-+
-+      /* Free the MTD device structure */
-+      kfree (sl2312_mtd);
-+}
-+module_exit(sl2312_cleanup);
-+#endif
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
-+MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBsl2312");
---- /dev/null
-+++ b/drivers/mtd/nand/sl2312-flash-nand.h
-@@ -0,0 +1,24 @@
-+#ifndef SL2312_FLASH_NAND_H
-+#define SL2312_FLASH_NAND_H
-+
-+#include <linux/wait.h>
-+#include <linux/spinlock.h>
-+
-+/*Add function*/
-+static void nand_read_id(int chip_no,unsigned char *id);
-+
-+
-+
-+#define       NFLASH_WiDTH8              0x00000000
-+#define       NFLASH_WiDTH16             0x00000400
-+#define       NFLASH_WiDTH32             0x00000800
-+#define NFLASH_CHIP0_EN            0x00000000  // 16th bit = 0
-+#define NFLASH_CHIP1_EN            0x00010000  // 16th bit = 1
-+#define       NFLASH_DIRECT              0x00004000
-+#define       NFLASH_INDIRECT            0x00000000
-+
-+
-+#define       DWIDTH             NFLASH_WiDTH8
-+
-+
-+#endif /* SL2312_FLASH_NAND_H */
---- /dev/null
-+++ b/include/linux/mtd/kvctl.h
-@@ -0,0 +1,40 @@
-+#ifndef KVCTL_H
-+#define KVCTL_H
-+
-+#define VCTL_HEAD_SIZE        8
-+#define VCTL_ENTRY_LEN        20
-+
-+typedef struct
-+{
-+  char header[4];
-+  unsigned int entry_num;
-+} vctl_mheader;
-+
-+typedef struct
-+{
-+  char header[4];
-+  unsigned int size;
-+  unsigned int type;
-+  char majorver[4];
-+  char minorver[4];
-+  unsigned char *payload;
-+} vctl_entry;
-+
-+typedef struct
-+{
-+  unsigned char mac[6];
-+  unsigned char vlanid;
-+  unsigned char vlanmap;
-+} vlaninfo;
-+
-+#define VCT_VENDORSPEC                0
-+#define VCT_BOOTLOADER                1
-+#define VCT_KERNEL            2
-+#define VCT_VERCTL            3
-+#define VCT_CURRCONF          4
-+#define VCT_DEFAULTCONF               5
-+#define VCT_ROOTFS            6
-+#define VCT_APP                       7
-+#define VCT_VLAN              8
-+
-+#endif
---- a/drivers/mtd/maps/Makefile
-+++ b/drivers/mtd/maps/Makefile
-@@ -71,3 +71,7 @@ obj-$(CONFIG_MTD_PLATRAM)    += plat-ram.o
- obj-$(CONFIG_MTD_OMAP_NOR)    += omap_nor.o
- obj-$(CONFIG_MTD_MTX1)                += mtx-1_flash.o
- obj-$(CONFIG_MTD_TQM834x)     += tqm834x.o
-+###### for Storlink Soc #######
-+obj-$(CONFIG_MTD_SL2312_CFI) += sl2312-flash-cfi.o
-+obj-$(CONFIG_MTD_SL2312_SERIAL_ATMEL) += sl2312-flash-atmel.o
-+obj-$(CONFIG_MTD_SL2312_SERIAL_ST) += sl2312-flash-m25p80.o