mtd: nand: multi-line comment style fixups
Artem: while on it, do other commentaries clean-ups: 1. Start one-line comments with capital letter and no dot at the end 2. Turn sparse multi-line comments into one-line comments 3. Change "phrase ?" to "phrase?" and the same with "!". 4. Remove tabs from the kerneldoc parameters comments - they are mixed with tabs often, and inconsistent. 5. Put dot at the end of descriptions in kerneldoc comments. 6. Some other small commentaries clean-ups Signed-off-by: Brian Norris <computersforpeace@gmail.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
committed by
Artem Bityutskiy
parent
18f8eb1b23
commit
8b6e50c9eb
@@ -138,7 +138,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -159,7 +159,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -171,8 +171,7 @@ 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
|
* Default read function for 16bit buswith with endianess conversion.
|
||||||
* endianess conversion
|
|
||||||
*/
|
*/
|
||||||
static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
@@ -184,8 +183,7 @@ 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
|
* Default read function for 16bit buswith without endianess conversion.
|
||||||
* endianess conversion
|
|
||||||
*/
|
*/
|
||||||
static u16 nand_read_word(struct mtd_info *mtd)
|
static u16 nand_read_word(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
@@ -222,7 +220,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
|||||||
* @buf: data buffer
|
* @buf: data buffer
|
||||||
* @len: number of bytes to write
|
* @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)
|
||||||
{
|
{
|
||||||
@@ -239,7 +237,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||||||
* @buf: buffer to store date
|
* @buf: buffer to store date
|
||||||
* @len: number of bytes to read
|
* @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)
|
||||||
{
|
{
|
||||||
@@ -256,7 +254,7 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||||||
* @buf: buffer containing the data to compare
|
* @buf: buffer containing the data to compare
|
||||||
* @len: number of bytes 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)
|
||||||
{
|
{
|
||||||
@@ -275,7 +273,7 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||||||
* @buf: data buffer
|
* @buf: data buffer
|
||||||
* @len: number of bytes to write
|
* @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)
|
||||||
{
|
{
|
||||||
@@ -295,7 +293,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|||||||
* @buf: buffer to store date
|
* @buf: buffer to store date
|
||||||
* @len: number of bytes to read
|
* @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)
|
||||||
{
|
{
|
||||||
@@ -314,7 +312,7 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||||||
* @buf: buffer containing the data to compare
|
* @buf: buffer containing the data to compare
|
||||||
* @len: number of bytes 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)
|
||||||
{
|
{
|
||||||
@@ -387,8 +385,8 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @ofs: offset from device start
|
* @ofs: offset from device start
|
||||||
*
|
*
|
||||||
* This is the default implementation, which can be overridden by
|
* This is the default implementation, which can be overridden by a hardware
|
||||||
* a hardware specific driver.
|
* 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)
|
||||||
{
|
{
|
||||||
@@ -440,15 +438,15 @@ 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
|
* @mtd: MTD device structure
|
||||||
* Check, if the device is write protected
|
|
||||||
*
|
*
|
||||||
* 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;
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -532,8 +527,8 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
|
|||||||
* @column: the column address for this command, -1 if none
|
* @column: the column address for this command, -1 if none
|
||||||
* @page_addr: the page 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
|
* Send command to NAND device. This function is used for small page devices
|
||||||
* devices (256/512 Bytes per page)
|
* (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
|
* Program and erase have their own busy handlers status and sequential
|
||||||
* status and sequential in needs no delay
|
* 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);
|
||||||
@@ -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
|
* Program and erase have their own busy handlers status, sequential
|
||||||
* status, sequential in, and deplete1 need no delay
|
* 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);
|
||||||
@@ -811,7 +804,7 @@ retry:
|
|||||||
* panic_nand_wait - [GENERIC] wait until the command is done
|
* panic_nand_wait - [GENERIC] wait until the command is done
|
||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @chip: NAND chip structure
|
* @chip: NAND chip structure
|
||||||
* @timeo: Timeout
|
* @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
|
||||||
@@ -838,9 +831,9 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @chip: NAND chip structure
|
* @chip: NAND chip structure
|
||||||
*
|
*
|
||||||
* Wait for command done. This applies to erase and program only
|
* Wait for command done. This applies to erase and program only. Erase can
|
||||||
* Erase can take up to 400ms and program up to 20ms according to
|
* take up to 400ms and program up to 20ms according to general NAND and
|
||||||
* general NAND and SmartMedia specs
|
* 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,7 +881,6 @@ 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
|
||||||
@@ -895,7 +889,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|||||||
* when = 1, unlock the range of blocks outside the boundaries
|
* when = 1, unlock the range of blocks outside the boundaries
|
||||||
* of the lower and upper boundary address
|
* 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. Implementing 'lock' feature by making use of 'unlock', for
|
||||||
|
* now.
|
||||||
*
|
*
|
||||||
* This feature is not supported in many NAND parts. 'Micron' NAND parts
|
* Returns lock status.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -1047,7 +1038,8 @@ EXPORT_SYMBOL(nand_lock);
|
|||||||
* @buf: buffer to store read data
|
* @buf: buffer to store read data
|
||||||
* @page: page number to read
|
* @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)
|
||||||
@@ -1160,7 +1152,7 @@ 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;
|
||||||
@@ -1181,9 +1173,10 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|||||||
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
|
* The performance is faster if we position offsets according to
|
||||||
there are no gaps in ecc positions */
|
* 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);
|
||||||
@@ -1235,7 +1230,8 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|||||||
* @buf: buffer to store read data
|
* @buf: buffer to store read data
|
||||||
* @page: page number to read
|
* @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)
|
||||||
@@ -1280,12 +1276,11 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|||||||
* @buf: buffer to store read data
|
* @buf: buffer to store read data
|
||||||
* @page: page number to read
|
* @page: page number to read
|
||||||
*
|
*
|
||||||
* Hardware ECC for large page chips, require OOB to be read first.
|
* Hardware ECC for large page chips, require OOB to be read first. For this
|
||||||
* For this ECC mode, the write_page method is re-used from ECC_HW.
|
* ECC mode, the write_page method is re-used from ECC_HW. These methods
|
||||||
* These methods read/write ECC from the OOB area, unlike the
|
* read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
|
||||||
* ECC_HW_SYNDROME support with multiple ECC steps, follows the
|
* multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
|
||||||
* "infix ECC" scheme and reads/writes ECC from the data area, by
|
* the data area, by overwriting the NAND manufacturer bad block markings.
|
||||||
* 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)
|
||||||
@@ -1329,8 +1324,8 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
|
|||||||
* @buf: buffer to store read data
|
* @buf: buffer to store read data
|
||||||
* @page: page number to read
|
* @page: page number to read
|
||||||
*
|
*
|
||||||
* The hw generator calculates the error syndrome automatically. Therefor
|
* The hw generator calculates the error syndrome automatically. Therefore we
|
||||||
* we need a special oob layout and handling.
|
* 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)
|
||||||
@@ -1427,7 +1422,6 @@ 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
|
* @mtd: MTD device structure
|
||||||
* @from: offset to read from
|
* @from: offset to read from
|
||||||
* @ops: oob ops structure
|
* @ops: oob ops structure
|
||||||
@@ -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;
|
||||||
@@ -1574,7 +1569,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|||||||
* @retlen: pointer to variable to store the number of read bytes
|
* @retlen: pointer to variable to store the number of read bytes
|
||||||
* @buf: the databuffer to put data
|
* @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)
|
||||||
@@ -1685,7 +1680,7 @@ 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 !
|
* with syndrome - only for large page flash
|
||||||
* @mtd: mtd info structure
|
* @mtd: mtd info structure
|
||||||
* @chip: nand chip info structure
|
* @chip: nand chip info structure
|
||||||
* @page: page number to write
|
* @page: page number to write
|
||||||
@@ -1748,7 +1743,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
|
|||||||
* @from: offset to read from
|
* @from: offset to read from
|
||||||
* @ops: oob operations description structure
|
* @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;
|
||||||
@@ -1841,7 +1837,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|||||||
* @from: offset to read from
|
* @from: offset to read from
|
||||||
* @ops: oob operation description structure
|
* @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)
|
||||||
@@ -1887,7 +1883,8 @@ out:
|
|||||||
* @chip: nand chip info structure
|
* @chip: nand chip info structure
|
||||||
* @buf: data buffer
|
* @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)
|
||||||
@@ -1995,8 +1992,8 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|||||||
* @chip: nand chip info structure
|
* @chip: nand chip info structure
|
||||||
* @buf: data buffer
|
* @buf: data buffer
|
||||||
*
|
*
|
||||||
* The hw generator calculates the error syndrome automatically. Therefor
|
* The hw generator calculates the error syndrome automatically. Therefore we
|
||||||
* we need a special oob layout and handling.
|
* 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)
|
||||||
@@ -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,
|
||||||
@@ -2145,7 +2142,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
|||||||
* @to: offset to write to
|
* @to: offset to write to
|
||||||
* @ops: oob operations description structure
|
* @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__);
|
||||||
@@ -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;
|
||||||
@@ -2299,7 +2296,7 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
* @retlen: pointer to variable to store the number of written bytes
|
* @retlen: pointer to variable to store the number of written bytes
|
||||||
* @buf: the data to write
|
* @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)
|
||||||
@@ -2334,7 +2331,7 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
* @to: offset to write to
|
* @to: offset to write to
|
||||||
* @ops: oob operation description structure
|
* @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)
|
||||||
@@ -2456,7 +2453,7 @@ out:
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @page: the page address of the block which will be erased
|
* @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)
|
||||||
{
|
{
|
||||||
@@ -2471,8 +2468,7 @@ static void single_erase_cmd(struct mtd_info *mtd, int page)
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @page: the page address of the block which will be erased
|
* @page: the page address of the block which will be erased
|
||||||
*
|
*
|
||||||
* AND multi block erase command function
|
* AND multi block erase command function. Erase 4 consecutive blocks.
|
||||||
* 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)
|
||||||
{
|
{
|
||||||
@@ -2490,7 +2486,7 @@ static void multi_erase_cmd(struct mtd_info *mtd, int page)
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @instr: erase instruction
|
* @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)
|
||||||
{
|
{
|
||||||
@@ -2504,7 +2500,7 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||||||
* @instr: erase instruction
|
* @instr: erase instruction
|
||||||
* @allowbbt: allow erasing the bbt area
|
* @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]);
|
||||||
@@ -2668,7 +2662,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
|
|
||||||
@@ -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 =
|
||||||
@@ -3146,11 +3138,11 @@ 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
|
* @mtd: MTD device structure
|
||||||
* @maxchips: Number of chips to scan for
|
* @maxchips: number of chips to scan for
|
||||||
* @table: Alternative NAND ID table
|
* @table: alternative NAND ID table
|
||||||
*
|
*
|
||||||
* This is the first phase of the normal nand_scan() function. It
|
* This is the first phase of the normal nand_scan() function. It reads the
|
||||||
* reads the flash ID and sets up MTD fields accordingly.
|
* 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.
|
||||||
*/
|
*/
|
||||||
@@ -3205,9 +3197,9 @@ 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
|
* This is the second phase of the normal nand_scan() function. It fills out
|
||||||
* fills out all the uninitialized function pointers with the defaults
|
* all the uninitialized function pointers with the defaults and scans for a
|
||||||
* and scans for a bad block table if appropriate.
|
* 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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -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.
|
* for details. Otherwise, default to 4 bits for large page
|
||||||
* Otherwise, default to 4 bits for large page devices
|
* 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
|
||||||
@@ -3477,14 +3468,12 @@ 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
|
* @mtd: MTD device structure
|
||||||
* @maxchips: Number of chips to scan for
|
* @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
|
|
||||||
*
|
*
|
||||||
|
* 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)
|
||||||
{
|
{
|
||||||
|
@@ -85,11 +85,9 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
|
|||||||
* @paglen: the pagelength
|
* @paglen: the pagelength
|
||||||
* @td: search pattern descriptor
|
* @td: search pattern descriptor
|
||||||
*
|
*
|
||||||
* Check for a pattern at the given place. Used to search bad block
|
* Check for a pattern at the given place. Used to search bad block tables and
|
||||||
* tables and good / bad block identifiers.
|
* good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
|
||||||
* If the SCAN_EMPTY option is set then check, if all bytes except the
|
* all bytes except the pattern area contain 0xff.
|
||||||
* pattern area contain 0xff
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
|
static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
|
||||||
{
|
{
|
||||||
@@ -130,10 +128,9 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
|
|||||||
* @buf: the buffer to search
|
* @buf: the buffer to search
|
||||||
* @td: search pattern descriptor
|
* @td: search pattern descriptor
|
||||||
*
|
*
|
||||||
* Check for a pattern at the given place. Used to search bad block
|
* Check for a pattern at the given place. Used to search bad block tables and
|
||||||
* tables and good / bad block identifiers. Same as check_pattern, but
|
* good / bad block identifiers. Same as check_pattern, but no optional empty
|
||||||
* no optional empty check
|
* check.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
|
static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
|
||||||
{
|
{
|
||||||
@@ -177,7 +174,6 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
|
|||||||
* @offs: offset in the memory table
|
* @offs: offset in the memory table
|
||||||
*
|
*
|
||||||
* Read the bad block table starting from page.
|
* Read the bad block table starting from page.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||||
struct nand_bbt_descr *td, int offs)
|
struct nand_bbt_descr *td, int offs)
|
||||||
@@ -229,8 +225,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
|||||||
mtd->ecc_stats.bbtblocks++;
|
mtd->ecc_stats.bbtblocks++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Leave it for now, if its matured we can move this
|
/*
|
||||||
* message to MTD_DEBUG_LEVEL0 */
|
* Leave it for now, if it's matured we can
|
||||||
|
* move this message to MTD_DEBUG_LEVEL0.
|
||||||
|
*/
|
||||||
printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
|
printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
|
||||||
(loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
(loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
||||||
/* Factory marked bad or worn out? */
|
/* Factory marked bad or worn out? */
|
||||||
@@ -252,11 +250,11 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @buf: temporary buffer
|
* @buf: temporary buffer
|
||||||
* @td: descriptor for the bad block table
|
* @td: descriptor for the bad block table
|
||||||
* @chip: read the table for a specific chip, -1 read all chips.
|
* @chip: read the table for a specific chip, -1 read all chips; aplies only if
|
||||||
* Applies only if NAND_BBT_PERCHIP option is set
|
* NAND_BBT_PERCHIP option is set
|
||||||
*
|
*
|
||||||
* Read the bad block table for all chips starting at a given page
|
* Read the bad block table for all chips starting at a given page. We assume
|
||||||
* We assume that the bbt bits are in consecutive order.
|
* that the bbt bits are in consecutive order.
|
||||||
*/
|
*/
|
||||||
static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
|
static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
|
||||||
{
|
{
|
||||||
@@ -283,9 +281,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* BBT marker is in the first page, no OOB */
|
||||||
* BBT marker is in the first page, no OOB.
|
|
||||||
*/
|
|
||||||
static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
|
static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
|
||||||
struct nand_bbt_descr *td)
|
struct nand_bbt_descr *td)
|
||||||
{
|
{
|
||||||
@@ -299,9 +295,7 @@ static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
|
|||||||
return mtd->read(mtd, offs, len, &retlen, buf);
|
return mtd->read(mtd, offs, len, &retlen, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Scan read raw data from flash */
|
||||||
* Scan read raw data from flash
|
|
||||||
*/
|
|
||||||
static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
|
static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
@@ -344,9 +338,7 @@ static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
|
|||||||
return scan_read_raw_oob(mtd, buf, offs, len);
|
return scan_read_raw_oob(mtd, buf, offs, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Scan write data with oob to flash */
|
||||||
* Scan write data with oob to flash
|
|
||||||
*/
|
|
||||||
static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
|
static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
|
||||||
uint8_t *buf, uint8_t *oob)
|
uint8_t *buf, uint8_t *oob)
|
||||||
{
|
{
|
||||||
@@ -378,9 +370,8 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||||||
* @td: descriptor for the bad block table
|
* @td: descriptor for the bad block table
|
||||||
* @md: descriptor for the bad block table mirror
|
* @md: descriptor for the bad block table mirror
|
||||||
*
|
*
|
||||||
* Read the bad block table(s) for all chips starting at a given page
|
* Read the bad block table(s) for all chips starting at a given page. We
|
||||||
* We assume that the bbt bits are in consecutive order.
|
* assume that the bbt bits are in consecutive order.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
|
static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
|
||||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
||||||
@@ -407,9 +398,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Scan a given block full */
|
||||||
* Scan a given block full
|
|
||||||
*/
|
|
||||||
static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
||||||
loff_t offs, uint8_t *buf, size_t readlen,
|
loff_t offs, uint8_t *buf, size_t readlen,
|
||||||
int scanlen, int len)
|
int scanlen, int len)
|
||||||
@@ -427,9 +416,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Scan a given block partially */
|
||||||
* Scan a given block partially
|
|
||||||
*/
|
|
||||||
static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
||||||
loff_t offs, uint8_t *buf, int len)
|
loff_t offs, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
@@ -444,9 +431,8 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
|||||||
|
|
||||||
for (j = 0; j < len; j++) {
|
for (j = 0; j < len; j++) {
|
||||||
/*
|
/*
|
||||||
* Read the full oob until read_oob is fixed to
|
* Read the full oob until read_oob is fixed to handle single
|
||||||
* handle single byte reads for 16 bit
|
* byte reads for 16 bit buswidth.
|
||||||
* buswidth
|
|
||||||
*/
|
*/
|
||||||
ret = mtd->read_oob(mtd, offs, &ops);
|
ret = mtd->read_oob(mtd, offs, &ops);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -465,11 +451,11 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @buf: temporary buffer
|
* @buf: temporary buffer
|
||||||
* @bd: descriptor for the good/bad block search pattern
|
* @bd: descriptor for the good/bad block search pattern
|
||||||
* @chip: create the table for a specific chip, -1 read all chips.
|
* @chip: create the table for a specific chip, -1 read all chips; applies only
|
||||||
* Applies only if NAND_BBT_PERCHIP option is set
|
* if NAND_BBT_PERCHIP option is set
|
||||||
*
|
*
|
||||||
* Create a bad block table by scanning the device
|
* Create a bad block table by scanning the device for the given good/bad block
|
||||||
* for the given good/bad block identify pattern
|
* identify pattern.
|
||||||
*/
|
*/
|
||||||
static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||||
struct nand_bbt_descr *bd, int chip)
|
struct nand_bbt_descr *bd, int chip)
|
||||||
@@ -500,8 +486,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (chip == -1) {
|
if (chip == -1) {
|
||||||
/* Note that numblocks is 2 * (real numblocks) here, see i+=2
|
/*
|
||||||
* below as it makes shifting and masking less painful */
|
* Note that numblocks is 2 * (real numblocks) here, see i+=2
|
||||||
|
* below as it makes shifting and masking less painful
|
||||||
|
*/
|
||||||
numblocks = mtd->size >> (this->bbt_erase_shift - 1);
|
numblocks = mtd->size >> (this->bbt_erase_shift - 1);
|
||||||
startblock = 0;
|
startblock = 0;
|
||||||
from = 0;
|
from = 0;
|
||||||
@@ -553,16 +541,14 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
* @buf: temporary buffer
|
* @buf: temporary buffer
|
||||||
* @td: descriptor for the bad block table
|
* @td: descriptor for the bad block table
|
||||||
*
|
*
|
||||||
* Read the bad block table by searching for a given ident pattern.
|
* Read the bad block table by searching for a given ident pattern. Search is
|
||||||
* Search is preformed either from the beginning up or from the end of
|
* preformed either from the beginning up or from the end of the device
|
||||||
* the device downwards. The search starts always at the start of a
|
* downwards. The search starts always at the start of a block. If the option
|
||||||
* block.
|
* NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains
|
||||||
* If the option NAND_BBT_PERCHIP is given, each chip is searched
|
* the bad block information of this chip. This is necessary to provide support
|
||||||
* for a bbt, which contains the bad block information of this chip.
|
* for certain DOC devices.
|
||||||
* This is necessary to provide support for certain DOC devices.
|
|
||||||
*
|
*
|
||||||
* The bbt ident pattern resides in the oob area of the first page
|
* The bbt ident pattern resides in the oob area of the first page in a block.
|
||||||
* in a block.
|
|
||||||
*/
|
*/
|
||||||
static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
|
static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
|
||||||
{
|
{
|
||||||
@@ -636,7 +622,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
|||||||
* @td: descriptor for the bad block table
|
* @td: descriptor for the bad block table
|
||||||
* @md: descriptor for the bad block table mirror
|
* @md: descriptor for the bad block table mirror
|
||||||
*
|
*
|
||||||
* Search and read the bad block table(s)
|
* Search and read the bad block table(s).
|
||||||
*/
|
*/
|
||||||
static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
||||||
{
|
{
|
||||||
@@ -653,15 +639,13 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* write_bbt - [GENERIC] (Re)write the bad block table
|
* write_bbt - [GENERIC] (Re)write the bad block table
|
||||||
*
|
|
||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @buf: temporary buffer
|
* @buf: temporary buffer
|
||||||
* @td: descriptor for the bad block table
|
* @td: descriptor for the bad block table
|
||||||
* @md: descriptor for the bad block table mirror
|
* @md: descriptor for the bad block table mirror
|
||||||
* @chipsel: selector for a specific chip, -1 for all
|
* @chipsel: selector for a specific chip, -1 for all
|
||||||
*
|
*
|
||||||
* (Re)write the bad block table
|
* (Re)write the bad block table.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md,
|
struct nand_bbt_descr *td, struct nand_bbt_descr *md,
|
||||||
@@ -702,8 +686,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
|
|
||||||
/* Loop through the chips */
|
/* Loop through the chips */
|
||||||
for (; chip < nrchips; chip++) {
|
for (; chip < nrchips; chip++) {
|
||||||
|
/*
|
||||||
/* There was already a version of the table, reuse the page
|
* There was already a version of the table, reuse the page
|
||||||
* This applies for absolute placement too, as we have the
|
* This applies for absolute placement too, as we have the
|
||||||
* page nr. in td->pages.
|
* page nr. in td->pages.
|
||||||
*/
|
*/
|
||||||
@@ -712,8 +696,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
goto write;
|
goto write;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Automatic placement of the bad block table */
|
/*
|
||||||
/* Search direction top -> down ? */
|
* Automatic placement of the bad block table. Search direction
|
||||||
|
* top -> down?
|
||||||
|
*/
|
||||||
if (td->options & NAND_BBT_LASTBLOCK) {
|
if (td->options & NAND_BBT_LASTBLOCK) {
|
||||||
startblock = numblocks * (chip + 1) - 1;
|
startblock = numblocks * (chip + 1) - 1;
|
||||||
dir = -1;
|
dir = -1;
|
||||||
@@ -798,7 +784,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
} else if (td->options & NAND_BBT_NO_OOB) {
|
} else if (td->options & NAND_BBT_NO_OOB) {
|
||||||
ooboffs = 0;
|
ooboffs = 0;
|
||||||
offs = td->len;
|
offs = td->len;
|
||||||
/* the version byte */
|
/* The version byte */
|
||||||
if (td->options & NAND_BBT_VERSION)
|
if (td->options & NAND_BBT_VERSION)
|
||||||
offs++;
|
offs++;
|
||||||
/* Calc length */
|
/* Calc length */
|
||||||
@@ -827,7 +813,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
if (td->options & NAND_BBT_VERSION)
|
if (td->options & NAND_BBT_VERSION)
|
||||||
buf[ooboffs + td->veroffs] = td->version[chip];
|
buf[ooboffs + td->veroffs] = td->version[chip];
|
||||||
|
|
||||||
/* walk through the memory table */
|
/* Walk through the memory table */
|
||||||
for (i = 0; i < numblocks;) {
|
for (i = 0; i < numblocks;) {
|
||||||
uint8_t dat;
|
uint8_t dat;
|
||||||
dat = this->bbt[bbtoffs + (i >> 2)];
|
dat = this->bbt[bbtoffs + (i >> 2)];
|
||||||
@@ -873,8 +859,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @bd: descriptor for the good/bad block search pattern
|
* @bd: descriptor for the good/bad block search pattern
|
||||||
*
|
*
|
||||||
* The function creates a memory based bbt by scanning the device
|
* The function creates a memory based bbt by scanning the device for
|
||||||
* for manufacturer / software marked good / bad blocks
|
* manufacturer / software marked good / bad blocks.
|
||||||
*/
|
*/
|
||||||
static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||||
{
|
{
|
||||||
@@ -890,11 +876,10 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
|
|||||||
* @buf: temporary buffer
|
* @buf: temporary buffer
|
||||||
* @bd: descriptor for the good/bad block search pattern
|
* @bd: descriptor for the good/bad block search pattern
|
||||||
*
|
*
|
||||||
* The function checks the results of the previous call to read_bbt
|
* The function checks the results of the previous call to read_bbt and creates
|
||||||
* and creates / updates the bbt(s) if necessary
|
* / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
|
||||||
* Creation is necessary if no bbt was found for the chip/device
|
* for the chip/device. Update is necessary if one of the tables is missing or
|
||||||
* Update is necessary if one of the tables is missing or the
|
* the version nr. of one table is less than the other.
|
||||||
* version nr. of one table is less than the other
|
|
||||||
*/
|
*/
|
||||||
static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
|
static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
|
||||||
{
|
{
|
||||||
@@ -977,10 +962,10 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
|||||||
if (md)
|
if (md)
|
||||||
md->version[i] = 1;
|
md->version[i] = 1;
|
||||||
writecheck:
|
writecheck:
|
||||||
/* read back first ? */
|
/* Read back first? */
|
||||||
if (rd)
|
if (rd)
|
||||||
read_abs_bbt(mtd, buf, rd, chipsel);
|
read_abs_bbt(mtd, buf, rd, chipsel);
|
||||||
/* If they weren't versioned, read both. */
|
/* If they weren't versioned, read both */
|
||||||
if (rd2)
|
if (rd2)
|
||||||
read_abs_bbt(mtd, buf, rd2, chipsel);
|
read_abs_bbt(mtd, buf, rd2, chipsel);
|
||||||
|
|
||||||
@@ -1006,9 +991,8 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @td: bad block table descriptor
|
* @td: bad block table descriptor
|
||||||
*
|
*
|
||||||
* The bad block table regions are marked as "bad" to prevent
|
* The bad block table regions are marked as "bad" to prevent accidental
|
||||||
* accidental erasures / writes. The regions are identified by
|
* erasures / writes. The regions are identified by the mark 0x02.
|
||||||
* the mark 0x02.
|
|
||||||
*/
|
*/
|
||||||
static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||||
{
|
{
|
||||||
@@ -1053,9 +1037,11 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||||||
update = 1;
|
update = 1;
|
||||||
block += 2;
|
block += 2;
|
||||||
}
|
}
|
||||||
/* If we want reserved blocks to be recorded to flash, and some
|
/*
|
||||||
new ones have been marked, then we need to update the stored
|
* If we want reserved blocks to be recorded to flash, and some
|
||||||
bbts. This should only happen once. */
|
* new ones have been marked, then we need to update the stored
|
||||||
|
* bbts. This should only happen once.
|
||||||
|
*/
|
||||||
if (update && td->reserved_block_code)
|
if (update && td->reserved_block_code)
|
||||||
nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
|
nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
|
||||||
}
|
}
|
||||||
@@ -1114,14 +1100,12 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @bd: descriptor for the good/bad block search pattern
|
* @bd: descriptor for the good/bad block search pattern
|
||||||
*
|
*
|
||||||
* The function checks, if a bad block table(s) is/are already
|
* The function checks, if a bad block table(s) is/are already available. If
|
||||||
* available. If not it scans the device for manufacturer
|
* not it scans the device for manufacturer marked good / bad blocks and writes
|
||||||
* marked good / bad blocks and writes the bad block table(s) to
|
* the bad block table(s) to the selected place.
|
||||||
* the selected place.
|
|
||||||
*
|
|
||||||
* The bad block table memory is allocated here. It must be freed
|
|
||||||
* by calling the nand_free_bbt function.
|
|
||||||
*
|
*
|
||||||
|
* The bad block table memory is allocated here. It must be freed by calling
|
||||||
|
* the nand_free_bbt function.
|
||||||
*/
|
*/
|
||||||
int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||||
{
|
{
|
||||||
@@ -1132,15 +1116,19 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||||||
struct nand_bbt_descr *md = this->bbt_md;
|
struct nand_bbt_descr *md = this->bbt_md;
|
||||||
|
|
||||||
len = mtd->size >> (this->bbt_erase_shift + 2);
|
len = mtd->size >> (this->bbt_erase_shift + 2);
|
||||||
/* Allocate memory (2bit per block) and clear the memory bad block table */
|
/*
|
||||||
|
* Allocate memory (2bit per block) and clear the memory bad block
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
this->bbt = kzalloc(len, GFP_KERNEL);
|
this->bbt = kzalloc(len, GFP_KERNEL);
|
||||||
if (!this->bbt) {
|
if (!this->bbt) {
|
||||||
printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
|
printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no primary table decriptor is given, scan the device
|
/*
|
||||||
* to build a memory based bad block table
|
* If no primary table decriptor is given, scan the device to build a
|
||||||
|
* memory based bad block table.
|
||||||
*/
|
*/
|
||||||
if (!td) {
|
if (!td) {
|
||||||
if ((res = nand_memory_bbt(mtd, bd))) {
|
if ((res = nand_memory_bbt(mtd, bd))) {
|
||||||
@@ -1189,7 +1177,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @offs: the offset of the newly marked block
|
* @offs: the offset of the newly marked block
|
||||||
*
|
*
|
||||||
* The function updates the bad block table(s)
|
* The function updates the bad block table(s).
|
||||||
*/
|
*/
|
||||||
int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||||
{
|
{
|
||||||
@@ -1243,8 +1231,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define some generic bad / good block scan pattern which are used
|
/*
|
||||||
* while scanning a device for factory marked good / bad blocks. */
|
* Define some generic bad / good block scan pattern which are used
|
||||||
|
* while scanning a device for factory marked good / bad blocks.
|
||||||
|
*/
|
||||||
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
||||||
|
|
||||||
static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
|
static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
|
||||||
@@ -1256,8 +1246,7 @@ static struct nand_bbt_descr agand_flashbased = {
|
|||||||
.pattern = scan_agand_pattern
|
.pattern = scan_agand_pattern
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Generic flash bbt decriptors
|
/* Generic flash bbt decriptors */
|
||||||
*/
|
|
||||||
static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
|
static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
|
||||||
static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
|
static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
|
||||||
|
|
||||||
@@ -1309,7 +1298,6 @@ static struct nand_bbt_descr bbt_mirror_no_bbt_descr = {
|
|||||||
* based on the properties of "this". The new descriptor is stored in
|
* based on the properties of "this". The new descriptor is stored in
|
||||||
* this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
|
* this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
|
||||||
* passed to this function.
|
* passed to this function.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static int nand_create_default_bbt_descr(struct nand_chip *this)
|
static int nand_create_default_bbt_descr(struct nand_chip *this)
|
||||||
{
|
{
|
||||||
@@ -1336,20 +1324,18 @@ static int nand_create_default_bbt_descr(struct nand_chip *this)
|
|||||||
* nand_default_bbt - [NAND Interface] Select a default bad block table for the device
|
* nand_default_bbt - [NAND Interface] Select a default bad block table for the device
|
||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
*
|
*
|
||||||
* This function selects the default bad block table
|
* This function selects the default bad block table support for the device and
|
||||||
* support for the device and calls the nand_scan_bbt function
|
* calls the nand_scan_bbt function.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
int nand_default_bbt(struct mtd_info *mtd)
|
int nand_default_bbt(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
struct nand_chip *this = mtd->priv;
|
struct nand_chip *this = mtd->priv;
|
||||||
|
|
||||||
/* Default for AG-AND. We must use a flash based
|
/*
|
||||||
* bad block table as the devices have factory marked
|
* Default for AG-AND. We must use a flash based bad block table as the
|
||||||
* _good_ blocks. Erasing those blocks leads to loss
|
* devices have factory marked _good_ blocks. Erasing those blocks
|
||||||
* of the good / bad information, so we _must_ store
|
* leads to loss of the good / bad information, so we _must_ store this
|
||||||
* this information in a good / bad table during
|
* information in a good / bad table during startup.
|
||||||
* startup
|
|
||||||
*/
|
*/
|
||||||
if (this->options & NAND_IS_AND) {
|
if (this->options & NAND_IS_AND) {
|
||||||
/* Use the default pattern descriptors */
|
/* Use the default pattern descriptors */
|
||||||
@@ -1389,7 +1375,6 @@ int nand_default_bbt(struct mtd_info *mtd)
|
|||||||
* @mtd: MTD device structure
|
* @mtd: MTD device structure
|
||||||
* @offs: offset in the device
|
* @offs: offset in the device
|
||||||
* @allowbbt: allow access to bad block table region
|
* @allowbbt: allow access to bad block table region
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
|
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user