mtd/drivers/mtd/chips Config.in,1.16,1.17 Kconfig,1.3,1.4
Makefile.common,1.2,1.3 cfi_cmdset_0002.c,1.78,1.79
cfi_util.c,1.1,1.2
Thayne Harbaugh
tharbaugh at lnxi.com
Thu Sep 25 10:40:37 EDT 2003
Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv14496
Modified Files:
Config.in Kconfig Makefile.common cfi_cmdset_0002.c cfi_util.c
Log Message:
- Add CONFIG_MTD_CFI_AMDSTD_RETRY for dealing with broken flash chips.
Unfortunately this is for the SST49LF0*0 series using an LPC interface.
These SST chips have a horribly broken LPC interface that don't
filter out traffic for other devices on the LPC bus. Did I mention
how horribly broken the SST chips are?
- Tied the CONFIG_MTD_CFI_AMDSTD_RETRY options into the kernel config
mechanism, added documentation, and did some minor cleanup of the
config files.
- Fixed cfi_util so that it is an individual module that can be used
by cfi_cmdset_* without requiring cfi_probe - there is a different
setup through jedec_probe. This had some accompanying changes in
the config files.
Index: Config.in
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/Config.in,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- Config.in 3 Sep 2002 13:30:43 -0000 1.16
+++ Config.in 25 Sep 2003 14:40:34 -0000 1.17
@@ -11,13 +11,12 @@
if [ "$CONFIG_MTD_CFI" = "y" -o "$CONFIG_MTD_JEDECPROBE" = "y" ]; then
define_bool CONFIG_MTD_GEN_PROBE y
+elif [ "$CONFIG_MTD_CFI" = "m" -o "$CONFIG_MTD_JEDECPROBE" = "m" ]; then
+ define_bool CONFIG_MTD_GEN_PROBE m
else
- if [ "$CONFIG_MTD_CFI" = "m" -o "$CONFIG_MTD_JEDECPROBE" = "m" ]; then
- define_bool CONFIG_MTD_GEN_PROBE m
- else
- define_bool CONFIG_MTD_GEN_PROBE n
- fi
+ define_bool CONFIG_MTD_GEN_PROBE n
fi
+
if [ "$CONFIG_MTD_GEN_PROBE" = "y" -o "$CONFIG_MTD_GEN_PROBE" = "m" ]; then
bool ' Flash chip driver advanced configuration options' CONFIG_MTD_CFI_ADV_OPTIONS
if [ "$CONFIG_MTD_CFI_ADV_OPTIONS" = "y" ]; then
@@ -44,7 +43,26 @@
fi
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
+if [ "$CONFIG_MTD_CFI_AMDSTD" = "y" -o "$CONFIG_MTD_CFI_AMDSTD" = "m" ]; then
+ bool ' Retry failed commands (erase/program)' CONFIG_MTD_CFI_AMDSTD_RETRY n
+ if [ "$CONFIG_MTD_CFI_AMDSTD_RETRY" = "y" ]; then
+ int ' Max retries of failed commands (erase/program)' CONFIG_MTD_CFI_AMDSTD_RETRY_MAX 0
+ fi
+fi
+
dep_tristate ' Support for ST (Advanced Architecture) flash chips' CONFIG_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE
+
+if [ "$CONFIG_MTD_CFI_INTELEXT" = "y" \
+ -o "$CONFIG_MTD_CFI_AMDSTD" = "y" \
+ -o "$CONFIG_MTD_CFI_STAA" = "y" ]; then
+ define_bool CONFIG_MTD_CFI_UTIL y
+elif [ "$CONFIG_MTD_CFI_INTELEXT" = "m" \
+ -o "$CONFIG_MTD_CFI_AMDSTD" = "m" \
+ -o "$CONFIG_MTD_CFI_STAA" = "m" ]; then
+ define_bool CONFIG_MTD_CFI_UTIL m
+else
+ define_bool CONFIG_MTD_CFI_UTIL n
+fi
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
Index: Kconfig
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/Kconfig,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Kconfig 28 May 2003 15:13:24 -0000 1.3
+++ Kconfig 25 Sep 2003 14:40:34 -0000 1.4
@@ -160,6 +160,25 @@
provides support for one of those command sets, used on chips
including the AMD Am29LV320.
+config MTD_CFI_AMDSTD_RETRY
+ int "Retry failed commands (erase/program)"
+ depends on MTD_CFI_AMDSTD
+ help
+ Some chips, when attached to a shared bus, don't properly filter
+ bus traffic that is destined to other devices. This broken
+ behavior causes erase and program sequences to be aborted when
+ the sequences are mixed with traffic for other devices.
+
+ SST49LF040 (and related) chips are know to be broken.
+
+config MTD_CFI_AMDSTD_RETRY_MAX
+ int "Max retries of failed commands (erase/program)"
+ depends on MTD_CFI_AMDSTD_RETRY
+ help
+ If you have an SST49LF040 (or related chip) then this value should
+ be set to at least 1. This can also be adjusted at driver load
+ time with the retry_cmd_max module parameter.
+
config MTD_CFI_STAA
tristate "Support for ST (Advanced Architecture) flash chips"
depends on MTD_GEN_PROBE
@@ -167,6 +186,11 @@
The Common Flash Interface defines a number of different command
sets which a CFI-compliant chip may claim to implement. This code
provides support for one of those command sets.
+
+config MTD_UTIL
+ tristate
+ default y if MTD_CFI_INTELEXT=y || MTD_CFI_AMDSTD=y || MTD_CFI_STAA=y
+ default m if MTD_CFI_INTELEXT=m || MTD_CFI_AMDSTD=m || MTD_CFI_STAA=m
config MTD_RAM
tristate "Support for RAM chips in bus mapping"
Index: Makefile.common
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/Makefile.common,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Makefile.common 22 Jul 2003 13:23:38 -0000 1.2
+++ Makefile.common 25 Sep 2003 14:40:34 -0000 1.3
@@ -5,7 +5,7 @@
ifeq ($(PATCHLEVEL),4)
O_TARGET := chipslink.o
-export-objs := chipreg.o gen_probe.o
+export-objs := chipreg.o gen_probe.o cfi_util.o
endif
# *** BIG UGLY NOTE ***
@@ -17,7 +17,8 @@
obj-$(CONFIG_MTD) += chipreg.o
obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o
-obj-$(CONFIG_MTD_CFI) += cfi_probe.o cfi_util.o
+obj-$(CONFIG_MTD_CFI) += cfi_probe.o
+obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o
obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o
obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o
obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
Index: cfi_cmdset_0002.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0002.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -r1.78 -r1.79
--- cfi_cmdset_0002.c 17 Sep 2003 23:05:08 -0000 1.78
+++ cfi_cmdset_0002.c 25 Sep 2003 14:40:34 -0000 1.79
@@ -12,6 +12,7 @@
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -31,6 +32,52 @@
#define AMD_BOOTLOC_BUG
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+
+#ifndef CONFIG_MTD_CFI_AMDSTD_RETRY_MAX
+#define CONFIG_MTD_CFI_AMDSTD_RETRY_MAX 0
+#endif
+
+static int retry_cmd_max = CONFIG_MTD_CFI_AMDSTD_RETRY_MAX;
+
+#define HANDLE_WACKY_STATE \
+do { \
+ if ( retry_cmd_cnt == retry_cmd_max ) { \
+ printk(KERN_WARNING \
+ "MTD %s(): Wacky! Unable to decode failure status\n" \
+ "Possible buggy device - try setting driver" \
+ " retry_cmd_max\n", \
+ __func__ ); \
+ printk(KERN_WARNING \
+ "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", \
+ __func__, adr, datum, \
+ prev_oldstatus, prev_status, \
+ oldstatus, status); \
+ } \
+} while (0)
+
+#else /* CONFIG_MTD_CFI_AMDSTD_RETRY */
+
+#define HANDLE_WACKY_STATE \
+do { \
+ printk(KERN_WARNING \
+ "MTD %s(): Wacky! Unable to decode failure status\n" \
+ "Possible buggy device - try enabling" \
+ " CONFIG_MTD_CFI_AMDSTD_RETRY\n" \
+ "in your kernel config and setting driver retry_cmd_max\n", \
+ __func__ ); \
+ printk(KERN_WARNING \
+ "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", \
+ __func__, adr, datum, \
+ prev_oldstatus, prev_status, \
+ oldstatus, status); \
+} while (0)
+
+#endif /* !defined(CONFIG_MTD_CFI_AMDSTD_RETRY) */
+
+
+
+
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
@@ -185,7 +232,7 @@
}
/*
* FIXME - These might already be setup (more correctly)
- * buy jedec_probe.c.
+ * by jedec_probe.c.
*/
switch (cfi->device_type) {
case CFI_DEVICETYPE_X8:
@@ -556,6 +603,9 @@
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ta = 0;
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ int retry_cmd_cnt = 0;
+#endif
retry:
cfi_spin_lock(chip->mutex);
@@ -584,6 +634,9 @@
chip->state = FL_WRITING;
adr += chip->start;
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ retry_cmd:
+#endif
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n",
__func__, adr, datum );
@@ -691,7 +744,7 @@
if ( oldstatus == datum && status == datum ) {
/* success - do nothing */
- goto write_done;
+ goto op_done;
}
if ( ta ) {
@@ -707,7 +760,7 @@
"MTD %s(): Software timed out during write.\n",
__func__ );
}
- goto write_failed;
+ goto op_failed;
}
/*
@@ -715,23 +768,32 @@
* is wrong and it's not a timeout. Something
* is seriously wacky! Dump some debug info.
*/
- printk(KERN_WARNING
- "MTD %s(): Wacky! Unable to decode failure status\n",
- __func__ );
-
- printk(KERN_WARNING
- "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
- __func__, adr, datum,
- prev_oldstatus, prev_status,
- oldstatus, status);
+ /*
+ * Found a clue about the chips that reach this state.
+ * Some flash chips (SST >cough<)
+ * are horribly broken. They do not ignore traffic that is
+ * destined to other devices. This happens because some solutions
+ * are on shared busses, the erase and program sequences have
+ * have multiple commands, and the sequence is interspersed with
+ * commands destined to other devices. A good flash chip will
+ * examine the command and destination address and will ignore
+ * commands that are for other devices.
+ */
+ HANDLE_WACKY_STATE;
- write_failed:
- ret = -EIO;
+ op_failed:
/* reset on all failures. */
cfi_write( map, CMD(0xF0), chip->start );
/* FIXME - should have reset delay before continuing */
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ retry_cmd_cnt++;
+ if (retry_cmd_cnt <= retry_cmd_max) {
+ goto retry_cmd;
+ }
+#endif
+ ret = -EIO;
- write_done:
+ op_done:
DISABLE_VPP(map);
chip->state = FL_READY;
wake_up(&chip->wq);
@@ -885,6 +947,11 @@
return 0;
}
+
+/*
+ * Handle devices with one erase region, that only implement
+ * the chip erase command.
+ */
static inline int do_erase_chip(struct map_info *map, struct flchip *chip)
{
unsigned int oldstatus, status, prev_oldstatus, prev_status;
@@ -895,7 +962,10 @@
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ta = 0;
- cfi_word ones = 0;
+ cfi_word datum = 0;
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ int retry_cmd_cnt = 0;
+#endif
retry:
cfi_spin_lock(chip->mutex);
@@ -918,12 +988,13 @@
}
chip->state = FL_ERASING;
+
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
__func__, chip->start );
-
- /* Handle devices with one erase region, that only implement
- * the chip erase command.
- */
+
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ retry_cmd:
+#endif
ENABLE_VPP(map);
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
@@ -966,7 +1037,7 @@
add_wait_queue(&chip->wq, &wait);
cfi_spin_unlock(chip->mutex);
- printk("erase suspended. Sleeping\n");
+ printk(KERN_DEBUG "erase suspended. Sleeping\n");
schedule();
remove_wait_queue(&chip->wq, &wait);
@@ -1010,19 +1081,19 @@
__func__, oldstatus, status );
if ( cfi_buswidth_is_1() ) {
- ones = (__u8)~0;
+ datum = (__u8)~0;
} else if ( cfi_buswidth_is_2() ) {
- ones = (__u16)~0;
+ datum = (__u16)~0;
} else if ( cfi_buswidth_is_4() ) {
- ones = (__u32)~0;
+ datum = (__u32)~0;
} else {
printk(KERN_WARNING "Unsupported buswidth\n");
- goto erase_failed;
+ goto op_failed;
}
-
- if ( oldstatus == ones && status == ones ) {
+
+ if ( oldstatus == datum && status == datum ) {
/* success - do nothing */
- goto erase_done;
+ goto op_done;
}
if ( ta ) {
@@ -1038,26 +1109,24 @@
"MTD %s(): Software timed out during write.\n",
__func__ );
}
- goto erase_failed;
+ goto op_failed;
}
- printk(KERN_WARNING
- "MTD %s(): Wacky! Unable to decode failure status\n",
- __func__ );
-
- printk(KERN_WARNING
- "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
- __func__, adr, ones,
- prev_oldstatus, prev_status,
- oldstatus, status);
+ HANDLE_WACKY_STATE;
- erase_failed:
- ret = -EIO;
+ op_failed:
/* reset on all failures. */
cfi_write( map, CMD(0xF0), chip->start );
/* FIXME - should have reset delay before continuing */
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ retry_cmd_cnt++;
+ if (retry_cmd_cnt <= retry_cmd_max) {
+ goto retry_cmd;
+ }
+#endif
+ ret = -EIO;
- erase_done:
+ op_done:
DISABLE_VPP(map);
chip->state = FL_READY;
wake_up(&chip->wq);
@@ -1075,7 +1144,10 @@
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ta = 0;
- cfi_word ones = 0;
+ cfi_word datum = 0;
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ int retry_cmd_cnt = 0;
+#endif
retry:
cfi_spin_lock(chip->mutex);
@@ -1098,11 +1170,14 @@
}
chip->state = FL_ERASING;
-
adr += chip->start;
+
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
__func__, adr );
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ retry_cmd:
+#endif
ENABLE_VPP(map);
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
@@ -1167,9 +1242,9 @@
/* Latency issues. Drop the lock, wait a while and retry */
cfi_spin_unlock(chip->mutex);
-
+
cfi_udelay(1);
-
+
cfi_spin_lock(chip->mutex);
oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
@@ -1190,19 +1265,19 @@
__func__, oldstatus, status );
if ( cfi_buswidth_is_1() ) {
- ones = (__u8)~0;
+ datum = (__u8)~0;
} else if ( cfi_buswidth_is_2() ) {
- ones = (__u16)~0;
+ datum = (__u16)~0;
} else if ( cfi_buswidth_is_4() ) {
- ones = (__u32)~0;
+ datum = (__u32)~0;
} else {
printk(KERN_WARNING "Unsupported buswidth\n");
- goto erase_failed;
+ goto op_failed;
}
- if ( oldstatus == ones && status == ones ) {
+ if ( oldstatus == datum && status == datum ) {
/* success - do nothing */
- goto erase_done;
+ goto op_done;
}
if ( ta ) {
@@ -1218,26 +1293,24 @@
"MTD %s(): Software timed out during write.\n",
__func__ );
}
- goto erase_failed;
+ goto op_failed;
}
- printk(KERN_WARNING
- "MTD %s(): Wacky! Unable to decode failure status\n",
- __func__ );
+ HANDLE_WACKY_STATE;
- printk(KERN_WARNING
- "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
- __func__, adr, ones,
- prev_oldstatus, prev_status,
- oldstatus, status);
-
- erase_failed:
- ret = -EIO;
+ op_failed:
/* reset on all failures. */
cfi_write( map, CMD(0xF0), chip->start );
/* FIXME - should have reset delay before continuing */
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+ retry_cmd_cnt++;
+ if (retry_cmd_cnt <= retry_cmd_max) {
+ goto retry_cmd;
+ }
+#endif
+ ret = -EIO;
- erase_done:
+ op_done:
DISABLE_VPP(map);
chip->state = FL_READY;
wake_up(&chip->wq);
@@ -1573,3 +1646,7 @@
MODULE_AUTHOR("Crossnet Co. <info at crossnet.co.jp> et al.");
MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips");
+#ifdef CONFIG_MTD_CFI_AMDSTD_RETRY
+MODULE_PARM(retry_cmd_max, "i");
+MODULE_PARM_DESC(retry_cmd_max, "Number of times to retry an erase or program command if it fails - should only be needed by buggy hardware: default 0");
+#endif
Index: cfi_util.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_util.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- cfi_util.c 22 Jul 2003 13:23:38 -0000 1.1
+++ cfi_util.c 25 Sep 2003 14:40:34 -0000 1.2
@@ -71,6 +71,8 @@
return extp;
}
+EXPORT_SYMBOL(cfi_read_pri);
+
void cfi_fixup(struct map_info *map, struct cfi_fixup* fixups)
{
struct cfi_private *cfi = map->fldrv_priv;
@@ -83,3 +85,5 @@
}
}
}
+
+EXPORT_SYMBOL(cfi_fixup);
More information about the linux-mtd-cvs
mailing list