patch-2.4.6 linux/drivers/mtd/cfi_cmdset_0001.c
Next file: linux/drivers/mtd/cfi_cmdset_0002.c
Previous file: linux/drivers/mtd/bootldr.c
Back to the patch index
Back to the overall index
- Lines: 892
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.4.5/linux/drivers/mtd/cfi_cmdset_0001.c
- Orig date:
Fri Feb 9 11:30:23 2001
diff -u --recursive --new-file v2.4.5/linux/drivers/mtd/cfi_cmdset_0001.c linux/drivers/mtd/cfi_cmdset_0001.c
@@ -1,891 +0,0 @@
-/*
- * Common Flash Interface support:
- * Intel Extended Vendor Command Set (ID 0x0001)
- *
- * (C) 2000 Red Hat. GPL'd
- *
- * $Id: cfi_cmdset_0001.c,v 1.21 2000/07/13 10:36:14 dwmw2 Exp $
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/io.h>
-#include <asm/byteorder.h>
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/cfi.h>
-
-#if LINUX_VERSION_CODE < 0x20300
-#define set_current_state(x) current->state = (x);
-#endif
-static int cfi_intelext_read_1_by_16 (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
-static int cfi_intelext_write_1_by_16(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
-static int cfi_intelext_erase_1_by_16 (struct mtd_info *, struct erase_info *);
-static void cfi_intelext_sync (struct mtd_info *);
-static int cfi_intelext_suspend (struct mtd_info *);
-static void cfi_intelext_resume (struct mtd_info *);
-
-static void cfi_intelext_destroy(struct mtd_info *);
-
-static void cfi_cmdset_0001(struct map_info *, int, unsigned long);
-
-static struct mtd_info *cfi_intelext_setup (struct map_info *);
-
-static const char im_name[] = "cfi_cmdset_0001";
-
-/* This routine is made available to other mtd code via
- * inter_module_register. It must only be accessed through
- * inter_module_get which will bump the use count of this module. The
- * addresses passed back in cfi are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
-static void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base)
-{
- struct cfi_private *cfi = map->fldrv_priv;
- int i;
- struct cfi_pri_intelext *extp;
-
- __u16 adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR;
-
- printk(" Intel/Sharp Extended Query Table at 0x%4.4X\n", adr);
-
- if (!adr)
- return;
-
- /* Switch it into Query Mode */
- switch(map->buswidth) {
- case 1:
- map->write8(map, 0x98, 0x55);
- break;
- case 2:
- map->write16(map, 0x9898, 0xaa);
- break;
- case 4:
- map->write32(map, 0x98989898, 0x154);
- break;
- }
-
- extp = kmalloc(sizeof(*extp), GFP_KERNEL);
- if (!extp) {
- printk("Failed to allocate memory\n");
- return;
- }
-
- /* Read in the Extended Query Table */
- for (i=0; i<sizeof(*extp); i++) {
- ((unsigned char *)extp)[i] =
- map->read8(map, (base+((adr+i)*map->buswidth)));
- }
-
- if (extp->MajorVersion != '1' ||
- (extp->MinorVersion < '0' || extp->MinorVersion > '2')) {
- printk(" Unknown IntelExt Extended Query version %c.%c.\n",
- extp->MajorVersion, extp->MinorVersion);
- kfree(extp);
- return;
- }
-
- /* Do some byteswapping if necessary */
- extp->FeatureSupport = le32_to_cpu(extp->FeatureSupport);
- extp->BlkStatusRegMask = le32_to_cpu(extp->BlkStatusRegMask);
-
-
- /* Tell the user about it in lots of lovely detail */
-#if 0
- printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport);
- printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported");
- printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported");
- printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported");
- printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported");
- printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported");
- printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported");
- printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported");
- printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
- printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
- for (i=9; i<32; i++) {
- if (extp->FeatureSupport & (1<<i))
- printk(" - Unknown Bit %X: supported\n", i);
- }
-
- printk(" Supported functions after Suspend: %2.2X\n", extp->SuspendCmdSupport);
- printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported");
- for (i=1; i<8; i++) {
- if (extp->SuspendCmdSupport & (1<<i))
- printk(" - Unknown Bit %X: supported\n", i);
- }
-
- printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
- printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
- printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
- for (i=2; i<16; i++) {
- if (extp->BlkStatusRegMask & (1<<i))
- printk(" - Unknown Bit %X Active: yes\n",i);
- }
-
- printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
- extp->VccOptimal >> 8, extp->VccOptimal & 0xf);
- if (extp->VppOptimal)
- printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
- extp->VppOptimal >> 8, extp->VppOptimal & 0xf);
-#endif
- /* OK. We like it. Take over the control of it. */
-
- /* Switch it into Read Mode */
- switch(map->buswidth) {
- case 1:
- map->write8(map, 0xff, 0x55);
- break;
- case 2:
- map->write16(map, 0xffff, 0xaa);
- break;
- case 4:
- map->write32(map, 0xffffffff, 0x154);
- break;
- }
-
-
- /* If there was an old setup function, decrease its use count */
- if (cfi->cmdset_setup)
- inter_module_put(cfi->im_name);
- if (cfi->cmdset_priv)
- kfree(cfi->cmdset_priv);
-
- for (i=0; i< cfi->numchips; i++) {
- cfi->chips[i].word_write_time = 128;
- cfi->chips[i].buffer_write_time = 128;
- cfi->chips[i].erase_time = 1024;
- }
-
-
- cfi->cmdset_setup = cfi_intelext_setup;
- cfi->im_name = im_name;
- cfi->cmdset_priv = extp;
-
- return;
-}
-
-static struct mtd_info *cfi_intelext_setup(struct map_info *map)
-{
- struct cfi_private *cfi = map->fldrv_priv;
- struct mtd_info *mtd;
-
- mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
- printk("number of CFI chips: %d\n", cfi->numchips);
-
- if (!mtd) {
- printk("Failed to allocate memory for MTD device\n");
- kfree(cfi->cmdset_priv);
- return NULL;
- }
-
- memset(mtd, 0, sizeof(*mtd));
- mtd->priv = map;
- mtd->type = MTD_NORFLASH;
- mtd->erasesize = 0x20000; /* FIXME */
- /* Also select the correct geometry setup too */
- mtd->size = (1 << cfi->cfiq.DevSize) * cfi->numchips;
- mtd->erase = cfi_intelext_erase_1_by_16;
- mtd->read = cfi_intelext_read_1_by_16;
- mtd->write = cfi_intelext_write_1_by_16;
- mtd->sync = cfi_intelext_sync;
- mtd->suspend = cfi_intelext_suspend;
- mtd->resume = cfi_intelext_resume;
- mtd->flags = MTD_CAP_NORFLASH;
- map->fldrv_destroy = cfi_intelext_destroy;
- mtd->name = map->name;
- return mtd;
-}
-
-static inline int do_read_1_by_16_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
-{
- __u16 status;
- unsigned long timeo = jiffies + HZ;
- DECLARE_WAITQUEUE(wait, current);
-
- adr += chip->start;
-
- retry:
- spin_lock_bh(chip->mutex);
-
- /* Check that the chip's ready to talk to us.
- * Later, we can actually think about interrupting it
- * if it's in FL_ERASING or FL_WRITING state.
- * Not just yet, though.
- */
- switch (chip->state) {
-#if 0
- case FL_ERASING:
- case FL_WRITING:
- /* Suspend the operation, set state to FL_xxx_SUSPENDED */
-#endif
-
- case FL_CFI_QUERY:
- case FL_JEDEC_QUERY:
- case FL_READY:
- map->write16(map, cpu_to_le16(0x0070), adr);
- chip->state = FL_STATUS;
-
- case FL_STATUS:
- status = le16_to_cpu(map->read16(map, adr));
-
- if (!(status & (1<<7))) {
- static int z=0;
- /* Urgh. Chip not yet ready to talk to us. */
- if (time_after(jiffies, timeo)) {
- spin_unlock_bh(chip->mutex);
- printk("waiting for chip to be ready timed out in read");
- return -EIO;
- }
-
- /* Latency issues. Drop the lock, wait a while and retry */
- spin_unlock_bh(chip->mutex);
-
- z++;
- if ( 0 && !(z % 100 ))
- printk("chip not ready yet before read. looping\n");
-
- udelay(1);
-
- goto retry;
- }
- break;
-
- default:
- printk("Waiting for chip, status = %d\n", chip->state);
-
- /* Stick ourselves on a wait queue to be woken when
- someone changes the status */
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&chip->wq, &wait);
-
- spin_unlock_bh(chip->mutex);
-
- schedule();
- remove_wait_queue(&chip->wq, &wait);
-
- if(signal_pending(current))
- return -EINTR;
-
-
- timeo = jiffies + HZ;
-
- goto retry;
- }
-
- map->write16(map, cpu_to_le16(0x00ff), adr);
- chip->state = FL_READY;
-
- map->copy_from(map, buf, adr, len);
-
- if (chip->state == FL_ERASE_SUSPENDED ||
- chip->state == FL_WRITE_SUSPENDED) {
- printk("Who in hell suspended the pending operation? I didn't write that code yet!\n");
- /* Restart it and set the state accordingly */
- }
-
- wake_up(&chip->wq);
- spin_unlock_bh(chip->mutex);
-
- return 0;
-}
-
-static int cfi_intelext_read_1_by_16 (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- unsigned long ofs;
- int chipnum;
- int ret = 0;
-
- /* ofs: offset within the first chip that the first read should start */
- chipnum = (from >> cfi->chipshift);
- ofs = from - (chipnum << cfi->chipshift);
-
- *retlen = 0;
-
- while (len) {
- unsigned long thislen;
-
- if (chipnum >= cfi->numchips)
- break;
-
- if ((len + ofs -1) >> cfi->chipshift)
- thislen = (1<<cfi->chipshift) - ofs;
- else
- thislen = len;
-
- ret = do_read_1_by_16_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
- if (ret)
- break;
-
- *retlen += thislen;
- len -= thislen;
- buf += thislen;
-
- ofs = 0;
- chipnum++;
- }
- return ret;
-}
-
-static inline int do_write_1_by_16_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u16 datum)
-{
- __u16 status;
- unsigned long timeo = jiffies + HZ;
- DECLARE_WAITQUEUE(wait, current);
- int z = 0;
- adr += chip->start;
-
- retry:
- spin_lock_bh(chip->mutex);
-
- /* Check that the chip's ready to talk to us.
- * Later, we can actually think about interrupting it
- * if it's in FL_ERASING state.
- * Not just yet, though.
- */
- switch (chip->state) {
- case FL_CFI_QUERY:
- case FL_JEDEC_QUERY:
- case FL_READY:
- map->write16(map, cpu_to_le16(0x0070), adr);
- chip->state = FL_STATUS;
- timeo = jiffies + HZ;
-
- case FL_STATUS:
- status = le16_to_cpu(map->read16(map, adr));
-
- if (!(status & (1<<7))) {
-
- /* Urgh. Chip not yet ready to talk to us. */
- if (time_after(jiffies, timeo)) {
- spin_unlock_bh(chip->mutex);
- printk("waiting for chip to be ready timed out in read");
- return -EIO;
- }
-
- /* Latency issues. Drop the lock, wait a while and retry */
- spin_unlock_bh(chip->mutex);
-
- z++;
- if ( 0 && !(z % 100 ))
- printk("chip not ready yet before write. looping\n");
-
- udelay(1);
-
- goto retry;
- }
- break;
-
- default:
- printk("Waiting for chip, status = %d\n", chip->state);
-
- /* Stick ourselves on a wait queue to be woken when
- someone changes the status */
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&chip->wq, &wait);
-
- spin_unlock_bh(chip->mutex);
-
- schedule();
- remove_wait_queue(&chip->wq, &wait);
-
- if(signal_pending(current))
- return -EINTR;
-
- timeo = jiffies + HZ;
-
- goto retry;
- }
-
- map->write16(map, cpu_to_le16(0x0040), adr);
- map->write16(map, datum, adr);
- chip->state = FL_WRITING;
-
- timeo = jiffies + (HZ/2);
-
- spin_unlock_bh(chip->mutex);
- udelay(chip->word_write_time);
- spin_lock_bh(chip->mutex);
-
- z = 0;
- while ( !( (status = le16_to_cpu(map->read16(map, adr))) & 0x80 ) ) {
-
- if (chip->state != FL_WRITING) {
- /* Someone's suspended the write. Sleep */
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&chip->wq, &wait);
-
- spin_unlock_bh(chip->mutex);
-
- schedule();
- remove_wait_queue(&chip->wq, &wait);
-
- if (signal_pending(current))
- return -EINTR;
-
- timeo = jiffies + (HZ / 2); /* FIXME */
-
- spin_lock_bh(chip->mutex);
- continue;
- }
-
- /* OK Still waiting */
- if (time_after(jiffies, timeo)) {
- chip->state = FL_STATUS;
- spin_unlock_bh(chip->mutex);
- printk("waiting for chip to be ready timed out in read");
- return -EIO;
- }
-
- /* Latency issues. Drop the lock, wait a while and retry */
- spin_unlock_bh(chip->mutex);
-
- z++;
- if ( 0 && !(z % 100 ))
- printk("chip not ready yet after write. looping\n");
-
- udelay(1);
-
- spin_lock_bh(chip->mutex);
- continue;
- }
- if (!z) {
- chip->word_write_time--;
- if (!chip->word_write_time)
- chip->word_write_time++;
- }
- if (z > 1)
- chip->word_write_time++;
-
- /* Done and happy. */
- chip->state = FL_STATUS;
- wake_up(&chip->wq);
- spin_unlock_bh(chip->mutex);
- // printk("write ret OK at %lx\n", adr);
- return 0;
-}
-
-
-/* This version only uses the 'word write' instruction. We should update it
- * to write using 'buffer write' if it's available
- */
-static int cfi_intelext_write_1_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- int ret = 0;
- int chipnum;
- unsigned long ofs;
-
- *retlen = 0;
- chipnum = to >> cfi->chipshift;
- ofs = to - (chipnum << cfi->chipshift);
-
- /* If it's not word-aligned, do the first byte write */
- if (ofs & 1) {
-#if defined(__LITTLE_ENDIAN)
- ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],
- ofs, 0xFF | (*buf << 8));
-#elif defined(__BIG_ENDIAN)
- ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],
- ofs, 0xFF00 | (*buf));
-#else
-#error define a sensible endianness
-#endif
- if (ret)
- return ret;
-
- ofs++;
- buf++;
- (*retlen)++;
- len--;
-
- if (ofs >> cfi->chipshift) {
- chipnum ++;
- ofs = 0;
- if (chipnum == cfi->numchips)
- return 0;
- }
- }
-
- while(len > 1) {
- ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],
- ofs, *(__u16 *)buf);
- if (ret)
- return ret;
-
- ofs += 2;
- buf += 2;
- (*retlen) += 2;
- len -= 2;
-
- if (ofs >> cfi->chipshift) {
- chipnum ++;
- ofs = 0;
- if (chipnum == cfi->numchips)
- return 0;
- }
- }
-
- if (len) {
- /* Final byte to write */
-#if defined(__LITTLE_ENDIAN)
- ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],
- ofs, 0xFF00 | (*buf));
-#elif defined(__BIG_ENDIAN)
- ret = do_write_1_by_16_oneword(map, &cfi->chips[chipnum],
- ofs, 0xFF | (*buf << 8));
-#else
-#error define a sensible endianness
-#endif
- if (ret)
- return ret;
-
- (*retlen)++;
- }
-
- return 0;
-}
-
-
-static inline int do_erase_1_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
-{
- __u16 status;
- unsigned long timeo = jiffies + HZ;
- DECLARE_WAITQUEUE(wait, current);
-
- adr += chip->start;
-
- retry:
- spin_lock_bh(chip->mutex);
-
- /* Check that the chip's ready to talk to us. */
- switch (chip->state) {
- case FL_CFI_QUERY:
- case FL_JEDEC_QUERY:
- case FL_READY:
- map->write16(map, cpu_to_le16(0x0070), adr);
- chip->state = FL_STATUS;
- timeo = jiffies + HZ;
-
- case FL_STATUS:
- status = le16_to_cpu(map->read16(map, adr));
-
- if (!(status & (1<<7))) {
- static int z=0;
- /* Urgh. Chip not yet ready to talk to us. */
- if (time_after(jiffies, timeo)) {
- spin_unlock_bh(chip->mutex);
- printk("waiting for chip to be ready timed out in erase");
- return -EIO;
- }
-
- /* Latency issues. Drop the lock, wait a while and retry */
- spin_unlock_bh(chip->mutex);
-
- z++;
- if ( 0 && !(z % 100 ))
- printk("chip not ready yet before erase. looping\n");
-
- udelay(1);
-
- goto retry;
- }
- break;
-
- default:
- printk("Waiting for chip, status = %d\n", chip->state);
-
- /* Stick ourselves on a wait queue to be woken when
- someone changes the status */
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&chip->wq, &wait);
-
- spin_unlock_bh(chip->mutex);
-
- schedule();
- remove_wait_queue(&chip->wq, &wait);
-
- if(signal_pending(current))
- return -EINTR;
-
- timeo = jiffies + HZ;
-
- goto retry;
- }
-
- map->write16(map, cpu_to_le16(0x0020), adr);
- map->write16(map, cpu_to_le16(0x00D0), adr);
-
- chip->state = FL_ERASING;
-
- timeo = jiffies + (HZ*2);
- spin_unlock_bh(chip->mutex);
- schedule_timeout(HZ);
- spin_lock_bh(chip->mutex);
-
- /* FIXME. Use a timer to check this, and return immediately. */
- /* Once the state machine's known to be working I'll do that */
-
- while ( !( (status = le16_to_cpu(map->read16(map, adr))) & 0x80 ) ) {
- static int z=0;
-
- if (chip->state != FL_ERASING) {
- /* Someone's suspended the erase. Sleep */
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&chip->wq, &wait);
-
- spin_unlock_bh(chip->mutex);
- printk("erase suspended. Sleeping\n");
-
- schedule();
- remove_wait_queue(&chip->wq, &wait);
-
- if (signal_pending(current))
- return -EINTR;
-
- timeo = jiffies + (HZ*2); /* FIXME */
- spin_lock_bh(chip->mutex);
- continue;
- }
-
- /* OK Still waiting */
- if (time_after(jiffies, timeo)) {
- chip->state = FL_STATUS;
- spin_unlock_bh(chip->mutex);
- printk("waiting for erase to complete timed out.");
- return -EIO;
- }
-
- /* Latency issues. Drop the lock, wait a while and retry */
- spin_unlock_bh(chip->mutex);
-
- z++;
- if ( 0 && !(z % 100 ))
- printk("chip not ready yet after erase. looping\n");
-
- udelay(1);
-
- spin_lock_bh(chip->mutex);
- continue;
- }
-
- /* Done and happy. */
- chip->state = FL_STATUS;
- wake_up(&chip->wq);
- spin_unlock_bh(chip->mutex);
- //printk("erase ret OK\n");
- return 0;
-}
-
-static int cfi_intelext_erase_1_by_16 (struct mtd_info *mtd, struct erase_info *instr)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- unsigned long adr, len;
- int chipnum, ret = 0;
-
- if (instr->addr & (mtd->erasesize - 1))
- return -EINVAL;
-
- if (instr->len & (mtd->erasesize -1))
- return -EINVAL;
-
- if ((instr->len + instr->addr) > mtd->size)
- return -EINVAL;
-
- chipnum = instr->addr >> cfi->chipshift;
- adr = instr->addr - (chipnum << cfi->chipshift);
- len = instr->len;
-
- while(len) {
- ret = do_erase_1_by_16_oneblock(map, &cfi->chips[chipnum], adr);
-
- if (ret)
- return ret;
-
- adr += mtd->erasesize;
- len -= mtd->erasesize;
-
- if (adr >> cfi->chipshift) {
- adr = 0;
- chipnum++;
-
- if (chipnum >= cfi->numchips)
- break;
- }
- }
-
- if (instr->callback)
- instr->callback(instr);
-
- return 0;
-}
-
-
-
-static void cfi_intelext_sync (struct mtd_info *mtd)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- int i;
- struct flchip *chip;
- int ret = 0;
- DECLARE_WAITQUEUE(wait, current);
-
- for (i=0; !ret && i<cfi->numchips; i++) {
- chip = &cfi->chips[i];
-
- retry:
- spin_lock_bh(chip->mutex);
-
- switch(chip->state) {
- case FL_READY:
- case FL_STATUS:
- case FL_CFI_QUERY:
- case FL_JEDEC_QUERY:
- 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.
- */
- spin_unlock_bh(chip->mutex);
- break;
-
- default:
- /* Not an idle state */
- add_wait_queue(&chip->wq, &wait);
-
- spin_unlock_bh(chip->mutex);
- schedule();
-
- remove_wait_queue(&chip->wq, &wait);
-
- goto retry;
- }
- }
-
- /* Unlock the chips again */
-
- for (i--; i >=0; i--) {
- chip = &cfi->chips[i];
-
- spin_lock_bh(chip->mutex);
-
- if (chip->state == FL_SYNCING) {
- chip->state = chip->oldstate;
- wake_up(&chip->wq);
- }
- spin_unlock_bh(chip->mutex);
- }
-}
-
-
-static int cfi_intelext_suspend(struct mtd_info *mtd)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- int i;
- struct flchip *chip;
- int ret = 0;
-
- for (i=0; !ret && i<cfi->numchips; i++) {
- chip = &cfi->chips[i];
-
- spin_lock_bh(chip->mutex);
-
- switch(chip->state) {
- case FL_READY:
- case FL_STATUS:
- case FL_CFI_QUERY:
- case FL_JEDEC_QUERY:
- 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.
- */
- break;
-
- default:
- ret = -EAGAIN;
- break;
- }
- spin_unlock_bh(chip->mutex);
- }
-
- /* Unlock the chips again */
-
- for (i--; i >=0; i--) {
- chip = &cfi->chips[i];
-
- spin_lock_bh(chip->mutex);
-
- if (chip->state == FL_PM_SUSPENDED) {
- chip->state = chip->oldstate;
- wake_up(&chip->wq);
- }
- spin_unlock_bh(chip->mutex);
- }
-
- return ret;
-}
-
-static void cfi_intelext_resume(struct mtd_info *mtd)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- int i;
- struct flchip *chip;
-
- for (i=0; i<cfi->numchips; i++) {
-
- chip = &cfi->chips[i];
-
- spin_lock_bh(chip->mutex);
-
- if (chip->state == FL_PM_SUSPENDED) {
- chip->state = chip->oldstate;
- wake_up(&chip->wq);
- }
- else
- printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
-
- spin_unlock_bh(chip->mutex);
- }
-}
-
-static void cfi_intelext_destroy(struct mtd_info *mtd)
-{
- struct map_info *map = mtd->priv;
- struct cfi_private *cfi = map->fldrv_priv;
- kfree(cfi->cmdset_priv);
- inter_module_put(cfi->im_name);
- kfree(cfi);
-}
-
-
-static int __init cfi_intelext_init(void)
-{
- inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0001);
- return 0;
-}
-
-static void __exit cfi_intelext_exit(void)
-{
- inter_module_unregister(im_name);
-}
-
-module_init(cfi_intelext_init);
-module_exit(cfi_intelext_exit);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)