From 697c74552a2cd97b639ef6551575e1d6cbc30c27 Mon Sep 17 00:00:00 2001
From: Imre Kaloz <kaloz@openwrt.org>
Date: Sat, 2 Jul 2005 11:08:39 +0000
Subject: unify gcc 3.4 fixes, move flash chip drivers to generic patches, move
 diag_led driver to separate patch, update docs

SVN-Revision: 1316
---
 openwrt/target/linux/linux-2.4/README              |   67 +-
 .../linux/linux-2.4/patches/brcm/001-bcm47xx.patch | 1185 --------------------
 .../linux-2.4/patches/brcm/004-diag_led.patch      |  265 +++++
 .../patches/generic/005-mtd_flashtypes.patch       |  925 +++++++++++++++
 .../patches/generic/205-gcc_3.4_ldscript.patch     |   10 -
 .../patches/generic/206-gcc_3.4_fixes.patch        |   53 +-
 6 files changed, 1267 insertions(+), 1238 deletions(-)
 create mode 100644 openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch
 create mode 100644 openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch
 delete mode 100644 openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch

(limited to 'openwrt/target')

diff --git a/openwrt/target/linux/linux-2.4/README b/openwrt/target/linux/linux-2.4/README
index 3f7cad2..d5e2d63 100644
--- a/openwrt/target/linux/linux-2.4/README
+++ b/openwrt/target/linux/linux-2.4/README
@@ -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.
 
-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.
 
-004-squashfs_lzma.patch
+002-squashfs_lzma.patch
 	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.
-	
+
+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
 
@@ -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
 
-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
@@ -71,8 +65,37 @@ Description of kernel patches in patches:
 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
+	mips specific gcc 3.4 fixes
 
 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
diff --git a/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch b/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch
index 5e3fc34..80145c9 100644
--- a/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch
+++ b/openwrt/target/linux/linux-2.4/patches/brcm/001-bcm47xx.patch
@@ -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;
-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
@@ -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
-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 --git a/openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch b/openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch
new file mode 100644
index 0000000..77fb289
--- /dev/null
+++ b/openwrt/target/linux/linux-2.4/patches/brcm/004-diag_led.patch
@@ -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/openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch b/openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch
new file mode 100644
index 0000000..9115b9f
--- /dev/null
+++ b/openwrt/target/linux/linux-2.4/patches/generic/005-mtd_flashtypes.patch
@@ -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/openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch b/openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch
deleted file mode 100644
index 782a9ce..0000000
--- a/openwrt/target/linux/linux-2.4/patches/generic/205-gcc_3.4_ldscript.patch
+++ /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)
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch b/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch
index 27adbf1..9cf0553 100644
--- a/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch
+++ b/openwrt/target/linux/linux-2.4/patches/generic/206-gcc_3.4_fixes.patch
@@ -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
@@ -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;
-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
@@ -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;
-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
@@ -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;
-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
@@ -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;
-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.
@@ -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;
-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.
   *
@@ -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. */
-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
-- 
cgit v1.1