unify gcc 3.4 fixes, move flash chip drivers to generic patches, move diag_led driver...
authorkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 2 Jul 2005 11:08:39 +0000 (11:08 +0000)
committerkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 2 Jul 2005 11:08:39 +0000 (11:08 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@1316 3c298f89-4303-0410-b956-a3cf2f4a3e73

target/linux/linux-2.4/README
target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch
target/linux/linux-2.4/patches/brcm/004-diag_led.patch [new file with mode: 0644]
target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch [new file with mode: 0644]
target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch [deleted file]
target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch

index 3f7cad2..d5e2d63 100644 (file)
@@ -1,32 +1,29 @@
-Description of kernel patches in patches:
+Description of kernel patches:
+
+
+generic/
+       Generic patches for vanilla Linux kernel
 
 000-linux_mips.patch
        This is the diff between vanilla linux-2.4.30 and linux-mips.org kernel
        (CVS tag 2_4_30 used). The kernel source from linux-mips.org CVS repository has
        newer drivers and code then vanilla linux-2.4.30 especially for the mips architecture.
 
 
 000-linux_mips.patch
        This is the diff between vanilla linux-2.4.30 and linux-mips.org kernel
        (CVS tag 2_4_30 used). The kernel source from linux-mips.org CVS repository has
        newer drivers and code then vanilla linux-2.4.30 especially for the mips architecture.
 
-001-bcm47xx.patch
-       This is the broadcom specific code from asus (1941) GPL source tarball. 
-       There are many small patches included, so it works with linux 2.4.30 kernel. 
-       The original code is based on Linux 2.4.20.
-
-002-wl_fix.patch
-       The driver for the wireless lan chip on brcm47xx based routers is binary only. 
-       This means it depends on older data structures in the kernel. We backported some
-       of the changes or changed some of the data structures to work with the binary modul. 
-       This is a really bad hack, but without source code, there is no better chance to get
-       the driver working with newer kernels.
-
-003-squashfs.patch
+001-squashfs.patch
        Support for the squashfs filesystem. It has better compression ratio then cramfs.
 
        Support for the squashfs filesystem. It has better compression ratio then cramfs.
 
-004-squashfs_lzma.patch
+002-squashfs_lzma.patch
        LZMA Addon patch from Oleg I. Vdovikin for the squashfs filesystem. 
        Even better compression ratio. 
 
        LZMA Addon patch from Oleg I. Vdovikin for the squashfs filesystem. 
        Even better compression ratio. 
 
-005-jffs2_compression.patch
+003-jffs2_compression.patch
        Compression for jffs2 filesystem.
        Compression for jffs2 filesystem.
-       
+
+004-exec_pagesize.patch
+
+005-mtd_flashtypes.patch
+       Additional mtd drivers for flash chips
+
 100-ebtables.patch
        Filtering packets on ethernet layer. See http://ebtables.sf.net
 
 100-ebtables.patch
        Filtering packets on ethernet layer. See http://ebtables.sf.net
 
@@ -57,9 +54,6 @@ Description of kernel patches in patches:
 110-netdev_random_core.patch
        Support for gathering entropy from network devices for /dev/random
 
 110-netdev_random_core.patch
        Support for gathering entropy from network devices for /dev/random
 
-111-netdev_random_et.patch
-       Patch agains the Broadcom et driver to gather entropy for /dev/random
-
 200-i4l.patch
 
 201-hfc_usb_backport.patch
 200-i4l.patch
 
 201-hfc_usb_backport.patch
@@ -71,8 +65,37 @@ Description of kernel patches in patches:
 204-net_b44.patch
        Support for the BCM47xx chipset in the b44 driver
 
 204-net_b44.patch
        Support for the BCM47xx chipset in the b44 driver
 
-205-gcc_3.4_ldscript.patch
-
 206-gcc_3.4_fixes.patch
 206-gcc_3.4_fixes.patch
+       mips specific gcc 3.4 fixes
 
 207-gcc_4.0_fixes.patch
 
 207-gcc_4.0_fixes.patch
+       gcc 4.0 fixes
+
+
+brcm/
+       Broadcom specific patches
+
+001-bcm47xx.patch
+       This is the broadcom specific code from asus (1941) GPL source tarball. 
+       There are many small patches included, so it works with linux 2.4.30 kernel. 
+       The original code is based on Linux 2.4.20.
+
+002-wl_fix.patch
+       The driver for the wireless lan chip on brcm47xx based routers is binary only. 
+       This means it depends on older data structures in the kernel. We backported some
+       of the changes or changed some of the data structures to work with the binary modul. 
+       This is a really bad hack, but without source code, there is no better chance to get
+       the driver working with newer kernels.
+
+003-bcm47xx_cache_fixes.patch
+
+004-diag_led.patch
+       OpenWrt diag (led and reset button) driver
+
+
+ar7/
+       TI AR7 specific patches
+
+000-ar7_support.patch
+
+001-flash_map.patch
index 5e3fc34..80145c9 100644 (file)
@@ -12831,926 +12831,6 @@ diff -Nur linux-2.4.30/drivers/char/serial.c linux-2.4.30-brcm/drivers/char/seri
        if (doflow)
                state->flags |= ASYNC_CONS_FLOW;
        info = &async_sercons;
        if (doflow)
                state->flags |= ASYNC_CONS_FLOW;
        info = &async_sercons;
-diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c linux-2.4.30-brcm/drivers/mtd/chips/cfi_cmdset_0701.c
---- linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.30-brcm/drivers/mtd/chips/cfi_cmdset_0701.c      2005-05-22 22:55:52.000000000 +0200
-@@ -0,0 +1,855 @@
-+/*
-+ * Common Flash Interface support:
-+ *   SST Standard Vendor Command Set (ID 0x0701)
-+ *
-+ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
-+ *
-+ * 2_by_8 routines added by Simon Munton
-+ *
-+ * This code is GPL
-+ *
-+ * $Id: cfi_cmdset_0701.c,v 1.1 2005/03/16 13:50:00 wbx Exp $
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <asm/io.h>
-+#include <asm/byteorder.h>
-+
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/mtd/map.h>
-+#include <linux/mtd/cfi.h>
-+
-+static int cfi_sststd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
-+static int cfi_sststd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
-+static int cfi_sststd_erase_onesize(struct mtd_info *, struct erase_info *);
-+static int cfi_sststd_erase_varsize(struct mtd_info *, struct erase_info *);
-+static void cfi_sststd_sync (struct mtd_info *);
-+static int cfi_sststd_suspend (struct mtd_info *);
-+static void cfi_sststd_resume (struct mtd_info *);
-+
-+static void cfi_sststd_destroy(struct mtd_info *);
-+
-+struct mtd_info *cfi_cmdset_0701(struct map_info *, int);
-+static struct mtd_info *cfi_sststd_setup (struct map_info *);
-+
-+
-+static struct mtd_chip_driver cfi_sststd_chipdrv = {
-+      probe: NULL, /* Not usable directly */
-+      destroy: cfi_sststd_destroy,
-+      name: "cfi_cmdset_0701",
-+      module: THIS_MODULE
-+};
-+
-+struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary)
-+{
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      int ofs_factor = cfi->interleave * cfi->device_type;
-+      int i;
-+      __u8 major, minor;
-+      __u32 base = cfi->chips[0].start;
-+
-+      if (cfi->cfi_mode==1){
-+              __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
-+
-+              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              
-+              major = cfi_read_query(map, base + (adr+3)*ofs_factor);
-+              minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
-+              
-+              printk(" SST Query Table v%c.%c at 0x%4.4X\n",
-+                     major, minor, adr);
-+              cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              
-+              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              cfi->mfr = cfi_read_query(map, base);
-+              cfi->id = cfi_read_query(map, base + ofs_factor);
-+
-+              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              
-+              switch (cfi->device_type) {
-+              case CFI_DEVICETYPE_X16:
-+                      cfi->addr_unlock1 = 0x5555;
-+                      cfi->addr_unlock2 = 0x2AAA;
-+                      break;
-+              default:
-+                      printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type);
-+                      return NULL;
-+              }
-+      } /* CFI mode */
-+
-+      for (i=0; i< cfi->numchips; i++) {
-+              cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
-+              cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
-+              cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
-+      }               
-+      
-+      map->fldrv = &cfi_sststd_chipdrv;
-+      MOD_INC_USE_COUNT;
-+
-+      cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+      return cfi_sststd_setup(map);
-+}
-+
-+static struct mtd_info *cfi_sststd_setup(struct map_info *map)
-+{
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      struct mtd_info *mtd;
-+      unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
-+
-+      mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
-+      printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips);
-+
-+      if (!mtd) {
-+        printk("Failed to allocate memory for MTD device\n");
-+        kfree(cfi->cmdset_priv);
-+        return NULL;
-+      }
-+
-+      memset(mtd, 0, sizeof(*mtd));
-+      mtd->priv = map;
-+      mtd->type = MTD_NORFLASH;
-+      /* Also select the correct geometry setup too */ 
-+      mtd->size = devsize * cfi->numchips;
-+      
-+      if (cfi->cfiq->NumEraseRegions == 1) {
-+              /* No need to muck about with multiple erase sizes */
-+              mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave;
-+      } else {
-+              unsigned long offset = 0;
-+              int i,j;
-+
-+              mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
-+              mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL);
-+              if (!mtd->eraseregions) { 
-+                      printk("Failed to allocate memory for MTD erase region info\n");
-+                      kfree(cfi->cmdset_priv);
-+                      return NULL;
-+              }
-+                      
-+              for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
-+                      unsigned long ernum, ersize;
-+                      ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
-+                      ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
-+                      
-+                      if (mtd->erasesize < ersize) {
-+                              mtd->erasesize = ersize;
-+                      }
-+                      for (j=0; j<cfi->numchips; j++) {
-+                              mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
-+                              mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
-+                              mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
-+                      }
-+                      offset += (ersize * ernum);
-+              }
-+
-+              // debug
-+              for (i=0; i<mtd->numeraseregions;i++){
-+                      printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
-+                             i,mtd->eraseregions[i].offset,
-+                             mtd->eraseregions[i].erasesize,
-+                             mtd->eraseregions[i].numblocks);
-+              }
-+      }
-+
-+      switch (CFIDEV_BUSWIDTH)
-+      {
-+      case 1:
-+      case 2:
-+      case 4:
-+              if (mtd->numeraseregions > 1)
-+                      mtd->erase = cfi_sststd_erase_varsize;
-+              else
-+                      mtd->erase = cfi_sststd_erase_onesize;
-+              mtd->read = cfi_sststd_read;
-+              mtd->write = cfi_sststd_write;
-+              break;
-+
-+      default:
-+              printk("Unsupported buswidth\n");
-+              kfree(mtd);
-+              kfree(cfi->cmdset_priv);
-+              return NULL;
-+              break;
-+      }
-+      mtd->sync = cfi_sststd_sync;
-+      mtd->suspend = cfi_sststd_suspend;
-+      mtd->resume = cfi_sststd_resume;
-+      mtd->flags = MTD_CAP_NORFLASH;
-+      map->fldrv = &cfi_sststd_chipdrv;
-+      mtd->name = map->name;
-+      MOD_INC_USE_COUNT;
-+      return mtd;
-+}
-+
-+static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
-+{
-+      DECLARE_WAITQUEUE(wait, current);
-+      unsigned long timeo = jiffies + HZ;
-+
-+ retry:
-+      cfi_spin_lock(chip->mutex);
-+
-+      if (chip->state != FL_READY){
-+              printk("Waiting for chip to read, status = %d\n", chip->state);
-+              set_current_state(TASK_UNINTERRUPTIBLE);
-+              add_wait_queue(&chip->wq, &wait);
-+                
-+              cfi_spin_unlock(chip->mutex);
-+
-+              schedule();
-+              remove_wait_queue(&chip->wq, &wait);
-+              timeo = jiffies + HZ;
-+
-+              goto retry;
-+      }       
-+
-+      adr += chip->start;
-+
-+      chip->state = FL_READY;
-+
-+      map->copy_from(map, buf, adr, len);
-+
-+      wake_up(&chip->wq);
-+      cfi_spin_unlock(chip->mutex);
-+
-+      return 0;
-+}
-+
-+static int cfi_sststd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      unsigned long ofs;
-+      int chipnum;
-+      int ret = 0;
-+
-+      /* ofs: offset within the first chip that the first read should start */
-+
-+      chipnum = (from >> cfi->chipshift);
-+      ofs = from - (chipnum <<  cfi->chipshift);
-+
-+
-+      *retlen = 0;
-+
-+      while (len) {
-+              unsigned long thislen;
-+
-+              if (chipnum >= cfi->numchips)
-+                      break;
-+
-+              if ((len + ofs -1) >> cfi->chipshift)
-+                      thislen = (1<<cfi->chipshift) - ofs;
-+              else
-+                      thislen = len;
-+
-+              ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
-+              if (ret)
-+                      break;
-+
-+              *retlen += thislen;
-+              len -= thislen;
-+              buf += thislen;
-+
-+              ofs = 0;
-+              chipnum++;
-+      }
-+      return ret;
-+}
-+
-+static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast)
-+{
-+      unsigned long timeo = jiffies + HZ;
-+      unsigned int Last[4];
-+      unsigned long Count = 0;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      DECLARE_WAITQUEUE(wait, current);
-+      int ret = 0;
-+
-+ retry:
-+      cfi_spin_lock(chip->mutex);
-+
-+      if (chip->state != FL_READY){
-+              printk("Waiting for chip to write, status = %d\n", chip->state);
-+              set_current_state(TASK_UNINTERRUPTIBLE);
-+              add_wait_queue(&chip->wq, &wait);
-+                
-+              cfi_spin_unlock(chip->mutex);
-+
-+              schedule();
-+              remove_wait_queue(&chip->wq, &wait);
-+              printk("Wake up to write:\n");
-+              timeo = jiffies + HZ;
-+
-+              goto retry;
-+      }       
-+
-+      chip->state = FL_WRITING;
-+
-+      adr += chip->start;
-+      ENABLE_VPP(map);
-+    cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+    cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+    cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+
-+      cfi_write(map, datum, adr);
-+
-+      cfi_spin_unlock(chip->mutex);
-+      cfi_udelay(chip->word_write_time);
-+      cfi_spin_lock(chip->mutex);
-+
-+      Last[0] = cfi_read(map, adr);
-+      //      printk("Last[0] is %x\n", Last[0]);
-+      Last[1] = cfi_read(map, adr);
-+      //      printk("Last[1] is %x\n", Last[1]);
-+      Last[2] = cfi_read(map, adr);
-+      //      printk("Last[2] is %x\n", Last[2]);
-+
-+      for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
-+              cfi_spin_unlock(chip->mutex);
-+              cfi_udelay(10);
-+              cfi_spin_lock(chip->mutex);
-+              
-+              Last[Count % 4] = cfi_read(map, adr);
-+              //              printk("Last[%d%%4] is %x\n", Count, Last[Count%4]);
-+      }
-+      
-+      if (Last[(Count - 1) % 4] != datum){
-+              printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum);
-+              cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL);
-+              DISABLE_VPP(map);
-+              ret = -EIO;
-+      }       
-+      DISABLE_VPP(map);
-+      chip->state = FL_READY;
-+      wake_up(&chip->wq);
-+      cfi_spin_unlock(chip->mutex);
-+      
-+      return ret;
-+}
-+
-+static int cfi_sststd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      int ret = 0;
-+      int chipnum;
-+      unsigned long ofs, chipstart;
-+
-+      *retlen = 0;
-+      if (!len)
-+              return 0;
-+
-+      chipnum = to >> cfi->chipshift;
-+      ofs = to  - (chipnum << cfi->chipshift);
-+      chipstart = cfi->chips[chipnum].start;
-+
-+      /* If it's not bus-aligned, do the first byte write */
-+      if (ofs & (CFIDEV_BUSWIDTH-1)) {
-+              unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
-+              int i = ofs - bus_ofs;
-+              int n = 0;
-+              u_char tmp_buf[4];
-+              __u32 datum;
-+
-+              map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
-+              while (len && i < CFIDEV_BUSWIDTH)
-+                      tmp_buf[i++] = buf[n++], len--;
-+
-+              if (cfi_buswidth_is_2()) {
-+                      datum = *(__u16*)tmp_buf;
-+              } else if (cfi_buswidth_is_4()) {
-+                      datum = *(__u32*)tmp_buf;
-+              } else {
-+                      return -EINVAL;  /* should never happen, but be safe */
-+              }
-+
-+              ret = do_write_oneword(map, &cfi->chips[chipnum], 
-+                              bus_ofs, datum, 0);
-+              if (ret) 
-+                      return ret;
-+              
-+              ofs += n;
-+              buf += n;
-+              (*retlen) += n;
-+
-+              if (ofs >> cfi->chipshift) {
-+                      chipnum ++; 
-+                      ofs = 0;
-+                      if (chipnum == cfi->numchips)
-+                              return 0;
-+              }
-+      }
-+      
-+      /* We are now aligned, write as much as possible */
-+      while(len >= CFIDEV_BUSWIDTH) {
-+              __u32 datum;
-+
-+              if (cfi_buswidth_is_1()) {
-+                      datum = *(__u8*)buf;
-+              } else if (cfi_buswidth_is_2()) {
-+                      datum = *(__u16*)buf;
-+              } else if (cfi_buswidth_is_4()) {
-+                      datum = *(__u32*)buf;
-+              } else {
-+                      return -EINVAL;
-+              }
-+              ret = do_write_oneword(map, &cfi->chips[chipnum],
-+                                     ofs, datum, cfi->fast_prog);
-+              if (ret) {
-+                      return ret;
-+              }
-+
-+              ofs += CFIDEV_BUSWIDTH;
-+              buf += CFIDEV_BUSWIDTH;
-+              (*retlen) += CFIDEV_BUSWIDTH;
-+              len -= CFIDEV_BUSWIDTH;
-+
-+              if (ofs >> cfi->chipshift) {
-+                      chipnum ++; 
-+                      ofs = 0;
-+                      if (chipnum == cfi->numchips)
-+                              return 0;
-+                      chipstart = cfi->chips[chipnum].start;
-+              }
-+      }
-+
-+      if (len & (CFIDEV_BUSWIDTH-1)) {
-+              int i = 0, n = 0;
-+              u_char tmp_buf[4];
-+              __u32 datum;
-+
-+              map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
-+              while (len--)
-+                      tmp_buf[i++] = buf[n++];
-+
-+              if (cfi_buswidth_is_2()) {
-+                      datum = *(__u16*)tmp_buf;
-+              } else if (cfi_buswidth_is_4()) {
-+                      datum = *(__u32*)tmp_buf;
-+              } else {
-+                      return -EINVAL;  /* should never happen, but be safe */
-+              }
-+
-+              ret = do_write_oneword(map, &cfi->chips[chipnum], 
-+                              ofs, datum, 0);
-+              if (ret) 
-+                      return ret;
-+              
-+              (*retlen) += n;
-+      }
-+
-+      return 0;
-+}
-+
-+static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
-+{
-+      unsigned int status;
-+      unsigned long timeo = jiffies + HZ;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      unsigned int rdy_mask;
-+      DECLARE_WAITQUEUE(wait, current);
-+
-+ retry:
-+      cfi_spin_lock(chip->mutex);
-+
-+      if (chip->state != FL_READY){
-+              set_current_state(TASK_UNINTERRUPTIBLE);
-+              add_wait_queue(&chip->wq, &wait);
-+                
-+              cfi_spin_unlock(chip->mutex);
-+
-+              schedule();
-+              remove_wait_queue(&chip->wq, &wait);
-+              timeo = jiffies + HZ;
-+
-+              goto retry;
-+      }       
-+
-+      chip->state = FL_ERASING;
-+
-+      adr += chip->start;
-+      ENABLE_VPP(map);
-+      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+      cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
-+      cfi_write(map, CMD(0x30), adr);
-+      
-+      timeo = jiffies + (HZ*20);
-+
-+      cfi_spin_unlock(chip->mutex);
-+      schedule_timeout(HZ);
-+      cfi_spin_lock(chip->mutex);
-+      
-+      rdy_mask = CMD(0x80);
-+
-+      /* Once the state machine's known to be working I'll do that */
-+
-+      while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) {
-+              static int z=0;
-+
-+              if (chip->state != FL_ERASING) {
-+                      /* Someone's suspended the erase. Sleep */
-+                      set_current_state(TASK_UNINTERRUPTIBLE);
-+                      add_wait_queue(&chip->wq, &wait);
-+                      
-+                      cfi_spin_unlock(chip->mutex);
-+                      printk("erase suspended. Sleeping\n");
-+                      
-+                      schedule();
-+                      remove_wait_queue(&chip->wq, &wait);
-+                      timeo = jiffies + (HZ*2); 
-+                      cfi_spin_lock(chip->mutex);
-+                      continue;
-+              }
-+
-+              /* OK Still waiting */
-+              if (time_after(jiffies, timeo)) {
-+                      chip->state = FL_READY;
-+                      cfi_spin_unlock(chip->mutex);
-+                      printk("waiting for erase to complete timed out.");
-+                      DISABLE_VPP(map);
-+                      return -EIO;
-+              }
-+              
-+              /* Latency issues. Drop the lock, wait a while and retry */
-+              cfi_spin_unlock(chip->mutex);
-+
-+              z++;
-+              if ( 0 && !(z % 100 )) 
-+                      printk("chip not ready yet after erase. looping\n");
-+
-+              cfi_udelay(1);
-+              
-+              cfi_spin_lock(chip->mutex);
-+              continue;
-+      }
-+      
-+      /* Done and happy. */
-+      DISABLE_VPP(map);
-+      chip->state = FL_READY;
-+      wake_up(&chip->wq);
-+      cfi_spin_unlock(chip->mutex);
-+      return 0;
-+}
-+
-+static int cfi_sststd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      unsigned long adr, len;
-+      int chipnum, ret = 0;
-+      int i, first;
-+      struct mtd_erase_region_info *regions = mtd->eraseregions;
-+
-+      if (instr->addr > mtd->size)
-+              return -EINVAL;
-+
-+      if ((instr->len + instr->addr) > mtd->size)
-+              return -EINVAL;
-+
-+      /* Check that both start and end of the requested erase are
-+       * aligned with the erasesize at the appropriate addresses.
-+       */
-+
-+      i = 0;
-+
-+      /* Skip all erase regions which are ended before the start of 
-+         the requested erase. Actually, to save on the calculations,
-+         we skip to the first erase region which starts after the
-+         start of the requested erase, and then go back one.
-+      */
-+      
-+      while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
-+             i++;
-+      i--;
-+
-+      /* OK, now i is pointing at the erase region in which this 
-+         erase request starts. Check the start of the requested
-+         erase range is aligned with the erase size which is in
-+         effect here.
-+      */
-+
-+      if (instr->addr & (regions[i].erasesize-1))
-+              return -EINVAL;
-+
-+      /* Remember the erase region we start on */
-+      first = i;
-+
-+      /* Next, check that the end of the requested erase is aligned
-+       * with the erase region at that address.
-+       */
-+
-+      while (i<mtd->numeraseregions && (instr->addr + instr->len) >= regions[i].offset)
-+              i++;
-+
-+      /* As before, drop back one to point at the region in which
-+         the address actually falls
-+      */
-+      i--;
-+      
-+      if ((instr->addr + instr->len) & (regions[i].erasesize-1))
-+              return -EINVAL;
-+      
-+      chipnum = instr->addr >> cfi->chipshift;
-+      adr = instr->addr - (chipnum << cfi->chipshift);
-+      len = instr->len;
-+
-+      i=first;
-+
-+      while(len) {
-+              ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
-+
-+              if (ret)
-+                      return ret;
-+
-+              adr += regions[i].erasesize;
-+              len -= regions[i].erasesize;
-+
-+              if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
-+                      i++;
-+
-+              if (adr >> cfi->chipshift) {
-+                      adr = 0;
-+                      chipnum++;
-+                      
-+                      if (chipnum >= cfi->numchips)
-+                      break;
-+              }
-+      }
-+
-+      instr->state = MTD_ERASE_DONE;
-+      if (instr->callback)
-+              instr->callback(instr);
-+      
-+      return 0;
-+}
-+
-+static int cfi_sststd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      unsigned long adr, len;
-+      int chipnum, ret = 0;
-+
-+      if (instr->addr & (mtd->erasesize - 1))
-+              return -EINVAL;
-+
-+      if (instr->len & (mtd->erasesize -1))
-+              return -EINVAL;
-+
-+      if ((instr->len + instr->addr) > mtd->size)
-+              return -EINVAL;
-+
-+      chipnum = instr->addr >> cfi->chipshift;
-+      adr = instr->addr - (chipnum << cfi->chipshift);
-+      len = instr->len;
-+
-+      while(len) {
-+              ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
-+
-+              if (ret)
-+                      return ret;
-+
-+              adr += mtd->erasesize;
-+              len -= mtd->erasesize;
-+
-+              if (adr >> cfi->chipshift) {
-+                      adr = 0;
-+                      chipnum++;
-+                      
-+                      if (chipnum >= cfi->numchips)
-+                      break;
-+              }
-+      }
-+              
-+      instr->state = MTD_ERASE_DONE;
-+      if (instr->callback)
-+              instr->callback(instr);
-+      
-+      return 0;
-+}
-+
-+static void cfi_sststd_sync (struct mtd_info *mtd)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      int i;
-+      struct flchip *chip;
-+      int ret = 0;
-+      DECLARE_WAITQUEUE(wait, current);
-+
-+      for (i=0; !ret && i<cfi->numchips; i++) {
-+              chip = &cfi->chips[i];
-+
-+      retry:
-+              cfi_spin_lock(chip->mutex);
-+
-+              switch(chip->state) {
-+              case FL_READY:
-+              case FL_STATUS:
-+              case FL_CFI_QUERY:
-+              case FL_JEDEC_QUERY:
-+                      chip->oldstate = chip->state;
-+                      chip->state = FL_SYNCING;
-+                      /* No need to wake_up() on this state change - 
-+                       * as the whole point is that nobody can do anything
-+                       * with the chip now anyway.
-+                       */
-+              case FL_SYNCING:
-+                      cfi_spin_unlock(chip->mutex);
-+                      break;
-+
-+              default:
-+                      /* Not an idle state */
-+                      add_wait_queue(&chip->wq, &wait);
-+                      
-+                      cfi_spin_unlock(chip->mutex);
-+
-+                      schedule();
-+
-+                      remove_wait_queue(&chip->wq, &wait);
-+                      
-+                      goto retry;
-+              }
-+      }
-+
-+      /* Unlock the chips again */
-+
-+      for (i--; i >=0; i--) {
-+              chip = &cfi->chips[i];
-+
-+              cfi_spin_lock(chip->mutex);
-+              
-+              if (chip->state == FL_SYNCING) {
-+                      chip->state = chip->oldstate;
-+                      wake_up(&chip->wq);
-+              }
-+              cfi_spin_unlock(chip->mutex);
-+      }
-+}
-+
-+
-+static int cfi_sststd_suspend(struct mtd_info *mtd)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      int i;
-+      struct flchip *chip;
-+      int ret = 0;
-+//printk("suspend\n");
-+
-+      for (i=0; !ret && i<cfi->numchips; i++) {
-+              chip = &cfi->chips[i];
-+
-+              cfi_spin_lock(chip->mutex);
-+
-+              switch(chip->state) {
-+              case FL_READY:
-+              case FL_STATUS:
-+              case FL_CFI_QUERY:
-+              case FL_JEDEC_QUERY:
-+                      chip->oldstate = chip->state;
-+                      chip->state = FL_PM_SUSPENDED;
-+                      /* No need to wake_up() on this state change - 
-+                       * as the whole point is that nobody can do anything
-+                       * with the chip now anyway.
-+                       */
-+              case FL_PM_SUSPENDED:
-+                      break;
-+
-+              default:
-+                      ret = -EAGAIN;
-+                      break;
-+              }
-+              cfi_spin_unlock(chip->mutex);
-+      }
-+
-+      /* Unlock the chips again */
-+
-+      if (ret) {
-+              for (i--; i >=0; i--) {
-+                      chip = &cfi->chips[i];
-+
-+                      cfi_spin_lock(chip->mutex);
-+              
-+                      if (chip->state == FL_PM_SUSPENDED) {
-+                              chip->state = chip->oldstate;
-+                              wake_up(&chip->wq);
-+                      }
-+                      cfi_spin_unlock(chip->mutex);
-+              }
-+      }
-+      
-+      return ret;
-+}
-+
-+static void cfi_sststd_resume(struct mtd_info *mtd)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      int i;
-+      struct flchip *chip;
-+//printk("resume\n");
-+
-+      for (i=0; i<cfi->numchips; i++) {
-+      
-+              chip = &cfi->chips[i];
-+
-+              cfi_spin_lock(chip->mutex);
-+              
-+              if (chip->state == FL_PM_SUSPENDED) {
-+                      chip->state = FL_READY;
-+                      cfi_write(map, CMD(0xF0), chip->start);
-+                      wake_up(&chip->wq);
-+              }
-+              else
-+                      printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
-+
-+              cfi_spin_unlock(chip->mutex);
-+      }
-+}
-+
-+static void cfi_sststd_destroy(struct mtd_info *mtd)
-+{
-+      struct map_info *map = mtd->priv;
-+      struct cfi_private *cfi = map->fldrv_priv;
-+      kfree(cfi->cmdset_priv);
-+      kfree(cfi);
-+}
-+
-+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
-+#define cfi_sststd_init init_module
-+#define cfi_sststd_exit cleanup_module
-+#endif
-+
-+static char im_name[]="cfi_cmdset_0701";
-+
-+mod_init_t cfi_sststd_init(void)
-+{
-+      inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0701);
-+      return 0;
-+}
-+
-+mod_exit_t cfi_sststd_exit(void)
-+{
-+      inter_module_unregister(im_name);
-+}
-+
-+module_init(cfi_sststd_init);
-+module_exit(cfi_sststd_exit);
-+
-diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_probe.c linux-2.4.30-brcm/drivers/mtd/chips/cfi_probe.c
---- linux-2.4.30/drivers/mtd/chips/cfi_probe.c 2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.30-brcm/drivers/mtd/chips/cfi_probe.c    2005-05-22 22:55:52.000000000 +0200
-@@ -67,8 +67,15 @@
-       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
--      if (!qry_present(map,base,cfi))
--              return 0;
-+      if (!qry_present(map,base,cfi)) {
-+              /* rather broken SST cfi probe (requires SST unlock) */
-+              cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
-+              cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
-+              if (!qry_present(map,base,cfi))
-+                      return 0;
-+      }
-       if (!cfi->numchips) {
-               /* This is the first time we're called. Set up the CFI 
-diff -Nur linux-2.4.30/drivers/mtd/chips/Config.in linux-2.4.30-brcm/drivers/mtd/chips/Config.in
---- linux-2.4.30/drivers/mtd/chips/Config.in   2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.30-brcm/drivers/mtd/chips/Config.in      2005-05-22 22:55:52.000000000 +0200
-@@ -45,6 +45,7 @@
- dep_tristate '  Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE
- dep_tristate '  Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE
- dep_tristate '  Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE
-+dep_tristate '  Support for SST flash chips' CONFIG_MTD_CFI_SSTSTD $CONFIG_MTD_GEN_PROBE
- dep_tristate '  Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD
- dep_tristate '  Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD
-diff -Nur linux-2.4.30/drivers/mtd/chips/gen_probe.c linux-2.4.30-brcm/drivers/mtd/chips/gen_probe.c
---- linux-2.4.30/drivers/mtd/chips/gen_probe.c 2003-08-25 13:44:42.000000000 +0200
-+++ linux-2.4.30-brcm/drivers/mtd/chips/gen_probe.c    2005-05-22 22:55:52.000000000 +0200
-@@ -332,9 +332,13 @@
-               return cfi_cmdset_0002(map, primary);
- #endif
- #ifdef CONFIG_MTD_CFI_STAA
--        case 0x0020:
-+      case 0x0020:
-               return cfi_cmdset_0020(map, primary);
- #endif
-+#ifdef CONFIG_MTD_CFI_SSTSTD
-+      case 0x0701:
-+              return cfi_cmdset_0701(map, primary);
-+#endif
-       }
-       return cfi_cmdset_unknown(map, primary);
-diff -Nur linux-2.4.30/drivers/mtd/chips/Makefile linux-2.4.30-brcm/drivers/mtd/chips/Makefile
---- linux-2.4.30/drivers/mtd/chips/Makefile    2003-06-13 16:51:34.000000000 +0200
-+++ linux-2.4.30-brcm/drivers/mtd/chips/Makefile       2005-05-22 22:55:52.000000000 +0200
-@@ -18,6 +18,7 @@
- obj-$(CONFIG_MTD_AMDSTD)      += amd_flash.o 
- obj-$(CONFIG_MTD_CFI)         += cfi_probe.o
- obj-$(CONFIG_MTD_CFI_STAA)    += cfi_cmdset_0020.o
-+obj-$(CONFIG_MTD_CFI_SSTSTD)   += cfi_cmdset_0701.o
- obj-$(CONFIG_MTD_CFI_AMDSTD)  += cfi_cmdset_0002.o
- obj-$(CONFIG_MTD_CFI_INTELEXT)        += cfi_cmdset_0001.o
- obj-$(CONFIG_MTD_GEN_PROBE)   += gen_probe.o
 diff -Nur linux-2.4.30/drivers/mtd/maps/bcm947xx-flash.c linux-2.4.30-brcm/drivers/mtd/maps/bcm947xx-flash.c
 --- linux-2.4.30/drivers/mtd/maps/bcm947xx-flash.c     1970-01-01 01:00:00.000000000 +0100
 +++ linux-2.4.30-brcm/drivers/mtd/maps/bcm947xx-flash.c        2005-05-22 22:55:52.000000000 +0200
 diff -Nur linux-2.4.30/drivers/mtd/maps/bcm947xx-flash.c linux-2.4.30-brcm/drivers/mtd/maps/bcm947xx-flash.c
 --- linux-2.4.30/drivers/mtd/maps/bcm947xx-flash.c     1970-01-01 01:00:00.000000000 +0100
 +++ linux-2.4.30-brcm/drivers/mtd/maps/bcm947xx-flash.c        2005-05-22 22:55:52.000000000 +0200
@@ -14042,271 +13122,6 @@ diff -Nur linux-2.4.30/drivers/net/Config.in linux-2.4.30-brcm/drivers/net/Confi
        dep_tristate '    CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA
        dep_tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI
        if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
        dep_tristate '    CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA
        dep_tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI
        if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
-diff -Nur linux-2.4.30/drivers/net/diag/diag_led.c linux-2.4.30-brcm/drivers/net/diag/diag_led.c
---- linux-2.4.30/drivers/net/diag/diag_led.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.30-brcm/drivers/net/diag/diag_led.c      2005-05-25 20:41:19.000000000 +0200
-@@ -0,0 +1,244 @@
-+/*
-+ * diag_led.c - replacement diag module
-+ *
-+ * Copyright (C) 2004 Mike Baker,
-+ *                    Imre Kaloz <kaloz@dune.hu>
-+ *
-+ * 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.
-+ *
-+ * $Id: diag_led.c,v 1.5 2005/04/18 09:05:24 mbm Exp $
-+ */
-+
-+/*
-+ * ChangeLog:
-+ * 2004/03/28 initial release 
-+ * 2004/08/26 asus & buffalo support added
-+ * 2005/03/14 asus wl-500g deluxe and buffalo v2 support added
-+ * 2005/04/13 added licensing informations
-+ * 2005/04/18 base reset polarity off initial readings
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sysctl.h>
-+#include <asm/io.h>
-+#include <typedefs.h>
-+#include <bcmdevs.h>
-+#include <sbutils.h>
-+
-+extern char * nvram_get(const char *name);
-+static void *sbh;
-+
-+// v2.x - - - - -
-+#define DIAG_GPIO (1<<1)
-+#define DMZ_GPIO  (1<<7)
-+
-+static void set_gpio(uint32 mask, uint32 value) {
-+      sb_gpiocontrol(sbh,mask,0);
-+      sb_gpioouten(sbh,mask,mask);
-+      sb_gpioout(sbh,mask,value);
-+}
-+
-+static void v2_set_diag(u8 state) {
-+      set_gpio(DIAG_GPIO,state);
-+}
-+static void v2_set_dmz(u8 state) {
-+      set_gpio(DMZ_GPIO,state);
-+}
-+
-+// v1.x - - - - -
-+#define LED_DIAG   0x13
-+#define LED_DMZ    0x12
-+
-+static void v1_set_diag(u8 state) {
-+      if (!state) {
-+              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF;
-+      } else {
-+              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG);
-+      }
-+}
-+static void v1_set_dmz(u8 state) {
-+      if (!state) {
-+              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF;
-+      } else {
-+              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ);
-+      }
-+}
-+
-+// - - - - -
-+static void ignore(u8 ignored) {};
-+
-+// - - - - -
-+#define BIT_DMZ         0x01
-+#define BIT_DIAG        0x04
-+
-+void (*set_diag)(u8 state);
-+void (*set_dmz)(u8 state);
-+
-+static unsigned int diag = 0;
-+
-+static void diag_change()
-+{
-+      set_diag(0xFF); // off
-+      set_dmz(0xFF); // off
-+
-+      if(diag & BIT_DIAG)
-+              set_diag(0x00); // on
-+      if(diag & BIT_DMZ)
-+              set_dmz(0x00); // on
-+}
-+
-+static int proc_diag(ctl_table *table, int write, struct file *filp,
-+              void *buffer, size_t *lenp)
-+{
-+      int r;
-+      r = proc_dointvec(table, write, filp, buffer, lenp);
-+      if (write && !r) {
-+              diag_change();
-+      }
-+      return r;
-+}
-+
-+// - - - - -
-+static unsigned char reset_gpio = 0;
-+static unsigned char reset_polarity = 0;
-+static unsigned int reset = 0;
-+
-+static int proc_reset(ctl_table *table, int write, struct file *filp,
-+              void *buffer, size_t *lenp)
-+{
-+
-+      if (reset_gpio) {
-+              sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
-+              sb_gpioouten(sbh,reset_gpio,0);
-+              reset=!(sb_gpioin(sbh)&reset_gpio);
-+
-+              if (reset_polarity) reset=!reset;
-+      } else {
-+              reset=0;
-+      }
-+
-+      return proc_dointvec(table, write, filp, buffer, lenp);
-+}
-+
-+// - - - - -
-+static struct ctl_table_header *diag_sysctl_header;
-+
-+static ctl_table sys_diag[] = {
-+         { 
-+         ctl_name: 2000,
-+         procname: "diag", 
-+         data: &diag,
-+         maxlen: sizeof(diag), 
-+         mode: 0644,
-+         proc_handler: proc_diag
-+       },
-+       {
-+         ctl_name: 2001,
-+         procname: "reset",
-+         data: &reset,
-+         maxlen: sizeof(reset),
-+         mode: 0444,
-+         proc_handler: proc_reset 
-+       },
-+         { 0 }
-+};
-+
-+static int __init diag_init()
-+{
-+      char *buf;
-+      u32 board_type;
-+      sbh = sb_kattach();
-+      sb_gpiosetcore(sbh);
-+
-+      board_type = sb_boardtype(sbh);
-+      printk(KERN_INFO "diag boardtype: %08x\n",board_type);
-+
-+      set_diag=ignore;
-+      set_dmz=ignore;
-+      
-+      if ((board_type & 0xf00) == 0x400) {
-+              buf=nvram_get("boardtype")?:"";
-+              if (!strcmp(buf,"bcm94710dev")) {
-+                      buf=nvram_get("boardnum")?:"";
-+                      if (!strcmp(buf,"42")) {
-+                              // wrt54g v1.x
-+                              set_diag=v1_set_diag;
-+                              set_dmz=v1_set_dmz;
-+                              reset_gpio=(1<<6);
-+                      }
-+                      if (!strcmp(buf,"asusX")) {
-+                              //asus wl-500g
-+                              reset_gpio=(1<<6);
-+                      }
-+              }
-+              if (!strcmp(buf,"bcm94710ap")) {
-+                      buf=nvram_get("boardnum")?:"";
-+                      if (!strcmp(buf,"42")) {
-+                              // buffalo
-+                              set_dmz=v2_set_dmz;
-+                              reset_gpio=(1<<4);
-+                      }
-+                      if (!strcmp(buf,"44")) {
-+                              //dell truemobile
-+                              set_dmz=v2_set_dmz;
-+                              reset_gpio=(1<<0);
-+                      }
-+              }
-+      } else {
-+              buf=nvram_get("boardnum")?:"";
-+              if (!strcmp(buf,"42")) {
-+                      //linksys
-+                      set_diag=v2_set_diag;
-+                      set_dmz=v2_set_dmz;
-+                      reset_gpio=(1<<6);
-+              }
-+              if (!strcmp(buf,"44")) {
-+                      //motorola
-+                      reset_gpio=(1<<5);
-+              }
-+              if (!strcmp(buf,"00")) {
-+                      //buffalo
-+                      reset_gpio=(1<<7);
-+              }
-+              if (!strcmp(buf,"45")) {
-+                      //wl-500g deluxe
-+                      reset_gpio=(1<<6);
-+              }
-+      }
-+
-+      
-+      sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
-+      sb_gpioouten(sbh,reset_gpio,0);
-+      reset_polarity=!(sb_gpioin(sbh)&reset_gpio);
-+
-+      diag_sysctl_header = register_sysctl_table(sys_diag, 0);
-+      diag_change();
-+
-+      return 0;
-+}
-+
-+static void __exit diag_exit()
-+{
-+      unregister_sysctl_table(diag_sysctl_header);
-+}
-+
-+EXPORT_NO_SYMBOLS;
-+MODULE_AUTHOR("openwrt.org");
-+MODULE_LICENSE("GPL");
-+
-+module_init(diag_init);
-+module_exit(diag_exit);
-diff -Nur linux-2.4.30/drivers/net/diag/Makefile linux-2.4.30-brcm/drivers/net/diag/Makefile
---- linux-2.4.30/drivers/net/diag/Makefile     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.4.30-brcm/drivers/net/diag/Makefile        2005-05-26 17:13:16.000000000 +0200
-@@ -0,0 +1,13 @@
-+#$Id$
-+
-+EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER
-+
-+O_TARGET       := diag.o
-+
-+MAC_OBJS       := diag_led.o
-+
-+export-objs    := 
-+obj-y          := $(MAC_OBJS)
-+obj-m          := $(O_TARGET)
-+
-+include $(TOPDIR)/Rules.make
 diff -Nur linux-2.4.30/drivers/net/et/Makefile linux-2.4.30-brcm/drivers/net/et/Makefile
 --- linux-2.4.30/drivers/net/et/Makefile       1970-01-01 01:00:00.000000000 +0100
 +++ linux-2.4.30-brcm/drivers/net/et/Makefile  2005-05-26 02:37:05.000000000 +0200
 diff -Nur linux-2.4.30/drivers/net/et/Makefile linux-2.4.30-brcm/drivers/net/et/Makefile
 --- linux-2.4.30/drivers/net/et/Makefile       1970-01-01 01:00:00.000000000 +0100
 +++ linux-2.4.30-brcm/drivers/net/et/Makefile  2005-05-26 02:37:05.000000000 +0200
diff --git a/target/linux/linux-2.4/patches/brcm/004-diag_led.patch b/target/linux/linux-2.4/patches/brcm/004-diag_led.patch
new file mode 100644 (file)
index 0000000..77fb289
--- /dev/null
@@ -0,0 +1,265 @@
+diff -Nur linux-2.4.30/drivers/net/diag/Makefile linux-2.4.30.openwrt/drivers/net/diag/Makefile
+--- linux-2.4.30/drivers/net/diag/Makefile     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30.openwrt/drivers/net/diag/Makefile     2005-06-28 11:35:26.000000000 +0200
+@@ -0,0 +1,13 @@
++#$Id$
++
++EXTRA_CFLAGS := -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER
++
++O_TARGET       := diag.o
++
++MAC_OBJS       := diag_led.o
++
++export-objs    := 
++obj-y          := $(MAC_OBJS)
++obj-m          := $(O_TARGET)
++
++include $(TOPDIR)/Rules.make
+diff -Nur linux-2.4.30/drivers/net/diag/diag_led.c linux-2.4.30.openwrt/drivers/net/diag/diag_led.c
+--- linux-2.4.30/drivers/net/diag/diag_led.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30.openwrt/drivers/net/diag/diag_led.c   2005-06-28 11:35:26.000000000 +0200
+@@ -0,0 +1,244 @@
++/*
++ * diag_led.c - replacement diag module
++ *
++ * Copyright (C) 2004 Mike Baker,
++ *                    Imre Kaloz <kaloz@dune.hu>
++ *
++ * 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.
++ *
++ * $Id: diag_led.c,v 1.5 2005/04/18 09:05:24 mbm Exp $
++ */
++
++/*
++ * ChangeLog:
++ * 2004/03/28 initial release 
++ * 2004/08/26 asus & buffalo support added
++ * 2005/03/14 asus wl-500g deluxe and buffalo v2 support added
++ * 2005/04/13 added licensing informations
++ * 2005/04/18 base reset polarity off initial readings
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sysctl.h>
++#include <asm/io.h>
++#include <typedefs.h>
++#include <bcmdevs.h>
++#include <sbutils.h>
++
++extern char * nvram_get(const char *name);
++static void *sbh;
++
++// v2.x - - - - -
++#define DIAG_GPIO (1<<1)
++#define DMZ_GPIO  (1<<7)
++
++static void set_gpio(uint32 mask, uint32 value) {
++      sb_gpiocontrol(sbh,mask,0);
++      sb_gpioouten(sbh,mask,mask);
++      sb_gpioout(sbh,mask,value);
++}
++
++static void v2_set_diag(u8 state) {
++      set_gpio(DIAG_GPIO,state);
++}
++static void v2_set_dmz(u8 state) {
++      set_gpio(DMZ_GPIO,state);
++}
++
++// v1.x - - - - -
++#define LED_DIAG   0x13
++#define LED_DMZ    0x12
++
++static void v1_set_diag(u8 state) {
++      if (!state) {
++              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF;
++      } else {
++              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG);
++      }
++}
++static void v1_set_dmz(u8 state) {
++      if (!state) {
++              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF;
++      } else {
++              *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ);
++      }
++}
++
++// - - - - -
++static void ignore(u8 ignored) {};
++
++// - - - - -
++#define BIT_DMZ         0x01
++#define BIT_DIAG        0x04
++
++void (*set_diag)(u8 state);
++void (*set_dmz)(u8 state);
++
++static unsigned int diag = 0;
++
++static void diag_change()
++{
++      set_diag(0xFF); // off
++      set_dmz(0xFF); // off
++
++      if(diag & BIT_DIAG)
++              set_diag(0x00); // on
++      if(diag & BIT_DMZ)
++              set_dmz(0x00); // on
++}
++
++static int proc_diag(ctl_table *table, int write, struct file *filp,
++              void *buffer, size_t *lenp)
++{
++      int r;
++      r = proc_dointvec(table, write, filp, buffer, lenp);
++      if (write && !r) {
++              diag_change();
++      }
++      return r;
++}
++
++// - - - - -
++static unsigned char reset_gpio = 0;
++static unsigned char reset_polarity = 0;
++static unsigned int reset = 0;
++
++static int proc_reset(ctl_table *table, int write, struct file *filp,
++              void *buffer, size_t *lenp)
++{
++
++      if (reset_gpio) {
++              sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
++              sb_gpioouten(sbh,reset_gpio,0);
++              reset=!(sb_gpioin(sbh)&reset_gpio);
++
++              if (reset_polarity) reset=!reset;
++      } else {
++              reset=0;
++      }
++
++      return proc_dointvec(table, write, filp, buffer, lenp);
++}
++
++// - - - - -
++static struct ctl_table_header *diag_sysctl_header;
++
++static ctl_table sys_diag[] = {
++         { 
++         ctl_name: 2000,
++         procname: "diag", 
++         data: &diag,
++         maxlen: sizeof(diag), 
++         mode: 0644,
++         proc_handler: proc_diag
++       },
++       {
++         ctl_name: 2001,
++         procname: "reset",
++         data: &reset,
++         maxlen: sizeof(reset),
++         mode: 0444,
++         proc_handler: proc_reset 
++       },
++         { 0 }
++};
++
++static int __init diag_init()
++{
++      char *buf;
++      u32 board_type;
++      sbh = sb_kattach();
++      sb_gpiosetcore(sbh);
++
++      board_type = sb_boardtype(sbh);
++      printk(KERN_INFO "diag boardtype: %08x\n",board_type);
++
++      set_diag=ignore;
++      set_dmz=ignore;
++      
++      if ((board_type & 0xf00) == 0x400) {
++              buf=nvram_get("boardtype")?:"";
++              if (!strcmp(buf,"bcm94710dev")) {
++                      buf=nvram_get("boardnum")?:"";
++                      if (!strcmp(buf,"42")) {
++                              // wrt54g v1.x
++                              set_diag=v1_set_diag;
++                              set_dmz=v1_set_dmz;
++                              reset_gpio=(1<<6);
++                      }
++                      if (!strcmp(buf,"asusX")) {
++                              //asus wl-500g
++                              reset_gpio=(1<<6);
++                      }
++              }
++              if (!strcmp(buf,"bcm94710ap")) {
++                      buf=nvram_get("boardnum")?:"";
++                      if (!strcmp(buf,"42")) {
++                              // buffalo
++                              set_dmz=v2_set_dmz;
++                              reset_gpio=(1<<4);
++                      }
++                      if (!strcmp(buf,"44")) {
++                              //dell truemobile
++                              set_dmz=v2_set_dmz;
++                              reset_gpio=(1<<0);
++                      }
++              }
++      } else {
++              buf=nvram_get("boardnum")?:"";
++              if (!strcmp(buf,"42")) {
++                      //linksys
++                      set_diag=v2_set_diag;
++                      set_dmz=v2_set_dmz;
++                      reset_gpio=(1<<6);
++              }
++              if (!strcmp(buf,"44")) {
++                      //motorola
++                      reset_gpio=(1<<5);
++              }
++              if (!strcmp(buf,"00")) {
++                      //buffalo
++                      reset_gpio=(1<<7);
++              }
++              if (!strcmp(buf,"45")) {
++                      //wl-500g deluxe
++                      reset_gpio=(1<<6);
++              }
++      }
++
++      
++      sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
++      sb_gpioouten(sbh,reset_gpio,0);
++      reset_polarity=!(sb_gpioin(sbh)&reset_gpio);
++
++      diag_sysctl_header = register_sysctl_table(sys_diag, 0);
++      diag_change();
++
++      return 0;
++}
++
++static void __exit diag_exit()
++{
++      unregister_sysctl_table(diag_sysctl_header);
++}
++
++EXPORT_NO_SYMBOLS;
++MODULE_AUTHOR("openwrt.org");
++MODULE_LICENSE("GPL");
++
++module_init(diag_init);
++module_exit(diag_exit);
diff --git a/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch b/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch
new file mode 100644 (file)
index 0000000..9115b9f
--- /dev/null
@@ -0,0 +1,925 @@
+diff -Nur linux-2.4.30/drivers/mtd/chips/Config.in linux-2.4.30.openwrt/drivers/mtd/chips/Config.in
+--- linux-2.4.30/drivers/mtd/chips/Config.in   2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/Config.in   2005-06-28 11:26:26.000000000 +0200
+@@ -45,6 +45,7 @@
+ dep_tristate '  Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_GEN_PROBE
+ dep_tristate '  Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_GEN_PROBE
+ dep_tristate '  Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE
++dep_tristate '  Support for SST flash chips' CONFIG_MTD_CFI_SSTSTD $CONFIG_MTD_GEN_PROBE
+ dep_tristate '  Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD
+ dep_tristate '  Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD
+diff -Nur linux-2.4.30/drivers/mtd/chips/Makefile linux-2.4.30.openwrt/drivers/mtd/chips/Makefile
+--- linux-2.4.30/drivers/mtd/chips/Makefile    2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/Makefile    2005-06-28 11:26:26.000000000 +0200
+@@ -18,6 +18,7 @@
+ obj-$(CONFIG_MTD_AMDSTD)      += amd_flash.o 
+ obj-$(CONFIG_MTD_CFI)         += cfi_probe.o
+ obj-$(CONFIG_MTD_CFI_STAA)    += cfi_cmdset_0020.o
++obj-$(CONFIG_MTD_CFI_SSTSTD)   += cfi_cmdset_0701.o
+ obj-$(CONFIG_MTD_CFI_AMDSTD)  += cfi_cmdset_0002.o
+ obj-$(CONFIG_MTD_CFI_INTELEXT)        += cfi_cmdset_0001.o
+ obj-$(CONFIG_MTD_GEN_PROBE)   += gen_probe.o
+diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c linux-2.4.30.openwrt/drivers/mtd/chips/cfi_cmdset_0701.c
+--- linux-2.4.30/drivers/mtd/chips/cfi_cmdset_0701.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.30.openwrt/drivers/mtd/chips/cfi_cmdset_0701.c   2005-06-28 11:26:26.000000000 +0200
+@@ -0,0 +1,855 @@
++/*
++ * Common Flash Interface support:
++ *   SST Standard Vendor Command Set (ID 0x0701)
++ *
++ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
++ *
++ * 2_by_8 routines added by Simon Munton
++ *
++ * This code is GPL
++ *
++ * $Id: cfi_cmdset_0701.c,v 1.1 2005/03/16 13:50:00 wbx Exp $
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <asm/io.h>
++#include <asm/byteorder.h>
++
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/cfi.h>
++
++static int cfi_sststd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
++static int cfi_sststd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
++static int cfi_sststd_erase_onesize(struct mtd_info *, struct erase_info *);
++static int cfi_sststd_erase_varsize(struct mtd_info *, struct erase_info *);
++static void cfi_sststd_sync (struct mtd_info *);
++static int cfi_sststd_suspend (struct mtd_info *);
++static void cfi_sststd_resume (struct mtd_info *);
++
++static void cfi_sststd_destroy(struct mtd_info *);
++
++struct mtd_info *cfi_cmdset_0701(struct map_info *, int);
++static struct mtd_info *cfi_sststd_setup (struct map_info *);
++
++
++static struct mtd_chip_driver cfi_sststd_chipdrv = {
++      probe: NULL, /* Not usable directly */
++      destroy: cfi_sststd_destroy,
++      name: "cfi_cmdset_0701",
++      module: THIS_MODULE
++};
++
++struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary)
++{
++      struct cfi_private *cfi = map->fldrv_priv;
++      int ofs_factor = cfi->interleave * cfi->device_type;
++      int i;
++      __u8 major, minor;
++      __u32 base = cfi->chips[0].start;
++
++      if (cfi->cfi_mode==1){
++              __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
++
++              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              
++              major = cfi_read_query(map, base + (adr+3)*ofs_factor);
++              minor = cfi_read_query(map, base + (adr+4)*ofs_factor);
++              
++              printk(" SST Query Table v%c.%c at 0x%4.4X\n",
++                     major, minor, adr);
++              cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              
++              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x90, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              cfi->mfr = cfi_read_query(map, base);
++              cfi->id = cfi_read_query(map, base + ofs_factor);
++
++              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              
++              switch (cfi->device_type) {
++              case CFI_DEVICETYPE_X16:
++                      cfi->addr_unlock1 = 0x5555;
++                      cfi->addr_unlock2 = 0x2AAA;
++                      break;
++              default:
++                      printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0701 device type %d\n", cfi->device_type);
++                      return NULL;
++              }
++      } /* CFI mode */
++
++      for (i=0; i< cfi->numchips; i++) {
++              cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
++              cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
++              cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
++      }               
++      
++      map->fldrv = &cfi_sststd_chipdrv;
++      MOD_INC_USE_COUNT;
++
++      cfi_send_gen_cmd(0xf0, 0x5555, base, map, cfi, cfi->device_type, NULL);
++      return cfi_sststd_setup(map);
++}
++
++static struct mtd_info *cfi_sststd_setup(struct map_info *map)
++{
++      struct cfi_private *cfi = map->fldrv_priv;
++      struct mtd_info *mtd;
++      unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
++
++      mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
++      printk("number of %s chips: %d\n", (cfi->cfi_mode)?"JEDEC":"CFI",cfi->numchips);
++
++      if (!mtd) {
++        printk("Failed to allocate memory for MTD device\n");
++        kfree(cfi->cmdset_priv);
++        return NULL;
++      }
++
++      memset(mtd, 0, sizeof(*mtd));
++      mtd->priv = map;
++      mtd->type = MTD_NORFLASH;
++      /* Also select the correct geometry setup too */ 
++      mtd->size = devsize * cfi->numchips;
++      
++      if (cfi->cfiq->NumEraseRegions == 1) {
++              /* No need to muck about with multiple erase sizes */
++              mtd->erasesize = ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi->interleave;
++      } else {
++              unsigned long offset = 0;
++              int i,j;
++
++              mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
++              mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions, GFP_KERNEL);
++              if (!mtd->eraseregions) { 
++                      printk("Failed to allocate memory for MTD erase region info\n");
++                      kfree(cfi->cmdset_priv);
++                      return NULL;
++              }
++                      
++              for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
++                      unsigned long ernum, ersize;
++                      ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
++                      ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
++                      
++                      if (mtd->erasesize < ersize) {
++                              mtd->erasesize = ersize;
++                      }
++                      for (j=0; j<cfi->numchips; j++) {
++                              mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
++                              mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
++                              mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
++                      }
++                      offset += (ersize * ernum);
++              }
++
++              // debug
++              for (i=0; i<mtd->numeraseregions;i++){
++                      printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
++                             i,mtd->eraseregions[i].offset,
++                             mtd->eraseregions[i].erasesize,
++                             mtd->eraseregions[i].numblocks);
++              }
++      }
++
++      switch (CFIDEV_BUSWIDTH)
++      {
++      case 1:
++      case 2:
++      case 4:
++              if (mtd->numeraseregions > 1)
++                      mtd->erase = cfi_sststd_erase_varsize;
++              else
++                      mtd->erase = cfi_sststd_erase_onesize;
++              mtd->read = cfi_sststd_read;
++              mtd->write = cfi_sststd_write;
++              break;
++
++      default:
++              printk("Unsupported buswidth\n");
++              kfree(mtd);
++              kfree(cfi->cmdset_priv);
++              return NULL;
++              break;
++      }
++      mtd->sync = cfi_sststd_sync;
++      mtd->suspend = cfi_sststd_suspend;
++      mtd->resume = cfi_sststd_resume;
++      mtd->flags = MTD_CAP_NORFLASH;
++      map->fldrv = &cfi_sststd_chipdrv;
++      mtd->name = map->name;
++      MOD_INC_USE_COUNT;
++      return mtd;
++}
++
++static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
++{
++      DECLARE_WAITQUEUE(wait, current);
++      unsigned long timeo = jiffies + HZ;
++
++ retry:
++      cfi_spin_lock(chip->mutex);
++
++      if (chip->state != FL_READY){
++              printk("Waiting for chip to read, status = %d\n", chip->state);
++              set_current_state(TASK_UNINTERRUPTIBLE);
++              add_wait_queue(&chip->wq, &wait);
++                
++              cfi_spin_unlock(chip->mutex);
++
++              schedule();
++              remove_wait_queue(&chip->wq, &wait);
++              timeo = jiffies + HZ;
++
++              goto retry;
++      }       
++
++      adr += chip->start;
++
++      chip->state = FL_READY;
++
++      map->copy_from(map, buf, adr, len);
++
++      wake_up(&chip->wq);
++      cfi_spin_unlock(chip->mutex);
++
++      return 0;
++}
++
++static int cfi_sststd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      unsigned long ofs;
++      int chipnum;
++      int ret = 0;
++
++      /* ofs: offset within the first chip that the first read should start */
++
++      chipnum = (from >> cfi->chipshift);
++      ofs = from - (chipnum <<  cfi->chipshift);
++
++
++      *retlen = 0;
++
++      while (len) {
++              unsigned long thislen;
++
++              if (chipnum >= cfi->numchips)
++                      break;
++
++              if ((len + ofs -1) >> cfi->chipshift)
++                      thislen = (1<<cfi->chipshift) - ofs;
++              else
++                      thislen = len;
++
++              ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
++              if (ret)
++                      break;
++
++              *retlen += thislen;
++              len -= thislen;
++              buf += thislen;
++
++              ofs = 0;
++              chipnum++;
++      }
++      return ret;
++}
++
++static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum, int fast)
++{
++      unsigned long timeo = jiffies + HZ;
++      unsigned int Last[4];
++      unsigned long Count = 0;
++      struct cfi_private *cfi = map->fldrv_priv;
++      DECLARE_WAITQUEUE(wait, current);
++      int ret = 0;
++
++ retry:
++      cfi_spin_lock(chip->mutex);
++
++      if (chip->state != FL_READY){
++              printk("Waiting for chip to write, status = %d\n", chip->state);
++              set_current_state(TASK_UNINTERRUPTIBLE);
++              add_wait_queue(&chip->wq, &wait);
++                
++              cfi_spin_unlock(chip->mutex);
++
++              schedule();
++              remove_wait_queue(&chip->wq, &wait);
++              printk("Wake up to write:\n");
++              timeo = jiffies + HZ;
++
++              goto retry;
++      }       
++
++      chip->state = FL_WRITING;
++
++      adr += chip->start;
++      ENABLE_VPP(map);
++    cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++    cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++    cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++
++      cfi_write(map, datum, adr);
++
++      cfi_spin_unlock(chip->mutex);
++      cfi_udelay(chip->word_write_time);
++      cfi_spin_lock(chip->mutex);
++
++      Last[0] = cfi_read(map, adr);
++      //      printk("Last[0] is %x\n", Last[0]);
++      Last[1] = cfi_read(map, adr);
++      //      printk("Last[1] is %x\n", Last[1]);
++      Last[2] = cfi_read(map, adr);
++      //      printk("Last[2] is %x\n", Last[2]);
++
++      for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
++              cfi_spin_unlock(chip->mutex);
++              cfi_udelay(10);
++              cfi_spin_lock(chip->mutex);
++              
++              Last[Count % 4] = cfi_read(map, adr);
++              //              printk("Last[%d%%4] is %x\n", Count, Last[Count%4]);
++      }
++      
++      if (Last[(Count - 1) % 4] != datum){
++              printk("Last[%ld] is %x, datum is %x\n",(Count - 1) % 4,Last[(Count - 1) % 4],datum);
++              cfi_send_gen_cmd(0xF0, 0, chip->start, map, cfi, cfi->device_type, NULL);
++              DISABLE_VPP(map);
++              ret = -EIO;
++      }       
++      DISABLE_VPP(map);
++      chip->state = FL_READY;
++      wake_up(&chip->wq);
++      cfi_spin_unlock(chip->mutex);
++      
++      return ret;
++}
++
++static int cfi_sststd_write (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      int ret = 0;
++      int chipnum;
++      unsigned long ofs, chipstart;
++
++      *retlen = 0;
++      if (!len)
++              return 0;
++
++      chipnum = to >> cfi->chipshift;
++      ofs = to  - (chipnum << cfi->chipshift);
++      chipstart = cfi->chips[chipnum].start;
++
++      /* If it's not bus-aligned, do the first byte write */
++      if (ofs & (CFIDEV_BUSWIDTH-1)) {
++              unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
++              int i = ofs - bus_ofs;
++              int n = 0;
++              u_char tmp_buf[4];
++              __u32 datum;
++
++              map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
++              while (len && i < CFIDEV_BUSWIDTH)
++                      tmp_buf[i++] = buf[n++], len--;
++
++              if (cfi_buswidth_is_2()) {
++                      datum = *(__u16*)tmp_buf;
++              } else if (cfi_buswidth_is_4()) {
++                      datum = *(__u32*)tmp_buf;
++              } else {
++                      return -EINVAL;  /* should never happen, but be safe */
++              }
++
++              ret = do_write_oneword(map, &cfi->chips[chipnum], 
++                              bus_ofs, datum, 0);
++              if (ret) 
++                      return ret;
++              
++              ofs += n;
++              buf += n;
++              (*retlen) += n;
++
++              if (ofs >> cfi->chipshift) {
++                      chipnum ++; 
++                      ofs = 0;
++                      if (chipnum == cfi->numchips)
++                              return 0;
++              }
++      }
++      
++      /* We are now aligned, write as much as possible */
++      while(len >= CFIDEV_BUSWIDTH) {
++              __u32 datum;
++
++              if (cfi_buswidth_is_1()) {
++                      datum = *(__u8*)buf;
++              } else if (cfi_buswidth_is_2()) {
++                      datum = *(__u16*)buf;
++              } else if (cfi_buswidth_is_4()) {
++                      datum = *(__u32*)buf;
++              } else {
++                      return -EINVAL;
++              }
++              ret = do_write_oneword(map, &cfi->chips[chipnum],
++                                     ofs, datum, cfi->fast_prog);
++              if (ret) {
++                      return ret;
++              }
++
++              ofs += CFIDEV_BUSWIDTH;
++              buf += CFIDEV_BUSWIDTH;
++              (*retlen) += CFIDEV_BUSWIDTH;
++              len -= CFIDEV_BUSWIDTH;
++
++              if (ofs >> cfi->chipshift) {
++                      chipnum ++; 
++                      ofs = 0;
++                      if (chipnum == cfi->numchips)
++                              return 0;
++                      chipstart = cfi->chips[chipnum].start;
++              }
++      }
++
++      if (len & (CFIDEV_BUSWIDTH-1)) {
++              int i = 0, n = 0;
++              u_char tmp_buf[4];
++              __u32 datum;
++
++              map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
++              while (len--)
++                      tmp_buf[i++] = buf[n++];
++
++              if (cfi_buswidth_is_2()) {
++                      datum = *(__u16*)tmp_buf;
++              } else if (cfi_buswidth_is_4()) {
++                      datum = *(__u32*)tmp_buf;
++              } else {
++                      return -EINVAL;  /* should never happen, but be safe */
++              }
++
++              ret = do_write_oneword(map, &cfi->chips[chipnum], 
++                              ofs, datum, 0);
++              if (ret) 
++                      return ret;
++              
++              (*retlen) += n;
++      }
++
++      return 0;
++}
++
++static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
++{
++      unsigned int status;
++      unsigned long timeo = jiffies + HZ;
++      struct cfi_private *cfi = map->fldrv_priv;
++      unsigned int rdy_mask;
++      DECLARE_WAITQUEUE(wait, current);
++
++ retry:
++      cfi_spin_lock(chip->mutex);
++
++      if (chip->state != FL_READY){
++              set_current_state(TASK_UNINTERRUPTIBLE);
++              add_wait_queue(&chip->wq, &wait);
++                
++              cfi_spin_unlock(chip->mutex);
++
++              schedule();
++              remove_wait_queue(&chip->wq, &wait);
++              timeo = jiffies + HZ;
++
++              goto retry;
++      }       
++
++      chip->state = FL_ERASING;
++
++      adr += chip->start;
++      ENABLE_VPP(map);
++      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++      cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++      cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++      cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X16, NULL);
++      cfi_write(map, CMD(0x30), adr);
++      
++      timeo = jiffies + (HZ*20);
++
++      cfi_spin_unlock(chip->mutex);
++      schedule_timeout(HZ);
++      cfi_spin_lock(chip->mutex);
++      
++      rdy_mask = CMD(0x80);
++
++      /* Once the state machine's known to be working I'll do that */
++
++      while ( ( (status = cfi_read(map,adr)) & rdy_mask ) != rdy_mask ) {
++              static int z=0;
++
++              if (chip->state != FL_ERASING) {
++                      /* Someone's suspended the erase. Sleep */
++                      set_current_state(TASK_UNINTERRUPTIBLE);
++                      add_wait_queue(&chip->wq, &wait);
++                      
++                      cfi_spin_unlock(chip->mutex);
++                      printk("erase suspended. Sleeping\n");
++                      
++                      schedule();
++                      remove_wait_queue(&chip->wq, &wait);
++                      timeo = jiffies + (HZ*2); 
++                      cfi_spin_lock(chip->mutex);
++                      continue;
++              }
++
++              /* OK Still waiting */
++              if (time_after(jiffies, timeo)) {
++                      chip->state = FL_READY;
++                      cfi_spin_unlock(chip->mutex);
++                      printk("waiting for erase to complete timed out.");
++                      DISABLE_VPP(map);
++                      return -EIO;
++              }
++              
++              /* Latency issues. Drop the lock, wait a while and retry */
++              cfi_spin_unlock(chip->mutex);
++
++              z++;
++              if ( 0 && !(z % 100 )) 
++                      printk("chip not ready yet after erase. looping\n");
++
++              cfi_udelay(1);
++              
++              cfi_spin_lock(chip->mutex);
++              continue;
++      }
++      
++      /* Done and happy. */
++      DISABLE_VPP(map);
++      chip->state = FL_READY;
++      wake_up(&chip->wq);
++      cfi_spin_unlock(chip->mutex);
++      return 0;
++}
++
++static int cfi_sststd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      unsigned long adr, len;
++      int chipnum, ret = 0;
++      int i, first;
++      struct mtd_erase_region_info *regions = mtd->eraseregions;
++
++      if (instr->addr > mtd->size)
++              return -EINVAL;
++
++      if ((instr->len + instr->addr) > mtd->size)
++              return -EINVAL;
++
++      /* Check that both start and end of the requested erase are
++       * aligned with the erasesize at the appropriate addresses.
++       */
++
++      i = 0;
++
++      /* Skip all erase regions which are ended before the start of 
++         the requested erase. Actually, to save on the calculations,
++         we skip to the first erase region which starts after the
++         start of the requested erase, and then go back one.
++      */
++      
++      while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
++             i++;
++      i--;
++
++      /* OK, now i is pointing at the erase region in which this 
++         erase request starts. Check the start of the requested
++         erase range is aligned with the erase size which is in
++         effect here.
++      */
++
++      if (instr->addr & (regions[i].erasesize-1))
++              return -EINVAL;
++
++      /* Remember the erase region we start on */
++      first = i;
++
++      /* Next, check that the end of the requested erase is aligned
++       * with the erase region at that address.
++       */
++
++      while (i<mtd->numeraseregions && (instr->addr + instr->len) >= regions[i].offset)
++              i++;
++
++      /* As before, drop back one to point at the region in which
++         the address actually falls
++      */
++      i--;
++      
++      if ((instr->addr + instr->len) & (regions[i].erasesize-1))
++              return -EINVAL;
++      
++      chipnum = instr->addr >> cfi->chipshift;
++      adr = instr->addr - (chipnum << cfi->chipshift);
++      len = instr->len;
++
++      i=first;
++
++      while(len) {
++              ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
++
++              if (ret)
++                      return ret;
++
++              adr += regions[i].erasesize;
++              len -= regions[i].erasesize;
++
++              if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
++                      i++;
++
++              if (adr >> cfi->chipshift) {
++                      adr = 0;
++                      chipnum++;
++                      
++                      if (chipnum >= cfi->numchips)
++                      break;
++              }
++      }
++
++      instr->state = MTD_ERASE_DONE;
++      if (instr->callback)
++              instr->callback(instr);
++      
++      return 0;
++}
++
++static int cfi_sststd_erase_onesize(struct mtd_info *mtd, struct erase_info *instr)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      unsigned long adr, len;
++      int chipnum, ret = 0;
++
++      if (instr->addr & (mtd->erasesize - 1))
++              return -EINVAL;
++
++      if (instr->len & (mtd->erasesize -1))
++              return -EINVAL;
++
++      if ((instr->len + instr->addr) > mtd->size)
++              return -EINVAL;
++
++      chipnum = instr->addr >> cfi->chipshift;
++      adr = instr->addr - (chipnum << cfi->chipshift);
++      len = instr->len;
++
++      while(len) {
++              ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
++
++              if (ret)
++                      return ret;
++
++              adr += mtd->erasesize;
++              len -= mtd->erasesize;
++
++              if (adr >> cfi->chipshift) {
++                      adr = 0;
++                      chipnum++;
++                      
++                      if (chipnum >= cfi->numchips)
++                      break;
++              }
++      }
++              
++      instr->state = MTD_ERASE_DONE;
++      if (instr->callback)
++              instr->callback(instr);
++      
++      return 0;
++}
++
++static void cfi_sststd_sync (struct mtd_info *mtd)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      int i;
++      struct flchip *chip;
++      int ret = 0;
++      DECLARE_WAITQUEUE(wait, current);
++
++      for (i=0; !ret && i<cfi->numchips; i++) {
++              chip = &cfi->chips[i];
++
++      retry:
++              cfi_spin_lock(chip->mutex);
++
++              switch(chip->state) {
++              case FL_READY:
++              case FL_STATUS:
++              case FL_CFI_QUERY:
++              case FL_JEDEC_QUERY:
++                      chip->oldstate = chip->state;
++                      chip->state = FL_SYNCING;
++                      /* No need to wake_up() on this state change - 
++                       * as the whole point is that nobody can do anything
++                       * with the chip now anyway.
++                       */
++              case FL_SYNCING:
++                      cfi_spin_unlock(chip->mutex);
++                      break;
++
++              default:
++                      /* Not an idle state */
++                      add_wait_queue(&chip->wq, &wait);
++                      
++                      cfi_spin_unlock(chip->mutex);
++
++                      schedule();
++
++                      remove_wait_queue(&chip->wq, &wait);
++                      
++                      goto retry;
++              }
++      }
++
++      /* Unlock the chips again */
++
++      for (i--; i >=0; i--) {
++              chip = &cfi->chips[i];
++
++              cfi_spin_lock(chip->mutex);
++              
++              if (chip->state == FL_SYNCING) {
++                      chip->state = chip->oldstate;
++                      wake_up(&chip->wq);
++              }
++              cfi_spin_unlock(chip->mutex);
++      }
++}
++
++
++static int cfi_sststd_suspend(struct mtd_info *mtd)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      int i;
++      struct flchip *chip;
++      int ret = 0;
++//printk("suspend\n");
++
++      for (i=0; !ret && i<cfi->numchips; i++) {
++              chip = &cfi->chips[i];
++
++              cfi_spin_lock(chip->mutex);
++
++              switch(chip->state) {
++              case FL_READY:
++              case FL_STATUS:
++              case FL_CFI_QUERY:
++              case FL_JEDEC_QUERY:
++                      chip->oldstate = chip->state;
++                      chip->state = FL_PM_SUSPENDED;
++                      /* No need to wake_up() on this state change - 
++                       * as the whole point is that nobody can do anything
++                       * with the chip now anyway.
++                       */
++              case FL_PM_SUSPENDED:
++                      break;
++
++              default:
++                      ret = -EAGAIN;
++                      break;
++              }
++              cfi_spin_unlock(chip->mutex);
++      }
++
++      /* Unlock the chips again */
++
++      if (ret) {
++              for (i--; i >=0; i--) {
++                      chip = &cfi->chips[i];
++
++                      cfi_spin_lock(chip->mutex);
++              
++                      if (chip->state == FL_PM_SUSPENDED) {
++                              chip->state = chip->oldstate;
++                              wake_up(&chip->wq);
++                      }
++                      cfi_spin_unlock(chip->mutex);
++              }
++      }
++      
++      return ret;
++}
++
++static void cfi_sststd_resume(struct mtd_info *mtd)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      int i;
++      struct flchip *chip;
++//printk("resume\n");
++
++      for (i=0; i<cfi->numchips; i++) {
++      
++              chip = &cfi->chips[i];
++
++              cfi_spin_lock(chip->mutex);
++              
++              if (chip->state == FL_PM_SUSPENDED) {
++                      chip->state = FL_READY;
++                      cfi_write(map, CMD(0xF0), chip->start);
++                      wake_up(&chip->wq);
++              }
++              else
++                      printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
++
++              cfi_spin_unlock(chip->mutex);
++      }
++}
++
++static void cfi_sststd_destroy(struct mtd_info *mtd)
++{
++      struct map_info *map = mtd->priv;
++      struct cfi_private *cfi = map->fldrv_priv;
++      kfree(cfi->cmdset_priv);
++      kfree(cfi);
++}
++
++#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
++#define cfi_sststd_init init_module
++#define cfi_sststd_exit cleanup_module
++#endif
++
++static char im_name[]="cfi_cmdset_0701";
++
++mod_init_t cfi_sststd_init(void)
++{
++      inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0701);
++      return 0;
++}
++
++mod_exit_t cfi_sststd_exit(void)
++{
++      inter_module_unregister(im_name);
++}
++
++module_init(cfi_sststd_init);
++module_exit(cfi_sststd_exit);
++
+diff -Nur linux-2.4.30/drivers/mtd/chips/cfi_probe.c linux-2.4.30.openwrt/drivers/mtd/chips/cfi_probe.c
+--- linux-2.4.30/drivers/mtd/chips/cfi_probe.c 2003-06-13 16:51:34.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/cfi_probe.c 2005-06-28 11:26:26.000000000 +0200
+@@ -67,8 +67,15 @@
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+-      if (!qry_present(map,base,cfi))
+-              return 0;
++      if (!qry_present(map,base,cfi)) {
++              /* rather broken SST cfi probe (requires SST unlock) */
++              cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
++              cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
++              if (!qry_present(map,base,cfi))
++                      return 0;
++      }
+       if (!cfi->numchips) {
+               /* This is the first time we're called. Set up the CFI 
+diff -Nur linux-2.4.30/drivers/mtd/chips/gen_probe.c linux-2.4.30.openwrt/drivers/mtd/chips/gen_probe.c
+--- linux-2.4.30/drivers/mtd/chips/gen_probe.c 2003-08-25 13:44:42.000000000 +0200
++++ linux-2.4.30.openwrt/drivers/mtd/chips/gen_probe.c 2005-06-28 11:29:23.000000000 +0200
+@@ -328,13 +328,18 @@
+               return cfi_cmdset_0001(map, primary);
+ #endif
+ #ifdef CONFIG_MTD_CFI_AMDSTD
++      case 0x0006:
+       case 0x0002:
+               return cfi_cmdset_0002(map, primary);
+ #endif
+ #ifdef CONFIG_MTD_CFI_STAA
+-        case 0x0020:
++      case 0x0020:
+               return cfi_cmdset_0020(map, primary);
+ #endif
++#ifdef CONFIG_MTD_CFI_SSTSTD
++      case 0x0701:
++              return cfi_cmdset_0701(map, primary);
++#endif
+       }
+       return cfi_cmdset_unknown(map, primary);
diff --git a/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch b/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch
deleted file mode 100644 (file)
index 782a9ce..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
---- linux-2.4.30.old/arch/mips/ld.script.in      2005-04-28 23:22:23.513764016 +0400
-+++ linux-2.4.30/arch/mips/ld.script.in   2005-04-28 23:22:36.329673152 +0400
-@@ -9,6 +9,7 @@
-   {
-     _ftext = . ;
-     *(.text)
-+    *(.fixup)
-     *(.rodata)
-     *(.rodata.*)
-     *(.rodata1)
index 27adbf1..9cf0553 100644 (file)
@@ -1,6 +1,6 @@
-diff -Nur linux-2.4.29/arch/mips/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips/kernel/signal.c
---- linux-2.4.29/arch/mips/kernel/signal.c     2005-01-19 15:09:29.000000000 +0100
-+++ linux-2.4.29-gcc3.4/arch/mips/kernel/signal.c      2005-03-27 23:09:57.000000000 +0200
+diff -Nur linux-2.4.30/arch/mips/kernel/signal.c linux-2.4.30.openwrt/arch/mips/kernel/signal.c
+--- linux-2.4.30/arch/mips/kernel/signal.c     2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips/kernel/signal.c     2005-07-02 13:00:49.000000000 +0200
 @@ -6,8 +6,10 @@
   * Copyright (C) 1991, 1992  Linus Torvalds
   * Copyright (C) 1994 - 1999  Ralf Baechle
 @@ -6,8 +6,10 @@
   * Copyright (C) 1991, 1992  Linus Torvalds
   * Copyright (C) 1994 - 1999  Ralf Baechle
@@ -34,9 +34,9 @@ diff -Nur linux-2.4.29/arch/mips/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips/k
  {
        sigset_t *unewset, saveset, newset;
          size_t sigsetsize;
  {
        sigset_t *unewset, saveset, newset;
          size_t sigsetsize;
-diff -Nur linux-2.4.29/arch/mips/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mips/kernel/syscall.c
---- linux-2.4.29/arch/mips/kernel/syscall.c    2005-01-19 15:09:29.000000000 +0100
-+++ linux-2.4.29-gcc3.4/arch/mips/kernel/syscall.c     2005-03-27 23:09:57.000000000 +0200
+diff -Nur linux-2.4.30/arch/mips/kernel/syscall.c linux-2.4.30.openwrt/arch/mips/kernel/syscall.c
+--- linux-2.4.30/arch/mips/kernel/syscall.c    2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips/kernel/syscall.c    2005-07-02 13:00:49.000000000 +0200
 @@ -5,6 +5,7 @@
   *
   * Copyright (C) 1995 - 2000 by Ralf Baechle
 @@ -5,6 +5,7 @@
   *
   * Copyright (C) 1995 - 2000 by Ralf Baechle
@@ -67,9 +67,20 @@ diff -Nur linux-2.4.29/arch/mips/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mips/
  {
        unsigned long clone_flags;
        unsigned long newsp;
  {
        unsigned long clone_flags;
        unsigned long newsp;
-diff -Nur linux-2.4.29/arch/mips64/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips64/kernel/signal.c
---- linux-2.4.29/arch/mips64/kernel/signal.c   2005-01-19 15:09:32.000000000 +0100
-+++ linux-2.4.29-gcc3.4/arch/mips64/kernel/signal.c    2005-03-27 23:09:57.000000000 +0200
+diff -Nur linux-2.4.30/arch/mips/ld.script.in linux-2.4.30.openwrt/arch/mips/ld.script.in
+--- linux-2.4.30/arch/mips/ld.script.in        2005-07-02 13:00:22.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips/ld.script.in        2005-07-02 13:00:42.000000000 +0200
+@@ -9,6 +9,7 @@
+   {
+     _ftext = . ;
+     *(.text)
++    *(.fixup)
+     *(.rodata)
+     *(.rodata.*)
+     *(.rodata1)
+diff -Nur linux-2.4.30/arch/mips64/kernel/signal.c linux-2.4.30.openwrt/arch/mips64/kernel/signal.c
+--- linux-2.4.30/arch/mips64/kernel/signal.c   2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips64/kernel/signal.c   2005-07-02 13:00:49.000000000 +0200
 @@ -6,8 +6,10 @@
   * Copyright (C) 1991, 1992  Linus Torvalds
   * Copyright (C) 1994 - 2000  Ralf Baechle
 @@ -6,8 +6,10 @@
   * Copyright (C) 1991, 1992  Linus Torvalds
   * Copyright (C) 1994 - 2000  Ralf Baechle
@@ -92,9 +103,9 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/signal.c linux-2.4.29-gcc3.4/arch/mips
  {
        sigset_t *unewset, saveset, newset;
          size_t sigsetsize;
  {
        sigset_t *unewset, saveset, newset;
          size_t sigsetsize;
-diff -Nur linux-2.4.29/arch/mips64/kernel/signal32.c linux-2.4.29-gcc3.4/arch/mips64/kernel/signal32.c
---- linux-2.4.29/arch/mips64/kernel/signal32.c 2005-01-19 15:09:33.000000000 +0100
-+++ linux-2.4.29-gcc3.4/arch/mips64/kernel/signal32.c  2005-03-27 23:09:57.000000000 +0200
+diff -Nur linux-2.4.30/arch/mips64/kernel/signal32.c linux-2.4.30.openwrt/arch/mips64/kernel/signal32.c
+--- linux-2.4.30/arch/mips64/kernel/signal32.c 2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips64/kernel/signal32.c 2005-07-02 13:00:49.000000000 +0200
 @@ -6,7 +6,9 @@
   * Copyright (C) 1991, 1992  Linus Torvalds
   * Copyright (C) 1994 - 2000  Ralf Baechle
 @@ -6,7 +6,9 @@
   * Copyright (C) 1991, 1992  Linus Torvalds
   * Copyright (C) 1994 - 2000  Ralf Baechle
@@ -127,9 +138,9 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/signal32.c linux-2.4.29-gcc3.4/arch/mi
  {
        sigset32_t *uset;
        sigset_t newset, saveset;
  {
        sigset32_t *uset;
        sigset_t newset, saveset;
-diff -Nur linux-2.4.29/arch/mips64/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mips64/kernel/syscall.c
---- linux-2.4.29/arch/mips64/kernel/syscall.c  2005-01-19 15:09:33.000000000 +0100
-+++ linux-2.4.29-gcc3.4/arch/mips64/kernel/syscall.c   2005-03-27 23:09:57.000000000 +0200
+diff -Nur linux-2.4.30/arch/mips64/kernel/syscall.c linux-2.4.30.openwrt/arch/mips64/kernel/syscall.c
+--- linux-2.4.30/arch/mips64/kernel/syscall.c  2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/arch/mips64/kernel/syscall.c  2005-07-02 13:00:49.000000000 +0200
 @@ -6,7 +6,9 @@
   * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
   * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
 @@ -6,7 +6,9 @@
   * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
   * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
@@ -162,9 +173,9 @@ diff -Nur linux-2.4.29/arch/mips64/kernel/syscall.c linux-2.4.29-gcc3.4/arch/mip
  {
        unsigned long clone_flags;
        unsigned long newsp;
  {
        unsigned long clone_flags;
        unsigned long newsp;
-diff -Nur linux-2.4.29/include/asm-mips/ptrace.h linux-2.4.29-gcc3.4/include/asm-mips/ptrace.h
---- linux-2.4.29/include/asm-mips/ptrace.h     2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.29-gcc3.4/include/asm-mips/ptrace.h      2005-03-27 23:09:57.000000000 +0200
+diff -Nur linux-2.4.30/include/asm-mips/ptrace.h linux-2.4.30.openwrt/include/asm-mips/ptrace.h
+--- linux-2.4.30/include/asm-mips/ptrace.h     2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/include/asm-mips/ptrace.h     2005-07-02 13:00:49.000000000 +0200
 @@ -4,6 +4,7 @@
   * for more details.
   *
 @@ -4,6 +4,7 @@
   * for more details.
   *
@@ -187,9 +198,9 @@ diff -Nur linux-2.4.29/include/asm-mips/ptrace.h linux-2.4.29-gcc3.4/include/asm
  #endif /* !__ASSEMBLY__ */
  
  /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
  #endif /* !__ASSEMBLY__ */
  
  /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-diff -Nur linux-2.4.29/include/asm-mips64/ptrace.h linux-2.4.29-gcc3.4/include/asm-mips64/ptrace.h
---- linux-2.4.29/include/asm-mips64/ptrace.h   2004-02-18 14:36:32.000000000 +0100
-+++ linux-2.4.29-gcc3.4/include/asm-mips64/ptrace.h    2005-03-27 23:09:57.000000000 +0200
+diff -Nur linux-2.4.30/include/asm-mips64/ptrace.h linux-2.4.30.openwrt/include/asm-mips64/ptrace.h
+--- linux-2.4.30/include/asm-mips64/ptrace.h   2005-07-02 13:00:13.000000000 +0200
++++ linux-2.4.30.openwrt/include/asm-mips64/ptrace.h   2005-07-02 13:00:49.000000000 +0200
 @@ -5,6 +5,7 @@
   *
   * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle
 @@ -5,6 +5,7 @@
   *
   * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 by Ralf Baechle