mtd/drivers/mtd/chips fwh_lock.h, NONE, 1.1 cfi_cmdset_0001.c, 1.154, 1.155 cfi_cmdset_0002.c, 1.106, 1.107 cfi_util.c, 1.4, 1.5 gen_probe.c, 1.19, 1.20

ebiederman at lnxi.com ebiederman at lnxi.com
Thu Aug 12 02:40:25 EDT 2004


Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv5114/mtd/chips

Modified Files:
	cfi_cmdset_0001.c cfi_cmdset_0002.c cfi_util.c gen_probe.c 
Added Files:
	fwh_lock.h 
Log Message:
- Move support firmware hub style lock and unlock into fhw_lock.h (from cfi_cmdset_0002)
- Move cfi_varsize_frob into cfi_util from cfi_cmdset_0001.c and cfi_cmdset_0002.c
- reduce gen_probe probe failuers to a debug level message
- Modify cfi_fixup to take a struct mtd_info instead of a struct map_info
  So that the fixup routines can modify the mtd functions.
- Modify cfi_cmdset_0001() to allocate and initialize the mtd structure
  before calling cfi_fixup.
- Modify cfi_cmdset_0002() to allocate and initialize the mtd structure
  before calling cfi_fixup.
- Refactor the hard coded fixups in cfi_cmdset_0001 and cfi_cmdset_0002
  so the improved cfi_fixup infrastructure.
- Rewrote amd76xrom and ichxrom.
  They now report their starting physical address in their name.
  They now both handle multiple bankwidth configurations
  They both can create multipe mtd devices.
  They both now assume the rom windows are properly opened by the BIOS
   or whatever runs previous to them.
  Their code is now synchromized so it is almost identical, 
     and could be a starting point for a x86_rom_probe.



--- NEW FILE fwh_lock.h ---
#ifndef FWH_LOCK_H
#define FWH_LOCK_H


enum fwh_lock_state {
        FWH_UNLOCKED   = 0,
	FWH_DENY_WRITE = 1,
	FWH_IMMUTABLE  = 2,
	FWH_DENY_READ  = 4,
};

struct fwh_xxlock_thunk {
	enum fwh_lock_state val;
	flstate_t state;
};


#define FWH_XXLOCK_ONEBLOCK_LOCK   ((struct fwh_xxlock_thunk){ FWH_DENY_WRITE, FL_LOCKING})
#define FWH_XXLOCK_ONEBLOCK_UNLOCK ((struct fwh_xxlock_thunk){ FWH_UNLOCKED,   FL_UNLOCKING})

/*
 * This locking/unlock is specific to firmware hub parts.  Only one
 * is known that supports the Intel command set.    Firmware
 * hub parts cannot be interleaved as they are on the LPC bus
 * so this code has not been tested with interleaved chips,
 * and will likely fail in that context.
 */
static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip, 
	unsigned long adr, int len, void *thunk)
{
	struct cfi_private *cfi = map->fldrv_priv;
	struct fwh_xxlock_thunk *xxlt = (struct fwh_xxlock_thunk *)thunk;
	int ret;

	/* Refuse the operation if the we cannot look behind the chip */
	if (chip->start < 0x400000) {
		return -EIO;
	}
	/*
	 * lock block registers:
	 * - on 64k boundariesand
	 * - bit 1 set high
	 * - block lock registers are 4MiB lower - overflow subtract (danger)
	 * 
	 * The address manipulation is first done on the logical address
	 * which is 0 at the start of the chip, and then the offset of
	 * the individual chip is addted to it.  Any other order a weird
	 * map offset could cause problems.
	 */
	adr = (adr & ~0xffffUL) | 0x2;
	adr += chip->start - 0x400000;

	/*
	 * This is easy because these are writes to registers and not writes
	 * to flash memory - that means that we don't have to check status
	 * and timeout.
	 */
	cfi_spin_lock(chip->mutex);
	ret = get_chip(map, chip, adr, FL_LOCKING);
	if (ret) {
		cfi_spin_unlock(chip->mutex);
		return ret;
	}

	chip->state = xxlt->state;
	map_write(map, CMD(xxlt->val), adr);

	/* Done and happy. */
	chip->state = FL_READY;
	put_chip(map, chip, adr);
	cfi_spin_unlock(chip->mutex);
	return 0;
}


static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
{
	int ret;

	ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
		(void *)&FWH_XXLOCK_ONEBLOCK_LOCK);

	return ret;
}


static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
{
	int ret;

	ret = cfi_varsize_frob(mtd, fwh_xxlock_oneblock, ofs, len,
		(void *)&FWH_XXLOCK_ONEBLOCK_UNLOCK);
	
	return ret;
}

static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param)
{
	printk(KERN_NOTICE "using fwh lock/unlock method\n");
	/* Setup for the chips with the fwh lock method */
	mtd->lock   = fwh_lock_varsize;
	mtd->unlock = fwh_unlock_varsize;
}
#endif /* FWH_LOCK_H */

Index: cfi_cmdset_0001.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0001.c,v
retrieving revision 1.154
retrieving revision 1.155
diff -u -r1.154 -r1.155
--- cfi_cmdset_0001.c	9 Aug 2004 13:19:43 -0000	1.154
+++ cfi_cmdset_0001.c	12 Aug 2004 06:40:22 -0000	1.155
@@ -39,6 +39,10 @@
 // debugging, turns off buffer write mode if set to 1
 #define FORCE_WORD_WRITE 0
 
+#define MANUFACTURER_INTEL	0x0089
+#define I82802AB	0x00ad
+#define I82802AC	0x00ac
+
 static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 //static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 //static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
@@ -55,7 +59,7 @@
 
 struct mtd_info *cfi_cmdset_0001(struct map_info *, int);
 
-static struct mtd_info *cfi_intelext_setup (struct map_info *);
+static struct mtd_info *cfi_intelext_setup (struct mtd_info *);
 static int cfi_intelext_partition_fixup(struct map_info *, struct cfi_private **);
 
 static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
@@ -63,6 +67,11 @@
 static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
 			size_t len);
 
+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
+static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
+#include "fwh_lock.h"
+
+
 
 /*
  *  *********** SETUP AND PROBE BITS  ***********
@@ -123,8 +132,9 @@
 
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
 /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */ 
-static void fixup_intel_strataflash(struct map_info *map, void* param)
+static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
 {
+	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
 
@@ -134,16 +144,18 @@
 }
 #endif
 
-static void fixup_st_m28w320ct(struct map_info *map, void* param)
+static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
 {
+	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	
 	cfi->cfiq->BufWriteTimeoutTyp = 0;	/* Not supported */
 	cfi->cfiq->BufWriteTimeoutMax = 0;	/* Not supported */
 }
 
-static void fixup_st_m28w320cb(struct map_info *map, void* param)
+static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
 {
+	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	
 	/* Note this is done after the region info is endian swapped */
@@ -151,24 +163,50 @@
 		(cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
 };
 
-static struct cfi_fixup fixup_table[] = {
+static void fixup_use_point(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	if (!mtd->point && map_is_linear(map)) {
+		mtd->point   = cfi_intelext_point;
+		mtd->unpoint = cfi_intelext_unpoint;
+	}
+}
+
+static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	if (cfi->cfiq->BufWriteTimeoutTyp) {
+		printk(KERN_INFO "Using buffer write method\n" );
+		mtd->write = cfi_intelext_write_buffers;
+	}
+}
+
+static struct cfi_fixup cfi_fixup_table[] = {
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
-	{
-		CFI_MFR_ANY, CFI_ID_ANY,
-		fixup_intel_strataflash, NULL
-	}, 
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, 
 #endif
-	{
-		0x0020,	/* STMicroelectronics */
-		0x00ba,	/* M28W320CT */
-		fixup_st_m28w320ct, NULL
-	}, {
-		0x0020,	/* STMicroelectronics */
-		0x00bb,	/* M28W320CB */
-		fixup_st_m28w320cb, NULL
-	}, {
-		0, 0, NULL, NULL
-	}
+#if !FORCE_WORD_WRITE
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL },
+#endif
+	{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
+	{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
+	{ 0, 0, NULL, NULL }
+};
+
+static struct cfi_fixup jedec_fixup_table[] = {
+	{ MANUFACTURER_INTEL, I82802AB, fixup_use_fwh_lock, NULL, },
+	{ MANUFACTURER_INTEL, I82802AC, fixup_use_fwh_lock, NULL, },
+	{ 0, 0, NULL, NULL }
+};
+static struct cfi_fixup fixup_table[] = {
+	/* The CFI vendor ids and the JEDEC vendor IDs appear
+	 * to be common.  It is like the devices id's are as
+	 * well.  This table is to pick all cases where
+	 * we know that is the case.
+	 */
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL },
+	{ 0, 0, NULL, NULL }
 };
 
 /* This routine is made available to other mtd code via
@@ -181,8 +219,30 @@
 struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
+	struct mtd_info *mtd;
 	int i;
 
+	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	if (!mtd) {
+		printk(KERN_ERR "Failed to allocate memory for MTD device\n");
+		return NULL;
+	}
+	memset(mtd, 0, sizeof(*mtd));
+	mtd->priv = map;
+	mtd->type = MTD_NORFLASH;
+
+	/* Fill in the default mtd operations */
+	mtd->erase   = cfi_intelext_erase_varsize;
+	mtd->read    = cfi_intelext_read;
+	mtd->write   = cfi_intelext_write_words;
+	mtd->sync    = cfi_intelext_sync;
+	mtd->lock    = cfi_intelext_lock;
+	mtd->unlock  = cfi_intelext_unlock;
+	mtd->suspend = cfi_intelext_suspend;
+	mtd->resume  = cfi_intelext_resume;
+	mtd->flags   = MTD_CAP_NORFLASH;
+	mtd->name    = map->name;
+	
 	if (cfi->cfi_mode == CFI_MODE_CFI) {
 		/* 
 		 * It's a real CFI chip, not one for which the probe
@@ -193,8 +253,10 @@
 		struct cfi_pri_intelext *extp;
 
 		extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp");
-		if (!extp)
+		if (!extp) {
+			kfree(mtd);
 			return NULL;
+		}
 		
 		/* Do some byteswapping if necessary */
 		extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
@@ -204,7 +266,7 @@
 		/* Install our own private info structure */
 		cfi->cmdset_priv = extp;	
 
-		cfi_fixup(map, fixup_table);
+		cfi_fixup(mtd, cfi_fixup_table);
 			
 #ifdef DEBUG_CFI_FEATURES
 		/* Tell the user about it in lots of lovely detail */
@@ -215,6 +277,12 @@
 			printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
 		}
 	}
+	else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
+		/* Apply jedec specific fixups */
+		cfi_fixup(mtd, jedec_fixup_table);
+	}
+	/* Apply generic fixups */
+	cfi_fixup(mtd, fixup_table);
 
 	for (i=0; i< cfi->numchips; i++) {
 		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
@@ -225,28 +293,19 @@
 
 	map->fldrv = &cfi_intelext_chipdrv;
 	
-	return cfi_intelext_setup(map);
+	return cfi_intelext_setup(mtd);
 }
 
-static struct mtd_info *cfi_intelext_setup(struct map_info *map)
+static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
 {
+	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
-	struct mtd_info *mtd;
 	unsigned long offset = 0;
 	int i,j;
 	unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
 	//printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
 
-	if (!mtd) {
-		printk(KERN_ERR "Failed to allocate memory for MTD device\n");
-		goto setup_err;
-	}
-
-	memset(mtd, 0, sizeof(*mtd));
-	mtd->priv = map;
-	mtd->type = MTD_NORFLASH;
 	mtd->size = devsize * cfi->numchips;
 
 	mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
@@ -286,34 +345,10 @@
 		       mtd->eraseregions[i].numblocks);
 	}
 
-	/* Also select the correct geometry setup too */ 
-	mtd->erase = cfi_intelext_erase_varsize;
-	mtd->read = cfi_intelext_read;
-
-	if (map_is_linear(map)) {
-		mtd->point = cfi_intelext_point;
-		mtd->unpoint = cfi_intelext_unpoint;
-	}
-
-	if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) {
-		printk(KERN_INFO "Using buffer write method\n" );
-		mtd->write = cfi_intelext_write_buffers;
-	} else {
-		printk(KERN_INFO "Using word write method\n" );
-		mtd->write = cfi_intelext_write_words;
-	}
 #if 0
 	mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;
 	mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
 #endif
-	mtd->sync = cfi_intelext_sync;
-	mtd->lock = cfi_intelext_lock;
-	mtd->unlock = cfi_intelext_unlock;
-	mtd->suspend = cfi_intelext_suspend;
-	mtd->resume = cfi_intelext_resume;
-	mtd->flags = MTD_CAP_NORFLASH;
-	map->fldrv = &cfi_intelext_chipdrv;
-	mtd->name = map->name;
 
 	/* This function has the potential to distort the reality
 	   a bit and therefore should be called last. */
@@ -517,6 +552,7 @@
 	case FL_ERASING:
 		if (!(cfip->FeatureSupport & 2) ||
 		    !(mode == FL_READY || mode == FL_POINT ||
+		     !cfip ||
 		     (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
 			goto sleep;
 
@@ -882,7 +918,7 @@
 	int base_offst,reg_sz;
 	
 	/* Check that we actually have some protection registers */
-	if(!(extp->FeatureSupport&64)){
+	if(!extp || !(extp->FeatureSupport&64)){
 		printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);
 		return 0;
 	}
@@ -901,7 +937,7 @@
 	int base_offst,reg_sz;
 	
 	/* Check that we actually have some protection registers */
-	if(!(extp->FeatureSupport&64)){
+	if(!extp || !(extp->FeatureSupport&64)){
 		printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);
 		return 0;
 	}
@@ -1306,102 +1342,6 @@
 	return 0;
 }
 
-typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
-			      unsigned long adr, int len, void *thunk);
-
-static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
-				     loff_t ofs, size_t len, void *thunk)
-{
-	struct map_info *map = mtd->priv;
-	struct cfi_private *cfi = map->fldrv_priv;
-	unsigned long adr;
-	int chipnum, ret = 0;
-	int i, first;
-	struct mtd_erase_region_info *regions = mtd->eraseregions;
-
-	if (ofs > mtd->size)
-		return -EINVAL;
-
-	if ((len + ofs) > 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 && ofs >= 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 (ofs & (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 && (ofs + len) >= regions[i].offset)
-		i++;
-
-	/* As before, drop back one to point at the region in which
-	   the address actually falls
-	*/
-	i--;
-	
-	if ((ofs + len) & (regions[i].erasesize-1))
-		return -EINVAL;
-
-	chipnum = ofs >> cfi->chipshift;
-	adr = ofs - (chipnum << cfi->chipshift);
-
-	i=first;
-
-	while(len) {
-		unsigned long chipmask;
-		int size = regions[i].erasesize;
-
-		ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
-		
-		if (ret)
-			return ret;
-
-		adr += size;
-		len -= size;
-
-		chipmask = (1 << cfi->chipshift) - 1;
-		if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask))
-			i++;
-
-		if (adr >> cfi->chipshift) {
-			adr = 0;
-			chipnum++;
-			
-			if (chipnum >= cfi->numchips)
-			break;
-		}
-	}
-
-	return 0;
-}
-
-
 static int do_erase_oneblock(struct map_info *map, struct flchip *chip,
 			     unsigned long adr, int len, void *thunk)
 {
@@ -1549,7 +1489,7 @@
 	ofs = instr->addr;
 	len = instr->len;
 
-	ret = cfi_intelext_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
+	ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
 	if (ret)
 		return ret;
 
@@ -1694,18 +1634,18 @@
 #ifdef DEBUG_LOCK_BITS
 	printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
 	       __FUNCTION__, ofs, len);
-	cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
-				  ofs, len, 0);
+	cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+		ofs, len, 0);
 #endif
 
-	ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock, 
-					ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
+	ret = cfi_varsize_frob(mtd, do_xxlock_oneblock, 
+		ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
 	
 #ifdef DEBUG_LOCK_BITS
 	printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
 	       __FUNCTION__, ret);
-	cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
-				  ofs, len, 0);
+	cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+		ofs, len, 0);
 #endif
 
 	return ret;
@@ -1718,18 +1658,18 @@
 #ifdef DEBUG_LOCK_BITS
 	printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
 	       __FUNCTION__, ofs, len);
-	cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
-				  ofs, len, 0);
+	cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
+		ofs, len, 0);
 #endif
 
-	ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock,
+	ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
 					ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK);
 	
 #ifdef DEBUG_LOCK_BITS
 	printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
 	       __FUNCTION__, ret);
-	cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock, 
-				  ofs, len, 0);
+	cfi_varsize_frob(mtd, do_printlockstatus_oneblock, 
+		ofs, len, 0);
 #endif
 	
 	return ret;

Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.106
retrieving revision 1.107
diff -u -r1.106 -r1.107
--- cfi_cmdset_0002.c	9 Aug 2004 14:02:32 -0000	1.106
+++ cfi_cmdset_0002.c	12 Aug 2004 06:40:22 -0000	1.107
@@ -40,13 +40,15 @@
 
 #define MAX_WORD_RETRIES 3
 
+#define MANUFACTURER_AMD	0x0001
+#define MANUFACTURER_SST	0x00BF
+#define SST49LF004B	        0x0060
+
 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
 static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
-static int cfi_amdstd_lock_varsize(struct mtd_info *, loff_t, size_t);
-static int cfi_amdstd_unlock_varsize(struct mtd_info *, loff_t, size_t);
 static void cfi_amdstd_sync (struct mtd_info *);
 static int cfi_amdstd_suspend (struct mtd_info *);
 static void cfi_amdstd_resume (struct mtd_info *);
@@ -55,8 +57,11 @@
 static void cfi_amdstd_destroy(struct mtd_info *);
 
 struct mtd_info *cfi_cmdset_0002(struct map_info *, int);
-static struct mtd_info *cfi_amdstd_setup (struct map_info *);
+static struct mtd_info *cfi_amdstd_setup (struct mtd_info *);
 
+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
+static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
+#include "fwh_lock.h"
 
 static struct mtd_chip_driver cfi_amdstd_chipdrv = {
 	.probe		= NULL, /* Not usable directly */
@@ -66,7 +71,6 @@
 };
 
 
-/* #define DEBUG_LOCK_BITS */
 /* #define DEBUG_CFI_FEATURES */
 
 
@@ -122,8 +126,9 @@
 
 #ifdef AMD_BOOTLOC_BUG
 /* Wheee. Bring me the head of someone at AMD. */
-static void fixup_amd_bootblock(struct map_info *map, void* param)
+static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
 {
+	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
 	__u8 major = extp->MajorVersion;
@@ -141,25 +146,92 @@
 }
 #endif
 
-static struct cfi_fixup fixup_table[] = {
+static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	if (cfi->cfiq->BufWriteTimeoutTyp) {
+		DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
+		mtd->write = cfi_amdstd_write_buffers;
+	}
+}
+
+static void fixup_use_secsi(struct mtd_info *mtd, void *param)
+{
+	/* Setup for chips with a secsi area */
+	mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
+	mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
+}
+
+static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	if ((cfi->cfiq->NumEraseRegions == 1) &&
+		((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) {
+		mtd->erase = cfi_amdstd_erase_chip;
+	}
+	
+}
+
+static struct cfi_fixup cfi_fixup_table[] = {
 #ifdef AMD_BOOTLOC_BUG
-	{
-		0x0001,		/* AMD */
-		CFI_ID_ANY,
-		fixup_amd_bootblock, NULL
-	},
+	{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
+#endif
+	{ CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
+	{ CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
+	{ CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, },
+	{ CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
+	{ CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
+	{ CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
+#if !FORCE_WORD_WRITE
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
 #endif
 	{ 0, 0, NULL, NULL }
 };
+static struct cfi_fixup jedec_fixup_table[] = {
+	{ MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
+	{ 0, 0, NULL, NULL }
+};
+
+static struct cfi_fixup fixup_table[] = {
+	/* The CFI vendor ids and the JEDEC vendor IDs appear
+	 * to be common.  It is like the devices id's are as
+	 * well.  This table is to pick all cases where
+	 * we know that is the case.
+	 */
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
+	{ 0, 0, NULL, NULL }
+};
 
 
 struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
-	unsigned char bootloc;
+	struct mtd_info *mtd;
 	int i;
 
+	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+	if (!mtd) {
+		printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
+		return NULL;
+	}
+	memset(mtd, 0, sizeof(*mtd));
+	mtd->priv = map;
+	mtd->type = MTD_NORFLASH;
+
+	/* Fill in the default mtd operations */
+	mtd->erase   = cfi_amdstd_erase_varsize;
+	mtd->write   = cfi_amdstd_write_words;
+	mtd->read    = cfi_amdstd_read;
+	mtd->sync    = cfi_amdstd_sync;
+	mtd->suspend = cfi_amdstd_suspend;
+	mtd->resume  = cfi_amdstd_resume;
+	mtd->flags   = MTD_CAP_NORFLASH;
+	mtd->name    = map->name;
+
 	if (cfi->cfi_mode==CFI_MODE_CFI){
+		unsigned char bootloc;
 		/* 
 		 * It's a real CFI chip, not one for which the probe
 		 * routine faked a CFI structure. So we read the feature
@@ -169,13 +241,16 @@
 		struct cfi_pri_amdstd *extp;
 
 		extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu");
-		if (!extp)
+		if (!extp) {
+			kfree(mtd);
 			return NULL;
+		}
 
 		/* Install our own private info structure */
 		cfi->cmdset_priv = extp;	
 
-		cfi_fixup(map, fixup_table);
+		/* Apply cfi device specific fixups */
+		cfi_fixup(mtd, cfi_fixup_table);
 
 #ifdef DEBUG_CFI_FEATURES
 		/* Tell the user about it in lots of lovely detail */
@@ -233,11 +308,19 @@
 				printk(KERN_WARNING
 				       "MTD %s(): Unsupported device type %d\n",
 				       __func__, cfi->device_type);
+				kfree(mtd);
+				kfree(extp);
 				return NULL;
 			}
 		}
 
 	} /* CFI mode */
+	else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
+		/* Apply jedec specific fixups */
+		cfi_fixup(mtd, jedec_fixup_table);
+	}
+	/* Apply generic fixups */
+	cfi_fixup(mtd, fixup_table);
 
 	for (i=0; i< cfi->numchips; i++) {
 		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
@@ -246,32 +329,22 @@
 	}		
 	
 	map->fldrv = &cfi_amdstd_chipdrv;
-
-	return cfi_amdstd_setup(map);
+	
+	return cfi_amdstd_setup(mtd);
 }
 
 
-static struct mtd_info *cfi_amdstd_setup(struct map_info *map)
+static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
 {
+	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
-	struct mtd_info *mtd;
 	unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
 	unsigned long offset = 0;
 	int i,j;
 
-	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
 	printk(KERN_NOTICE "number of %s chips: %d\n", 
 	       (cfi->cfi_mode == CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips);
-
-	if (!mtd) {
-		printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
-		goto setup_err;
-	}
-
-	memset(mtd, 0, sizeof(*mtd));
-	mtd->priv = map;
-	mtd->type = MTD_NORFLASH;
-	/* Also select the correct geometry setup too */ 
+	/* Select the correct geometry setup */ 
 	mtd->size = devsize * cfi->numchips;
 
 	mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
@@ -312,54 +385,10 @@
 	}
 #endif
 
-	if (mtd->numeraseregions == 1
-	    && ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) + 1) == 1) {
-		mtd->erase = cfi_amdstd_erase_chip;
-	} else {
-		mtd->erase = cfi_amdstd_erase_varsize;
-		mtd->lock = cfi_amdstd_lock_varsize;
-		mtd->unlock = cfi_amdstd_unlock_varsize;
-	}
-
-	if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) {
-		DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
-		mtd->write = cfi_amdstd_write_buffers;
-	} else {
-		DEBUG(MTD_DEBUG_LEVEL1, "Using word write method\n" );
-		mtd->write = cfi_amdstd_write_words;
-	}
-
-	mtd->read = cfi_amdstd_read;
-
 	/* FIXME: erase-suspend-program is broken.  See
 	   http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */
 	printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n");
 
-	/* does this chip have a secsi area? */
-	if(cfi->mfr==1){
-		
-		switch(cfi->id){
-		case 0x50:
-		case 0x53:
-		case 0x55:
-		case 0x56:
-		case 0x5C:
-		case 0x5F:
-			/* Yes */
-			mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
-			mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
-		default:		       
-			;
-		}
-	}
-	
-		
-	mtd->sync = cfi_amdstd_sync;
-	mtd->suspend = cfi_amdstd_suspend;
-	mtd->resume = cfi_amdstd_resume;
-	mtd->flags = MTD_CAP_NORFLASH;
-	map->fldrv = &cfi_amdstd_chipdrv;
-	mtd->name = map->name;
 	__module_get(THIS_MODULE);
 	return mtd;
 
@@ -434,6 +463,7 @@
 			goto sleep;
 
 		if (!(mode == FL_READY || mode == FL_POINT
+		      || !cfip
 		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
 		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1))))
 			goto sleep;
@@ -1229,100 +1259,7 @@
 }
 
 
-typedef int (*frob_t)(struct map_info *map, struct flchip *chip,
-		      unsigned long adr, void *thunk);
-
-
-static int cfi_amdstd_varsize_frob(struct mtd_info *mtd, frob_t frob,
-				   loff_t ofs, size_t len, void *thunk)
-{
-	struct map_info *map = mtd->priv;
-	struct cfi_private *cfi = map->fldrv_priv;
-	unsigned long adr;
-	int chipnum, ret = 0;
-	int i, first;
-	struct mtd_erase_region_info *regions = mtd->eraseregions;
-
-	if (ofs > mtd->size)
-		return -EINVAL;
-
-	if ((len + ofs) > 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 && ofs >= 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 (ofs & (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 && (ofs + len) >= regions[i].offset)
-		i++;
-
-	/* As before, drop back one to point at the region in which
-	   the address actually falls
-	*/
-	i--;
-	
-	if ((ofs + len) & (regions[i].erasesize-1))
-		return -EINVAL;
-
-	chipnum = ofs >> cfi->chipshift;
-	adr = ofs - (chipnum << cfi->chipshift);
-
-	i=first;
-
-	while (len) {
-		ret = (*frob)(map, &cfi->chips[chipnum], adr, thunk);
-		
-		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;
-		}
-	}
-
-	return 0;
-}
-
-
-static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk)
+static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	unsigned long timeo = jiffies + HZ;
@@ -1415,7 +1352,7 @@
 	ofs = instr->addr;
 	len = instr->len;
 
-	ret = cfi_amdstd_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
+	ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
 	if (ret)
 		return ret;
 
@@ -1588,137 +1525,6 @@
 	}
 }
 
-
-#ifdef DEBUG_LOCK_BITS
-
-static int do_printlockstatus_oneblock(struct map_info *map,
-				       struct flchip *chip,
-				       unsigned long adr,
-				       void *thunk)
-{
-	struct cfi_private *cfi = map->fldrv_priv;
-	int ofs_factor = cfi->interleave * cfi->device_type;
-
-	cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
-	printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
-	       adr, cfi_read_query(map, adr+(2*ofs_factor)));
-	cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
-	
-	return 0;
-}
-
-
-#define debug_dump_locks(mtd, frob, ofs, len, thunk) \
-	cfi_amdstd_varsize_frob((mtd), (frob), (ofs), (len), (thunk))
-
-#else
-
-#define debug_dump_locks(...)
-
-#endif /* DEBUG_LOCK_BITS */
-
-
-struct xxlock_thunk {
-	uint8_t val;
-	flstate_t state;
-};
-
-
-#define DO_XXLOCK_ONEBLOCK_LOCK   ((struct xxlock_thunk){0x01, FL_LOCKING})
-#define DO_XXLOCK_ONEBLOCK_UNLOCK ((struct xxlock_thunk){0x00, FL_UNLOCKING})
-
-
-/*
- * FIXME - this is *very* specific to a particular chip.  It likely won't
- * work for all chips that require unlock.  It also hasn't been tested
- * with interleaved chips.
- */
-static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, void *thunk)
-{
-	struct cfi_private *cfi = map->fldrv_priv;
-	struct xxlock_thunk *xxlt = (struct xxlock_thunk *)thunk;
-	int ret;
-
-	/*
-	 * This is easy because these are writes to registers and not writes
-	 * to flash memory - that means that we don't have to check status
-	 * and timeout.
-	 */
-
-	adr += chip->start;
-	/*
-	 * lock block registers:
-	 * - on 64k boundariesand
-	 * - bit 1 set high
-	 * - block lock registers are 4MiB lower - overflow subtract (danger)
-	 */
-	adr = ((adr & ~0xffff) | 0x2) + ~0x3fffff;
-
-	cfi_spin_lock(chip->mutex);
-	ret = get_chip(map, chip, adr, FL_LOCKING);
-	if (ret) {
-		cfi_spin_unlock(chip->mutex);
-		return ret;
-	}
-
-	chip->state = xxlt->state;
-	map_write(map, CMD(xxlt->val), adr);
-	
-	/* Done and happy. */
-	chip->state = FL_READY;
-	put_chip(map, chip, adr);
-	cfi_spin_unlock(chip->mutex);
-	return 0;
-}
-
-
-static int cfi_amdstd_lock_varsize(struct mtd_info *mtd,
-				   loff_t ofs,
-				   size_t len)
-{
-	int ret;
-
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "%s: lock status before, ofs=0x%08llx, len=0x%08zX\n",
-	      __func__, ofs, len);
-	debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0);
-
-	ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len,
-				      (void *)&DO_XXLOCK_ONEBLOCK_LOCK);
-	
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "%s: lock status after, ret=%d\n",
-	      __func__, ret);
-
-	debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0);
-
-	return ret;
-}
-
-
-static int cfi_amdstd_unlock_varsize(struct mtd_info *mtd,
-				     loff_t ofs,
-				     size_t len)
-{
-	int ret;
-
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "%s: lock status before, ofs=0x%08llx, len=0x%08zX\n",
-	      __func__, ofs, len);
-	debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0);
-
-	ret = cfi_amdstd_varsize_frob(mtd, do_xxlock_oneblock, ofs, len,
-				      (void *)&DO_XXLOCK_ONEBLOCK_UNLOCK);
-	
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "%s: lock status after, ret=%d\n",
-	      __func__, ret);
-	debug_dump_locks(mtd, do_printlockstatus_oneblock, ofs, len, 0);
-	
-	return ret;
-}
-
-
 static void cfi_amdstd_destroy(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;

Index: cfi_util.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_util.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- cfi_util.c	14 Jul 2004 08:38:44 -0000	1.4
+++ cfi_util.c	12 Aug 2004 06:40:23 -0000	1.5
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/compatmac.h>
@@ -74,19 +75,114 @@
 
 EXPORT_SYMBOL(cfi_read_pri);
 
-void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups)
+void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups)
 {
+	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_fixup *f;
 
 	for (f=fixups; f->fixup; f++) {
 		if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) &&
 		    ((f->id  == CFI_ID_ANY)  || (f->id  == cfi->id))) {
-			f->fixup(map, f->param);
+			f->fixup(mtd, f->param);
 		}
 	}
 }
 
 EXPORT_SYMBOL(cfi_fixup);
 
+int cfi_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
+				     loff_t ofs, size_t len, void *thunk)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	unsigned long adr;
+	int chipnum, ret = 0;
+	int i, first;
+	struct mtd_erase_region_info *regions = mtd->eraseregions;
+
+	if (ofs > mtd->size)
+		return -EINVAL;
+
+	if ((len + ofs) > 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 && ofs >= 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 (ofs & (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 && (ofs + len) >= regions[i].offset)
+		i++;
+
+	/* As before, drop back one to point at the region in which
+	   the address actually falls
+	*/
+	i--;
+	
+	if ((ofs + len) & (regions[i].erasesize-1))
+		return -EINVAL;
+
+	chipnum = ofs >> cfi->chipshift;
+	adr = ofs - (chipnum << cfi->chipshift);
+
+	i=first;
+
+	while(len) {
+		unsigned long chipmask;
+		int size = regions[i].erasesize;
+
+		ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
+		
+		if (ret)
+			return ret;
+
+		adr += size;
+		len -= size;
+
+		chipmask = (1 << cfi->chipshift) - 1;
+		if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask))
+			i++;
+
+		if (adr >> cfi->chipshift) {
+			adr = 0;
+			chipnum++;
+			
+			if (chipnum >= cfi->numchips)
+			break;
+		}
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL(cfi_varsize_frob);
+
 MODULE_LICENSE("GPL");

Index: gen_probe.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/gen_probe.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- gen_probe.c	13 Jul 2004 22:33:32 -0000	1.19
+++ gen_probe.c	12 Aug 2004 06:40:23 -0000	1.20
@@ -64,7 +64,7 @@
 	   interleave and device type, etc. */
 	if (!genprobe_new_chip(map, cp, &cfi)) {
 		/* The probe didn't like it */
-		printk(KERN_WARNING "%s: Found no %s device at location zero\n",
+		printk(KERN_DEBUG "%s: Found no %s device at location zero\n",
 		       cp->name, map->name);
 		return NULL;
 	}		





More information about the linux-mtd-cvs mailing list