Skip to contentSkip to conversation

mtd: cfi_util: add support for switching SST 39VF640xB chips into QRY mode

PATCH In review Guillaume LECERF 3 participants 5 messages Oct 26, 2010 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

PATCH 1/3 mtd: cfi_util: add support for switching SST 39VF640xB chips into QRY mode

---
 drivers/mtd/chips/cfi_util.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
drivers/mtd/chips/cfi_util.c +7 -0
index e503b2c..360525c 100644
@@ -77,6 +77,13 @@ int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
 	cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
 	if (cfi_qry_present(map, base, cfi))
 		return 1;
+	/* SST 39VF640xB */
+	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
+	if (cfi_qry_present(map, base, cfi))
+		return 1;
 	/* QRY not found */
 	return 0;
 }
#1 lore raw

PATCH 2/3 mtd: cfi_cmdset_0002: add CFI detection for SST 38VF640x chips

Add support for SST38VF640x chips in CFI mode.

---
 drivers/mtd/chips/cfi_cmdset_0002.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
drivers/mtd/chips/cfi_cmdset_0002.c +26 -0
index 1934476..1cdba02 100644
@@ -293,6 +293,21 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 	cfi->addr_unlock2 = 0x2AA;
 }
 
+static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	fixup_sst39vf_rev_b(mtd, param);
+
+	/*
+	 * CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
+	 * it should report a size of 8KBytes (0x0020 *256).
+	 */
+	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
+	pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);
+}
+
 static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
 {
 	struct map_info *map = mtd->priv;
@@ -344,6 +359,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
 	{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
+	{ CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
+	{ CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
+	{ CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
+	{ CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
 #if !FORCE_WORD_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
 #endif
@@ -374,6 +393,13 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
 	if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
 	    extp->MajorVersion == '0')
 		extp->MajorVersion = '1';
+	/*
+	 * SST 38VF640x chips report major=0xFF / minor=0xFF.
+	 */
+	if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) {
+		extp->MajorVersion = '1';
+		extp->MinorVersion = '0';
+	}
 }
 
 struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
#2 lore raw

Re: [PATCH 2 2/3] mtd: cfi_cmdset_0002: add CFI detection for SST 38VF640x chips

Quoted 16 lines · Guillaume LECERF

Add support for SST38VF640x chips in CFI mode.

---
 drivers/mtd/chips/cfi_cmdset_0002.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
drivers/mtd/chips/cfi_cmdset_0002.c +0 -0
index 1934476..1cdba02 100644
@@ -293,6 +293,21 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 	cfi->addr_unlock2 = 0x2AA;
 }
 

drivers/mtd/chips/cfi_cmdset_0002.c static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) · line 305

Quoted 10 lines
drivers/mtd/chips/cfi_cmdset_0002.c +10 -0
+static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	fixup_sst39vf_rev_b(mtd, param);
+
+	/*
+	 * CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
+	 * it should report a size of 8KBytes (0x0020 *256).

Spaces after operators?

drivers/mtd/chips/cfi_cmdset_0002.c static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) · line 308

Quoted 3 lines
drivers/mtd/chips/cfi_cmdset_0002.c +3 -0
+	 */
+	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
+	pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);

Should be "adjusting", otherwise it sounds like a task for the user to do.

Regards,

Wolfram

Signature · 2 lines
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
#3 lore raw

Re: [PATCH 2 2/3] mtd: cfi_cmdset_0002: add CFI detection for SST 38VF640x chips

Quoted 11 lines · Wolfram Sang

drivers/mtd/chips/cfi_cmdset_0002.c static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) · line 305

Quoted 3 lines
drivers/mtd/chips/cfi_cmdset_0002.c +3 -0
+	/*
+	 * CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
+	 * it should report a size of 8KBytes (0x0020 *256).

Spaces after operators?

drivers/mtd/chips/cfi_cmdset_0002.c static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) · line 308

Quoted 3 lines
drivers/mtd/chips/cfi_cmdset_0002.c +3 -0
+	 */
+	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
+	pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);

Should be "adjusting", otherwise it sounds like a task for the user to do.

And s/KBytes/KiB/ while we're nitpicking.

Signature · 2 lines
David Woodhouse                            Open Source Technology Centre
[email protected]                              Intel Corporation
#4 lore raw

PATCH 3/3 mtd: cfi_cmdset_0002: make sector erase command variable

In reply to Guillaume LECERF

Some old SST chips use 0x50 as sector erase command, instead of 0x30. Make this value variable to handle such chips.

---
 drivers/mtd/chips/cfi_cmdset_0002.c |   10 ++++++----
 drivers/mtd/chips/cfi_probe.c       |    2 ++
 include/linux/mtd/cfi.h             |    1 +
 3 files changed, 9 insertions(+), 4 deletions(-)
drivers/mtd/chips/cfi_cmdset_0002.c +6 -4
index 1cdba02..a6b6a78 100644
@@ -291,6 +291,8 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 
 	cfi->addr_unlock1 = 0x555;
 	cfi->addr_unlock2 = 0x2AA;
+
+	cfi->sector_erase_cmd = 0x50;
 }
 
 static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
@@ -691,7 +693,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 				 * there was an error (so leave the erase
 				 * routine to recover from it) or we trying to
 				 * use the erase-in-progress sector. */
-				map_write(map, CMD(0x30), chip->in_progress_block_addr);
+				map_write(map, CMD(cfi->sector_erase_cmd), chip->in_progress_block_addr);
 				chip->state = FL_ERASING;
 				chip->oldstate = FL_READY;
 				printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
@@ -744,7 +746,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 	switch(chip->oldstate) {
 	case FL_ERASING:
 		chip->state = chip->oldstate;
-		map_write(map, CMD(0x30), chip->in_progress_block_addr);
+		map_write(map, CMD(cfi->sector_erase_cmd), chip->in_progress_block_addr);
 		chip->oldstate = FL_READY;
 		chip->state = FL_ERASING;
 		break;
@@ -887,7 +889,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
 			local_irq_disable();
 
 			/* Resume the write or erase operation */
-			map_write(map, CMD(0x30), adr);
+			map_write(map, CMD(cfi->sector_erase_cmd), adr);
 			chip->state = oldstate;
 			start = xip_currtime();
 		} else if (usec >= 1000000/HZ) {
@@ -1670,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 	cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-	map_write(map, CMD(0x30), adr);
+	map_write(map, CMD(cfi->sector_erase_cmd), adr);
 
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
drivers/mtd/chips/cfi_probe.c +2 -0
index 8f5b96a..f030300 100644
@@ -177,6 +177,8 @@ static int __xipram cfi_chip_setup(struct map_info *map,
 
 	cfi->cfi_mode = CFI_MODE_CFI;
 
+	cfi->sector_erase_cmd = 0x30;
+
 	/* Read the CFI info structure */
 	xip_disable_qry(base, map, cfi);
 	for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
include/linux/mtd/cfi.h +1 -0
index d2118b0..b97a0f8 100644
@@ -289,6 +289,7 @@ struct cfi_private {
 				  must be of the same type. */
 	int mfr, id;
 	int numchips;
+	int sector_erase_cmd;
 	unsigned long chipshift; /* Because they're of the same type */
 	const char *im_name;	 /* inter_module name for cmdset_setup */
 	struct flchip chips[0];  /* per-chip data structure for each chip */