|
@@ -1,6 +1,4 @@
|
|
|
/*
|
|
|
- * drivers/mtd/nand.c
|
|
|
- *
|
|
|
* Overview:
|
|
|
* This is the generic MTD driver for NAND flash devices. It should be
|
|
|
* capable of working with almost all NAND chips currently available.
|
|
@@ -45,8 +43,6 @@
|
|
|
#include <asm/io.h>
|
|
|
#include <asm/errno.h>
|
|
|
|
|
|
-static bool is_module_text_address(unsigned long addr) {return 0;}
|
|
|
-
|
|
|
/* Define default oob placement schemes for large and small page devices */
|
|
|
static struct nand_ecclayout nand_oob_8 = {
|
|
|
.eccbytes = 3,
|
|
@@ -343,13 +339,12 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
* nand_block_bad - [DEFAULT] Read bad block marker from the chip
|
|
|
* @mtd: MTD device structure
|
|
|
* @ofs: offset from device start
|
|
|
- * @getchip: 0, if the chip is already selected
|
|
|
*
|
|
|
* Check, if the block is bad.
|
|
|
*/
|
|
|
-static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|
|
+static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
|
|
|
{
|
|
|
- int page, chipnr, res = 0, i = 0;
|
|
|
+ int page, res = 0, i = 0;
|
|
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
u16 bad;
|
|
|
|
|
@@ -358,15 +353,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|
|
|
|
|
page = (int)(ofs >> chip->page_shift) & chip->pagemask;
|
|
|
|
|
|
- if (getchip) {
|
|
|
- chipnr = (int)(ofs >> chip->chip_shift);
|
|
|
-
|
|
|
- nand_get_device(mtd, FL_READING);
|
|
|
-
|
|
|
- /* Select the NAND device */
|
|
|
- chip->select_chip(mtd, chipnr);
|
|
|
- }
|
|
|
-
|
|
|
do {
|
|
|
if (chip->options & NAND_BUSWIDTH_16) {
|
|
|
chip->cmdfunc(mtd, NAND_CMD_READOOB,
|
|
@@ -391,11 +377,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|
|
i++;
|
|
|
} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
|
|
|
|
|
|
- if (getchip) {
|
|
|
- chip->select_chip(mtd, -1);
|
|
|
- nand_release_device(mtd);
|
|
|
- }
|
|
|
-
|
|
|
return res;
|
|
|
}
|
|
|
|
|
@@ -533,14 +514,12 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
|
|
|
* nand_block_checkbad - [GENERIC] Check if a block is marked bad
|
|
|
* @mtd: MTD device structure
|
|
|
* @ofs: offset from device start
|
|
|
- * @getchip: 0, if the chip is already selected
|
|
|
* @allowbbt: 1, if its allowed to access the bbt area
|
|
|
*
|
|
|
* Check, if the block is bad. Either by reading the bad block table or
|
|
|
* calling of the scan function.
|
|
|
*/
|
|
|
-static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
|
|
- int allowbbt)
|
|
|
+static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
|
|
|
{
|
|
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
@@ -551,17 +530,22 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
|
|
}
|
|
|
|
|
|
if (!chip->bbt)
|
|
|
- return chip->block_bad(mtd, ofs, getchip);
|
|
|
+ return chip->block_bad(mtd, ofs);
|
|
|
|
|
|
/* Return info from the table */
|
|
|
return nand_isbad_bbt(mtd, ofs, allowbbt);
|
|
|
}
|
|
|
|
|
|
-/* Wait for the ready pin, after a command. The timeout is caught later. */
|
|
|
+/**
|
|
|
+ * nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
|
|
|
+ * @mtd: MTD device structure
|
|
|
+ *
|
|
|
+ * Wait for the ready pin after a command, and warn if a timeout occurs.
|
|
|
+ */
|
|
|
void nand_wait_ready(struct mtd_info *mtd)
|
|
|
{
|
|
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
- u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
|
|
|
+ u32 timeo = (CONFIG_SYS_HZ * 400) / 1000;
|
|
|
u32 time_start;
|
|
|
|
|
|
time_start = get_timer(0);
|
|
@@ -571,6 +555,9 @@ void nand_wait_ready(struct mtd_info *mtd)
|
|
|
if (chip->dev_ready(mtd))
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ if (!chip->dev_ready(mtd))
|
|
|
+ pr_warn("timeout while waiting for chip to become ready\n");
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(nand_wait_ready);
|
|
|
|
|
@@ -871,15 +858,13 @@ 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.
|
|
|
*/
|
|
|
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|
|
{
|
|
|
|
|
|
- int status, state = chip->state;
|
|
|
- unsigned long timeo = (state == FL_ERASING ? 400 : 20);
|
|
|
+ int status;
|
|
|
+ unsigned long timeo = 400;
|
|
|
|
|
|
led_trigger_event(nand_led_trigger, LED_FULL);
|
|
|
|
|
@@ -912,6 +897,135 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+#define BITS_PER_BYTE 8
|
|
|
+
|
|
|
+/**
|
|
|
+ * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
|
|
|
+ * @buf: buffer to test
|
|
|
+ * @len: buffer length
|
|
|
+ * @bitflips_threshold: maximum number of bitflips
|
|
|
+ *
|
|
|
+ * Check if a buffer contains only 0xff, which means the underlying region
|
|
|
+ * has been erased and is ready to be programmed.
|
|
|
+ * The bitflips_threshold specify the maximum number of bitflips before
|
|
|
+ * considering the region is not erased.
|
|
|
+ * Note: The logic of this function has been extracted from the memweight
|
|
|
+ * implementation, except that nand_check_erased_buf function exit before
|
|
|
+ * testing the whole buffer if the number of bitflips exceed the
|
|
|
+ * bitflips_threshold value.
|
|
|
+ *
|
|
|
+ * Returns a positive number of bitflips less than or equal to
|
|
|
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
|
|
|
+ * threshold.
|
|
|
+ */
|
|
|
+static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold)
|
|
|
+{
|
|
|
+ const unsigned char *bitmap = buf;
|
|
|
+ int bitflips = 0;
|
|
|
+ int weight;
|
|
|
+
|
|
|
+ for (; len && ((uintptr_t)bitmap) % sizeof(long);
|
|
|
+ len--, bitmap++) {
|
|
|
+ weight = hweight8(*bitmap);
|
|
|
+ bitflips += BITS_PER_BYTE - weight;
|
|
|
+ if (unlikely(bitflips > bitflips_threshold))
|
|
|
+ return -EBADMSG;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (; len >= 4; len -= 4, bitmap += 4) {
|
|
|
+ weight = hweight32(*((u32 *)bitmap));
|
|
|
+ bitflips += 32 - weight;
|
|
|
+ if (unlikely(bitflips > bitflips_threshold))
|
|
|
+ return -EBADMSG;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (; len > 0; len--, bitmap++) {
|
|
|
+ weight = hweight8(*bitmap);
|
|
|
+ bitflips += BITS_PER_BYTE - weight;
|
|
|
+ if (unlikely(bitflips > bitflips_threshold))
|
|
|
+ return -EBADMSG;
|
|
|
+ }
|
|
|
+
|
|
|
+ return bitflips;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only
|
|
|
+ * 0xff data
|
|
|
+ * @data: data buffer to test
|
|
|
+ * @datalen: data length
|
|
|
+ * @ecc: ECC buffer
|
|
|
+ * @ecclen: ECC length
|
|
|
+ * @extraoob: extra OOB buffer
|
|
|
+ * @extraooblen: extra OOB length
|
|
|
+ * @bitflips_threshold: maximum number of bitflips
|
|
|
+ *
|
|
|
+ * Check if a data buffer and its associated ECC and OOB data contains only
|
|
|
+ * 0xff pattern, which means the underlying region has been erased and is
|
|
|
+ * ready to be programmed.
|
|
|
+ * The bitflips_threshold specify the maximum number of bitflips before
|
|
|
+ * considering the region as not erased.
|
|
|
+ *
|
|
|
+ * Note:
|
|
|
+ * 1/ ECC algorithms are working on pre-defined block sizes which are usually
|
|
|
+ * different from the NAND page size. When fixing bitflips, ECC engines will
|
|
|
+ * report the number of errors per chunk, and the NAND core infrastructure
|
|
|
+ * expect you to return the maximum number of bitflips for the whole page.
|
|
|
+ * This is why you should always use this function on a single chunk and
|
|
|
+ * not on the whole page. After checking each chunk you should update your
|
|
|
+ * max_bitflips value accordingly.
|
|
|
+ * 2/ When checking for bitflips in erased pages you should not only check
|
|
|
+ * the payload data but also their associated ECC data, because a user might
|
|
|
+ * have programmed almost all bits to 1 but a few. In this case, we
|
|
|
+ * shouldn't consider the chunk as erased, and checking ECC bytes prevent
|
|
|
+ * this case.
|
|
|
+ * 3/ The extraoob argument is optional, and should be used if some of your OOB
|
|
|
+ * data are protected by the ECC engine.
|
|
|
+ * It could also be used if you support subpages and want to attach some
|
|
|
+ * extra OOB data to an ECC chunk.
|
|
|
+ *
|
|
|
+ * Returns a positive number of bitflips less than or equal to
|
|
|
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
|
|
|
+ * threshold. In case of success, the passed buffers are filled with 0xff.
|
|
|
+ */
|
|
|
+int nand_check_erased_ecc_chunk(void *data, int datalen,
|
|
|
+ void *ecc, int ecclen,
|
|
|
+ void *extraoob, int extraooblen,
|
|
|
+ int bitflips_threshold)
|
|
|
+{
|
|
|
+ int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0;
|
|
|
+
|
|
|
+ data_bitflips = nand_check_erased_buf(data, datalen,
|
|
|
+ bitflips_threshold);
|
|
|
+ if (data_bitflips < 0)
|
|
|
+ return data_bitflips;
|
|
|
+
|
|
|
+ bitflips_threshold -= data_bitflips;
|
|
|
+
|
|
|
+ ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold);
|
|
|
+ if (ecc_bitflips < 0)
|
|
|
+ return ecc_bitflips;
|
|
|
+
|
|
|
+ bitflips_threshold -= ecc_bitflips;
|
|
|
+
|
|
|
+ extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen,
|
|
|
+ bitflips_threshold);
|
|
|
+ if (extraoob_bitflips < 0)
|
|
|
+ return extraoob_bitflips;
|
|
|
+
|
|
|
+ if (data_bitflips)
|
|
|
+ memset(data, 0xff, datalen);
|
|
|
+
|
|
|
+ if (ecc_bitflips)
|
|
|
+ memset(ecc, 0xff, ecclen);
|
|
|
+
|
|
|
+ if (extraoob_bitflips)
|
|
|
+ memset(extraoob, 0xff, extraooblen);
|
|
|
+
|
|
|
+ return data_bitflips + ecc_bitflips + extraoob_bitflips;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(nand_check_erased_ecc_chunk);
|
|
|
+
|
|
|
/**
|
|
|
* nand_read_page_raw - [INTERN] read raw page data without ecc
|
|
|
* @mtd: mtd info structure
|
|
@@ -1103,6 +1217,16 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
|
|
|
stat = chip->ecc.correct(mtd, p,
|
|
|
&chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
|
|
|
+ if (stat == -EBADMSG &&
|
|
|
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
|
|
+ /* check for empty pages with bitflips */
|
|
|
+ stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
|
|
|
+ &chip->buffers->ecccode[i],
|
|
|
+ chip->ecc.bytes,
|
|
|
+ NULL, 0,
|
|
|
+ chip->ecc.strength);
|
|
|
+ }
|
|
|
+
|
|
|
if (stat < 0) {
|
|
|
mtd->ecc_stats.failed++;
|
|
|
} else {
|
|
@@ -1152,6 +1276,15 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
int stat;
|
|
|
|
|
|
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
|
|
|
+ if (stat == -EBADMSG &&
|
|
|
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
|
|
+ /* check for empty pages with bitflips */
|
|
|
+ stat = nand_check_erased_ecc_chunk(p, eccsize,
|
|
|
+ &ecc_code[i], eccbytes,
|
|
|
+ NULL, 0,
|
|
|
+ chip->ecc.strength);
|
|
|
+ }
|
|
|
+
|
|
|
if (stat < 0) {
|
|
|
mtd->ecc_stats.failed++;
|
|
|
} else {
|
|
@@ -1204,6 +1337,15 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
|
|
|
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
|
|
|
|
|
|
stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
|
|
|
+ if (stat == -EBADMSG &&
|
|
|
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
|
|
+ /* check for empty pages with bitflips */
|
|
|
+ stat = nand_check_erased_ecc_chunk(p, eccsize,
|
|
|
+ &ecc_code[i], eccbytes,
|
|
|
+ NULL, 0,
|
|
|
+ chip->ecc.strength);
|
|
|
+ }
|
|
|
+
|
|
|
if (stat < 0) {
|
|
|
mtd->ecc_stats.failed++;
|
|
|
} else {
|
|
@@ -1231,6 +1373,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
int i, eccsize = chip->ecc.size;
|
|
|
int eccbytes = chip->ecc.bytes;
|
|
|
int eccsteps = chip->ecc.steps;
|
|
|
+ int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
|
|
|
uint8_t *p = buf;
|
|
|
uint8_t *oob = chip->oob_poi;
|
|
|
unsigned int max_bitflips = 0;
|
|
@@ -1250,19 +1393,29 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
chip->read_buf(mtd, oob, eccbytes);
|
|
|
stat = chip->ecc.correct(mtd, p, oob, NULL);
|
|
|
|
|
|
- if (stat < 0) {
|
|
|
- mtd->ecc_stats.failed++;
|
|
|
- } else {
|
|
|
- mtd->ecc_stats.corrected += stat;
|
|
|
- max_bitflips = max_t(unsigned int, max_bitflips, stat);
|
|
|
- }
|
|
|
-
|
|
|
oob += eccbytes;
|
|
|
|
|
|
if (chip->ecc.postpad) {
|
|
|
chip->read_buf(mtd, oob, chip->ecc.postpad);
|
|
|
oob += chip->ecc.postpad;
|
|
|
}
|
|
|
+
|
|
|
+ if (stat == -EBADMSG &&
|
|
|
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
|
|
|
+ /* check for empty pages with bitflips */
|
|
|
+ stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
|
|
|
+ oob - eccpadbytes,
|
|
|
+ eccpadbytes,
|
|
|
+ NULL, 0,
|
|
|
+ chip->ecc.strength);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stat < 0) {
|
|
|
+ mtd->ecc_stats.failed++;
|
|
|
+ } else {
|
|
|
+ mtd->ecc_stats.corrected += stat;
|
|
|
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Calculate remaining oob bytes */
|
|
@@ -1361,8 +1514,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|
|
int ret = 0;
|
|
|
uint32_t readlen = ops->len;
|
|
|
uint32_t oobreadlen = ops->ooblen;
|
|
|
- uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ?
|
|
|
- mtd->oobavail : mtd->oobsize;
|
|
|
+ uint32_t max_oobsize = mtd_oobavail(mtd, ops);
|
|
|
|
|
|
uint8_t *bufpoi, *oob, *buf;
|
|
|
int use_bufpoi;
|
|
@@ -1712,10 +1864,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|
|
|
|
|
stats = mtd->ecc_stats;
|
|
|
|
|
|
- if (ops->mode == MTD_OPS_AUTO_OOB)
|
|
|
- len = chip->ecc.layout->oobavail;
|
|
|
- else
|
|
|
- len = mtd->oobsize;
|
|
|
+ len = mtd_oobavail(mtd, ops);
|
|
|
|
|
|
if (unlikely(ops->ooboffs >= len)) {
|
|
|
pr_debug("%s: attempt to start read outside oob\n",
|
|
@@ -1845,8 +1994,7 @@ out:
|
|
|
* Not for syndrome calculating ECC controllers, which use a special oob layout.
|
|
|
*/
|
|
|
static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
- const uint8_t *buf, int oob_required,
|
|
|
- int page)
|
|
|
+ const uint8_t *buf, int oob_required, int page)
|
|
|
{
|
|
|
chip->write_buf(mtd, buf, mtd->writesize);
|
|
|
if (oob_required)
|
|
@@ -1861,6 +2009,7 @@ static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
* @chip: nand chip info structure
|
|
|
* @buf: data buffer
|
|
|
* @oob_required: must write chip->oob_poi to OOB
|
|
|
+ * @page: page number to write
|
|
|
*
|
|
|
* We need a special oob layout and handling even when ECC isn't checked.
|
|
|
*/
|
|
@@ -1907,8 +2056,8 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
|
|
|
* @page: page number to write
|
|
|
*/
|
|
|
static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
- const uint8_t *buf, int oob_required,
|
|
|
- int page)
|
|
|
+ const uint8_t *buf, int oob_required,
|
|
|
+ int page)
|
|
|
{
|
|
|
int i, eccsize = chip->ecc.size;
|
|
|
int eccbytes = chip->ecc.bytes;
|
|
@@ -2029,6 +2178,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
|
|
|
* @chip: nand chip info structure
|
|
|
* @buf: data buffer
|
|
|
* @oob_required: must write chip->oob_poi to OOB
|
|
|
+ * @page: page number to write
|
|
|
*
|
|
|
* The hw generator calculates the error syndrome automatically. Therefore we
|
|
|
* need a special oob layout and handling.
|
|
@@ -2103,7 +2253,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
oob_required, page);
|
|
|
else if (subpage)
|
|
|
status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
|
|
|
- buf, oob_required, page);
|
|
|
+ buf, oob_required, page);
|
|
|
else
|
|
|
status = chip->ecc.write_page(mtd, chip, buf, oob_required,
|
|
|
page);
|
|
@@ -2145,7 +2295,6 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
* @oob: oob data buffer
|
|
|
* @len: oob data write length
|
|
|
* @ops: oob ops structure
|
|
|
- * @page: page number to write
|
|
|
*/
|
|
|
static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
|
|
|
struct mtd_oob_ops *ops)
|
|
@@ -2214,8 +2363,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
|
uint32_t writelen = ops->len;
|
|
|
|
|
|
uint32_t oobwritelen = ops->ooblen;
|
|
|
- uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
|
|
|
- mtd->oobavail : mtd->oobsize;
|
|
|
+ uint32_t oobmaxlen = mtd_oobavail(mtd, ops);
|
|
|
|
|
|
uint8_t *oob = ops->oobbuf;
|
|
|
uint8_t *buf = ops->datbuf;
|
|
@@ -2404,10 +2552,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
|
|
|
pr_debug("%s: to = 0x%08x, len = %i\n",
|
|
|
__func__, (unsigned int)to, (int)ops->ooblen);
|
|
|
|
|
|
- if (ops->mode == MTD_OPS_AUTO_OOB)
|
|
|
- len = chip->ecc.layout->oobavail;
|
|
|
- else
|
|
|
- len = mtd->oobsize;
|
|
|
+ len = mtd_oobavail(mtd, ops);
|
|
|
|
|
|
/* Do not allow write past end of page */
|
|
|
if ((ops->ooboffs + ops->ooblen) > len) {
|
|
@@ -2597,7 +2742,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
|
|
|
|
/* Check if we have a bad block, we do not erase bad blocks! */
|
|
|
if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<
|
|
|
- chip->page_shift, 0, allowbbt)) {
|
|
|
+ chip->page_shift, allowbbt)) {
|
|
|
pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
|
|
|
__func__, page);
|
|
|
instr->state = MTD_ERASE_FAILED;
|
|
@@ -2684,7 +2829,20 @@ static void nand_sync(struct mtd_info *mtd)
|
|
|
*/
|
|
|
static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
|
|
|
{
|
|
|
- return nand_block_checkbad(mtd, offs, 1, 0);
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
+ int chipnr = (int)(offs >> chip->chip_shift);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* Select the NAND device */
|
|
|
+ nand_get_device(mtd, FL_READING);
|
|
|
+ chip->select_chip(mtd, chipnr);
|
|
|
+
|
|
|
+ ret = nand_block_checkbad(mtd, offs, 0);
|
|
|
+
|
|
|
+ chip->select_chip(mtd, -1);
|
|
|
+ nand_release_device(mtd);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -2756,9 +2914,6 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
return -EINVAL;
|
|
|
#endif
|
|
|
|
|
|
- /* clear the sub feature parameters */
|
|
|
- memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
|
|
|
-
|
|
|
chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
|
|
|
for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
|
|
|
*subfeature_param++ = chip->read_byte(mtd);
|
|
@@ -3491,7 +3646,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
|
if (find_full_id_nand(mtd, chip, type, id_data, &busw))
|
|
|
goto ident_done;
|
|
|
} else if (*dev_id == type->dev_id) {
|
|
|
- break;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3514,10 +3669,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 */
|
|
|
- busw = chip->init_size(mtd, chip, id_data);
|
|
|
- } else if (!type->pagesize) {
|
|
|
+ if (!type->pagesize) {
|
|
|
/* Decode parameters from extended ID */
|
|
|
nand_decode_ext_id(mtd, chip, id_data, &busw);
|
|
|
} else {
|
|
@@ -3621,7 +3773,6 @@ ident_done:
|
|
|
* 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.
|
|
|
*/
|
|
|
int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
|
|
struct nand_flash_dev *table)
|
|
@@ -3797,7 +3948,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
|
ecc->write_oob = nand_write_oob_std;
|
|
|
if (!ecc->read_subpage)
|
|
|
ecc->read_subpage = nand_read_subpage;
|
|
|
- if (!ecc->write_subpage)
|
|
|
+ if (!ecc->write_subpage && ecc->hwctl && ecc->calculate)
|
|
|
ecc->write_subpage = nand_write_subpage_hwecc;
|
|
|
|
|
|
case NAND_ECC_HW_SYNDROME:
|
|
@@ -3875,10 +4026,8 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|
|
}
|
|
|
|
|
|
/* See nand_bch_init() for details. */
|
|
|
- ecc->bytes = DIV_ROUND_UP(
|
|
|
- ecc->strength * fls(8 * ecc->size), 8);
|
|
|
- ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes,
|
|
|
- &ecc->layout);
|
|
|
+ ecc->bytes = 0;
|
|
|
+ ecc->priv = nand_bch_init(mtd);
|
|
|
if (!ecc->priv) {
|
|
|
pr_warn("BCH ECC initialization failed!\n");
|
|
|
BUG();
|
|
@@ -3913,11 +4062,11 @@ 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.
|
|
|
*/
|
|
|
- ecc->layout->oobavail = 0;
|
|
|
- for (i = 0; ecc->layout->oobfree[i].length
|
|
|
- && i < ARRAY_SIZE(ecc->layout->oobfree); i++)
|
|
|
- ecc->layout->oobavail += ecc->layout->oobfree[i].length;
|
|
|
- mtd->oobavail = ecc->layout->oobavail;
|
|
|
+ mtd->oobavail = 0;
|
|
|
+ if (ecc->layout) {
|
|
|
+ for (i = 0; ecc->layout->oobfree[i].length; i++)
|
|
|
+ mtd->oobavail += ecc->layout->oobfree[i].length;
|
|
|
+ }
|
|
|
|
|
|
/* ECC sanity check: warn if it's too weak */
|
|
|
if (!nand_ecc_strength_good(mtd))
|
|
@@ -4002,18 +4151,6 @@ 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
|
|
|
- * 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.
|
|
|
- */
|
|
|
-#ifdef MODULE
|
|
|
-#define caller_is_module() (1)
|
|
|
-#else
|
|
|
-#define caller_is_module() \
|
|
|
- is_module_text_address((unsigned long)__builtin_return_address(0))
|
|
|
-#endif
|
|
|
-
|
|
|
/**
|
|
|
* nand_scan - [NAND Interface] Scan for the NAND device
|
|
|
* @mtd: MTD device structure
|
|
@@ -4021,19 +4158,12 @@ EXPORT_SYMBOL(nand_scan_tail);
|
|
|
*
|
|
|
* 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.
|
|
|
+ * appropriate values.
|
|
|
*/
|
|
|
int nand_scan(struct mtd_info *mtd, int maxchips)
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
- /* Many callers got this wrong, so check for it for a while... */
|
|
|
- if (!mtd->owner && caller_is_module()) {
|
|
|
- pr_crit("%s called with NULL mtd->owner!\n", __func__);
|
|
|
- BUG();
|
|
|
- }
|
|
|
-
|
|
|
ret = nand_scan_ident(mtd, maxchips, NULL);
|
|
|
if (!ret)
|
|
|
ret = nand_scan_tail(mtd);
|
|
@@ -4041,9 +4171,6 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
|
|
}
|
|
|
EXPORT_SYMBOL(nand_scan);
|
|
|
|
|
|
-module_init(nand_base_init);
|
|
|
-module_exit(nand_base_exit);
|
|
|
-
|
|
|
MODULE_LICENSE("GPL");
|
|
|
MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
|
|
|
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
|