mtd/drivers/mtd/chips cfi_cmdset_0001.c,1.142,1.143
Nicolas Pitre
nico at infradead.org
Wed Jun 9 14:35:54 EDT 2004
Update of /home/cvs/mtd/drivers/mtd/chips
In directory phoenix.infradead.org:/tmp/cvs-serv27991/drivers/mtd/chips
Modified Files:
cfi_cmdset_0001.c
Log Message:
No, I'm nuts. My curent approach for L18 support is getting more
and more messy as I consider all the details that were still missing
and needed extra mods here and there. When I can't stand my own code
anymore that's a sign that the whole thing should be scrapped. And
this commit is exactly that. Stay tuned for an alternate approach.
Index: cfi_cmdset_0001.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/chips/cfi_cmdset_0001.c,v
retrieving revision 1.142
retrieving revision 1.143
diff -u -r1.142 -r1.143
--- cfi_cmdset_0001.c 8 Jun 2004 21:26:21 -0000 1.142
+++ cfi_cmdset_0001.c 9 Jun 2004 18:35:51 -0000 1.143
@@ -216,35 +216,10 @@
}
for (i=0; i< cfi->numchips; i++) {
- struct flchip *chip = &cfi->chips[i];
- chip->word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
- chip->buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
- chip->erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
- chip->ref_point_counter = 0;
-
- /*
- * Probing of multi-partition flash ships.
- * This is extremely crude at the moment and should be
- * extracted entirely from the Intel extended query
- * data instead.
- */
- if (cfi->cmdset_priv) {
- struct cfi_pri_intelext *extp = cfi->cmdset_priv;
- if (extp->FeatureSupport & (1 << 9)) {
- /*
- * The L18 flash memory array is divided
- * into multiple 8-Mbit partitions.
- */
- int nbparts = 1 << (cfi->cfiq->DevSize - 20);
- chip->partshift = __ffs(cfi->interleave) + 20;
- chip->parts = kmalloc(nbparts * sizeof(*chip->parts), GFP_KERNEL);
- if (!chip->parts) {
- kfree(extp);
- return NULL;
- }
- memset(chip->parts, 0, nbparts * sizeof(*chip->parts));
- }
- }
+ cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
+ cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
+ cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+ cfi->chips[i].ref_point_counter = 0;
}
map->fldrv = &cfi_intelext_chipdrv;
@@ -354,82 +329,7 @@
* *********** CHIP ACCESS FUNCTIONS ***********
*/
-static flstate_t get_state(struct flchip *chip, unsigned long adr)
-{
- flstate_t state = chip->state;
- if (chip->parts) {
- int part = (adr - chip->start) >> chip->partshift;
- state = chip->parts[part].state;
- }
- return state;
-}
-
-static void set_state(struct flchip *chip, unsigned long adr, flstate_t mode)
-{
- if (!chip->parts) {
- chip->state = mode;
- } else {
- int part = (adr - chip->start) >> chip->partshift;
- chip->parts[part].state = mode;
- /* erasing and writing are global states to the chip */
- switch (mode) {
- case FL_ERASING:
- chip->in_progress_block_addr = adr;
- case FL_ERASE_SUSPENDING:
- case FL_ERASE_SUSPENDED:
- case FL_WRITING:
- case FL_WRITING_TO_BUFFER:
- case FL_WRITE_SUSPENDING:
- case FL_WRITE_SUSPENDED:
- chip->state = mode;
- default:
- chip->state = FL_READY;
- }
- }
-}
-
-static flstate_t get_oldstate(struct flchip *chip, unsigned long adr)
-{
- flstate_t state = chip->oldstate;
- if (chip->parts) {
- int part = (adr - chip->start) >> chip->partshift;
- state = chip->parts[part].oldstate;
- }
- return state;
-}
-
-static void set_oldstate(struct flchip *chip, unsigned long adr, flstate_t mode)
-{
- if (!chip->parts) {
- chip->oldstate = mode;
- } else {
- int part = (adr - chip->start) >> chip->partshift;
- chip->parts[part].oldstate = mode;
- /* erasing and writing are still global states to the chip */
- switch (mode) {
- case FL_ERASING:
- case FL_ERASE_SUSPENDING:
- case FL_ERASE_SUSPENDED:
- case FL_WRITING:
- case FL_WRITING_TO_BUFFER:
- case FL_WRITE_SUSPENDING:
- case FL_WRITE_SUSPENDED:
- chip->oldstate = mode;
- default:
- chip->oldstate = FL_READY;
- }
- }
-}
-
-static inline int same_partition(struct flchip *chip,
- unsigned long addr_a, unsigned long addr_b)
-{
- if (!chip->parts)
- return 1;
- return (((addr_a ^ addr_b) >> chip->partshift) == 0);
-}
-
-static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, flstate_t mode)
+static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
{
DECLARE_WAITQUEUE(wait, current);
struct cfi_private *cfi = map->fldrv_priv;
@@ -440,23 +340,7 @@
resettime:
timeo = jiffies + HZ;
retry:
- if ( !same_partition(chip, adr, chip->in_progress_block_addr) &&
- !(chip->state == FL_READY && chip->oldstate == FL_READY) &&
- (mode == FL_WRITING || mode == FL_ERASING) ) {
- /*
- * OK. We have contension on the write/erase operations
- * which are global to the chip and not per partition.
- * So let's fight it over in the partition where the
- * write/erase is currently occurring first.
- */
- int ret = get_chip(map, chip, chip->in_progress_block_addr, mode);
- if (ret)
- return ret;
- chip->suspender_block_addr = adr;
- timeo = jiffies + HZ;
- }
-
- switch (get_state(chip, adr)) {
+ switch (chip->state) {
case FL_STATUS:
for (;;) {
@@ -498,8 +382,8 @@
* mode so we get the right data. --rmk
*/
cfi_write(map, CMD(0x70), adr);
- set_oldstate(chip, adr, FL_ERASING);
- set_state(chip, adr, FL_ERASE_SUSPENDING);
+ chip->oldstate = FL_ERASING;
+ chip->state = FL_ERASE_SUSPENDING;
chip->erase_suspended = 1;
for (;;) {
status = cfi_read(map, adr);
@@ -511,8 +395,8 @@
cfi_write(map, CMD(0xd0), adr);
/* Make sure we're in 'read status' mode if it had finished */
cfi_write(map, CMD(0x70), adr);
- set_state(chip, adr, FL_ERASING);
- set_oldstate(chip, adr, FL_READY);
+ chip->state = FL_ERASING;
+ chip->oldstate = FL_READY;
printk(KERN_ERR "Chip not ready after erase "
"suspended: status = 0x%x\n", status);
return -EIO;
@@ -524,12 +408,12 @@
/* Nobody will touch it while it's in state FL_ERASE_SUSPENDING.
So we can just loop here. */
}
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
return 0;
case FL_POINT:
/* Only if there's no operation suspended... */
- if (mode == FL_READY && get_state(chip, adr) == FL_READY)
+ if (mode == FL_READY && chip->oldstate == FL_READY)
return 0;
default:
@@ -548,13 +432,9 @@
{
struct cfi_private *cfi = map->fldrv_priv;
- if ( !same_partition(chip, adr, chip->in_progress_block_addr) &&
- same_partition(chip, adr, chip->suspender_block_addr) &&
- chip->oldstate != FL_READY )
- put_chip(map, chip, chip->in_progress_block_addr);
-
- switch(get_oldstate(chip, adr)) {
+ switch(chip->oldstate) {
case FL_ERASING:
+ chip->state = chip->oldstate;
/* What if one interleaved chip has finished and the
other hasn't? The old code would leave the finished
one in READY mode. That's bad, and caused -EROFS
@@ -566,8 +446,8 @@
do. */
cfi_write(map, CMD(0xd0), adr);
cfi_write(map, CMD(0x70), adr);
- set_oldstate(chip, adr, FL_READY);
- set_state(chip, adr, FL_ERASING);
+ chip->oldstate = FL_READY;
+ chip->state = FL_ERASING;
break;
case FL_READY:
@@ -577,7 +457,7 @@
DISABLE_VPP(map);
break;
default:
- printk(KERN_ERR "put_chip() called with oldstate %d!!\n", get_oldstate(chip, adr));
+ printk(KERN_ERR "put_chip() called with oldstate %d!!\n", chip->oldstate);
}
wake_up(&chip->wq);
}
@@ -598,15 +478,10 @@
ret = get_chip(map, chip, cmd_addr, FL_POINT);
if (!ret) {
- switch (get_state(chip, cmd_addr)) {
- case FL_POINT:
- case FL_READY:
- break;
- default:
+ if (chip->state != FL_POINT && chip->state != FL_READY)
cfi_write(map, CMD(0xff), cmd_addr);
- }
- set_state(chip, cmd_addr, FL_POINT);
+ chip->state = FL_POINT;
chip->ref_point_counter++;
}
spin_unlock(chip->mutex);
@@ -674,7 +549,6 @@
while (len) {
unsigned long thislen;
struct flchip *chip;
- unsigned long cmd_addr;
chip = &cfi->chips[chipnum];
if (chipnum >= cfi->numchips)
@@ -685,17 +559,15 @@
else
thislen = len;
- cmd_addr = (chip->start + ofs) & ~(CFIDEV_BUSWIDTH-1);
-
spin_lock(chip->mutex);
- if (get_state(chip, cmd_addr) == FL_POINT) {
+ if (chip->state == FL_POINT) {
chip->ref_point_counter--;
if(chip->ref_point_counter == 0)
- set_state(chip, cmd_addr, FL_READY);
+ chip->state = FL_READY;
} else
printk(KERN_ERR "Warning: unpoint called on non pointed region\n"); /* Should this give an error? */
- put_chip(map, chip, cmd_addr);
+ put_chip(map, chip, chip->start);
spin_unlock(chip->mutex);
len -= thislen;
@@ -722,13 +594,10 @@
return ret;
}
- switch (get_state(chip, cmd_addr)) {
- case FL_POINT:
- case FL_READY:
- break;
- default:
+ if (chip->state != FL_POINT && chip->state != FL_READY) {
cfi_write(map, CMD(0xff), cmd_addr);
- set_state(chip, cmd_addr, FL_READY);
+
+ chip->state = FL_READY;
}
map_copy_from(map, buf, adr, len);
@@ -807,9 +676,9 @@
return (len-count)?:ret;
}
- if (get_state(chip, chip->start) != FL_JEDEC_QUERY) {
+ if (chip->state != FL_JEDEC_QUERY) {
cfi_write(map, CMD(0x90), chip->start);
- set_state(chip, chip->start, FL_JEDEC_QUERY);
+ chip->state = FL_JEDEC_QUERY;
}
while (count && ((offst-base_offst) < reg_sz)) {
@@ -892,7 +761,7 @@
ENABLE_VPP(map);
cfi_write(map, CMD(0x40), adr);
cfi_write(map, datum, adr);
- set_state(chip, adr, FL_WRITING);
+ chip->state = FL_WRITING;
spin_unlock(chip->mutex);
INVALIDATE_CACHED_RANGE(map, adr, CFIDEV_BUSWIDTH);
@@ -902,7 +771,7 @@
timeo = jiffies + (HZ/2);
z = 0;
for (;;) {
- if (get_state(chip, adr) != FL_WRITING) {
+ if (chip->state != FL_WRITING) {
/* Someone's suspended the write. Sleep */
DECLARE_WAITQUEUE(wait, current);
@@ -922,7 +791,7 @@
/* OK Still waiting */
if (time_after(jiffies, timeo)) {
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
printk(KERN_ERR "waiting for chip to be ready timed out in word write\n");
ret = -EIO;
goto out;
@@ -943,7 +812,7 @@
chip->word_write_time++;
/* Done and happy. */
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
/* check for lock bit */
if (status & CMD(0x02)) {
/* clear status */
@@ -1108,7 +977,7 @@
[...], the device will not accept any more Write to Buffer commands".
So we must check here and reset those bits if they're set. Otherwise
we're just pissing in the wind */
- if (get_state(chip, cmd_adr) != FL_STATUS)
+ if (chip->state != FL_STATUS)
cfi_write(map, CMD(0x70), cmd_adr);
status = cfi_read(map, cmd_adr);
if (status & CMD(0x30)) {
@@ -1118,11 +987,12 @@
}
ENABLE_VPP(map);
- set_state(chip, cmd_adr, FL_WRITING_TO_BUFFER);
+ chip->state = FL_WRITING_TO_BUFFER;
z = 0;
for (;;) {
cfi_write(map, CMD(0xe8), cmd_adr);
+
status = cfi_read(map, cmd_adr);
if ((status & status_OK) == status_OK)
break;
@@ -1134,7 +1004,7 @@
if (++z > 20) {
/* Argh. Not ready for write to buffer */
cfi_write(map, CMD(0x70), cmd_adr);
- set_state(chip, cmd_adr, FL_STATUS);
+ chip->state = FL_STATUS;
printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %llx, status = %llx\n", (__u64)status, (__u64)cfi_read(map, cmd_adr));
/* Odd. Clear status bits */
cfi_write(map, CMD(0x50), cmd_adr);
@@ -1185,7 +1055,7 @@
}
/* GO GO GO */
cfi_write(map, CMD(0xd0), cmd_adr);
- set_state(chip, cmd_adr, FL_WRITING);
+ chip->state = FL_WRITING;
spin_unlock(chip->mutex);
INVALIDATE_CACHED_RANGE(map, adr, len);
@@ -1195,7 +1065,7 @@
timeo = jiffies + (HZ/2);
z = 0;
for (;;) {
- if (get_state(chip, cmd_adr) != FL_WRITING) {
+ if (chip->state != FL_WRITING) {
/* Someone's suspended the write. Sleep */
DECLARE_WAITQUEUE(wait, current);
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -1214,7 +1084,7 @@
/* OK Still waiting */
if (time_after(jiffies, timeo)) {
- set_state(chip, cmd_adr, FL_STATUS);
+ chip->state = FL_STATUS;
printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n");
ret = -EIO;
goto out;
@@ -1235,7 +1105,7 @@
chip->buffer_write_time++;
/* Done and happy. */
- set_state(chip, cmd_adr, FL_STATUS);
+ chip->state = FL_STATUS;
/* check for lock bit */
if (status & CMD(0x02)) {
@@ -1442,7 +1312,7 @@
/* Now erase */
cfi_write(map, CMD(0x20), adr);
cfi_write(map, CMD(0xD0), adr);
- set_state(chip, adr, FL_ERASING);
+ chip->state = FL_ERASING;
chip->erase_suspended = 0;
spin_unlock(chip->mutex);
@@ -1456,7 +1326,7 @@
timeo = jiffies + (HZ*20);
for (;;) {
- if (get_state(chip, adr) != FL_ERASING) {
+ if (chip->state != FL_ERASING) {
/* Someone's suspended the erase. Sleep */
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
@@ -1480,7 +1350,7 @@
/* OK Still waiting */
if (time_after(jiffies, timeo)) {
cfi_write(map, CMD(0x70), adr);
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
printk(KERN_ERR "waiting for erase at %08lx to complete timed out. Xstatus = %llx, status = %llx.\n",
adr, (__u64)status, (__u64)cfi_read(map, adr));
/* Clear status bits */
@@ -1503,7 +1373,7 @@
/* We've broken this before. It doesn't hurt to be safe */
cfi_write(map, CMD(0x70), adr);
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
status = cfi_read(map, adr);
/* check for lock bit */
@@ -1534,7 +1404,7 @@
if (retries--) {
printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%llx. Retrying...\n", adr, (__u64)status);
timeo = jiffies + HZ;
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
spin_unlock(chip->mutex);
goto retry;
}
@@ -1582,8 +1452,8 @@
ret = get_chip(map, chip, chip->start, FL_SYNCING);
if (!ret) {
- set_oldstate(chip, chip->start, get_state(chip, chip->start));
- set_state(chip, chip->start, FL_SYNCING);
+ chip->oldstate = chip->state;
+ chip->state = FL_SYNCING;
/* No need to wake_up() on this state change -
* as the whole point is that nobody can do anything
* with the chip now anyway.
@@ -1599,8 +1469,8 @@
spin_lock(chip->mutex);
- if (get_state(chip, chip->start) == FL_SYNCING) {
- set_state(chip, chip->start, get_oldstate(chip, chip->start));
+ if (chip->state == FL_SYNCING) {
+ chip->state = chip->oldstate;
wake_up(&chip->wq);
}
spin_unlock(chip->mutex);
@@ -1617,7 +1487,7 @@
cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
printk(KERN_DEBUG "block status register for 0x%08lx is %x\n",
adr, cfi_read_query(map, adr+(2*ofs_factor)));
- set_state(chip, chip->start, FL_JEDEC_QUERY);
+ chip->state = FL_JEDEC_QUERY;
return 0;
}
#endif
@@ -1650,10 +1520,10 @@
if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
cfi_write(map, CMD(0x01), adr);
- set_state(chip, adr, FL_LOCKING);
+ chip->state = FL_LOCKING;
} else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) {
cfi_write(map, CMD(0xD0), adr);
- set_state(chip, adr, FL_UNLOCKING);
+ chip->state = FL_UNLOCKING;
} else
BUG();
@@ -1674,7 +1544,7 @@
/* OK Still waiting */
if (time_after(jiffies, timeo)) {
cfi_write(map, CMD(0x70), adr);
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %llx, status = %llx.\n", (__u64)status, (__u64)cfi_read(map, adr));
DISABLE_VPP(map);
spin_unlock(chip->mutex);
@@ -1688,7 +1558,7 @@
}
/* Done and happy. */
- set_state(chip, adr, FL_STATUS);
+ chip->state = FL_STATUS;
put_chip(map, chip, adr);
spin_unlock(chip->mutex);
return 0;
@@ -1754,14 +1624,14 @@
spin_lock(chip->mutex);
- switch (get_state(chip, chip->start)) {
+ switch (chip->state) {
case FL_READY:
case FL_STATUS:
case FL_CFI_QUERY:
case FL_JEDEC_QUERY:
- if (get_oldstate(chip, chip->start) == FL_READY) {
- set_oldstate(chip, chip->start, get_state(chip, chip->start));
- set_state(chip, chip->start, FL_PM_SUSPENDED);
+ if (chip->oldstate == FL_READY) {
+ chip->oldstate = chip->state;
+ chip->state = FL_PM_SUSPENDED;
/* No need to wake_up() on this state change -
* as the whole point is that nobody can do anything
* with the chip now anyway.
@@ -1784,11 +1654,11 @@
spin_lock(chip->mutex);
- if (get_state(chip, chip->start) == FL_PM_SUSPENDED) {
+ if (chip->state == FL_PM_SUSPENDED) {
/* No need to force it into a known state here,
because we're returning failure, and it didn't
get power cycled */
- set_state(chip, chip->start, get_oldstate(chip, chip->start));
+ chip->state = chip->oldstate;
wake_up(&chip->wq);
}
spin_unlock(chip->mutex);
@@ -1812,9 +1682,9 @@
spin_lock(chip->mutex);
/* Go to known state. Chip may have been power cycled */
- if (get_state(chip, chip->start) == FL_PM_SUSPENDED) {
+ if (chip->state == FL_PM_SUSPENDED) {
cfi_write(map, CMD(0xFF), cfi->chips[i].start);
- set_state(chip, chip->start, FL_READY);
+ chip->state = FL_READY;
wake_up(&chip->wq);
}
@@ -1824,13 +1694,10 @@
static void cfi_intelext_destroy(struct mtd_info *mtd)
{
- int i;
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
kfree(cfi->cmdset_priv);
kfree(cfi->cfiq);
- for (i = 0; i < cfi->numchips; i++)
- kfree(cfi->chips[i].parts);
kfree(cfi);
kfree(mtd->eraseregions);
}
More information about the linux-mtd-cvs
mailing list