mtd/drivers/mtd/nand nand.c,1.72,1.73
gleixner at infradead.org
gleixner at infradead.org
Mon Mar 29 11:04:00 EST 2004
Update of /home/cvs/mtd/drivers/mtd/nand
In directory phoenix.infradead.org:/tmp/cvs-serv15178
Modified Files:
nand.c
Log Message:
change handling of block_bad function, implement mtd interface for bad block management, use a common release_chip function, merge block_bad and block_bad16
Index: nand.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nand/nand.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- nand.c 29 Mar 2004 09:49:34 -0000 1.72
+++ nand.c 29 Mar 2004 16:03:58 -0000 1.73
@@ -181,7 +181,24 @@
unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
static void nand_sync (struct mtd_info *mtd);
+
+/* Some internal functions */
static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr);
+static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state, int *erase_state);
+
+/* Deselect and wake up anyone waiting on the device */
+static void nand_release_chip (struct mtd_info *mtd)
+{
+ struct nand_chip *this = mtd->priv;
+
+ /* De-select the NAND device */
+ this->select_chip(mtd, -1);
+ /* Release the chip */
+ spin_lock_bh (&this->chip_lock);
+ this->state = FL_READY;
+ wake_up (&this->wq);
+ spin_unlock_bh (&this->chip_lock);
+}
static u_char nand_read_byte(struct mtd_info *mtd)
{
@@ -302,34 +319,53 @@
return 0;
}
-/* Appropriate chip should already be selected */
-static int nand_block_bad(struct mtd_info *mtd, unsigned long page)
+static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
{
+ int page, chipnr, res = 0;
struct nand_chip *this = mtd->priv;
-
- this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page);
- if (this->read_byte(mtd) != 0xff)
- return 1;
+ u16 bad;
- return 0;
+ /* Shift to get page */
+ page = ((int) ofs) >> this->page_shift;
+ chipnr = (int)((unsigned long) ofs / this->chipsize);
+
+ /* Grab the lock and see if the device is available */
+ nand_get_chip (this, mtd, FL_READING, NULL);
+
+ /* Select the NAND device */
+ this->select_chip(mtd, chipnr);
+
+ if (this->options & NAND_BUSWIDTH_16) {
+ this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask);
+ bad = cpu_to_le16(this->read_word(mtd));
+ if (this->badblockpos & 0x1)
+ bad >>= 1;
+ if ((bad & 0xFF) != 0xff)
+ res = 1;
+ } else {
+ this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);
+ if (this->read_byte(mtd) != 0xff)
+ res = 1;
+ }
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_chip(mtd);
+
+ return res;
}
-/* Appropriate chip should already be selected */
-static int nand_block_bad16(struct mtd_info *mtd, unsigned long page)
+/* This is the default implementation, which can be overridden by
+ * a hardware specific driver.
+*/
+static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
struct nand_chip *this = mtd->priv;
- u16 bad;
+ u_char buf[2] = {0, 0};
+ size_t retlen;
- this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page);
-
- bad = cpu_to_le16(this->read_word(mtd));
- if (this->badblockpos & 0x1)
- bad >>= 1;
-
- if ((bad & 0xFF) != 0xff)
- return 1;
-
- return 0;
+ ofs += mtd->oobsize + (this->badblockpos & ~0x01);
+
+ /* We write two bytes, so we dont have to mess with 16 bit access */
+ return nand_write_oob (mtd, ofs , 2, &retlen, buf);
}
/*
@@ -522,7 +558,7 @@
/*
* Get chip for selected access
*/
-static inline void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state, int *erase_state)
+static void nand_get_chip (struct nand_chip *this, struct mtd_info *mtd, int new_state, int *erase_state)
{
DECLARE_WAITQUEUE (wait, current);
@@ -944,14 +980,8 @@
}
}
- /* De-select the NAND device */
- this->select_chip(mtd, -1);
-
- /* Wake up anyone waiting on the device */
- spin_lock_bh (&this->chip_lock);
- this->state = FL_READY;
- wake_up (&this->wq);
- spin_unlock_bh (&this->chip_lock);
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_chip(mtd);
/*
* Return success, if no ECC failures, else -EIO
@@ -1041,14 +1071,9 @@
}
}
}
- /* De-select the NAND device */
- this->select_chip(mtd, -1);
- /* Wake up anyone waiting on the device */
- spin_lock_bh (&this->chip_lock);
- this->state = FL_READY;
- wake_up (&this->wq);
- spin_unlock_bh (&this->chip_lock);
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_chip(mtd);
/* Return happy */
*retlen = len;
@@ -1137,14 +1162,8 @@
}
out:
- /* De-select the NAND device */
- this->select_chip(mtd, -1);
-
- /* Wake up anyone waiting on the device */
- spin_lock_bh (&this->chip_lock);
- this->state = FL_READY;
- wake_up (&this->wq);
- spin_unlock_bh (&this->chip_lock);
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_chip(mtd);
*retlen = written;
return ret;
@@ -1249,14 +1268,8 @@
#endif
out:
- /* De-select the NAND device */
- this->select_chip(mtd, -1);
-
- /* Wake up anyone waiting on the device */
- spin_lock_bh (&this->chip_lock);
- this->state = FL_READY;
- wake_up (&this->wq);
- spin_unlock_bh (&this->chip_lock);
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_chip(mtd);
return ret;
}
@@ -1377,14 +1390,8 @@
}
out:
- /* De-select the NAND device */
- this->select_chip(mtd, -1);
-
- /* Wake up anyone waiting on the device */
- spin_lock_bh (&this->chip_lock);
- this->state = FL_READY;
- wake_up (&this->wq);
- spin_unlock_bh (&this->chip_lock);
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_chip(mtd);
*retlen = written;
return ret;
@@ -1480,19 +1487,14 @@
instr->state = MTD_ERASE_DONE;
erase_exit:
- /* De-select the NAND device */
- this->select_chip(mtd, -1);
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;;
/* Do call back function */
if (!ret && instr->callback)
instr->callback (instr);
- /* The device is ready */
- spin_lock_bh (&this->chip_lock);
- this->state = FL_READY;
- wake_up (&this->wq);
- spin_unlock_bh (&this->chip_lock);
+ /* Deselect and wake up anyone waiting on the device */
+ nand_release_chip(mtd);
/* Return more or less happy */
return ret;
@@ -1544,6 +1546,34 @@
}
/*
+ * Check whether the block at the given offset is bad
+ */
+static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
+{
+ struct nand_chip *this = mtd->priv;
+
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ return this->block_bad(mtd, ofs);
+}
+
+/*
+ * Mark the block at the given offset as bad
+ */
+static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
+{
+ struct nand_chip *this = mtd->priv;
+
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ return this->block_markbad(mtd, ofs);
+}
+
+/*
* Scan for the NAND device
*/
int nand_scan (struct mtd_info *mtd, int maxchips)
@@ -1577,7 +1607,9 @@
if (!this->read_word)
this->read_word = nand_read_word;
if (!this->block_bad)
- this->block_bad = busw ? nand_block_bad16 : nand_block_bad;
+ this->block_bad = nand_block_bad;
+ if (!this->block_markbad)
+ this->block_markbad = nand_default_block_markbad;
if (!this->write_buf)
this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
if (!this->read_buf)
@@ -1764,6 +1796,8 @@
mtd->unlock = NULL;
mtd->suspend = NULL;
mtd->resume = NULL;
+ mtd->block_isbad = nand_block_isbad;
+ mtd->block_markbad = nand_block_markbad;
mtd->owner = THIS_MODULE;
/* Return happy */
More information about the linux-mtd-cvs
mailing list