summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c42
-rw-r--r--include/linux/mtd/cfi.h1
2 files changed, 35 insertions, 8 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index a8e1a961e844..e3477b5bceaf 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -49,6 +49,10 @@
#define SST49LF008A 0x005a
#define AT49BV6416 0x00d6
+enum cfi_quirks {
+ CFI_QUIRK_DQ_TRUE_DATA = BIT(0),
+};
+
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 *);
@@ -365,6 +369,15 @@ static void fixup_s29ns512p_sectors(struct mtd_info *mtd)
mtd->name);
}
+static void fixup_quirks(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+
+ if (cfi->mfr == CFI_MFR_AMD && cfi->id == 0x0c01)
+ cfi->quirks |= CFI_QUIRK_DQ_TRUE_DATA;
+}
+
/* Used to fix CFI-Tables of chips without Extended Query Tables */
static struct cfi_fixup cfi_nopri_fixup_table[] = {
{ CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */
@@ -403,6 +416,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
#if !FORCE_WORD_WRITE
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers },
#endif
+ { CFI_MFR_ANY, CFI_ID_ANY, fixup_quirks },
{ 0, 0, NULL }
};
static struct cfi_fixup jedec_fixup_table[] = {
@@ -760,6 +774,18 @@ static int __xipram chip_ready(struct map_info *map, unsigned long addr,
return map_word_equal(map, t, *expected);
}
+static int __xipram chip_good(struct map_info *map, unsigned long addr,
+ map_word *expected)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+ map_word *datum = expected;
+
+ if (cfi->quirks & CFI_QUIRK_DQ_TRUE_DATA)
+ datum = NULL;
+
+ return chip_ready(map, addr, datum);
+}
+
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
{
DECLARE_WAITQUEUE(wait, current);
@@ -1612,11 +1638,11 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
}
/*
- * We check "time_after" and "!chip_ready" before checking
- * "chip_ready" to avoid the failure due to scheduling.
+ * We check "time_after" and "!chip_good" before checking
+ * "chip_good" to avoid the failure due to scheduling.
*/
if (time_after(jiffies, timeo) &&
- !chip_ready(map, adr, &datum)) {
+ !chip_good(map, adr, &datum)) {
xip_enable(map, chip, adr);
printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
xip_disable(map, chip, adr);
@@ -1624,7 +1650,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
break;
}
- if (chip_ready(map, adr, &datum))
+ if (chip_good(map, adr, &datum))
break;
/* Latency issues. Drop the lock, wait a while and retry */
@@ -1868,13 +1894,13 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
}
/*
- * We check "time_after" and "!chip_ready" before checking
- * "chip_ready" to avoid the failure due to scheduling.
+ * We check "time_after" and "!chip_good" before checking
+ * "chip_good" to avoid the failure due to scheduling.
*/
- if (time_after(jiffies, timeo) && !chip_ready(map, adr, &datum))
+ if (time_after(jiffies, timeo) && !chip_good(map, adr, &datum))
break;
- if (chip_ready(map, adr, &datum)) {
+ if (chip_good(map, adr, &datum)) {
xip_enable(map, chip, adr);
goto op_done;
}
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index 9b57a9b1b081..4ead3d1559f5 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -293,6 +293,7 @@ struct cfi_private {
map_word sector_erase_cmd;
unsigned long chipshift; /* Because they're of the same type */
const char *im_name; /* inter_module name for cmdset_setup */
+ unsigned long quirks;
struct flchip chips[0]; /* per-chip data structure for each chip */
};