how to handle Atmel fixup -- swapping erase regions

Kumar Gala galak at kernel.crashing.org
Sun Mar 11 19:23:22 EDT 2007


I'm working with a Atmel AT49BV162A and it appears that the device reports
the order of erase sectors incorrectly:

Number of Erase Block Regions: 2
  Erase Region #0: BlockSize 0x10000 bytes, 31 blocks
  Erase Region #1: BlockSize 0x2000 bytes, 8 blocks

Amd/Fujitsu Extended Query Table at 0x0041
  Silicon revision: 0
  Address sensitive unlock: Required
  Erase Suspend: Read/write
  Block protection: Not supported
  Temporary block unprotect: Not supported
  Block protect/unprotect scheme: 0
  Number of simultaneous operations: 0
  Burst mode: Not supported
  Page mode: Not supported
  Vpp Supply Minimum Program/Erase Voltage: 0.0 V
  Vpp Supply Maximum Program/Erase Voltage: 0.0 V
  Top/Bottom Boot Block: Bottom boot

When the devices are 'Bottom boot' region 0 should be 8/8k blocks, and
region 1 should be 31/64k blocks.

I'm not sure how many other Atmel devices this effects.  I was wondering
what the best way to implement the fixup was.  Something like:

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 702ae4c..9b47f2b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -50,6 +50,7 @@
 #define SST49LF004B	        0x0060
 #define SST49LF008A		0x005a
 #define AT49BV6416		0x00d6
+#define AT49BV162		0x00c0

 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 *);
@@ -215,6 +216,27 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
 	mtd->flags |= MTD_STUPID_LOCK;
 }

+static void fixup_swap_atmel(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;
+	unsigned char bootloc = extp->TopBottom;
+
+	if (bootloc == 2 && cfi->cfiq->NumEraseRegions > 1) {
+		int i;
+
+		for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
+			int j = (cfi->cfiq->NumEraseRegions-1)-i;
+			__u32 swap;
+
+			swap = cfi->cfiq->EraseRegionInfo[i];
+			cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
+			cfi->cfiq->EraseRegionInfo[j] = swap;
+		}
+	}
+}
+
 static struct cfi_fixup cfi_fixup_table[] = {
 #ifdef AMD_BOOTLOC_BUG
 	{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
@@ -245,6 +267,7 @@ static struct cfi_fixup fixup_table[] = {
 	 */
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
 	{ CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL },
+	{ CFI_MFR_ATMEL, AT49BV162, fixup_swap_atmel, NULL },
 	{ 0, 0, NULL, NULL }
 };

diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c





More information about the linux-mtd mailing list