|
@@ -136,9 +136,9 @@ static int check_offs_len(struct mtd_info *mtd,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_release_device - [GENERIC] release chip
|
|
* nand_release_device - [GENERIC] release chip
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*
|
|
*
|
|
- * Deselect, release chip lock and wake up anyone waiting on the device
|
|
|
|
|
|
+ * Deselect, release chip lock and wake up anyone waiting on the device.
|
|
*/
|
|
*/
|
|
static void nand_release_device(struct mtd_info *mtd)
|
|
static void nand_release_device(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -157,9 +157,9 @@ static void nand_release_device(struct mtd_info *mtd)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_byte - [DEFAULT] read one byte from the chip
|
|
* nand_read_byte - [DEFAULT] read one byte from the chip
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*
|
|
*
|
|
- * Default read function for 8bit buswith
|
|
|
|
|
|
+ * Default read function for 8bit buswith.
|
|
*/
|
|
*/
|
|
static uint8_t nand_read_byte(struct mtd_info *mtd)
|
|
static uint8_t nand_read_byte(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -169,10 +169,9 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
|
|
* nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*
|
|
*
|
|
- * Default read function for 16bit buswith with
|
|
|
|
- * endianess conversion
|
|
|
|
|
|
+ * Default read function for 16bit buswith with endianess conversion.
|
|
*/
|
|
*/
|
|
static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
|
static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -182,10 +181,9 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_word - [DEFAULT] read one word from the chip
|
|
* nand_read_word - [DEFAULT] read one word from the chip
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*
|
|
*
|
|
- * Default read function for 16bit buswith without
|
|
|
|
- * endianess conversion
|
|
|
|
|
|
+ * Default read function for 16bit buswith without endianess conversion.
|
|
*/
|
|
*/
|
|
static u16 nand_read_word(struct mtd_info *mtd)
|
|
static u16 nand_read_word(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -195,8 +193,8 @@ static u16 nand_read_word(struct mtd_info *mtd)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_select_chip - [DEFAULT] control CE line
|
|
* nand_select_chip - [DEFAULT] control CE line
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @chipnr: chipnumber to select, -1 for deselect
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @chipnr: chipnumber to select, -1 for deselect
|
|
*
|
|
*
|
|
* Default select function for 1 chip devices.
|
|
* Default select function for 1 chip devices.
|
|
*/
|
|
*/
|
|
@@ -218,11 +216,11 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_buf - [DEFAULT] write buffer to chip
|
|
* nand_write_buf - [DEFAULT] write buffer to chip
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @buf: data buffer
|
|
|
|
- * @len: number of bytes to write
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @buf: data buffer
|
|
|
|
+ * @len: number of bytes to write
|
|
*
|
|
*
|
|
- * Default write function for 8bit buswith
|
|
|
|
|
|
+ * Default write function for 8bit buswith.
|
|
*/
|
|
*/
|
|
static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
{
|
|
{
|
|
@@ -235,11 +233,11 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_buf - [DEFAULT] read chip data into buffer
|
|
* nand_read_buf - [DEFAULT] read chip data into buffer
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @buf: buffer to store date
|
|
|
|
- * @len: number of bytes to read
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @buf: buffer to store date
|
|
|
|
+ * @len: number of bytes to read
|
|
*
|
|
*
|
|
- * Default read function for 8bit buswith
|
|
|
|
|
|
+ * Default read function for 8bit buswith.
|
|
*/
|
|
*/
|
|
static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
{
|
|
{
|
|
@@ -252,11 +250,11 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_verify_buf - [DEFAULT] Verify chip data against buffer
|
|
* nand_verify_buf - [DEFAULT] Verify chip data against buffer
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @buf: buffer containing the data to compare
|
|
|
|
- * @len: number of bytes to compare
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @buf: buffer containing the data to compare
|
|
|
|
+ * @len: number of bytes to compare
|
|
*
|
|
*
|
|
- * Default verify function for 8bit buswith
|
|
|
|
|
|
+ * Default verify function for 8bit buswith.
|
|
*/
|
|
*/
|
|
static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
{
|
|
{
|
|
@@ -271,11 +269,11 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_buf16 - [DEFAULT] write buffer to chip
|
|
* nand_write_buf16 - [DEFAULT] write buffer to chip
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @buf: data buffer
|
|
|
|
- * @len: number of bytes to write
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @buf: data buffer
|
|
|
|
+ * @len: number of bytes to write
|
|
*
|
|
*
|
|
- * Default write function for 16bit buswith
|
|
|
|
|
|
+ * Default write function for 16bit buswith.
|
|
*/
|
|
*/
|
|
static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
{
|
|
{
|
|
@@ -291,11 +289,11 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_buf16 - [DEFAULT] read chip data into buffer
|
|
* nand_read_buf16 - [DEFAULT] read chip data into buffer
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @buf: buffer to store date
|
|
|
|
- * @len: number of bytes to read
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @buf: buffer to store date
|
|
|
|
+ * @len: number of bytes to read
|
|
*
|
|
*
|
|
- * Default read function for 16bit buswith
|
|
|
|
|
|
+ * Default read function for 16bit buswith.
|
|
*/
|
|
*/
|
|
static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
{
|
|
{
|
|
@@ -310,11 +308,11 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
|
|
* nand_verify_buf16 - [DEFAULT] Verify chip data against buffer
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @buf: buffer containing the data to compare
|
|
|
|
- * @len: number of bytes to compare
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @buf: buffer containing the data to compare
|
|
|
|
+ * @len: number of bytes to compare
|
|
*
|
|
*
|
|
- * Default verify function for 16bit buswith
|
|
|
|
|
|
+ * Default verify function for 16bit buswith.
|
|
*/
|
|
*/
|
|
static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
{
|
|
{
|
|
@@ -332,9 +330,9 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_block_bad - [DEFAULT] Read bad block marker from the chip
|
|
* nand_block_bad - [DEFAULT] Read bad block marker from the chip
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @ofs: offset from device start
|
|
|
|
- * @getchip: 0, if the chip is already selected
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @ofs: offset from device start
|
|
|
|
+ * @getchip: 0, if the chip is already selected
|
|
*
|
|
*
|
|
* Check, if the block is bad.
|
|
* Check, if the block is bad.
|
|
*/
|
|
*/
|
|
@@ -384,11 +382,11 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_default_block_markbad - [DEFAULT] mark a block bad
|
|
* nand_default_block_markbad - [DEFAULT] mark a block bad
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @ofs: offset from device start
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @ofs: offset from device start
|
|
*
|
|
*
|
|
- * This is the default implementation, which can be overridden by
|
|
|
|
- * a hardware specific driver.
|
|
|
|
|
|
+ * 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)
|
|
static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
{
|
|
{
|
|
@@ -404,7 +402,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
if (chip->bbt)
|
|
if (chip->bbt)
|
|
chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
|
|
chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
|
|
|
|
|
|
- /* Do we have a flash based bad block table ? */
|
|
|
|
|
|
+ /* Do we have a flash based bad block table? */
|
|
if (chip->bbt_options & NAND_BBT_USE_FLASH)
|
|
if (chip->bbt_options & NAND_BBT_USE_FLASH)
|
|
ret = nand_update_bbt(mtd, ofs);
|
|
ret = nand_update_bbt(mtd, ofs);
|
|
else {
|
|
else {
|
|
@@ -439,16 +437,16 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_check_wp - [GENERIC] check if the chip is write protected
|
|
* nand_check_wp - [GENERIC] check if the chip is write protected
|
|
- * @mtd: MTD device structure
|
|
|
|
- * Check, if the device is write protected
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*
|
|
*
|
|
- * The function expects, that the device is already selected
|
|
|
|
|
|
+ * Check, if the device is write protected. The function expects, that the
|
|
|
|
+ * device is already selected.
|
|
*/
|
|
*/
|
|
static int nand_check_wp(struct mtd_info *mtd)
|
|
static int nand_check_wp(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
struct nand_chip *chip = mtd->priv;
|
|
struct nand_chip *chip = mtd->priv;
|
|
|
|
|
|
- /* broken xD cards report WP despite being writable */
|
|
|
|
|
|
+ /* Broken xD cards report WP despite being writable */
|
|
if (chip->options & NAND_BROKEN_XD)
|
|
if (chip->options & NAND_BROKEN_XD)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -459,10 +457,10 @@ static int nand_check_wp(struct mtd_info *mtd)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_block_checkbad - [GENERIC] Check if a block is marked bad
|
|
* nand_block_checkbad - [GENERIC] Check if a block is marked bad
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @ofs: offset from device start
|
|
|
|
- * @getchip: 0, if the chip is already selected
|
|
|
|
- * @allowbbt: 1, if its allowed to access the bbt area
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @ofs: offset from device start
|
|
|
|
+ * @getchip: 0, if the chip is already selected
|
|
|
|
+ * @allowbbt: 1, if its allowed to access the bbt area
|
|
*
|
|
*
|
|
* Check, if the block is bad. Either by reading the bad block table or
|
|
* Check, if the block is bad. Either by reading the bad block table or
|
|
* calling of the scan function.
|
|
* calling of the scan function.
|
|
@@ -481,8 +479,8 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
|
|
* panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @timeo: Timeout
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @timeo: Timeout
|
|
*
|
|
*
|
|
* Helper function for nand_wait_ready used when needing to wait in interrupt
|
|
* Helper function for nand_wait_ready used when needing to wait in interrupt
|
|
* context.
|
|
* context.
|
|
@@ -501,10 +499,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Wait for the ready pin, after a command
|
|
|
|
- * The timeout is catched later.
|
|
|
|
- */
|
|
|
|
|
|
+/* Wait for the ready pin, after a command. The timeout is catched later */
|
|
void nand_wait_ready(struct mtd_info *mtd)
|
|
void nand_wait_ready(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
struct nand_chip *chip = mtd->priv;
|
|
struct nand_chip *chip = mtd->priv;
|
|
@@ -515,7 +510,7 @@ void nand_wait_ready(struct mtd_info *mtd)
|
|
return panic_nand_wait_ready(mtd, 400);
|
|
return panic_nand_wait_ready(mtd, 400);
|
|
|
|
|
|
led_trigger_event(nand_led_trigger, LED_FULL);
|
|
led_trigger_event(nand_led_trigger, LED_FULL);
|
|
- /* wait until command is processed or timeout occures */
|
|
|
|
|
|
+ /* Wait until command is processed or timeout occures */
|
|
do {
|
|
do {
|
|
if (chip->dev_ready(mtd))
|
|
if (chip->dev_ready(mtd))
|
|
break;
|
|
break;
|
|
@@ -527,13 +522,13 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_command - [DEFAULT] Send command to NAND device
|
|
* nand_command - [DEFAULT] Send command to NAND device
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @command: the command to be sent
|
|
|
|
- * @column: the column address for this command, -1 if none
|
|
|
|
- * @page_addr: the page address for this command, -1 if none
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @command: the command to be sent
|
|
|
|
+ * @column: the column address for this command, -1 if none
|
|
|
|
+ * @page_addr: the page address for this command, -1 if none
|
|
*
|
|
*
|
|
- * Send command to NAND device. This function is used for small page
|
|
|
|
- * devices (256/512 Bytes per page)
|
|
|
|
|
|
+ * Send command to NAND device. This function is used for small page devices
|
|
|
|
+ * (256/512 Bytes per page).
|
|
*/
|
|
*/
|
|
static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
int column, int page_addr)
|
|
int column, int page_addr)
|
|
@@ -541,9 +536,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
register struct nand_chip *chip = mtd->priv;
|
|
register struct nand_chip *chip = mtd->priv;
|
|
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
|
|
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
|
|
|
|
|
|
- /*
|
|
|
|
- * Write out the command to the device.
|
|
|
|
- */
|
|
|
|
|
|
+ /* Write out the command to the device */
|
|
if (command == NAND_CMD_SEQIN) {
|
|
if (command == NAND_CMD_SEQIN) {
|
|
int readcmd;
|
|
int readcmd;
|
|
|
|
|
|
@@ -563,9 +556,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
}
|
|
}
|
|
chip->cmd_ctrl(mtd, command, ctrl);
|
|
chip->cmd_ctrl(mtd, command, ctrl);
|
|
|
|
|
|
- /*
|
|
|
|
- * Address cycle, when necessary
|
|
|
|
- */
|
|
|
|
|
|
+ /* Address cycle, when necessary */
|
|
ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
|
|
ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
|
|
/* Serially input address */
|
|
/* Serially input address */
|
|
if (column != -1) {
|
|
if (column != -1) {
|
|
@@ -586,8 +577,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
|
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
|
|
|
|
|
/*
|
|
/*
|
|
- * program and erase have their own busy handlers
|
|
|
|
- * status and sequential in needs no delay
|
|
|
|
|
|
+ * Program and erase have their own busy handlers status and sequential
|
|
|
|
+ * in needs no delay
|
|
*/
|
|
*/
|
|
switch (command) {
|
|
switch (command) {
|
|
|
|
|
|
@@ -621,8 +612,10 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- /* Apply this short delay always to ensure that we do wait tWB in
|
|
|
|
- * any case on any machine. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Apply this short delay always to ensure that we do wait tWB in
|
|
|
|
+ * any case on any machine.
|
|
|
|
+ */
|
|
ndelay(100);
|
|
ndelay(100);
|
|
|
|
|
|
nand_wait_ready(mtd);
|
|
nand_wait_ready(mtd);
|
|
@@ -630,10 +623,10 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_command_lp - [DEFAULT] Send command to NAND large page device
|
|
* nand_command_lp - [DEFAULT] Send command to NAND large page device
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @command: the command to be sent
|
|
|
|
- * @column: the column address for this command, -1 if none
|
|
|
|
- * @page_addr: the page address for this command, -1 if none
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @command: the command to be sent
|
|
|
|
+ * @column: the column address for this command, -1 if none
|
|
|
|
+ * @page_addr: the page address for this command, -1 if none
|
|
*
|
|
*
|
|
* Send command to NAND device. This is the version for the new large page
|
|
* Send command to NAND device. This is the version for the new large page
|
|
* devices We dont have the separate regions as we have in the small page
|
|
* devices We dont have the separate regions as we have in the small page
|
|
@@ -679,8 +672,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
|
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
|
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
|
|
|
|
|
/*
|
|
/*
|
|
- * program and erase have their own busy handlers
|
|
|
|
- * status, sequential in, and deplete1 need no delay
|
|
|
|
|
|
+ * Program and erase have their own busy handlers status, sequential
|
|
|
|
+ * in, and deplete1 need no delay.
|
|
*/
|
|
*/
|
|
switch (command) {
|
|
switch (command) {
|
|
|
|
|
|
@@ -694,14 +687,12 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
|
case NAND_CMD_DEPLETE1:
|
|
case NAND_CMD_DEPLETE1:
|
|
return;
|
|
return;
|
|
|
|
|
|
- /*
|
|
|
|
- * read error status commands require only a short delay
|
|
|
|
- */
|
|
|
|
case NAND_CMD_STATUS_ERROR:
|
|
case NAND_CMD_STATUS_ERROR:
|
|
case NAND_CMD_STATUS_ERROR0:
|
|
case NAND_CMD_STATUS_ERROR0:
|
|
case NAND_CMD_STATUS_ERROR1:
|
|
case NAND_CMD_STATUS_ERROR1:
|
|
case NAND_CMD_STATUS_ERROR2:
|
|
case NAND_CMD_STATUS_ERROR2:
|
|
case NAND_CMD_STATUS_ERROR3:
|
|
case NAND_CMD_STATUS_ERROR3:
|
|
|
|
+ /* Read error status commands require only a short delay */
|
|
udelay(chip->chip_delay);
|
|
udelay(chip->chip_delay);
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -735,7 +726,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
|
default:
|
|
default:
|
|
/*
|
|
/*
|
|
* If we don't have access to the busy pin, we apply the given
|
|
* If we don't have access to the busy pin, we apply the given
|
|
- * command delay
|
|
|
|
|
|
+ * command delay.
|
|
*/
|
|
*/
|
|
if (!chip->dev_ready) {
|
|
if (!chip->dev_ready) {
|
|
udelay(chip->chip_delay);
|
|
udelay(chip->chip_delay);
|
|
@@ -743,8 +734,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /* Apply this short delay always to ensure that we do wait tWB in
|
|
|
|
- * any case on any machine. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Apply this short delay always to ensure that we do wait tWB in
|
|
|
|
+ * any case on any machine.
|
|
|
|
+ */
|
|
ndelay(100);
|
|
ndelay(100);
|
|
|
|
|
|
nand_wait_ready(mtd);
|
|
nand_wait_ready(mtd);
|
|
@@ -752,9 +745,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
|
|
|
|
|
/**
|
|
/**
|
|
* panic_nand_get_device - [GENERIC] Get chip for selected access
|
|
* panic_nand_get_device - [GENERIC] Get chip for selected access
|
|
- * @chip: the nand chip descriptor
|
|
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @new_state: the state which is requested
|
|
|
|
|
|
+ * @chip: the nand chip descriptor
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @new_state: the state which is requested
|
|
*
|
|
*
|
|
* Used when in panic, no locks are taken.
|
|
* Used when in panic, no locks are taken.
|
|
*/
|
|
*/
|
|
@@ -768,9 +761,9 @@ static void panic_nand_get_device(struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_get_device - [GENERIC] Get chip for selected access
|
|
* nand_get_device - [GENERIC] Get chip for selected access
|
|
- * @chip: the nand chip descriptor
|
|
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @new_state: the state which is requested
|
|
|
|
|
|
+ * @chip: the nand chip descriptor
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @new_state: the state which is requested
|
|
*
|
|
*
|
|
* Get the device and lock it for exclusive access
|
|
* Get the device and lock it for exclusive access
|
|
*/
|
|
*/
|
|
@@ -808,10 +801,10 @@ retry:
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * panic_nand_wait - [GENERIC] wait until the command is done
|
|
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @chip: NAND chip structure
|
|
|
|
- * @timeo: Timeout
|
|
|
|
|
|
+ * panic_nand_wait - [GENERIC] wait until the command is done
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @chip: NAND chip structure
|
|
|
|
+ * @timeo: timeout
|
|
*
|
|
*
|
|
* Wait for command done. This is a helper function for nand_wait used when
|
|
* Wait for command done. This is a helper function for nand_wait used when
|
|
* we are in interrupt context. May happen when in panic and trying to write
|
|
* we are in interrupt context. May happen when in panic and trying to write
|
|
@@ -834,13 +827,13 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * nand_wait - [DEFAULT] wait until the command is done
|
|
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @chip: NAND chip structure
|
|
|
|
|
|
+ * nand_wait - [DEFAULT] wait until the command is done
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @chip: NAND chip structure
|
|
*
|
|
*
|
|
- * Wait for command done. This applies to erase and program only
|
|
|
|
- * Erase can take up to 400ms and program up to 20ms according to
|
|
|
|
- * general NAND and SmartMedia specs
|
|
|
|
|
|
+ * Wait for command done. This applies to erase and program only. Erase can
|
|
|
|
+ * take up to 400ms and program up to 20ms according to general NAND and
|
|
|
|
+ * SmartMedia specs.
|
|
*/
|
|
*/
|
|
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|
{
|
|
{
|
|
@@ -855,8 +848,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|
|
|
|
|
led_trigger_event(nand_led_trigger, LED_FULL);
|
|
led_trigger_event(nand_led_trigger, LED_FULL);
|
|
|
|
|
|
- /* Apply this short delay always to ensure that we do wait tWB in
|
|
|
|
- * any case on any machine. */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Apply this short delay always to ensure that we do wait tWB in any
|
|
|
|
+ * case on any machine.
|
|
|
|
+ */
|
|
ndelay(100);
|
|
ndelay(100);
|
|
|
|
|
|
if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
|
|
if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
|
|
@@ -886,16 +881,15 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|
|
|
|
|
/**
|
|
/**
|
|
* __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
|
|
* __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
|
|
- *
|
|
|
|
* @mtd: mtd info
|
|
* @mtd: mtd info
|
|
* @ofs: offset to start unlock from
|
|
* @ofs: offset to start unlock from
|
|
* @len: length to unlock
|
|
* @len: length to unlock
|
|
- * @invert: when = 0, unlock the range of blocks within the lower and
|
|
|
|
- * upper boundary address
|
|
|
|
- * when = 1, unlock the range of blocks outside the boundaries
|
|
|
|
- * of the lower and upper boundary address
|
|
|
|
|
|
+ * @invert: when = 0, unlock the range of blocks within the lower and
|
|
|
|
+ * upper boundary address
|
|
|
|
+ * when = 1, unlock the range of blocks outside the boundaries
|
|
|
|
+ * of the lower and upper boundary address
|
|
*
|
|
*
|
|
- * return - unlock status
|
|
|
|
|
|
+ * Returs unlock status.
|
|
*/
|
|
*/
|
|
static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
|
|
static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
|
|
uint64_t len, int invert)
|
|
uint64_t len, int invert)
|
|
@@ -927,12 +921,11 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_unlock - [REPLACEABLE] unlocks specified locked blocks
|
|
* nand_unlock - [REPLACEABLE] unlocks specified locked blocks
|
|
- *
|
|
|
|
* @mtd: mtd info
|
|
* @mtd: mtd info
|
|
* @ofs: offset to start unlock from
|
|
* @ofs: offset to start unlock from
|
|
* @len: length to unlock
|
|
* @len: length to unlock
|
|
*
|
|
*
|
|
- * return - unlock status
|
|
|
|
|
|
+ * Returns unlock status.
|
|
*/
|
|
*/
|
|
int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
{
|
|
{
|
|
@@ -976,18 +969,16 @@ EXPORT_SYMBOL(nand_unlock);
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_lock - [REPLACEABLE] locks all blocks present in the device
|
|
* nand_lock - [REPLACEABLE] locks all blocks present in the device
|
|
- *
|
|
|
|
* @mtd: mtd info
|
|
* @mtd: mtd info
|
|
* @ofs: offset to start unlock from
|
|
* @ofs: offset to start unlock from
|
|
* @len: length to unlock
|
|
* @len: length to unlock
|
|
*
|
|
*
|
|
- * return - lock status
|
|
|
|
- *
|
|
|
|
- * This feature is not supported in many NAND parts. 'Micron' NAND parts
|
|
|
|
- * do have this feature, but it allows only to lock all blocks, not for
|
|
|
|
- * specified range for block.
|
|
|
|
|
|
+ * This feature is not supported in many NAND parts. 'Micron' NAND parts do
|
|
|
|
+ * have this feature, but it allows only to lock all blocks, not for specified
|
|
|
|
+ * range for block. Implementing 'lock' feature by making use of 'unlock', for
|
|
|
|
+ * now.
|
|
*
|
|
*
|
|
- * Implementing 'lock' feature by making use of 'unlock', for now.
|
|
|
|
|
|
+ * Returns lock status.
|
|
*/
|
|
*/
|
|
int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
{
|
|
{
|
|
@@ -1042,12 +1033,13 @@ EXPORT_SYMBOL(nand_lock);
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_page_raw - [Intern] read raw page data without ecc
|
|
* nand_read_page_raw - [Intern] read raw page data without ecc
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: buffer to store read data
|
|
|
|
- * @page: page number to read
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: buffer to store read data
|
|
|
|
+ * @page: page number to read
|
|
*
|
|
*
|
|
- * Not for syndrome calculating ecc controllers, which use a special oob layout
|
|
|
|
|
|
+ * Not for syndrome calculating ecc controllers, which use a special oob
|
|
|
|
+ * layout.
|
|
*/
|
|
*/
|
|
static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
uint8_t *buf, int page)
|
|
uint8_t *buf, int page)
|
|
@@ -1059,10 +1051,10 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_page_raw_syndrome - [Intern] read raw page data without ecc
|
|
* nand_read_page_raw_syndrome - [Intern] read raw page data without ecc
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: buffer to store read data
|
|
|
|
- * @page: page number to read
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: buffer to store read data
|
|
|
|
+ * @page: page number to read
|
|
*
|
|
*
|
|
* We need a special oob layout and handling even when OOB isn't used.
|
|
* We need a special oob layout and handling even when OOB isn't used.
|
|
*/
|
|
*/
|
|
@@ -1102,10 +1094,10 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_page_swecc - [REPLACABLE] software ecc based page read function
|
|
* nand_read_page_swecc - [REPLACABLE] software ecc based page read function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: buffer to store read data
|
|
|
|
- * @page: page number to read
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: buffer to store read data
|
|
|
|
+ * @page: page number to read
|
|
*/
|
|
*/
|
|
static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
uint8_t *buf, int page)
|
|
uint8_t *buf, int page)
|
|
@@ -1143,11 +1135,11 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
|
|
* nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @data_offs: offset of requested data within the page
|
|
|
|
- * @readlen: data length
|
|
|
|
- * @bufpoi: buffer to store read data
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @data_offs: offset of requested data within the page
|
|
|
|
+ * @readlen: data length
|
|
|
|
+ * @bufpoi: buffer to store read data
|
|
*/
|
|
*/
|
|
static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|
uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
|
|
uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
|
|
@@ -1160,12 +1152,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|
int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
|
|
int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
|
|
int index = 0;
|
|
int index = 0;
|
|
|
|
|
|
- /* Column address wihin the page aligned to ECC size (256bytes). */
|
|
|
|
|
|
+ /* Column address wihin the page aligned to ECC size (256bytes) */
|
|
start_step = data_offs / chip->ecc.size;
|
|
start_step = data_offs / chip->ecc.size;
|
|
end_step = (data_offs + readlen - 1) / chip->ecc.size;
|
|
end_step = (data_offs + readlen - 1) / chip->ecc.size;
|
|
num_steps = end_step - start_step + 1;
|
|
num_steps = end_step - start_step + 1;
|
|
|
|
|
|
- /* Data size aligned to ECC ecc.size*/
|
|
|
|
|
|
+ /* Data size aligned to ECC ecc.size */
|
|
datafrag_len = num_steps * chip->ecc.size;
|
|
datafrag_len = num_steps * chip->ecc.size;
|
|
eccfrag_len = num_steps * chip->ecc.bytes;
|
|
eccfrag_len = num_steps * chip->ecc.bytes;
|
|
|
|
|
|
@@ -1177,13 +1169,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|
p = bufpoi + data_col_addr;
|
|
p = bufpoi + data_col_addr;
|
|
chip->read_buf(mtd, p, datafrag_len);
|
|
chip->read_buf(mtd, p, datafrag_len);
|
|
|
|
|
|
- /* Calculate ECC */
|
|
|
|
|
|
+ /* Calculate ECC */
|
|
for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
|
|
for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
|
|
chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
|
|
chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
|
|
|
|
|
|
- /* The performance is faster if to position offsets
|
|
|
|
- according to ecc.pos. Let make sure here that
|
|
|
|
- there are no gaps in ecc positions */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * The performance is faster if we position offsets according to
|
|
|
|
+ * ecc.pos. Let's make sure that there are no gaps in ecc positions.
|
|
|
|
+ */
|
|
for (i = 0; i < eccfrag_len - 1; i++) {
|
|
for (i = 0; i < eccfrag_len - 1; i++) {
|
|
if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
|
|
if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
|
|
eccpos[i + start_step * chip->ecc.bytes + 1]) {
|
|
eccpos[i + start_step * chip->ecc.bytes + 1]) {
|
|
@@ -1195,8 +1188,10 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
|
|
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
|
|
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
|
} else {
|
|
} else {
|
|
- /* send the command to read the particular ecc bytes */
|
|
|
|
- /* take care about buswidth alignment in read_buf */
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Send the command to read the particular ecc bytes take care
|
|
|
|
+ * about buswidth alignment in read_buf.
|
|
|
|
+ */
|
|
index = start_step * chip->ecc.bytes;
|
|
index = start_step * chip->ecc.bytes;
|
|
|
|
|
|
aligned_pos = eccpos[index] & ~(busw - 1);
|
|
aligned_pos = eccpos[index] & ~(busw - 1);
|
|
@@ -1230,12 +1225,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
|
|
* nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: buffer to store read data
|
|
|
|
- * @page: page number to read
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: buffer to store read data
|
|
|
|
+ * @page: page number to read
|
|
*
|
|
*
|
|
- * Not for syndrome calculating ecc controllers which need a special oob layout
|
|
|
|
|
|
+ * Not for syndrome calculating ecc controllers which need a special oob
|
|
|
|
+ * layout.
|
|
*/
|
|
*/
|
|
static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
uint8_t *buf, int page)
|
|
uint8_t *buf, int page)
|
|
@@ -1275,17 +1271,16 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first
|
|
* nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: buffer to store read data
|
|
|
|
- * @page: page number to read
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: buffer to store read data
|
|
|
|
+ * @page: page number to read
|
|
*
|
|
*
|
|
- * Hardware ECC for large page chips, require OOB to be read first.
|
|
|
|
- * For this ECC mode, the write_page method is re-used from ECC_HW.
|
|
|
|
- * These methods read/write ECC from the OOB area, unlike the
|
|
|
|
- * ECC_HW_SYNDROME support with multiple ECC steps, follows the
|
|
|
|
- * "infix ECC" scheme and reads/writes ECC from the data area, by
|
|
|
|
- * overwriting the NAND manufacturer bad block markings.
|
|
|
|
|
|
+ * Hardware ECC for large page chips, require OOB to be read first. For this
|
|
|
|
+ * ECC mode, the write_page method is re-used from ECC_HW. These methods
|
|
|
|
+ * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
|
|
|
|
+ * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
|
|
|
|
+ * the data area, by overwriting the NAND manufacturer bad block markings.
|
|
*/
|
|
*/
|
|
static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
|
|
static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
|
|
struct nand_chip *chip, uint8_t *buf, int page)
|
|
struct nand_chip *chip, uint8_t *buf, int page)
|
|
@@ -1324,13 +1319,13 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
|
|
* nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: buffer to store read data
|
|
|
|
- * @page: page number to read
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: buffer to store read data
|
|
|
|
+ * @page: page number to read
|
|
*
|
|
*
|
|
- * The hw generator calculates the error syndrome automatically. Therefor
|
|
|
|
- * we need a special oob layout and handling.
|
|
|
|
|
|
+ * The hw generator calculates the error syndrome automatically. Therefore we
|
|
|
|
+ * need a special oob layout and handling.
|
|
*/
|
|
*/
|
|
static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
uint8_t *buf, int page)
|
|
uint8_t *buf, int page)
|
|
@@ -1379,10 +1374,10 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_transfer_oob - [Internal] Transfer oob to client buffer
|
|
* nand_transfer_oob - [Internal] Transfer oob to client buffer
|
|
- * @chip: nand chip structure
|
|
|
|
- * @oob: oob destination address
|
|
|
|
- * @ops: oob ops structure
|
|
|
|
- * @len: size of oob to transfer
|
|
|
|
|
|
+ * @chip: nand chip structure
|
|
|
|
+ * @oob: oob destination address
|
|
|
|
+ * @ops: oob ops structure
|
|
|
|
+ * @len: size of oob to transfer
|
|
*/
|
|
*/
|
|
static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
|
|
static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
|
|
struct mtd_oob_ops *ops, size_t len)
|
|
struct mtd_oob_ops *ops, size_t len)
|
|
@@ -1400,7 +1395,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
|
|
size_t bytes = 0;
|
|
size_t bytes = 0;
|
|
|
|
|
|
for (; free->length && len; free++, len -= bytes) {
|
|
for (; free->length && len; free++, len -= bytes) {
|
|
- /* Read request not from offset 0 ? */
|
|
|
|
|
|
+ /* Read request not from offset 0? */
|
|
if (unlikely(roffs)) {
|
|
if (unlikely(roffs)) {
|
|
if (roffs >= free->length) {
|
|
if (roffs >= free->length) {
|
|
roffs -= free->length;
|
|
roffs -= free->length;
|
|
@@ -1427,10 +1422,9 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_do_read_ops - [Internal] Read data with ECC
|
|
* nand_do_read_ops - [Internal] Read data with ECC
|
|
- *
|
|
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @from: offset to read from
|
|
|
|
- * @ops: oob ops structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @from: offset to read from
|
|
|
|
+ * @ops: oob ops structure
|
|
*
|
|
*
|
|
* Internal function. Called with chip held.
|
|
* Internal function. Called with chip held.
|
|
*/
|
|
*/
|
|
@@ -1467,7 +1461,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|
bytes = min(mtd->writesize - col, readlen);
|
|
bytes = min(mtd->writesize - col, readlen);
|
|
aligned = (bytes == mtd->writesize);
|
|
aligned = (bytes == mtd->writesize);
|
|
|
|
|
|
- /* Is the current page in the buffer ? */
|
|
|
|
|
|
+ /* Is the current page in the buffer? */
|
|
if (realpage != chip->pagebuf || oob) {
|
|
if (realpage != chip->pagebuf || oob) {
|
|
bufpoi = aligned ? buf : chip->buffers->databuf;
|
|
bufpoi = aligned ? buf : chip->buffers->databuf;
|
|
|
|
|
|
@@ -1533,7 +1527,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|
if (!readlen)
|
|
if (!readlen)
|
|
break;
|
|
break;
|
|
|
|
|
|
- /* For subsequent reads align to page boundary. */
|
|
|
|
|
|
+ /* For subsequent reads align to page boundary */
|
|
col = 0;
|
|
col = 0;
|
|
/* Increment page address */
|
|
/* Increment page address */
|
|
realpage++;
|
|
realpage++;
|
|
@@ -1546,8 +1540,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|
chip->select_chip(mtd, chipnr);
|
|
chip->select_chip(mtd, chipnr);
|
|
}
|
|
}
|
|
|
|
|
|
- /* Check, if the chip supports auto page increment
|
|
|
|
- * or if we have hit a block boundary.
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Check, if the chip supports auto page increment or if we
|
|
|
|
+ * have hit a block boundary.
|
|
*/
|
|
*/
|
|
if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
|
|
if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
|
|
sndcmd = 1;
|
|
sndcmd = 1;
|
|
@@ -1568,13 +1563,13 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc
|
|
* nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @from: offset to read from
|
|
|
|
- * @len: number of bytes to read
|
|
|
|
- * @retlen: pointer to variable to store the number of read bytes
|
|
|
|
- * @buf: the databuffer to put data
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @from: offset to read from
|
|
|
|
+ * @len: number of bytes to read
|
|
|
|
+ * @retlen: pointer to variable to store the number of read bytes
|
|
|
|
+ * @buf: the databuffer to put data
|
|
*
|
|
*
|
|
- * Get hold of the chip and call nand_do_read
|
|
|
|
|
|
+ * Get hold of the chip and call nand_do_read.
|
|
*/
|
|
*/
|
|
static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|
static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|
size_t *retlen, uint8_t *buf)
|
|
size_t *retlen, uint8_t *buf)
|
|
@@ -1605,10 +1600,10 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_oob_std - [REPLACABLE] the most common OOB data read function
|
|
* nand_read_oob_std - [REPLACABLE] the most common OOB data read function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @page: page number to read
|
|
|
|
- * @sndcmd: flag whether to issue read command or not
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @page: page number to read
|
|
|
|
+ * @sndcmd: flag whether to issue read command or not
|
|
*/
|
|
*/
|
|
static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
|
int page, int sndcmd)
|
|
int page, int sndcmd)
|
|
@@ -1624,10 +1619,10 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
|
/**
|
|
/**
|
|
* nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
|
|
* nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
|
|
* with syndromes
|
|
* with syndromes
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @page: page number to read
|
|
|
|
- * @sndcmd: flag whether to issue read command or not
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @page: page number to read
|
|
|
|
+ * @sndcmd: flag whether to issue read command or not
|
|
*/
|
|
*/
|
|
static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
int page, int sndcmd)
|
|
int page, int sndcmd)
|
|
@@ -1662,9 +1657,9 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_oob_std - [REPLACABLE] the most common OOB data write function
|
|
* nand_write_oob_std - [REPLACABLE] the most common OOB data write function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @page: page number to write
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @page: page number to write
|
|
*/
|
|
*/
|
|
static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
|
int page)
|
|
int page)
|
|
@@ -1685,10 +1680,10 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
|
|
* nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
|
|
- * with syndrome - only for large page flash !
|
|
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @page: page number to write
|
|
|
|
|
|
+ * with syndrome - only for large page flash
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @page: page number to write
|
|
*/
|
|
*/
|
|
static int nand_write_oob_syndrome(struct mtd_info *mtd,
|
|
static int nand_write_oob_syndrome(struct mtd_info *mtd,
|
|
struct nand_chip *chip, int page)
|
|
struct nand_chip *chip, int page)
|
|
@@ -1744,11 +1739,11 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_do_read_oob - [Intern] NAND read out-of-band
|
|
* nand_do_read_oob - [Intern] NAND read out-of-band
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @from: offset to read from
|
|
|
|
- * @ops: oob operations description structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @from: offset to read from
|
|
|
|
+ * @ops: oob operations description structure
|
|
*
|
|
*
|
|
- * NAND read out-of-band data from the spare area
|
|
|
|
|
|
+ * NAND read out-of-band data from the spare area.
|
|
*/
|
|
*/
|
|
static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|
static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|
struct mtd_oob_ops *ops)
|
|
struct mtd_oob_ops *ops)
|
|
@@ -1824,8 +1819,9 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|
chip->select_chip(mtd, chipnr);
|
|
chip->select_chip(mtd, chipnr);
|
|
}
|
|
}
|
|
|
|
|
|
- /* Check, if the chip supports auto page increment
|
|
|
|
- * or if we have hit a block boundary.
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Check, if the chip supports auto page increment or if we
|
|
|
|
+ * have hit a block boundary.
|
|
*/
|
|
*/
|
|
if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
|
|
if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
|
|
sndcmd = 1;
|
|
sndcmd = 1;
|
|
@@ -1837,11 +1833,11 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
|
|
* nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @from: offset to read from
|
|
|
|
- * @ops: oob operation description structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @from: offset to read from
|
|
|
|
+ * @ops: oob operation description structure
|
|
*
|
|
*
|
|
- * NAND read data and/or out-of-band data
|
|
|
|
|
|
+ * NAND read data and/or out-of-band data.
|
|
*/
|
|
*/
|
|
static int nand_read_oob(struct mtd_info *mtd, loff_t from,
|
|
static int nand_read_oob(struct mtd_info *mtd, loff_t from,
|
|
struct mtd_oob_ops *ops)
|
|
struct mtd_oob_ops *ops)
|
|
@@ -1883,11 +1879,12 @@ out:
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_page_raw - [Intern] raw page write function
|
|
* nand_write_page_raw - [Intern] raw page write function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: data buffer
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: data buffer
|
|
*
|
|
*
|
|
- * Not for syndrome calculating ecc controllers, which use a special oob layout
|
|
|
|
|
|
+ * Not for syndrome calculating ecc controllers, which use a special oob
|
|
|
|
+ * layout.
|
|
*/
|
|
*/
|
|
static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
const uint8_t *buf)
|
|
const uint8_t *buf)
|
|
@@ -1898,9 +1895,9 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_page_raw_syndrome - [Intern] raw page write function
|
|
* nand_write_page_raw_syndrome - [Intern] raw page write function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: data buffer
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: data buffer
|
|
*
|
|
*
|
|
* We need a special oob layout and handling even when ECC isn't checked.
|
|
* We need a special oob layout and handling even when ECC isn't checked.
|
|
*/
|
|
*/
|
|
@@ -1937,9 +1934,9 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
* nand_write_page_swecc - [REPLACABLE] software ecc based page write function
|
|
* nand_write_page_swecc - [REPLACABLE] software ecc based page write function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: data buffer
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: data buffer
|
|
*/
|
|
*/
|
|
static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
const uint8_t *buf)
|
|
const uint8_t *buf)
|
|
@@ -1963,9 +1960,9 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
|
|
* nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: data buffer
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: data buffer
|
|
*/
|
|
*/
|
|
static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
const uint8_t *buf)
|
|
const uint8_t *buf)
|
|
@@ -1991,12 +1988,12 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
|
|
* nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
|
|
- * @mtd: mtd info structure
|
|
|
|
- * @chip: nand chip info structure
|
|
|
|
- * @buf: data buffer
|
|
|
|
|
|
+ * @mtd: mtd info structure
|
|
|
|
+ * @chip: nand chip info structure
|
|
|
|
+ * @buf: data buffer
|
|
*
|
|
*
|
|
- * The hw generator calculates the error syndrome automatically. Therefor
|
|
|
|
- * we need a special oob layout and handling.
|
|
|
|
|
|
+ * The hw generator calculates the error syndrome automatically. Therefore we
|
|
|
|
+ * need a special oob layout and handling.
|
|
*/
|
|
*/
|
|
static void nand_write_page_syndrome(struct mtd_info *mtd,
|
|
static void nand_write_page_syndrome(struct mtd_info *mtd,
|
|
struct nand_chip *chip, const uint8_t *buf)
|
|
struct nand_chip *chip, const uint8_t *buf)
|
|
@@ -2035,12 +2032,12 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_page - [REPLACEABLE] write one page
|
|
* nand_write_page - [REPLACEABLE] write one page
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @chip: NAND chip descriptor
|
|
|
|
- * @buf: the data to write
|
|
|
|
- * @page: page number to write
|
|
|
|
- * @cached: cached programming
|
|
|
|
- * @raw: use _raw version of write_page
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @chip: NAND chip descriptor
|
|
|
|
+ * @buf: the data to write
|
|
|
|
+ * @page: page number to write
|
|
|
|
+ * @cached: cached programming
|
|
|
|
+ * @raw: use _raw version of write_page
|
|
*/
|
|
*/
|
|
static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
const uint8_t *buf, int page, int cached, int raw)
|
|
const uint8_t *buf, int page, int cached, int raw)
|
|
@@ -2056,7 +2053,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/*
|
|
/*
|
|
* Cached progamming disabled for now, Not sure if its worth the
|
|
* Cached progamming disabled for now, Not sure if its worth the
|
|
- * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
|
|
|
|
|
|
+ * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).
|
|
*/
|
|
*/
|
|
cached = 0;
|
|
cached = 0;
|
|
|
|
|
|
@@ -2066,7 +2063,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
status = chip->waitfunc(mtd, chip);
|
|
status = chip->waitfunc(mtd, chip);
|
|
/*
|
|
/*
|
|
* See if operation failed and additional status checks are
|
|
* See if operation failed and additional status checks are
|
|
- * available
|
|
|
|
|
|
+ * available.
|
|
*/
|
|
*/
|
|
if ((status & NAND_STATUS_FAIL) && (chip->errstat))
|
|
if ((status & NAND_STATUS_FAIL) && (chip->errstat))
|
|
status = chip->errstat(mtd, chip, FL_WRITING, status,
|
|
status = chip->errstat(mtd, chip, FL_WRITING, status,
|
|
@@ -2091,10 +2088,10 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_fill_oob - [Internal] Transfer client buffer to oob
|
|
* nand_fill_oob - [Internal] Transfer client buffer to oob
|
|
- * @chip: nand chip structure
|
|
|
|
- * @oob: oob data buffer
|
|
|
|
- * @len: oob data write length
|
|
|
|
- * @ops: oob ops structure
|
|
|
|
|
|
+ * @chip: nand chip structure
|
|
|
|
+ * @oob: oob data buffer
|
|
|
|
+ * @len: oob data write length
|
|
|
|
+ * @ops: oob ops structure
|
|
*/
|
|
*/
|
|
static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
|
static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
|
struct mtd_oob_ops *ops)
|
|
struct mtd_oob_ops *ops)
|
|
@@ -2112,7 +2109,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
|
size_t bytes = 0;
|
|
size_t bytes = 0;
|
|
|
|
|
|
for (; free->length && len; free++, len -= bytes) {
|
|
for (; free->length && len; free++, len -= bytes) {
|
|
- /* Write request not from offset 0 ? */
|
|
|
|
|
|
+ /* Write request not from offset 0? */
|
|
if (unlikely(woffs)) {
|
|
if (unlikely(woffs)) {
|
|
if (woffs >= free->length) {
|
|
if (woffs >= free->length) {
|
|
woffs -= free->length;
|
|
woffs -= free->length;
|
|
@@ -2141,11 +2138,11 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_do_write_ops - [Internal] NAND write with ECC
|
|
* nand_do_write_ops - [Internal] NAND write with ECC
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @to: offset to write to
|
|
|
|
- * @ops: oob operations description structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @to: offset to write to
|
|
|
|
+ * @ops: oob operations description structure
|
|
*
|
|
*
|
|
- * NAND write with ECC
|
|
|
|
|
|
+ * NAND write with ECC.
|
|
*/
|
|
*/
|
|
static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
struct mtd_oob_ops *ops)
|
|
struct mtd_oob_ops *ops)
|
|
@@ -2166,7 +2163,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
if (!writelen)
|
|
if (!writelen)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- /* reject writes, which are not page aligned */
|
|
|
|
|
|
+ /* Reject writes, which are not page aligned */
|
|
if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
|
|
if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
|
|
printk(KERN_NOTICE "%s: Attempt to write not "
|
|
printk(KERN_NOTICE "%s: Attempt to write not "
|
|
"page aligned data\n", __func__);
|
|
"page aligned data\n", __func__);
|
|
@@ -2208,7 +2205,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
int cached = writelen > bytes && page != blockmask;
|
|
int cached = writelen > bytes && page != blockmask;
|
|
uint8_t *wbuf = buf;
|
|
uint8_t *wbuf = buf;
|
|
|
|
|
|
- /* Partial page write ? */
|
|
|
|
|
|
+ /* Partial page write? */
|
|
if (unlikely(column || writelen < (mtd->writesize - 1))) {
|
|
if (unlikely(column || writelen < (mtd->writesize - 1))) {
|
|
cached = 0;
|
|
cached = 0;
|
|
bytes = min_t(int, bytes - column, (int) writelen);
|
|
bytes = min_t(int, bytes - column, (int) writelen);
|
|
@@ -2254,11 +2251,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
|
|
|
|
/**
|
|
/**
|
|
* panic_nand_write - [MTD Interface] NAND write with ECC
|
|
* panic_nand_write - [MTD Interface] NAND write with ECC
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @to: offset to write to
|
|
|
|
- * @len: number of bytes to write
|
|
|
|
- * @retlen: pointer to variable to store the number of written bytes
|
|
|
|
- * @buf: the data to write
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @to: offset to write to
|
|
|
|
+ * @len: number of bytes to write
|
|
|
|
+ * @retlen: pointer to variable to store the number of written bytes
|
|
|
|
+ * @buf: the data to write
|
|
*
|
|
*
|
|
* NAND write with ECC. Used when performing writes in interrupt context, this
|
|
* NAND write with ECC. Used when performing writes in interrupt context, this
|
|
* may for example be called by mtdoops when writing an oops while in panic.
|
|
* may for example be called by mtdoops when writing an oops while in panic.
|
|
@@ -2275,10 +2272,10 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
if (!len)
|
|
if (!len)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- /* Wait for the device to get ready. */
|
|
|
|
|
|
+ /* Wait for the device to get ready */
|
|
panic_nand_wait(mtd, chip, 400);
|
|
panic_nand_wait(mtd, chip, 400);
|
|
|
|
|
|
- /* Grab the device. */
|
|
|
|
|
|
+ /* Grab the device */
|
|
panic_nand_get_device(chip, mtd, FL_WRITING);
|
|
panic_nand_get_device(chip, mtd, FL_WRITING);
|
|
|
|
|
|
chip->ops.len = len;
|
|
chip->ops.len = len;
|
|
@@ -2293,13 +2290,13 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write - [MTD Interface] NAND write with ECC
|
|
* nand_write - [MTD Interface] NAND write with ECC
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @to: offset to write to
|
|
|
|
- * @len: number of bytes to write
|
|
|
|
- * @retlen: pointer to variable to store the number of written bytes
|
|
|
|
- * @buf: the data to write
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @to: offset to write to
|
|
|
|
+ * @len: number of bytes to write
|
|
|
|
+ * @retlen: pointer to variable to store the number of written bytes
|
|
|
|
+ * @buf: the data to write
|
|
*
|
|
*
|
|
- * NAND write with ECC
|
|
|
|
|
|
+ * NAND write with ECC.
|
|
*/
|
|
*/
|
|
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
size_t *retlen, const uint8_t *buf)
|
|
size_t *retlen, const uint8_t *buf)
|
|
@@ -2330,11 +2327,11 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_do_write_oob - [MTD Interface] NAND write out-of-band
|
|
* nand_do_write_oob - [MTD Interface] NAND write out-of-band
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @to: offset to write to
|
|
|
|
- * @ops: oob operation description structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @to: offset to write to
|
|
|
|
+ * @ops: oob operation description structure
|
|
*
|
|
*
|
|
- * NAND write out-of-band
|
|
|
|
|
|
+ * NAND write out-of-band.
|
|
*/
|
|
*/
|
|
static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
|
|
static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
|
|
struct mtd_oob_ops *ops)
|
|
struct mtd_oob_ops *ops)
|
|
@@ -2410,9 +2407,9 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
|
|
* nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @to: offset to write to
|
|
|
|
- * @ops: oob operation description structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @to: offset to write to
|
|
|
|
+ * @ops: oob operation description structure
|
|
*/
|
|
*/
|
|
static int nand_write_oob(struct mtd_info *mtd, loff_t to,
|
|
static int nand_write_oob(struct mtd_info *mtd, loff_t to,
|
|
struct mtd_oob_ops *ops)
|
|
struct mtd_oob_ops *ops)
|
|
@@ -2453,10 +2450,10 @@ out:
|
|
|
|
|
|
/**
|
|
/**
|
|
* single_erease_cmd - [GENERIC] NAND standard block erase command function
|
|
* single_erease_cmd - [GENERIC] NAND standard block erase command function
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @page: the page address of the block which will be erased
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @page: the page address of the block which will be erased
|
|
*
|
|
*
|
|
- * Standard erase command for NAND chips
|
|
|
|
|
|
+ * Standard erase command for NAND chips.
|
|
*/
|
|
*/
|
|
static void single_erase_cmd(struct mtd_info *mtd, int page)
|
|
static void single_erase_cmd(struct mtd_info *mtd, int page)
|
|
{
|
|
{
|
|
@@ -2468,11 +2465,10 @@ static void single_erase_cmd(struct mtd_info *mtd, int page)
|
|
|
|
|
|
/**
|
|
/**
|
|
* multi_erease_cmd - [GENERIC] AND specific block erase command function
|
|
* multi_erease_cmd - [GENERIC] AND specific block erase command function
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @page: the page address of the block which will be erased
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @page: the page address of the block which will be erased
|
|
*
|
|
*
|
|
- * AND multi block erase command function
|
|
|
|
- * Erase 4 consecutive blocks
|
|
|
|
|
|
+ * AND multi block erase command function. Erase 4 consecutive blocks.
|
|
*/
|
|
*/
|
|
static void multi_erase_cmd(struct mtd_info *mtd, int page)
|
|
static void multi_erase_cmd(struct mtd_info *mtd, int page)
|
|
{
|
|
{
|
|
@@ -2487,10 +2483,10 @@ static void multi_erase_cmd(struct mtd_info *mtd, int page)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_erase - [MTD Interface] erase block(s)
|
|
* nand_erase - [MTD Interface] erase block(s)
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @instr: erase instruction
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @instr: erase instruction
|
|
*
|
|
*
|
|
- * Erase one ore more blocks
|
|
|
|
|
|
+ * Erase one ore more blocks.
|
|
*/
|
|
*/
|
|
static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|
static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|
{
|
|
{
|
|
@@ -2500,11 +2496,11 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|
#define BBT_PAGE_MASK 0xffffff3f
|
|
#define BBT_PAGE_MASK 0xffffff3f
|
|
/**
|
|
/**
|
|
* nand_erase_nand - [Internal] erase block(s)
|
|
* nand_erase_nand - [Internal] erase block(s)
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @instr: erase instruction
|
|
|
|
- * @allowbbt: allow erasing the bbt area
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @instr: erase instruction
|
|
|
|
+ * @allowbbt: allow erasing the bbt area
|
|
*
|
|
*
|
|
- * Erase one ore more blocks
|
|
|
|
|
|
+ * Erase one ore more blocks.
|
|
*/
|
|
*/
|
|
int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
int allowbbt)
|
|
int allowbbt)
|
|
@@ -2549,7 +2545,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
* If BBT requires refresh, set the BBT page mask to see if the BBT
|
|
* If BBT requires refresh, set the BBT page mask to see if the BBT
|
|
* should be rewritten. Otherwise the mask is set to 0xffffffff which
|
|
* should be rewritten. Otherwise the mask is set to 0xffffffff which
|
|
* can not be matched. This is also done when the bbt is actually
|
|
* can not be matched. This is also done when the bbt is actually
|
|
- * erased to avoid recusrsive updates
|
|
|
|
|
|
+ * erased to avoid recusrsive updates.
|
|
*/
|
|
*/
|
|
if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
|
|
if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
|
|
bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
|
|
bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
|
|
@@ -2560,9 +2556,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
instr->state = MTD_ERASING;
|
|
instr->state = MTD_ERASING;
|
|
|
|
|
|
while (len) {
|
|
while (len) {
|
|
- /*
|
|
|
|
- * heck if we have a bad block, we do not erase bad blocks !
|
|
|
|
- */
|
|
|
|
|
|
+ /* Heck if we have a bad block, we do not erase bad blocks! */
|
|
if (nand_block_checkbad(mtd, ((loff_t) page) <<
|
|
if (nand_block_checkbad(mtd, ((loff_t) page) <<
|
|
chip->page_shift, 0, allowbbt)) {
|
|
chip->page_shift, 0, allowbbt)) {
|
|
printk(KERN_WARNING "%s: attempt to erase a bad block "
|
|
printk(KERN_WARNING "%s: attempt to erase a bad block "
|
|
@@ -2573,7 +2567,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
|
|
|
|
/*
|
|
/*
|
|
* Invalidate the page cache, if we erase the block which
|
|
* Invalidate the page cache, if we erase the block which
|
|
- * contains the current cached page
|
|
|
|
|
|
+ * contains the current cached page.
|
|
*/
|
|
*/
|
|
if (page <= chip->pagebuf && chip->pagebuf <
|
|
if (page <= chip->pagebuf && chip->pagebuf <
|
|
(page + pages_per_block))
|
|
(page + pages_per_block))
|
|
@@ -2603,7 +2597,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
|
|
|
|
/*
|
|
/*
|
|
* If BBT requires refresh, set the BBT rewrite flag to the
|
|
* If BBT requires refresh, set the BBT rewrite flag to the
|
|
- * page being erased
|
|
|
|
|
|
+ * page being erased.
|
|
*/
|
|
*/
|
|
if (bbt_masked_page != 0xffffffff &&
|
|
if (bbt_masked_page != 0xffffffff &&
|
|
(page & BBT_PAGE_MASK) == bbt_masked_page)
|
|
(page & BBT_PAGE_MASK) == bbt_masked_page)
|
|
@@ -2622,7 +2616,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
|
|
|
|
/*
|
|
/*
|
|
* If BBT requires refresh and BBT-PERCHIP, set the BBT
|
|
* If BBT requires refresh and BBT-PERCHIP, set the BBT
|
|
- * page mask to see if this BBT should be rewritten
|
|
|
|
|
|
+ * page mask to see if this BBT should be rewritten.
|
|
*/
|
|
*/
|
|
if (bbt_masked_page != 0xffffffff &&
|
|
if (bbt_masked_page != 0xffffffff &&
|
|
(chip->bbt_td->options & NAND_BBT_PERCHIP))
|
|
(chip->bbt_td->options & NAND_BBT_PERCHIP))
|
|
@@ -2645,7 +2639,7 @@ erase_exit:
|
|
|
|
|
|
/*
|
|
/*
|
|
* If BBT requires refresh and erase was successful, rewrite any
|
|
* If BBT requires refresh and erase was successful, rewrite any
|
|
- * selected bad block tables
|
|
|
|
|
|
+ * selected bad block tables.
|
|
*/
|
|
*/
|
|
if (bbt_masked_page == 0xffffffff || ret)
|
|
if (bbt_masked_page == 0xffffffff || ret)
|
|
return ret;
|
|
return ret;
|
|
@@ -2653,7 +2647,7 @@ erase_exit:
|
|
for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
|
|
for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
|
|
if (!rewrite_bbt[chipnr])
|
|
if (!rewrite_bbt[chipnr])
|
|
continue;
|
|
continue;
|
|
- /* update the BBT for chip */
|
|
|
|
|
|
+ /* Update the BBT for chip */
|
|
DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
|
|
DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
|
|
"(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
|
|
"(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
|
|
rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
|
|
rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
|
|
@@ -2666,9 +2660,9 @@ erase_exit:
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_sync - [MTD Interface] sync
|
|
* nand_sync - [MTD Interface] sync
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*
|
|
*
|
|
- * Sync is actually a wait for chip ready function
|
|
|
|
|
|
+ * Sync is actually a wait for chip ready function.
|
|
*/
|
|
*/
|
|
static void nand_sync(struct mtd_info *mtd)
|
|
static void nand_sync(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -2684,8 +2678,8 @@ static void nand_sync(struct mtd_info *mtd)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_block_isbad - [MTD Interface] Check if block at offset is bad
|
|
* nand_block_isbad - [MTD Interface] Check if block at offset is bad
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @offs: offset relative to mtd start
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @offs: offset relative to mtd start
|
|
*/
|
|
*/
|
|
static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
|
|
static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
|
|
{
|
|
{
|
|
@@ -2698,8 +2692,8 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
|
|
* nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @ofs: offset relative to mtd start
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @ofs: offset relative to mtd start
|
|
*/
|
|
*/
|
|
static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
{
|
|
{
|
|
@@ -2708,7 +2702,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
|
|
|
ret = nand_block_isbad(mtd, ofs);
|
|
ret = nand_block_isbad(mtd, ofs);
|
|
if (ret) {
|
|
if (ret) {
|
|
- /* If it was bad already, return success and do nothing. */
|
|
|
|
|
|
+ /* If it was bad already, return success and do nothing */
|
|
if (ret > 0)
|
|
if (ret > 0)
|
|
return 0;
|
|
return 0;
|
|
return ret;
|
|
return ret;
|
|
@@ -2719,7 +2713,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_suspend - [MTD Interface] Suspend the NAND flash
|
|
* nand_suspend - [MTD Interface] Suspend the NAND flash
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*/
|
|
*/
|
|
static int nand_suspend(struct mtd_info *mtd)
|
|
static int nand_suspend(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -2730,7 +2724,7 @@ static int nand_suspend(struct mtd_info *mtd)
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_resume - [MTD Interface] Resume the NAND flash
|
|
* nand_resume - [MTD Interface] Resume the NAND flash
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*/
|
|
*/
|
|
static void nand_resume(struct mtd_info *mtd)
|
|
static void nand_resume(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -2743,9 +2737,7 @@ static void nand_resume(struct mtd_info *mtd)
|
|
"in suspended state\n", __func__);
|
|
"in suspended state\n", __func__);
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Set default functions
|
|
|
|
- */
|
|
|
|
|
|
+/* Set default functions */
|
|
static void nand_set_defaults(struct nand_chip *chip, int busw)
|
|
static void nand_set_defaults(struct nand_chip *chip, int busw)
|
|
{
|
|
{
|
|
/* check for proper chip_delay setup, set 20us if not */
|
|
/* check for proper chip_delay setup, set 20us if not */
|
|
@@ -2787,23 +2779,21 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * sanitize ONFI strings so we can safely print them
|
|
|
|
- */
|
|
|
|
|
|
+/* Sanitize ONFI strings so we can safely print them */
|
|
static void sanitize_string(uint8_t *s, size_t len)
|
|
static void sanitize_string(uint8_t *s, size_t len)
|
|
{
|
|
{
|
|
ssize_t i;
|
|
ssize_t i;
|
|
|
|
|
|
- /* null terminate */
|
|
|
|
|
|
+ /* Null terminate */
|
|
s[len - 1] = 0;
|
|
s[len - 1] = 0;
|
|
|
|
|
|
- /* remove non printable chars */
|
|
|
|
|
|
+ /* Remove non printable chars */
|
|
for (i = 0; i < len - 1; i++) {
|
|
for (i = 0; i < len - 1; i++) {
|
|
if (s[i] < ' ' || s[i] > 127)
|
|
if (s[i] < ' ' || s[i] > 127)
|
|
s[i] = '?';
|
|
s[i] = '?';
|
|
}
|
|
}
|
|
|
|
|
|
- /* remove trailing spaces */
|
|
|
|
|
|
+ /* Remove trailing spaces */
|
|
strim(s);
|
|
strim(s);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2820,7 +2810,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
|
|
|
|
|
|
+ * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
|
|
*/
|
|
*/
|
|
static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
|
static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
|
int busw)
|
|
int busw)
|
|
@@ -2829,7 +2819,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
|
int i;
|
|
int i;
|
|
int val;
|
|
int val;
|
|
|
|
|
|
- /* try ONFI for unknow chip or LP */
|
|
|
|
|
|
+ /* Try ONFI for unknow chip or LP */
|
|
chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
|
|
chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
|
|
if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
|
|
if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
|
|
chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
|
|
chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
|
|
@@ -2849,7 +2839,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
|
if (i == 3)
|
|
if (i == 3)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- /* check version */
|
|
|
|
|
|
+ /* Check version */
|
|
val = le16_to_cpu(p->revision);
|
|
val = le16_to_cpu(p->revision);
|
|
if (val & (1 << 5))
|
|
if (val & (1 << 5))
|
|
chip->onfi_version = 23;
|
|
chip->onfi_version = 23;
|
|
@@ -2890,7 +2880,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Get the flash and manufacturer id and lookup if the type is supported
|
|
|
|
|
|
+ * Get the flash and manufacturer id and lookup if the type is supported.
|
|
*/
|
|
*/
|
|
static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
struct nand_chip *chip,
|
|
struct nand_chip *chip,
|
|
@@ -2907,7 +2897,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
|
|
|
|
/*
|
|
/*
|
|
* Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
|
|
* Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
|
|
- * after power-up
|
|
|
|
|
|
+ * after power-up.
|
|
*/
|
|
*/
|
|
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
|
|
|
|
@@ -2918,7 +2908,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
*maf_id = chip->read_byte(mtd);
|
|
*maf_id = chip->read_byte(mtd);
|
|
*dev_id = chip->read_byte(mtd);
|
|
*dev_id = chip->read_byte(mtd);
|
|
|
|
|
|
- /* Try again to make sure, as some systems the bus-hold or other
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Try again to make sure, as some systems the bus-hold or other
|
|
* interface concerns can cause random data which looks like a
|
|
* interface concerns can cause random data which looks like a
|
|
* possibly credible NAND flash to appear. If the two results do
|
|
* possibly credible NAND flash to appear. If the two results do
|
|
* not match, ignore the device completely.
|
|
* not match, ignore the device completely.
|
|
@@ -2967,7 +2958,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
chip->chipsize = (uint64_t)type->chipsize << 20;
|
|
chip->chipsize = (uint64_t)type->chipsize << 20;
|
|
|
|
|
|
if (!type->pagesize && chip->init_size) {
|
|
if (!type->pagesize && chip->init_size) {
|
|
- /* set the pagesize, oobsize, erasesize by the driver*/
|
|
|
|
|
|
+ /* Set the pagesize, oobsize, erasesize by the driver */
|
|
busw = chip->init_size(mtd, chip, id_data);
|
|
busw = chip->init_size(mtd, chip, id_data);
|
|
} else if (!type->pagesize) {
|
|
} else if (!type->pagesize) {
|
|
int extid;
|
|
int extid;
|
|
@@ -3027,7 +3018,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
/*
|
|
/*
|
|
- * Old devices have chip data hardcoded in the device id table
|
|
|
|
|
|
+ * Old devices have chip data hardcoded in the device id table.
|
|
*/
|
|
*/
|
|
mtd->erasesize = type->erasesize;
|
|
mtd->erasesize = type->erasesize;
|
|
mtd->writesize = type->pagesize;
|
|
mtd->writesize = type->pagesize;
|
|
@@ -3037,7 +3028,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
/*
|
|
/*
|
|
* Check for Spansion/AMD ID + repeating 5th, 6th byte since
|
|
* Check for Spansion/AMD ID + repeating 5th, 6th byte since
|
|
* some Spansion chips have erasesize that conflicts with size
|
|
* some Spansion chips have erasesize that conflicts with size
|
|
- * listed in nand_ids table
|
|
|
|
|
|
+ * listed in nand_ids table.
|
|
* Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
|
|
* Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
|
|
*/
|
|
*/
|
|
if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 &&
|
|
if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 &&
|
|
@@ -3051,15 +3042,16 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
chip->options &= ~NAND_CHIPOPTIONS_MSK;
|
|
chip->options &= ~NAND_CHIPOPTIONS_MSK;
|
|
chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
|
|
chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
|
|
|
|
|
|
- /* Check if chip is a not a samsung device. Do not clear the
|
|
|
|
- * options for chips which are not having an extended id.
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Check if chip is not a Samsung device. Do not clear the
|
|
|
|
+ * options for chips which do not have an extended id.
|
|
*/
|
|
*/
|
|
if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
|
|
if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
|
|
chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
|
|
chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
|
|
ident_done:
|
|
ident_done:
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Set chip as a default. Board drivers can override it, if necessary
|
|
|
|
|
|
+ * Set chip as a default. Board drivers can override it, if necessary.
|
|
*/
|
|
*/
|
|
chip->options |= NAND_NO_AUTOINCR;
|
|
chip->options |= NAND_NO_AUTOINCR;
|
|
|
|
|
|
@@ -3071,7 +3063,7 @@ ident_done:
|
|
|
|
|
|
/*
|
|
/*
|
|
* Check, if buswidth is correct. Hardware drivers should set
|
|
* Check, if buswidth is correct. Hardware drivers should set
|
|
- * chip correct !
|
|
|
|
|
|
+ * chip correct!
|
|
*/
|
|
*/
|
|
if (busw != (chip->options & NAND_BUSWIDTH_16)) {
|
|
if (busw != (chip->options & NAND_BUSWIDTH_16)) {
|
|
printk(KERN_INFO "NAND device: Manufacturer ID:"
|
|
printk(KERN_INFO "NAND device: Manufacturer ID:"
|
|
@@ -3085,7 +3077,7 @@ ident_done:
|
|
|
|
|
|
/* Calculate the address shift from the page size */
|
|
/* Calculate the address shift from the page size */
|
|
chip->page_shift = ffs(mtd->writesize) - 1;
|
|
chip->page_shift = ffs(mtd->writesize) - 1;
|
|
- /* Convert chipsize to number of pages per chip -1. */
|
|
|
|
|
|
+ /* Convert chipsize to number of pages per chip -1 */
|
|
chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
|
|
chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
|
|
|
|
|
|
chip->bbt_erase_shift = chip->phys_erase_shift =
|
|
chip->bbt_erase_shift = chip->phys_erase_shift =
|
|
@@ -3131,7 +3123,7 @@ ident_done:
|
|
else
|
|
else
|
|
chip->erase_cmd = single_erase_cmd;
|
|
chip->erase_cmd = single_erase_cmd;
|
|
|
|
|
|
- /* Do not replace user supplied command function ! */
|
|
|
|
|
|
+ /* Do not replace user supplied command function! */
|
|
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
|
|
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
|
|
chip->cmdfunc = nand_command_lp;
|
|
chip->cmdfunc = nand_command_lp;
|
|
|
|
|
|
@@ -3145,12 +3137,12 @@ ident_done:
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_scan_ident - [NAND Interface] Scan for the NAND device
|
|
* nand_scan_ident - [NAND Interface] Scan for the NAND device
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @maxchips: Number of chips to scan for
|
|
|
|
- * @table: Alternative NAND ID table
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @maxchips: number of chips to scan for
|
|
|
|
+ * @table: alternative NAND ID table
|
|
*
|
|
*
|
|
- * This is the first phase of the normal nand_scan() function. It
|
|
|
|
- * reads the flash ID and sets up MTD fields accordingly.
|
|
|
|
|
|
+ * This is the first phase of the normal nand_scan() function. It reads the
|
|
|
|
+ * flash ID and sets up MTD fields accordingly.
|
|
*
|
|
*
|
|
* The mtd->owner field must be set to the module of the caller.
|
|
* The mtd->owner field must be set to the module of the caller.
|
|
*/
|
|
*/
|
|
@@ -3203,11 +3195,11 @@ EXPORT_SYMBOL(nand_scan_ident);
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_scan_tail - [NAND Interface] Scan for the NAND device
|
|
* nand_scan_tail - [NAND Interface] Scan for the NAND device
|
|
- * @mtd: MTD device structure
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
*
|
|
*
|
|
- * This is the second phase of the normal nand_scan() function. It
|
|
|
|
- * fills out all the uninitialized function pointers with the defaults
|
|
|
|
- * and scans for a bad block table if appropriate.
|
|
|
|
|
|
+ * This is the second phase of the normal nand_scan() function. It fills out
|
|
|
|
+ * all the uninitialized function pointers with the defaults and scans for a
|
|
|
|
+ * bad block table if appropriate.
|
|
*/
|
|
*/
|
|
int nand_scan_tail(struct mtd_info *mtd)
|
|
int nand_scan_tail(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
@@ -3223,7 +3215,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
chip->oob_poi = chip->buffers->databuf + mtd->writesize;
|
|
chip->oob_poi = chip->buffers->databuf + mtd->writesize;
|
|
|
|
|
|
/*
|
|
/*
|
|
- * If no default placement scheme is given, select an appropriate one
|
|
|
|
|
|
+ * If no default placement scheme is given, select an appropriate one.
|
|
*/
|
|
*/
|
|
if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
|
|
if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
|
|
switch (mtd->oobsize) {
|
|
switch (mtd->oobsize) {
|
|
@@ -3250,7 +3242,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
chip->write_page = nand_write_page;
|
|
chip->write_page = nand_write_page;
|
|
|
|
|
|
/*
|
|
/*
|
|
- * check ECC mode, default to software if 3byte/512byte hardware ECC is
|
|
|
|
|
|
+ * Check ECC mode, default to software if 3byte/512byte hardware ECC is
|
|
* selected and we have 256 byte pagesize fallback to software ECC
|
|
* selected and we have 256 byte pagesize fallback to software ECC
|
|
*/
|
|
*/
|
|
|
|
|
|
@@ -3267,7 +3259,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
chip->ecc.read_page = nand_read_page_hwecc_oob_first;
|
|
chip->ecc.read_page = nand_read_page_hwecc_oob_first;
|
|
|
|
|
|
case NAND_ECC_HW:
|
|
case NAND_ECC_HW:
|
|
- /* Use standard hwecc read page function ? */
|
|
|
|
|
|
+ /* Use standard hwecc read page function? */
|
|
if (!chip->ecc.read_page)
|
|
if (!chip->ecc.read_page)
|
|
chip->ecc.read_page = nand_read_page_hwecc;
|
|
chip->ecc.read_page = nand_read_page_hwecc;
|
|
if (!chip->ecc.write_page)
|
|
if (!chip->ecc.write_page)
|
|
@@ -3292,7 +3284,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
"Hardware ECC not possible\n");
|
|
"Hardware ECC not possible\n");
|
|
BUG();
|
|
BUG();
|
|
}
|
|
}
|
|
- /* Use standard syndrome read/write page function ? */
|
|
|
|
|
|
+ /* Use standard syndrome read/write page function? */
|
|
if (!chip->ecc.read_page)
|
|
if (!chip->ecc.read_page)
|
|
chip->ecc.read_page = nand_read_page_syndrome;
|
|
chip->ecc.read_page = nand_read_page_syndrome;
|
|
if (!chip->ecc.write_page)
|
|
if (!chip->ecc.write_page)
|
|
@@ -3345,8 +3337,8 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
/*
|
|
/*
|
|
* Board driver should supply ecc.size and ecc.bytes values to
|
|
* Board driver should supply ecc.size and ecc.bytes values to
|
|
* select how many bits are correctable; see nand_bch_init()
|
|
* select how many bits are correctable; see nand_bch_init()
|
|
- * for details.
|
|
|
|
- * Otherwise, default to 4 bits for large page devices
|
|
|
|
|
|
+ * for details. Otherwise, default to 4 bits for large page
|
|
|
|
+ * devices.
|
|
*/
|
|
*/
|
|
if (!chip->ecc.size && (mtd->oobsize >= 64)) {
|
|
if (!chip->ecc.size && (mtd->oobsize >= 64)) {
|
|
chip->ecc.size = 512;
|
|
chip->ecc.size = 512;
|
|
@@ -3383,7 +3375,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
|
|
|
|
/*
|
|
/*
|
|
* The number of bytes available for a client to place data into
|
|
* The number of bytes available for a client to place data into
|
|
- * the out of band area
|
|
|
|
|
|
+ * the out of band area.
|
|
*/
|
|
*/
|
|
chip->ecc.layout->oobavail = 0;
|
|
chip->ecc.layout->oobavail = 0;
|
|
for (i = 0; chip->ecc.layout->oobfree[i].length
|
|
for (i = 0; chip->ecc.layout->oobfree[i].length
|
|
@@ -3394,7 +3386,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
|
|
|
|
/*
|
|
/*
|
|
* Set the number of read / write steps for one page depending on ECC
|
|
* Set the number of read / write steps for one page depending on ECC
|
|
- * mode
|
|
|
|
|
|
+ * mode.
|
|
*/
|
|
*/
|
|
chip->ecc.steps = mtd->writesize / chip->ecc.size;
|
|
chip->ecc.steps = mtd->writesize / chip->ecc.size;
|
|
if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
|
|
if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
|
|
@@ -3403,10 +3395,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
}
|
|
}
|
|
chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
|
|
chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
|
|
|
|
|
|
- /*
|
|
|
|
- * Allow subpage writes up to ecc.steps. Not possible for MLC
|
|
|
|
- * FLASH.
|
|
|
|
- */
|
|
|
|
|
|
+ /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
|
|
if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
|
|
if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
|
|
!(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
|
|
!(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
|
|
switch (chip->ecc.steps) {
|
|
switch (chip->ecc.steps) {
|
|
@@ -3464,9 +3453,11 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(nand_scan_tail);
|
|
EXPORT_SYMBOL(nand_scan_tail);
|
|
|
|
|
|
-/* is_module_text_address() isn't exported, and it's mostly a pointless
|
|
|
|
|
|
+/*
|
|
|
|
+ * is_module_text_address() isn't exported, and it's mostly a pointless
|
|
* test if this is a module _anyway_ -- they'd have to try _really_ hard
|
|
* test if this is a module _anyway_ -- they'd have to try _really_ hard
|
|
- * to call us from in-kernel code if the core NAND support is modular. */
|
|
|
|
|
|
+ * to call us from in-kernel code if the core NAND support is modular.
|
|
|
|
+ */
|
|
#ifdef MODULE
|
|
#ifdef MODULE
|
|
#define caller_is_module() (1)
|
|
#define caller_is_module() (1)
|
|
#else
|
|
#else
|
|
@@ -3476,15 +3467,13 @@ EXPORT_SYMBOL(nand_scan_tail);
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_scan - [NAND Interface] Scan for the NAND device
|
|
* nand_scan - [NAND Interface] Scan for the NAND device
|
|
- * @mtd: MTD device structure
|
|
|
|
- * @maxchips: Number of chips to scan for
|
|
|
|
- *
|
|
|
|
- * This fills out all the uninitialized function pointers
|
|
|
|
- * with the defaults.
|
|
|
|
- * The flash ID is read and the mtd/chip structures are
|
|
|
|
- * filled with the appropriate values.
|
|
|
|
- * The mtd->owner field must be set to the module of the caller
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ * @maxchips: number of chips to scan for
|
|
*
|
|
*
|
|
|
|
+ * This fills out all the uninitialized function pointers with the defaults.
|
|
|
|
+ * The flash ID is read and the mtd/chip structures are filled with the
|
|
|
|
+ * appropriate values. The mtd->owner field must be set to the module of the
|
|
|
|
+ * caller.
|
|
*/
|
|
*/
|
|
int nand_scan(struct mtd_info *mtd, int maxchips)
|
|
int nand_scan(struct mtd_info *mtd, int maxchips)
|
|
{
|
|
{
|
|
@@ -3506,8 +3495,8 @@ EXPORT_SYMBOL(nand_scan);
|
|
|
|
|
|
/**
|
|
/**
|
|
* nand_release - [NAND Interface] Free resources held by the NAND device
|
|
* nand_release - [NAND Interface] Free resources held by the NAND device
|
|
- * @mtd: MTD device structure
|
|
|
|
-*/
|
|
|
|
|
|
+ * @mtd: MTD device structure
|
|
|
|
+ */
|
|
void nand_release(struct mtd_info *mtd)
|
|
void nand_release(struct mtd_info *mtd)
|
|
{
|
|
{
|
|
struct nand_chip *chip = mtd->priv;
|
|
struct nand_chip *chip = mtd->priv;
|