New Intel chip with CFIext version 1.3 not working.
Jarkko Lavinen
jlavi at iki.fi
Wed Nov 14 04:53:35 EST 2001
Is anybody using Intel chips with extended CFI query version 1.3?
Current version of the cfi_cmdset_0001.c rejects the chip and accepts
only the extended CFI versions 1.0, 1.1, and 1.2. The chip I am trying
to get working is Intel's 28F640W18 and its datasheet is available
from http://www.intel.com/design/flash/datashts/index.htm. The
extended query is specified at the page 71 of the datasheet.
I tried to modify the driver by allowing also the extemded CFI version
1.3. After that the chip was accepted but sectors were locked and
writes failed The unlock function unlocked only the first sector, not
the whole region requested.
I modified the function cfi_intelext_unlock() to unlock the whole
region requested. After that it was possible to unlock the chip and
also erase it with erase_all. Mounting JFFS2, however, fails.
JFFS2 mount seems to fail because the chip has 4mbit partitions and
each of them has their own status. When the mount scans flash chip
contents and proceeds past the partition boundary, the status is not
anymore the same as in the previous boundary.
What happens is that cfi_cmdset_0001.c keeps the chip at state
FL_STATUS and when the mount proceeds to address 0x80000 it fails
because the chip is at read array mode and returns flash contents, not
the partition status.
I have attached the changes I made in cfi_cmdset_0001.c to get to this
point.
Could anyone help me on solving this problem? Suggestions, please?
Jarkko Lavinen
----
Changes in function cfi_cmdset_0001():
if (extp->MajorVersion != '1' ||
+#if 0
(extp->MinorVersion < '0' || extp->MinorVersion > '2')) {
+#else
+ (extp->MinorVersion < '0' || extp->MinorVersion > '3')) {
+#endif
printk(KERN_WARNING " Unknown IntelExt Extended Query "
"version %c.%c.\n", extp->MajorVersion,
extp->MinorVersion);
The function cfi_intelext_unlock() after my changes:
static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
int eraseoffset, erasesize, eraseblocks;
unsigned long adr;
int chipnum, ernum, ret = 0;
#ifdef DEBUG_LOCK_BITS
int ofs_factor = cfi->interleave * cfi->device_type;
unsigned long temp_adr = adr;
unsigned long temp_len = len;
#endif
/* Pass the whole chip through sector by sector and check for each
sector if the sector and the given interval overlap */
for(ernum = 0; ernum < mtd->numeraseregions; ernum++) {
struct mtd_erase_region_info *erp = &mtd->eraseregions[ernum];
eraseoffset = erp->offset;
erasesize = erp->erasesize;
eraseblocks = erp->numblocks;
#ifdef DEBUG_LOCK_BITS
printk("Erase offset %08x size %06x blocks %d\n",
eraseoffset, erasesize, eraseblocks);
#endif
if (ofs > eraseoffset + erasesize)
continue;
while (eraseblocks > 0) {
if (ofs < eraseoffset + erasesize &&
ofs + len > eraseoffset) {
chipnum = eraseoffset >> cfi->chipshift;
adr = eraseoffset -
(chipnum << cfi->chipshift);
#ifdef DEBUG_LOCK_BITS
temp_adr = adr;
temp_len = len;
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi,
cfi->device_type, NULL);
while (temp_len) {
printk("before unlock %x: block "
"status register is %x\n",
temp_adr, cfi_read_query(map, temp_adr+(2*ofs_factor)));
temp_adr += mtd->erasesize;
temp_len -= mtd->erasesize;
}
cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi,
cfi->device_type, NULL);
#endif
ret = do_unlock_oneblock(map,
&cfi->chips[chipnum],
adr);
#ifdef DEBUG_LOCK_BITS
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi,
cfi->device_type, NULL);
printk("after unlock: block status register "
"is %x\n",
cfi_read_query(map, adr+(2*ofs_factor)));
cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi,
cfi->device_type, NULL);
#endif
}
eraseoffset += erasesize;
eraseblocks --;
}
}
return ret;
}
More information about the linux-mtd
mailing list