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:
parent
18f8eb1b23
commit
8b6e50c9eb
@ -138,7 +138,7 @@ static int check_offs_len(struct mtd_info *mtd,
|
||||
* nand_release_device - [GENERIC] release chip
|
||||
* @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)
|
||||
{
|
||||
@ -159,7 +159,7 @@ static void nand_release_device(struct mtd_info *mtd)
|
||||
* nand_read_byte - [DEFAULT] read one byte from the chip
|
||||
* @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)
|
||||
{
|
||||
@ -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
|
||||
* @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)
|
||||
{
|
||||
@ -184,8 +183,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
||||
* nand_read_word - [DEFAULT] read one word from the chip
|
||||
* @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)
|
||||
{
|
||||
@ -222,7 +220,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
||||
* @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)
|
||||
{
|
||||
@ -239,7 +237,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
* @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)
|
||||
{
|
||||
@ -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
|
||||
* @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)
|
||||
{
|
||||
@ -275,7 +273,7 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
* @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)
|
||||
{
|
||||
@ -295,7 +293,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
||||
* @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)
|
||||
{
|
||||
@ -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
|
||||
* @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)
|
||||
{
|
||||
@ -387,8 +385,8 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
||||
* @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)
|
||||
{
|
||||
@ -404,7 +402,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||
if (chip->bbt)
|
||||
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)
|
||||
ret = nand_update_bbt(mtd, ofs);
|
||||
else {
|
||||
@ -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
|
||||
* @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)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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 {
|
||||
if (chip->dev_ready(mtd))
|
||||
break;
|
||||
@ -532,8 +527,8 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
|
||||
* @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,
|
||||
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;
|
||||
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) {
|
||||
int readcmd;
|
||||
|
||||
@ -563,9 +556,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
||||
}
|
||||
chip->cmd_ctrl(mtd, command, ctrl);
|
||||
|
||||
/*
|
||||
* Address cycle, when necessary
|
||||
*/
|
||||
/* Address cycle, when necessary */
|
||||
ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
|
||||
/* Serially input address */
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
|
||||
@ -621,8 +612,10 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
|
||||
@ -694,14 +687,12 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
||||
case NAND_CMD_DEPLETE1:
|
||||
return;
|
||||
|
||||
/*
|
||||
* read error status commands require only a short delay
|
||||
*/
|
||||
case NAND_CMD_STATUS_ERROR:
|
||||
case NAND_CMD_STATUS_ERROR0:
|
||||
case NAND_CMD_STATUS_ERROR1:
|
||||
case NAND_CMD_STATUS_ERROR2:
|
||||
case NAND_CMD_STATUS_ERROR3:
|
||||
/* Read error status commands require only a short delay */
|
||||
udelay(chip->chip_delay);
|
||||
return;
|
||||
|
||||
@ -735,7 +726,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
||||
default:
|
||||
/*
|
||||
* If we don't have access to the busy pin, we apply the given
|
||||
* command delay
|
||||
* command delay.
|
||||
*/
|
||||
if (!chip->dev_ready) {
|
||||
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);
|
||||
|
||||
nand_wait_ready(mtd);
|
||||
@ -811,7 +804,7 @@ retry:
|
||||
* panic_nand_wait - [GENERIC] wait until the command is done
|
||||
* @mtd: MTD device structure
|
||||
* @chip: NAND chip structure
|
||||
* @timeo: Timeout
|
||||
* @timeo: timeout
|
||||
*
|
||||
* 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
|
||||
@ -838,9 +831,9 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
* @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)
|
||||
{
|
||||
@ -855,8 +848,10 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
*
|
||||
* @mtd: mtd info
|
||||
* @ofs: offset to start unlock from
|
||||
* @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
|
||||
* of the lower and upper boundary address
|
||||
*
|
||||
* return - unlock status
|
||||
* Returs unlock status.
|
||||
*/
|
||||
static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
|
||||
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
|
||||
*
|
||||
* @mtd: mtd info
|
||||
* @ofs: offset to start unlock from
|
||||
* @len: length to unlock
|
||||
*
|
||||
* return - unlock status
|
||||
* Returns unlock status.
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @mtd: mtd info
|
||||
* @ofs: offset to start unlock from
|
||||
* @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
|
||||
* 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.
|
||||
* Returns lock status.
|
||||
*/
|
||||
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
|
||||
* @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,
|
||||
uint8_t *buf, int page)
|
||||
@ -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 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;
|
||||
end_step = (data_offs + readlen - 1) / chip->ecc.size;
|
||||
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;
|
||||
eccfrag_len = num_steps * chip->ecc.bytes;
|
||||
|
||||
@ -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)
|
||||
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++) {
|
||||
if (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->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||
} 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;
|
||||
|
||||
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
|
||||
* @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,
|
||||
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
|
||||
* @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,
|
||||
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
|
||||
* @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,
|
||||
uint8_t *buf, int page)
|
||||
@ -1400,7 +1395,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
|
||||
size_t bytes = 0;
|
||||
|
||||
for (; free->length && len; free++, len -= bytes) {
|
||||
/* Read request not from offset 0 ? */
|
||||
/* Read request not from offset 0? */
|
||||
if (unlikely(roffs)) {
|
||||
if (roffs >= free->length) {
|
||||
roffs -= free->length;
|
||||
@ -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
|
||||
*
|
||||
* @mtd: MTD device structure
|
||||
* @from: offset to read from
|
||||
* @ops: oob ops structure
|
||||
@ -1467,7 +1461,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
||||
bytes = min(mtd->writesize - col, readlen);
|
||||
aligned = (bytes == mtd->writesize);
|
||||
|
||||
/* Is the current page in the buffer ? */
|
||||
/* Is the current page in the buffer? */
|
||||
if (realpage != chip->pagebuf || oob) {
|
||||
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)
|
||||
break;
|
||||
|
||||
/* For subsequent reads align to page boundary. */
|
||||
/* For subsequent reads align to page boundary */
|
||||
col = 0;
|
||||
/* Increment page address */
|
||||
realpage++;
|
||||
@ -1546,8 +1540,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
||||
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))
|
||||
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
|
||||
* @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,
|
||||
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
|
||||
* with syndrome - only for large page flash !
|
||||
* with syndrome - only for large page flash
|
||||
* @mtd: mtd info structure
|
||||
* @chip: nand chip info structure
|
||||
* @page: page number to write
|
||||
@ -1748,7 +1743,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
|
||||
* @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,
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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))
|
||||
sndcmd = 1;
|
||||
@ -1841,7 +1837,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
||||
* @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,
|
||||
struct mtd_oob_ops *ops)
|
||||
@ -1887,7 +1883,8 @@ out:
|
||||
* @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,
|
||||
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
|
||||
* @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,
|
||||
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
|
||||
* 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;
|
||||
|
||||
@ -2066,7 +2063,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
status = chip->waitfunc(mtd, chip);
|
||||
/*
|
||||
* See if operation failed and additional status checks are
|
||||
* available
|
||||
* available.
|
||||
*/
|
||||
if ((status & NAND_STATUS_FAIL) && (chip->errstat))
|
||||
status = chip->errstat(mtd, chip, FL_WRITING, status,
|
||||
@ -2112,7 +2109,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len,
|
||||
size_t bytes = 0;
|
||||
|
||||
for (; free->length && len; free++, len -= bytes) {
|
||||
/* Write request not from offset 0 ? */
|
||||
/* Write request not from offset 0? */
|
||||
if (unlikely(woffs)) {
|
||||
if (woffs >= free->length) {
|
||||
woffs -= free->length;
|
||||
@ -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
|
||||
* @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,
|
||||
struct mtd_oob_ops *ops)
|
||||
@ -2166,7 +2163,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
||||
if (!writelen)
|
||||
return 0;
|
||||
|
||||
/* reject writes, which are not page aligned */
|
||||
/* Reject writes, which are not page aligned */
|
||||
if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
|
||||
printk(KERN_NOTICE "%s: Attempt to write not "
|
||||
"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;
|
||||
uint8_t *wbuf = buf;
|
||||
|
||||
/* Partial page write ? */
|
||||
/* Partial page write? */
|
||||
if (unlikely(column || writelen < (mtd->writesize - 1))) {
|
||||
cached = 0;
|
||||
bytes = min_t(int, bytes - column, (int) writelen);
|
||||
@ -2275,10 +2272,10 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
/* Wait for the device to get ready. */
|
||||
/* Wait for the device to get ready */
|
||||
panic_nand_wait(mtd, chip, 400);
|
||||
|
||||
/* Grab the device. */
|
||||
/* Grab the device */
|
||||
panic_nand_get_device(chip, mtd, FL_WRITING);
|
||||
|
||||
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
|
||||
* @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,
|
||||
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
|
||||
* @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,
|
||||
struct mtd_oob_ops *ops)
|
||||
@ -2456,7 +2453,7 @@ out:
|
||||
* @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)
|
||||
{
|
||||
@ -2471,8 +2468,7 @@ static void single_erase_cmd(struct mtd_info *mtd, int page)
|
||||
* @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)
|
||||
{
|
||||
@ -2490,7 +2486,7 @@ static void multi_erase_cmd(struct mtd_info *mtd, int page)
|
||||
* @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)
|
||||
{
|
||||
@ -2504,7 +2500,7 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
* @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 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
|
||||
* should be rewritten. Otherwise the mask is set to 0xffffffff which
|
||||
* 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)
|
||||
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;
|
||||
|
||||
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) <<
|
||||
chip->page_shift, 0, allowbbt)) {
|
||||
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
|
||||
* contains the current cached page
|
||||
* contains the current cached page.
|
||||
*/
|
||||
if (page <= chip->pagebuf && chip->pagebuf <
|
||||
(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
|
||||
* page being erased
|
||||
* page being erased.
|
||||
*/
|
||||
if (bbt_masked_page != 0xffffffff &&
|
||||
(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
|
||||
* 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 &&
|
||||
(chip->bbt_td->options & NAND_BBT_PERCHIP))
|
||||
@ -2645,7 +2639,7 @@ erase_exit:
|
||||
|
||||
/*
|
||||
* If BBT requires refresh and erase was successful, rewrite any
|
||||
* selected bad block tables
|
||||
* selected bad block tables.
|
||||
*/
|
||||
if (bbt_masked_page == 0xffffffff || ret)
|
||||
return ret;
|
||||
@ -2653,7 +2647,7 @@ erase_exit:
|
||||
for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
|
||||
if (!rewrite_bbt[chipnr])
|
||||
continue;
|
||||
/* update the BBT for chip */
|
||||
/* Update the BBT for chip */
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
|
||||
"(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
|
||||
rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
|
||||
@ -2668,7 +2662,7 @@ erase_exit:
|
||||
* nand_sync - [MTD Interface] sync
|
||||
* @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)
|
||||
{
|
||||
@ -2708,7 +2702,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||
|
||||
ret = nand_block_isbad(mtd, ofs);
|
||||
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)
|
||||
return 0;
|
||||
return ret;
|
||||
@ -2743,9 +2737,7 @@ static void nand_resume(struct mtd_info *mtd)
|
||||
"in suspended state\n", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set default functions
|
||||
*/
|
||||
/* Set default functions */
|
||||
static void nand_set_defaults(struct nand_chip *chip, int busw)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
ssize_t i;
|
||||
|
||||
/* null terminate */
|
||||
/* Null terminate */
|
||||
s[len - 1] = 0;
|
||||
|
||||
/* remove non printable chars */
|
||||
/* Remove non printable chars */
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
if (s[i] < ' ' || s[i] > 127)
|
||||
s[i] = '?';
|
||||
}
|
||||
|
||||
/* remove trailing spaces */
|
||||
/* Remove trailing spaces */
|
||||
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,
|
||||
int busw)
|
||||
@ -2829,7 +2819,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
int i;
|
||||
int val;
|
||||
|
||||
/* try ONFI for unknow chip or LP */
|
||||
/* Try ONFI for unknow chip or LP */
|
||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
|
||||
if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
/* check version */
|
||||
/* Check version */
|
||||
val = le16_to_cpu(p->revision);
|
||||
if (val & (1 << 5))
|
||||
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,
|
||||
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)
|
||||
* after power-up
|
||||
* after power-up.
|
||||
*/
|
||||
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);
|
||||
*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
|
||||
* possibly credible NAND flash to appear. If the two results do
|
||||
* 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;
|
||||
|
||||
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);
|
||||
} else if (!type->pagesize) {
|
||||
int extid;
|
||||
@ -3027,7 +3018,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
||||
}
|
||||
} 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->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
|
||||
* 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)
|
||||
*/
|
||||
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 |= 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)
|
||||
chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
|
||||
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;
|
||||
|
||||
@ -3071,7 +3063,7 @@ ident_done:
|
||||
|
||||
/*
|
||||
* Check, if buswidth is correct. Hardware drivers should set
|
||||
* chip correct !
|
||||
* chip correct!
|
||||
*/
|
||||
if (busw != (chip->options & NAND_BUSWIDTH_16)) {
|
||||
printk(KERN_INFO "NAND device: Manufacturer ID:"
|
||||
@ -3085,7 +3077,7 @@ ident_done:
|
||||
|
||||
/* Calculate the address shift from the page size */
|
||||
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->bbt_erase_shift = chip->phys_erase_shift =
|
||||
@ -3131,7 +3123,7 @@ ident_done:
|
||||
else
|
||||
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)
|
||||
chip->cmdfunc = nand_command_lp;
|
||||
|
||||
@ -3146,11 +3138,11 @@ ident_done:
|
||||
/**
|
||||
* 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
|
||||
* @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.
|
||||
*/
|
||||
@ -3205,9 +3197,9 @@ EXPORT_SYMBOL(nand_scan_ident);
|
||||
* nand_scan_tail - [NAND Interface] Scan for the NAND device
|
||||
* @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)
|
||||
{
|
||||
@ -3223,7 +3215,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
||||
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)) {
|
||||
switch (mtd->oobsize) {
|
||||
@ -3250,7 +3242,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
||||
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
|
||||
*/
|
||||
|
||||
@ -3267,7 +3259,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
||||
chip->ecc.read_page = nand_read_page_hwecc_oob_first;
|
||||
|
||||
case NAND_ECC_HW:
|
||||
/* Use standard hwecc read page function ? */
|
||||
/* Use standard hwecc read page function? */
|
||||
if (!chip->ecc.read_page)
|
||||
chip->ecc.read_page = nand_read_page_hwecc;
|
||||
if (!chip->ecc.write_page)
|
||||
@ -3292,7 +3284,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
||||
"Hardware ECC not possible\n");
|
||||
BUG();
|
||||
}
|
||||
/* Use standard syndrome read/write page function ? */
|
||||
/* Use standard syndrome read/write page function? */
|
||||
if (!chip->ecc.read_page)
|
||||
chip->ecc.read_page = nand_read_page_syndrome;
|
||||
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
|
||||
* 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)) {
|
||||
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 out of band area
|
||||
* the out of band area.
|
||||
*/
|
||||
chip->ecc.layout->oobavail = 0;
|
||||
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
|
||||
* mode
|
||||
* mode.
|
||||
*/
|
||||
chip->ecc.steps = mtd->writesize / chip->ecc.size;
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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) &&
|
||||
!(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
|
||||
switch (chip->ecc.steps) {
|
||||
@ -3464,9 +3453,11 @@ int nand_scan_tail(struct mtd_info *mtd)
|
||||
}
|
||||
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
|
||||
* 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
|
||||
#define caller_is_module() (1)
|
||||
#else
|
||||
@ -3477,14 +3468,12 @@ EXPORT_SYMBOL(nand_scan_tail);
|
||||
/**
|
||||
* 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
|
||||
* @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)
|
||||
{
|
||||
@ -3507,7 +3496,7 @@ EXPORT_SYMBOL(nand_scan);
|
||||
/**
|
||||
* nand_release - [NAND Interface] Free resources held by the NAND device
|
||||
* @mtd: MTD device structure
|
||||
*/
|
||||
*/
|
||||
void nand_release(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
@ -85,12 +85,10 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
|
||||
* @paglen: the pagelength
|
||||
* @td: search pattern descriptor
|
||||
*
|
||||
* Check for a pattern at the given place. Used to search bad block
|
||||
* tables and good / bad block identifiers.
|
||||
* If the SCAN_EMPTY option is set then check, if all bytes except the
|
||||
* pattern area contain 0xff
|
||||
*
|
||||
*/
|
||||
* Check for a pattern at the given place. Used to search bad block tables and
|
||||
* good / bad block identifiers. If the SCAN_EMPTY option is set then check, if
|
||||
* all bytes except the pattern area contain 0xff.
|
||||
*/
|
||||
static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
|
||||
{
|
||||
int i, end = 0;
|
||||
@ -130,11 +128,10 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
|
||||
* @buf: the buffer to search
|
||||
* @td: search pattern descriptor
|
||||
*
|
||||
* Check for a pattern at the given place. Used to search bad block
|
||||
* tables and good / bad block identifiers. Same as check_pattern, but
|
||||
* no optional empty check
|
||||
*
|
||||
*/
|
||||
* Check for a pattern at the given place. Used to search bad block tables and
|
||||
* good / bad block identifiers. Same as check_pattern, but no optional empty
|
||||
* check.
|
||||
*/
|
||||
static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
|
||||
{
|
||||
int i;
|
||||
@ -177,7 +174,6 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
|
||||
* @offs: offset in the memory table
|
||||
*
|
||||
* Read the bad block table starting from page.
|
||||
*
|
||||
*/
|
||||
static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
struct nand_bbt_descr *td, int offs)
|
||||
@ -229,11 +225,13 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
mtd->ecc_stats.bbtblocks++;
|
||||
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",
|
||||
(loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
||||
/* Factory marked bad or worn out ? */
|
||||
/* Factory marked bad or worn out? */
|
||||
if (tmp == 0)
|
||||
this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
|
||||
else
|
||||
@ -252,12 +250,12 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
* @mtd: MTD device structure
|
||||
* @buf: temporary buffer
|
||||
* @td: descriptor for the bad block table
|
||||
* @chip: read the table for a specific chip, -1 read all chips.
|
||||
* Applies only if NAND_BBT_PERCHIP option is set
|
||||
* @chip: read the table for a specific chip, -1 read all chips; aplies only if
|
||||
* NAND_BBT_PERCHIP option is set
|
||||
*
|
||||
* Read the bad block table for all chips starting at a given page
|
||||
* We assume that the bbt bits are in consecutive order.
|
||||
*/
|
||||
* Read the bad block table for all chips starting at a given page. We assume
|
||||
* 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)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
@ -283,9 +281,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
uint8_t *buf, uint8_t *oob)
|
||||
{
|
||||
@ -378,10 +370,9 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
* @td: descriptor for the bad block table
|
||||
* @md: descriptor for the bad block table mirror
|
||||
*
|
||||
* Read the bad block table(s) for all chips starting at a given page
|
||||
* We assume that the bbt bits are in consecutive order.
|
||||
*
|
||||
*/
|
||||
* Read the bad block table(s) for all chips starting at a given page. We
|
||||
* assume that the bbt bits are in consecutive order.
|
||||
*/
|
||||
static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan a given block full
|
||||
*/
|
||||
/* Scan a given block full */
|
||||
static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
||||
loff_t offs, uint8_t *buf, size_t readlen,
|
||||
int scanlen, int len)
|
||||
@ -427,9 +416,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
||||
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,
|
||||
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++) {
|
||||
/*
|
||||
* Read the full oob until read_oob is fixed to
|
||||
* handle single byte reads for 16 bit
|
||||
* buswidth
|
||||
* Read the full oob until read_oob is fixed to handle single
|
||||
* byte reads for 16 bit buswidth.
|
||||
*/
|
||||
ret = mtd->read_oob(mtd, offs, &ops);
|
||||
if (ret)
|
||||
@ -465,11 +451,11 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
|
||||
* @mtd: MTD device structure
|
||||
* @buf: temporary buffer
|
||||
* @bd: descriptor for the good/bad block search pattern
|
||||
* @chip: create the table for a specific chip, -1 read all chips.
|
||||
* Applies only if NAND_BBT_PERCHIP option is set
|
||||
* @chip: create the table for a specific chip, -1 read all chips; applies only
|
||||
* if NAND_BBT_PERCHIP option is set
|
||||
*
|
||||
* Create a bad block table by scanning the device
|
||||
* for the given good/bad block identify pattern
|
||||
* Create a bad block table by scanning the device for the given good/bad block
|
||||
* identify pattern.
|
||||
*/
|
||||
static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
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) {
|
||||
/* 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);
|
||||
startblock = 0;
|
||||
from = 0;
|
||||
@ -553,16 +541,14 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
* @buf: temporary buffer
|
||||
* @td: descriptor for the bad block table
|
||||
*
|
||||
* Read the bad block table by searching for a given ident pattern.
|
||||
* Search is preformed either from the beginning up or from the end of
|
||||
* the device downwards. The search starts always at the start of a
|
||||
* block.
|
||||
* If the option NAND_BBT_PERCHIP is given, each chip is searched
|
||||
* for a bbt, which contains the bad block information of this chip.
|
||||
* This is necessary to provide support for certain DOC devices.
|
||||
* Read the bad block table by searching for a given ident pattern. Search is
|
||||
* preformed either from the beginning up or from the end of the device
|
||||
* downwards. The search starts always at the start of a block. If the option
|
||||
* NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains
|
||||
* the bad block information of this chip. This is necessary to provide support
|
||||
* for certain DOC devices.
|
||||
*
|
||||
* The bbt ident pattern resides in the oob area of the first page
|
||||
* in a block.
|
||||
* The bbt ident pattern resides in the oob area of the first page in a block.
|
||||
*/
|
||||
static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
|
||||
{
|
||||
@ -573,7 +559,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
int bbtblocks;
|
||||
int blocktopage = this->bbt_erase_shift - this->page_shift;
|
||||
|
||||
/* Search direction top -> down ? */
|
||||
/* Search direction top -> down? */
|
||||
if (td->options & NAND_BBT_LASTBLOCK) {
|
||||
startblock = (mtd->size >> this->bbt_erase_shift) - 1;
|
||||
dir = -1;
|
||||
@ -582,7 +568,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
dir = 1;
|
||||
}
|
||||
|
||||
/* Do we have a bbt per chip ? */
|
||||
/* Do we have a bbt per chip? */
|
||||
if (td->options & NAND_BBT_PERCHIP) {
|
||||
chips = this->numchips;
|
||||
bbtblocks = this->chipsize >> this->bbt_erase_shift;
|
||||
@ -636,8 +622,8 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
* @td: descriptor for the bad block table
|
||||
* @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)
|
||||
{
|
||||
/* Search the primary table */
|
||||
@ -653,16 +639,14 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
|
||||
|
||||
/**
|
||||
* write_bbt - [GENERIC] (Re)write the bad block table
|
||||
*
|
||||
* @mtd: MTD device structure
|
||||
* @buf: temporary buffer
|
||||
* @td: descriptor for the bad block table
|
||||
* @md: descriptor for the bad block table mirror
|
||||
* @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,
|
||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md,
|
||||
int chipsel)
|
||||
@ -685,10 +669,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
|
||||
if (!rcode)
|
||||
rcode = 0xff;
|
||||
/* Write bad block table per chip rather than per device ? */
|
||||
/* Write bad block table per chip rather than per device? */
|
||||
if (td->options & NAND_BBT_PERCHIP) {
|
||||
numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
|
||||
/* Full device write or specific chip ? */
|
||||
/* Full device write or specific chip? */
|
||||
if (chipsel == -1) {
|
||||
nrchips = this->numchips;
|
||||
} else {
|
||||
@ -702,8 +686,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
|
||||
/* Loop through the chips */
|
||||
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
|
||||
* page nr. in td->pages.
|
||||
*/
|
||||
@ -712,8 +696,10 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
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) {
|
||||
startblock = numblocks * (chip + 1) - 1;
|
||||
dir = -1;
|
||||
@ -764,7 +750,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
|
||||
to = ((loff_t) page) << this->page_shift;
|
||||
|
||||
/* Must we save the block contents ? */
|
||||
/* Must we save the block contents? */
|
||||
if (td->options & NAND_BBT_SAVECONTENT) {
|
||||
/* Make it block aligned */
|
||||
to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
|
||||
@ -798,13 +784,13 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
} else if (td->options & NAND_BBT_NO_OOB) {
|
||||
ooboffs = 0;
|
||||
offs = td->len;
|
||||
/* the version byte */
|
||||
/* The version byte */
|
||||
if (td->options & NAND_BBT_VERSION)
|
||||
offs++;
|
||||
/* Calc length */
|
||||
len = (size_t) (numblocks >> sft);
|
||||
len += offs;
|
||||
/* Make it page aligned ! */
|
||||
/* Make it page aligned! */
|
||||
len = ALIGN(len, mtd->writesize);
|
||||
/* Preset the buffer with 0xff */
|
||||
memset(buf, 0xff, len);
|
||||
@ -813,7 +799,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
} else {
|
||||
/* Calc length */
|
||||
len = (size_t) (numblocks >> sft);
|
||||
/* Make it page aligned ! */
|
||||
/* Make it page aligned! */
|
||||
len = ALIGN(len, mtd->writesize);
|
||||
/* Preset the buffer with 0xff */
|
||||
memset(buf, 0xff, len +
|
||||
@ -827,13 +813,13 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
if (td->options & NAND_BBT_VERSION)
|
||||
buf[ooboffs + td->veroffs] = td->version[chip];
|
||||
|
||||
/* walk through the memory table */
|
||||
/* Walk through the memory table */
|
||||
for (i = 0; i < numblocks;) {
|
||||
uint8_t dat;
|
||||
dat = this->bbt[bbtoffs + (i >> 2)];
|
||||
for (j = 0; j < 4; j++, i++) {
|
||||
int sftcnt = (i << (3 - sft)) & sftmsk;
|
||||
/* Do not store the reserved bbt blocks ! */
|
||||
/* Do not store the reserved bbt blocks! */
|
||||
buf[offs + (i >> sft)] &=
|
||||
~(msk[dat & 0x03] << sftcnt);
|
||||
dat >>= 2;
|
||||
@ -873,9 +859,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
* @mtd: MTD device structure
|
||||
* @bd: descriptor for the good/bad block search pattern
|
||||
*
|
||||
* The function creates a memory based bbt by scanning the device
|
||||
* for manufacturer / software marked good / bad blocks
|
||||
*/
|
||||
* The function creates a memory based bbt by scanning the device for
|
||||
* manufacturer / software marked good / bad blocks.
|
||||
*/
|
||||
static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
@ -890,12 +876,11 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
|
||||
* @buf: temporary buffer
|
||||
* @bd: descriptor for the good/bad block search pattern
|
||||
*
|
||||
* The function checks the results of the previous call to read_bbt
|
||||
* and creates / updates the bbt(s) if necessary
|
||||
* Creation is necessary if no bbt was found for the chip/device
|
||||
* Update is necessary if one of the tables is missing or the
|
||||
* version nr. of one table is less than the other
|
||||
*/
|
||||
* The function checks the results of the previous call to read_bbt and creates
|
||||
* / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
|
||||
* for the chip/device. Update is necessary if one of the tables is missing or
|
||||
* the 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)
|
||||
{
|
||||
int i, chips, writeops, chipsel, res;
|
||||
@ -904,7 +889,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
||||
struct nand_bbt_descr *md = this->bbt_md;
|
||||
struct nand_bbt_descr *rd, *rd2;
|
||||
|
||||
/* Do we have a bbt per chip ? */
|
||||
/* Do we have a bbt per chip? */
|
||||
if (td->options & NAND_BBT_PERCHIP)
|
||||
chips = this->numchips;
|
||||
else
|
||||
@ -914,9 +899,9 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
||||
writeops = 0;
|
||||
rd = NULL;
|
||||
rd2 = NULL;
|
||||
/* Per chip or per device ? */
|
||||
/* Per chip or per device? */
|
||||
chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
|
||||
/* Mirrored table available ? */
|
||||
/* Mirrored table available? */
|
||||
if (md) {
|
||||
if (td->pages[i] == -1 && md->pages[i] == -1) {
|
||||
writeops = 0x03;
|
||||
@ -965,7 +950,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
||||
goto writecheck;
|
||||
}
|
||||
create:
|
||||
/* Create the bad block table by scanning the device ? */
|
||||
/* Create the bad block table by scanning the device? */
|
||||
if (!(td->options & NAND_BBT_CREATE))
|
||||
continue;
|
||||
|
||||
@ -977,21 +962,21 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
||||
if (md)
|
||||
md->version[i] = 1;
|
||||
writecheck:
|
||||
/* read back first ? */
|
||||
/* Read back first? */
|
||||
if (rd)
|
||||
read_abs_bbt(mtd, buf, rd, chipsel);
|
||||
/* If they weren't versioned, read both. */
|
||||
/* If they weren't versioned, read both */
|
||||
if (rd2)
|
||||
read_abs_bbt(mtd, buf, rd2, chipsel);
|
||||
|
||||
/* Write the bad block table to the device ? */
|
||||
/* Write the bad block table to the device? */
|
||||
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt(mtd, buf, td, md, chipsel);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Write the mirror bad block table to the device ? */
|
||||
/* Write the mirror bad block table to the device? */
|
||||
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt(mtd, buf, md, td, chipsel);
|
||||
if (res < 0)
|
||||
@ -1006,17 +991,16 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
|
||||
* @mtd: MTD device structure
|
||||
* @td: bad block table descriptor
|
||||
*
|
||||
* The bad block table regions are marked as "bad" to prevent
|
||||
* accidental erasures / writes. The regions are identified by
|
||||
* the mark 0x02.
|
||||
*/
|
||||
* The bad block table regions are marked as "bad" to prevent accidental
|
||||
* erasures / writes. The regions are identified by the mark 0x02.
|
||||
*/
|
||||
static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int i, j, chips, block, nrblocks, update;
|
||||
uint8_t oldval, newval;
|
||||
|
||||
/* Do we have a bbt per chip ? */
|
||||
/* Do we have a bbt per chip? */
|
||||
if (td->options & NAND_BBT_PERCHIP) {
|
||||
chips = this->numchips;
|
||||
nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
|
||||
@ -1053,9 +1037,11 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
update = 1;
|
||||
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
|
||||
bbts. This should only happen once. */
|
||||
/*
|
||||
* If we want reserved blocks to be recorded to flash, and some
|
||||
* new ones have been marked, then we need to update the stored
|
||||
* bbts. This should only happen once.
|
||||
*/
|
||||
if (update && td->reserved_block_code)
|
||||
nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
|
||||
}
|
||||
@ -1114,15 +1100,13 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
* @mtd: MTD device structure
|
||||
* @bd: descriptor for the good/bad block search pattern
|
||||
*
|
||||
* The function checks, if a bad block table(s) is/are already
|
||||
* available. If not it scans the device for manufacturer
|
||||
* marked good / bad blocks and writes the bad block table(s) to
|
||||
* the selected place.
|
||||
* The function checks, if a bad block table(s) is/are already available. If
|
||||
* not it scans the device for manufacturer marked good / bad blocks and writes
|
||||
* the bad block table(s) to 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)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
@ -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;
|
||||
|
||||
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);
|
||||
if (!this->bbt) {
|
||||
printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
|
||||
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 ((res = nand_memory_bbt(mtd, bd))) {
|
||||
@ -1164,7 +1152,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Is the bbt at a given page ? */
|
||||
/* Is the bbt at a given page? */
|
||||
if (td->options & NAND_BBT_ABSPAGE) {
|
||||
res = read_abs_bbts(mtd, buf, td, md);
|
||||
} else {
|
||||
@ -1189,8 +1177,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
* @mtd: MTD device structure
|
||||
* @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)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
@ -1214,7 +1202,7 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||
|
||||
writeops = md != NULL ? 0x03 : 0x01;
|
||||
|
||||
/* Do we have a bbt per chip ? */
|
||||
/* Do we have a bbt per chip? */
|
||||
if (td->options & NAND_BBT_PERCHIP) {
|
||||
chip = (int)(offs >> this->chip_shift);
|
||||
chipsel = chip;
|
||||
@ -1227,13 +1215,13 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||
if (md)
|
||||
md->version[chip]++;
|
||||
|
||||
/* Write the bad block table to the device ? */
|
||||
/* Write the bad block table to the device? */
|
||||
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt(mtd, buf, td, md, chipsel);
|
||||
if (res < 0)
|
||||
goto out;
|
||||
}
|
||||
/* Write the mirror bad block table to the device ? */
|
||||
/* Write the mirror bad block table to the device? */
|
||||
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt(mtd, buf, md, td, chipsel);
|
||||
}
|
||||
@ -1243,8 +1231,10 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||
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_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 };
|
||||
@ -1256,8 +1246,7 @@ static struct nand_bbt_descr agand_flashbased = {
|
||||
.pattern = scan_agand_pattern
|
||||
};
|
||||
|
||||
/* Generic flash bbt decriptors
|
||||
*/
|
||||
/* Generic flash bbt decriptors */
|
||||
static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
|
||||
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
|
||||
* this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
|
||||
* passed to this function.
|
||||
*
|
||||
*/
|
||||
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
|
||||
* @mtd: MTD device structure
|
||||
*
|
||||
* This function selects the default bad block table
|
||||
* support for the device and calls the nand_scan_bbt function
|
||||
*
|
||||
*/
|
||||
* This function selects the default bad block table support for the device and
|
||||
* calls the nand_scan_bbt function.
|
||||
*/
|
||||
int nand_default_bbt(struct mtd_info *mtd)
|
||||
{
|
||||
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
|
||||
* _good_ blocks. Erasing those blocks leads to loss
|
||||
* of the good / bad information, so we _must_ store
|
||||
* this information in a good / bad table during
|
||||
* startup
|
||||
/*
|
||||
* Default for AG-AND. We must use a flash based bad block table as the
|
||||
* devices have factory marked _good_ blocks. Erasing those blocks
|
||||
* leads to loss of the good / bad information, so we _must_ store this
|
||||
* information in a good / bad table during startup.
|
||||
*/
|
||||
if (this->options & NAND_IS_AND) {
|
||||
/* Use the default pattern descriptors */
|
||||
@ -1361,7 +1347,7 @@ int nand_default_bbt(struct mtd_info *mtd)
|
||||
return nand_scan_bbt(mtd, &agand_flashbased);
|
||||
}
|
||||
|
||||
/* Is a flash based bad block table requested ? */
|
||||
/* Is a flash based bad block table requested? */
|
||||
if (this->bbt_options & NAND_BBT_USE_FLASH) {
|
||||
/* Use the default pattern descriptors */
|
||||
if (!this->bbt_td) {
|
||||
@ -1389,8 +1375,7 @@ int nand_default_bbt(struct mtd_info *mtd)
|
||||
* @mtd: MTD device structure
|
||||
* @offs: offset in the device
|
||||
* @allowbbt: allow access to bad block table region
|
||||
*
|
||||
*/
|
||||
*/
|
||||
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
Loading…
Reference in New Issue
Block a user