*
* (C) 2000 Red Hat. GPL'd
*
- * $Id: cfi_cmdset_0001.c,v 1.160 2004/11/01 06:02:24 nico Exp $
- * (+ suspend fix from v1.162)
- * (+ partition detection fix from v1.163)
+ * $Id: cfi_cmdset_0001.c,v 1.154 2004/08/09 13:19:43 dwmw2 Exp $
+ *
*
* 10/10/2000 Nicolas Pitre <nico@cam.org>
* - completely revamped method functions so they are aware and
// debugging, turns off buffer write mode if set to 1
#define FORCE_WORD_WRITE 0
-#define MANUFACTURER_INTEL 0x0089
-#define I82802AB 0x00ad
-#define I82802AC 0x00ac
-#define MANUFACTURER_ST 0x0020
-#define M50LPW080 0x002F
-
static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
//static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
//static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
struct mtd_info *cfi_cmdset_0001(struct map_info *, int);
-static struct mtd_info *cfi_intelext_setup (struct mtd_info *);
-static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **);
+static struct mtd_info *cfi_intelext_setup (struct map_info *);
+static int cfi_intelext_partition_fixup(struct map_info *, struct cfi_private **);
static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char **mtdbuf);
static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
size_t len);
-static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
-static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
-#include "fwh_lock.h"
-
-
/*
* *********** SETUP AND PROBE BITS ***********
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
-static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
+static void fixup_intel_strataflash(struct map_info *map, void* param)
{
- struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
}
#endif
-static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
+static void fixup_st_m28w320ct(struct map_info *map, void* param)
{
- struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
cfi->cfiq->BufWriteTimeoutTyp = 0; /* Not supported */
cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */
}
-static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
+static void fixup_st_m28w320cb(struct map_info *map, void* param)
{
- struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
/* Note this is done after the region info is endian swapped */
(cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
};
-static void fixup_use_point(struct mtd_info *mtd, void *param)
-{
- struct map_info *map = mtd->priv;
- if (!mtd->point && map_is_linear(map)) {
- mtd->point = cfi_intelext_point;
- mtd->unpoint = cfi_intelext_unpoint;
- }
-}
-
-static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- if (cfi->cfiq->BufWriteTimeoutTyp) {
- printk(KERN_INFO "Using buffer write method\n" );
- mtd->write = cfi_intelext_write_buffers;
- }
-}
-
-static struct cfi_fixup cfi_fixup_table[] = {
+static struct cfi_fixup fixup_table[] = {
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
- { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
+ {
+ CFI_MFR_ANY, CFI_ID_ANY,
+ fixup_intel_strataflash, NULL
+ },
#endif
-#if !FORCE_WORD_WRITE
- { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL },
-#endif
- { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
- { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
- { 0, 0, NULL, NULL }
-};
-
-static struct cfi_fixup jedec_fixup_table[] = {
- { MANUFACTURER_INTEL, I82802AB, fixup_use_fwh_lock, NULL, },
- { MANUFACTURER_INTEL, I82802AC, fixup_use_fwh_lock, NULL, },
- { MANUFACTURER_ST, M50LPW080, fixup_use_fwh_lock, NULL, },
- { 0, 0, NULL, NULL }
-};
-static struct cfi_fixup fixup_table[] = {
- /* The CFI vendor ids and the JEDEC vendor IDs appear
- * to be common. It is like the devices id's are as
- * well. This table is to pick all cases where
- * we know that is the case.
- */
- { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL },
- { 0, 0, NULL, NULL }
-};
-
-static inline struct cfi_pri_intelext *
-read_pri_intelext(struct map_info *map, __u16 adr)
-{
- struct cfi_pri_intelext *extp;
- unsigned int extp_size = sizeof(*extp);
-
- again:
- extp = (struct cfi_pri_intelext *)cfi_read_pri(map, adr, extp_size, "Intel/Sharp");
- if (!extp)
- return NULL;
-
- /* Do some byteswapping if necessary */
- extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
- extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
- extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);
-
- if (extp->MajorVersion == '1' && extp->MinorVersion == '3') {
- unsigned int extra_size = 0;
- int nb_parts, i;
-
- /* Protection Register info */
- extra_size += (extp->NumProtectionFields - 1) * (4 + 6);
-
- /* Burst Read info */
- extra_size += 6;
-
- /* Number of hardware-partitions */
- extra_size += 1;
- if (extp_size < sizeof(*extp) + extra_size)
- goto need_more;
- nb_parts = extp->extra[extra_size - 1];
-
- for (i = 0; i < nb_parts; i++) {
- struct cfi_intelext_regioninfo *rinfo;
- rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size];
- extra_size += sizeof(*rinfo);
- if (extp_size < sizeof(*extp) + extra_size)
- goto need_more;
- rinfo->NumIdentPartitions=le16_to_cpu(rinfo->NumIdentPartitions);
- extra_size += (rinfo->NumBlockTypes - 1)
- * sizeof(struct cfi_intelext_blockinfo);
- }
-
- if (extp_size < sizeof(*extp) + extra_size) {
- need_more:
- extp_size = sizeof(*extp) + extra_size;
- kfree(extp);
- if (extp_size > 4096) {
- printk(KERN_ERR
- "%s: cfi_pri_intelext is too fat\n",
- __FUNCTION__);
- return NULL;
- }
- goto again;
- }
+ {
+ 0x0020, /* STMicroelectronics */
+ 0x00ba, /* M28W320CT */
+ fixup_st_m28w320ct, NULL
+ }, {
+ 0x0020, /* STMicroelectronics */
+ 0x00bb, /* M28W320CB */
+ fixup_st_m28w320cb, NULL
+ }, {
+ 0, 0, NULL, NULL
}
-
- return extp;
-}
+};
/* This routine is made available to other mtd code via
* inter_module_register. It must only be accessed through
struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
{
struct cfi_private *cfi = map->fldrv_priv;
- struct mtd_info *mtd;
int i;
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
- if (!mtd) {
- printk(KERN_ERR "Failed to allocate memory for MTD device\n");
- return NULL;
- }
- memset(mtd, 0, sizeof(*mtd));
- mtd->priv = map;
- mtd->type = MTD_NORFLASH;
-
- /* Fill in the default mtd operations */
- mtd->erase = cfi_intelext_erase_varsize;
- mtd->read = cfi_intelext_read;
- mtd->write = cfi_intelext_write_words;
- mtd->sync = cfi_intelext_sync;
- mtd->lock = cfi_intelext_lock;
- mtd->unlock = cfi_intelext_unlock;
- mtd->suspend = cfi_intelext_suspend;
- mtd->resume = cfi_intelext_resume;
- mtd->flags = MTD_CAP_NORFLASH;
- mtd->name = map->name;
-
if (cfi->cfi_mode == CFI_MODE_CFI) {
/*
* It's a real CFI chip, not one for which the probe
__u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
struct cfi_pri_intelext *extp;
- extp = read_pri_intelext(map, adr);
- if (!extp) {
- kfree(mtd);
+ extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "Intel/Sharp");
+ if (!extp)
return NULL;
- }
+
+ /* Do some byteswapping if necessary */
+ extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
+ extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask);
+ extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr);
/* Install our own private info structure */
cfi->cmdset_priv = extp;
- cfi_fixup(mtd, cfi_fixup_table);
-
+ cfi_fixup(map, fixup_table);
+
#ifdef DEBUG_CFI_FEATURES
/* Tell the user about it in lots of lovely detail */
cfi_tell_features(extp);
printk(KERN_NOTICE "cfi_cmdset_0001: Erase suspend on write enabled\n");
}
}
- else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
- /* Apply jedec specific fixups */
- cfi_fixup(mtd, jedec_fixup_table);
- }
- /* Apply generic fixups */
- cfi_fixup(mtd, fixup_table);
for (i=0; i< cfi->numchips; i++) {
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
map->fldrv = &cfi_intelext_chipdrv;
- return cfi_intelext_setup(mtd);
+ return cfi_intelext_setup(map);
}
-static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
+static struct mtd_info *cfi_intelext_setup(struct map_info *map)
{
- struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
+ struct mtd_info *mtd;
unsigned long offset = 0;
int i,j;
unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
+ mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
//printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
+ if (!mtd) {
+ printk(KERN_ERR "Failed to allocate memory for MTD device\n");
+ goto setup_err;
+ }
+
+ memset(mtd, 0, sizeof(*mtd));
+ mtd->priv = map;
+ mtd->type = MTD_NORFLASH;
mtd->size = devsize * cfi->numchips;
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
mtd->eraseregions[i].numblocks);
}
+ /* Also select the correct geometry setup too */
+ mtd->erase = cfi_intelext_erase_varsize;
+ mtd->read = cfi_intelext_read;
+
+ if (map_is_linear(map)) {
+ mtd->point = cfi_intelext_point;
+ mtd->unpoint = cfi_intelext_unpoint;
+ }
+
+ if ( cfi->cfiq->BufWriteTimeoutTyp && !FORCE_WORD_WRITE) {
+ printk(KERN_INFO "Using buffer write method\n" );
+ mtd->write = cfi_intelext_write_buffers;
+ } else {
+ printk(KERN_INFO "Using word write method\n" );
+ mtd->write = cfi_intelext_write_words;
+ }
#if 0
mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;
mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;
#endif
+ mtd->sync = cfi_intelext_sync;
+ mtd->lock = cfi_intelext_lock;
+ mtd->unlock = cfi_intelext_unlock;
+ mtd->suspend = cfi_intelext_suspend;
+ mtd->resume = cfi_intelext_resume;
+ mtd->flags = MTD_CAP_NORFLASH;
+ map->fldrv = &cfi_intelext_chipdrv;
+ mtd->name = map->name;
/* This function has the potential to distort the reality
a bit and therefore should be called last. */
- if (cfi_intelext_partition_fixup(mtd, &cfi) != 0)
+ if (cfi_intelext_partition_fixup(map, &cfi) != 0)
goto setup_err;
__module_get(THIS_MODULE);
return NULL;
}
-static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
+static int cfi_intelext_partition_fixup(struct map_info *map,
struct cfi_private **pcfi)
{
- struct map_info *map = mtd->priv;
struct cfi_private *cfi = *pcfi;
struct cfi_pri_intelext *extp = cfi->cmdset_priv;
/*
* Probing of multi-partition flash ships.
*
+ * This is extremely crude at the moment and should probably be
+ * extracted entirely from the Intel extended query data instead.
+ * Right now a L18 flash is assumed if multiple operations is
+ * detected.
+ *
* To support multiple partitions when available, we simply arrange
* for each of them to have their own flchip structure even if they
* are on the same physical chip. This means completely recreating
* arrangement at this point. This can be rearranged in the future
* if someone feels motivated enough. --nico
*/
- if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3'
- && extp->FeatureSupport & (1 << 9)) {
+ if (extp && extp->FeatureSupport & (1 << 9)) {
struct cfi_private *newcfi;
struct flchip *chip;
struct flchip_shared *shared;
- int offs, numregions, numparts, partshift, numvirtchips, i, j;
-
- /* Protection Register info */
- offs = (extp->NumProtectionFields - 1) * (4 + 6);
-
- /* Burst Read info */
- offs += 6;
-
- /* Number of partition regions */
- numregions = extp->extra[offs];
- offs += 1;
-
- /* Number of hardware partitions */
- numparts = 0;
- for (i = 0; i < numregions; i++) {
- struct cfi_intelext_regioninfo *rinfo;
- rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[offs];
- numparts += rinfo->NumIdentPartitions;
- offs += sizeof(*rinfo)
- + (rinfo->NumBlockTypes - 1) *
- sizeof(struct cfi_intelext_blockinfo);
- }
+ int numparts, partshift, numvirtchips, i, j;
/*
- * All functions below currently rely on all chips having
- * the same geometry so we'll just assume that all hardware
- * partitions are of the same size too.
+ * The L18 flash memory array is divided
+ * into multiple 8-Mbit partitions.
*/
- partshift = cfi->chipshift - __ffs(numparts);
-
- if ((1 << partshift) < mtd->erasesize) {
- printk( KERN_ERR
- "%s: bad number of hw partitions (%d)\n",
- __FUNCTION__, numparts);
- return -EINVAL;
- }
-
+ numparts = 1 << (cfi->cfiq->DevSize - 20);
+ partshift = 20 + __ffs(cfi->interleave);
numvirtchips = cfi->numchips * numparts;
+
newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL);
if (!newcfi)
return -ENOMEM;
}
}
- printk(KERN_DEBUG "%s: %d set(s) of %d interleaved chips "
- "--> %d partitions of %d KiB\n",
+ printk(KERN_DEBUG "%s: %d sets of %d interleaved chips "
+ "--> %d partitions of %#x bytes\n",
map->name, cfi->numchips, cfi->interleave,
- newcfi->numchips, 1<<(newcfi->chipshift-10));
+ newcfi->numchips, 1<<newcfi->chipshift);
map->fldrv_priv = newcfi;
*pcfi = newcfi;
return 0;
case FL_ERASING:
- if (!cfip ||
- !(cfip->FeatureSupport & 2) ||
+ if (!(cfip->FeatureSupport & 2) ||
!(mode == FL_READY || mode == FL_POINT ||
(mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
goto sleep;
}
return ret;
}
-
#if 0
static int cfi_intelext_read_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, int base_offst, int reg_sz)
{
int base_offst,reg_sz;
/* Check that we actually have some protection registers */
- if(!extp || !(extp->FeatureSupport&64)){
+ if(!(extp->FeatureSupport&64)){
printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);
return 0;
}
int base_offst,reg_sz;
/* Check that we actually have some protection registers */
- if(!extp || !(extp->FeatureSupport&64)){
+ if(!(extp->FeatureSupport&64)){
printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);
return 0;
}
/* Done and happy. */
chip->state = FL_STATUS;
-
/* check for lock bit */
if (map_word_bitsset(map, status, CMD(0x02))) {
/* clear status */
if (++z > 20) {
/* Argh. Not ready for write to buffer */
- map_word Xstatus;
map_write(map, CMD(0x70), cmd_adr);
chip->state = FL_STATUS;
- Xstatus = map_read(map, cmd_adr);
+ printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %lx, status = %lx\n",
+ status.x[0], map_read(map, cmd_adr).x[0]);
/* Odd. Clear status bits */
map_write(map, CMD(0x50), cmd_adr);
map_write(map, CMD(0x70), cmd_adr);
- printk(KERN_ERR "Chip not ready for buffer write. status = %lx, Xstatus = %lx\n",
- status.x[0], Xstatus.x[0]);
ret = -EIO;
goto out;
}
return 0;
}
+typedef int (*varsize_frob_t)(struct map_info *map, struct flchip *chip,
+ unsigned long adr, int len, void *thunk);
+
+static int cfi_intelext_varsize_frob(struct mtd_info *mtd, varsize_frob_t frob,
+ loff_t ofs, size_t len, void *thunk)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ unsigned long adr;
+ int chipnum, ret = 0;
+ int i, first;
+ struct mtd_erase_region_info *regions = mtd->eraseregions;
+
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ if ((len + ofs) > mtd->size)
+ return -EINVAL;
+
+ /* Check that both start and end of the requested erase are
+ * aligned with the erasesize at the appropriate addresses.
+ */
+
+ i = 0;
+
+ /* Skip all erase regions which are ended before the start of
+ the requested erase. Actually, to save on the calculations,
+ we skip to the first erase region which starts after the
+ start of the requested erase, and then go back one.
+ */
+
+ while (i < mtd->numeraseregions && ofs >= regions[i].offset)
+ i++;
+ i--;
+
+ /* OK, now i is pointing at the erase region in which this
+ erase request starts. Check the start of the requested
+ erase range is aligned with the erase size which is in
+ effect here.
+ */
+
+ if (ofs & (regions[i].erasesize-1))
+ return -EINVAL;
+
+ /* Remember the erase region we start on */
+ first = i;
+
+ /* Next, check that the end of the requested erase is aligned
+ * with the erase region at that address.
+ */
+
+ while (i<mtd->numeraseregions && (ofs + len) >= regions[i].offset)
+ i++;
+
+ /* As before, drop back one to point at the region in which
+ the address actually falls
+ */
+ i--;
+
+ if ((ofs + len) & (regions[i].erasesize-1))
+ return -EINVAL;
+
+ chipnum = ofs >> cfi->chipshift;
+ adr = ofs - (chipnum << cfi->chipshift);
+
+ i=first;
+
+ while(len) {
+ unsigned long chipmask;
+ int size = regions[i].erasesize;
+
+ ret = (*frob)(map, &cfi->chips[chipnum], adr, size, thunk);
+
+ if (ret)
+ return ret;
+
+ adr += size;
+ len -= size;
+
+ chipmask = (1 << cfi->chipshift) - 1;
+ if ((adr & chipmask) == ((regions[i].offset + size * regions[i].numblocks) & chipmask))
+ i++;
+
+ if (adr >> cfi->chipshift) {
+ adr = 0;
+ chipnum++;
+
+ if (chipnum >= cfi->numchips)
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
static int do_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr, int len, void *thunk)
{
/* OK Still waiting */
if (time_after(jiffies, timeo)) {
- map_word Xstatus;
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
- Xstatus = map_read(map, adr);
+ printk(KERN_ERR "waiting for erase at %08lx to complete timed out. Xstatus = %lx, status = %lx.\n",
+ adr, status.x[0], map_read(map, adr).x[0]);
/* Clear status bits */
map_write(map, CMD(0x50), adr);
map_write(map, CMD(0x70), adr);
- printk(KERN_ERR "waiting for erase at %08lx to complete timed out. status = %lx, Xstatus = %lx.\n",
- adr, status.x[0], Xstatus.x[0]);
- ret = -EIO;
- goto out;
+ DISABLE_VPP(map);
+ spin_unlock(chip->mutex);
+ return -EIO;
}
/* Latency issues. Drop the lock, wait a while and retry */
schedule_timeout(1);
spin_lock(chip->mutex);
}
+
+ DISABLE_VPP(map);
+ ret = 0;
/* We've broken this before. It doesn't hurt to be safe */
map_write(map, CMD(0x70), adr);
/* check for lock bit */
if (map_word_bitsset(map, status, CMD(0x3a))) {
- unsigned char chipstatus;
-
- /* Reset the error bits */
- map_write(map, CMD(0x50), adr);
- map_write(map, CMD(0x70), adr);
-
- chipstatus = status.x[0];
+ unsigned char chipstatus = status.x[0];
if (!map_word_equal(map, status, CMD(chipstatus))) {
int i, w;
for (w=0; w<map_words(map); w++) {
printk(KERN_WARNING "Status is not identical for all chips: 0x%lx. Merging to give 0x%02x\n",
status.x[0], chipstatus);
}
-
+ /* Reset the error bits */
+ map_write(map, CMD(0x50), adr);
+ map_write(map, CMD(0x70), adr);
+
if ((chipstatus & 0x30) == 0x30) {
printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus);
ret = -EIO;
if (retries--) {
printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, chipstatus);
timeo = jiffies + HZ;
- put_chip(map, chip, adr);
+ chip->state = FL_STATUS;
spin_unlock(chip->mutex);
goto retry;
}
printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus);
ret = -EIO;
}
- } else {
- ret = 0;
}
- out: put_chip(map, chip, adr);
+ wake_up(&chip->wq);
spin_unlock(chip->mutex);
return ret;
}
ofs = instr->addr;
len = instr->len;
- ret = cfi_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
+ ret = cfi_intelext_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
if (ret)
return ret;
unsigned long adr, int len, void *thunk)
{
struct cfi_private *cfi = map->fldrv_priv;
- int status, ofs_factor = cfi->interleave * cfi->device_type;
+ int ofs_factor = cfi->interleave * cfi->device_type;
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
- chip->state = FL_JEDEC_QUERY;
- status = cfi_read_query(map, adr+(2*ofs_factor));
printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
- adr, status);
+ adr, cfi_read_query(map, adr+(2*ofs_factor)));
+ chip->state = FL_JEDEC_QUERY;
return 0;
}
#endif
/* OK Still waiting */
if (time_after(jiffies, timeo)) {
- map_word Xstatus;
map_write(map, CMD(0x70), adr);
chip->state = FL_STATUS;
- Xstatus = map_read(map, adr);
- printk(KERN_ERR "waiting for unlock to complete timed out. status = %lx, Xstatus = %lx.\n",
- status.x[0], Xstatus.x[0]);
- put_chip(map, chip, adr);
+ printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %lx, status = %lx.\n",
+ status.x[0], map_read(map, adr).x[0]);
+ DISABLE_VPP(map);
spin_unlock(chip->mutex);
return -EIO;
}
#ifdef DEBUG_LOCK_BITS
printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
__FUNCTION__, ofs, len);
- cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
- ofs, len, 0);
+ cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, 0);
#endif
- ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
- ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
+ ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock,
+ ofs, len, DO_XXLOCK_ONEBLOCK_LOCK);
#ifdef DEBUG_LOCK_BITS
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
__FUNCTION__, ret);
- cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
- ofs, len, 0);
+ cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, 0);
#endif
return ret;
#ifdef DEBUG_LOCK_BITS
printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
__FUNCTION__, ofs, len);
- cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
- ofs, len, 0);
+ cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, 0);
#endif
- ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
+ ret = cfi_intelext_varsize_frob(mtd, do_xxlock_oneblock,
ofs, len, DO_XXLOCK_ONEBLOCK_UNLOCK);
#ifdef DEBUG_LOCK_BITS
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
__FUNCTION__, ret);
- cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
- ofs, len, 0);
+ cfi_intelext_varsize_frob(mtd, do_printlockstatus_oneblock,
+ ofs, len, 0);
#endif
return ret;
* as the whole point is that nobody can do anything
* with the chip now anyway.
*/
- } else {
- /* There seems to be an operation pending. We must wait for it. */
- printk(KERN_NOTICE "Flash device refused suspend due to pending operation (oldstate %d)\n", chip->oldstate);
- ret = -EAGAIN;
}
break;
default:
- /* Should we actually wait? Once upon a time these routines weren't
- allowed to. Or should we return -EAGAIN, because the upper layers
- ought to have already shut down anything which was using the device
- anyway? The latter for now. */
- printk(KERN_NOTICE "Flash device refused suspend due to active operation (state %d)\n", chip->oldstate);
ret = -EAGAIN;
case FL_PM_SUSPENDED:
break;
because we're returning failure, and it didn't
get power cycled */
chip->state = chip->oldstate;
- chip->oldstate = FL_READY;
wake_up(&chip->wq);
}
spin_unlock(chip->mutex);
/* Go to known state. Chip may have been power cycled */
if (chip->state == FL_PM_SUSPENDED) {
map_write(map, CMD(0xFF), cfi->chips[i].start);
- chip->oldstate = chip->state = FL_READY;
+ chip->state = FL_READY;
wake_up(&chip->wq);
}