|
@@ -106,7 +106,7 @@ DEFINE_LED_TRIGGER(nand_led_trigger);
|
|
|
static int check_offs_len(struct mtd_info *mtd,
|
|
|
loff_t ofs, uint64_t len)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
int ret = 0;
|
|
|
|
|
|
/* Start address must align on block boundary */
|
|
@@ -132,7 +132,7 @@ static int check_offs_len(struct mtd_info *mtd,
|
|
|
*/
|
|
|
static void nand_release_device(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
/* Release the controller and the chip */
|
|
|
spin_lock(&chip->controller->lock);
|
|
@@ -150,7 +150,7 @@ static void nand_release_device(struct mtd_info *mtd)
|
|
|
*/
|
|
|
static uint8_t nand_read_byte(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
return readb(chip->IO_ADDR_R);
|
|
|
}
|
|
|
|
|
@@ -163,7 +163,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
|
|
|
*/
|
|
|
static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
|
|
|
}
|
|
|
|
|
@@ -175,7 +175,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
|
|
|
*/
|
|
|
static u16 nand_read_word(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
return readw(chip->IO_ADDR_R);
|
|
|
}
|
|
|
|
|
@@ -188,7 +188,7 @@ static u16 nand_read_word(struct mtd_info *mtd)
|
|
|
*/
|
|
|
static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
switch (chipnr) {
|
|
|
case -1:
|
|
@@ -211,7 +211,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
|
|
*/
|
|
|
static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
chip->write_buf(mtd, &byte, 1);
|
|
|
}
|
|
@@ -225,7 +225,7 @@ static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
|
|
|
*/
|
|
|
static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
uint16_t word = byte;
|
|
|
|
|
|
/*
|
|
@@ -257,7 +257,7 @@ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
|
|
|
*/
|
|
|
static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
iowrite8_rep(chip->IO_ADDR_W, buf, len);
|
|
|
}
|
|
@@ -272,7 +272,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
*/
|
|
|
static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
ioread8_rep(chip->IO_ADDR_R, buf, len);
|
|
|
}
|
|
@@ -287,7 +287,7 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
*/
|
|
|
static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
u16 *p = (u16 *) buf;
|
|
|
|
|
|
iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
|
|
@@ -303,7 +303,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
|
|
|
*/
|
|
|
static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
u16 *p = (u16 *) buf;
|
|
|
|
|
|
ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
|
|
@@ -320,7 +320,7 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
|
|
|
static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|
|
{
|
|
|
int page, chipnr, res = 0, i = 0;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
u16 bad;
|
|
|
|
|
|
if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
|
|
@@ -380,7 +380,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|
|
*/
|
|
|
static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
struct mtd_oob_ops ops;
|
|
|
uint8_t buf[2] = { 0, 0 };
|
|
|
int ret = 0, res, i = 0;
|
|
@@ -430,7 +430,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
*/
|
|
|
static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
int res, ret = 0;
|
|
|
|
|
|
if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
|
|
@@ -471,7 +471,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
|
|
|
*/
|
|
|
static int nand_check_wp(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
/* Broken xD cards report WP despite being writable */
|
|
|
if (chip->options & NAND_BROKEN_XD)
|
|
@@ -491,7 +491,7 @@ static int nand_check_wp(struct mtd_info *mtd)
|
|
|
*/
|
|
|
static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
if (!chip->bbt)
|
|
|
return 0;
|
|
@@ -512,7 +512,7 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
|
|
|
static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
|
|
int allowbbt)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
if (!chip->bbt)
|
|
|
return chip->block_bad(mtd, ofs, getchip);
|
|
@@ -531,7 +531,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
|
|
|
*/
|
|
|
static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
int i;
|
|
|
|
|
|
/* Wait for the device to get ready */
|
|
@@ -551,7 +551,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
|
|
|
*/
|
|
|
void nand_wait_ready(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
unsigned long timeo = 400;
|
|
|
|
|
|
if (in_interrupt() || oops_in_progress)
|
|
@@ -582,7 +582,7 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
|
|
|
*/
|
|
|
static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
|
|
|
{
|
|
|
- register struct nand_chip *chip = mtd->priv;
|
|
|
+ register struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
timeo = jiffies + msecs_to_jiffies(timeo);
|
|
|
do {
|
|
@@ -605,7 +605,7 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
|
|
|
static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
|
int column, int page_addr)
|
|
|
{
|
|
|
- register struct nand_chip *chip = mtd->priv;
|
|
|
+ register struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
|
|
|
|
|
|
/* Write out the command to the device */
|
|
@@ -708,7 +708,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
|
|
|
static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
|
|
int column, int page_addr)
|
|
|
{
|
|
|
- register struct nand_chip *chip = mtd->priv;
|
|
|
+ register struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
/* Emulate NAND_CMD_READOOB */
|
|
|
if (command == NAND_CMD_READOOB) {
|
|
@@ -832,7 +832,7 @@ static void panic_nand_get_device(struct nand_chip *chip,
|
|
|
static int
|
|
|
nand_get_device(struct mtd_info *mtd, int new_state)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
spinlock_t *lock = &chip->controller->lock;
|
|
|
wait_queue_head_t *wq = &chip->controller->wq;
|
|
|
DECLARE_WAITQUEUE(wait, current);
|
|
@@ -952,7 +952,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
|
|
|
{
|
|
|
int ret = 0;
|
|
|
int status, page;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
/* Submit address of first page to unlock */
|
|
|
page = ofs >> chip->page_shift;
|
|
@@ -987,7 +987,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
int chipnr;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
pr_debug("%s: start = 0x%012llx, len = %llu\n",
|
|
|
__func__, (unsigned long long)ofs, len);
|
|
@@ -1050,7 +1050,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
int chipnr, status, page;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
pr_debug("%s: start = 0x%012llx, len = %llu\n",
|
|
|
__func__, (unsigned long long)ofs, len);
|
|
@@ -1426,6 +1426,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 {
|
|
@@ -1475,6 +1485,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 {
|
|
@@ -1527,6 +1546,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 {
|
|
@@ -1554,6 +1582,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;
|
|
@@ -1573,19 +1602,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 */
|
|
@@ -1655,7 +1694,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
|
|
|
*/
|
|
|
static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
pr_debug("setting READ RETRY mode %d\n", retry_mode);
|
|
|
|
|
@@ -1680,7 +1719,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
|
|
|
struct mtd_oob_ops *ops)
|
|
|
{
|
|
|
int chipnr, page, realpage, col, bytes, aligned, oob_required;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
int ret = 0;
|
|
|
uint32_t readlen = ops->len;
|
|
|
uint32_t oobreadlen = ops->ooblen;
|
|
@@ -2024,7 +2063,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|
|
struct mtd_oob_ops *ops)
|
|
|
{
|
|
|
int page, realpage, chipnr;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
struct mtd_ecc_stats stats;
|
|
|
int readlen = ops->ooblen;
|
|
|
int len;
|
|
@@ -2472,7 +2511,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
|
|
|
struct mtd_oob_ops *ops)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
/*
|
|
|
* Initialise to all 0xFF, to avoid the possibility of left over OOB
|
|
@@ -2532,7 +2571,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
|
struct mtd_oob_ops *ops)
|
|
|
{
|
|
|
int chipnr, realpage, page, blockmask, column;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
uint32_t writelen = ops->len;
|
|
|
|
|
|
uint32_t oobwritelen = ops->ooblen;
|
|
@@ -2662,7 +2701,7 @@ err_out:
|
|
|
static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
|
size_t *retlen, const uint8_t *buf)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
struct mtd_oob_ops ops;
|
|
|
int ret;
|
|
|
|
|
@@ -2722,7 +2761,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
|
|
|
struct mtd_oob_ops *ops)
|
|
|
{
|
|
|
int chipnr, page, status, len;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
pr_debug("%s: to = 0x%08x, len = %i\n",
|
|
|
__func__, (unsigned int)to, (int)ops->ooblen);
|
|
@@ -2847,7 +2886,7 @@ out:
|
|
|
*/
|
|
|
static int single_erase(struct mtd_info *mtd, int page)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
/* Send commands to erase a block */
|
|
|
chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
|
|
|
chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
|
|
@@ -2879,7 +2918,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
|
|
int allowbbt)
|
|
|
{
|
|
|
int page, status, pages_per_block, ret, chipnr;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
loff_t len;
|
|
|
|
|
|
pr_debug("%s: start = 0x%012llx, len = %llu\n",
|
|
@@ -3094,7 +3133,7 @@ static int nand_suspend(struct mtd_info *mtd)
|
|
|
*/
|
|
|
static void nand_resume(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
if (chip->state == FL_PM_SUSPENDED)
|
|
|
nand_release_device(mtd);
|
|
@@ -3266,7 +3305,7 @@ ext_out:
|
|
|
|
|
|
static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
|
|
|
|
|
|
return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
|
|
@@ -3937,11 +3976,14 @@ ident_done:
|
|
|
return type;
|
|
|
}
|
|
|
|
|
|
-static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip,
|
|
|
- struct device_node *dn)
|
|
|
+static int nand_dt_init(struct nand_chip *chip)
|
|
|
{
|
|
|
+ struct device_node *dn = nand_get_flash_node(chip);
|
|
|
int ecc_mode, ecc_strength, ecc_step;
|
|
|
|
|
|
+ if (!dn)
|
|
|
+ return 0;
|
|
|
+
|
|
|
if (of_get_nand_bus_width(dn) == 16)
|
|
|
chip->options |= NAND_BUSWIDTH_16;
|
|
|
|
|
@@ -3985,15 +4027,16 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
|
|
struct nand_flash_dev *table)
|
|
|
{
|
|
|
int i, nand_maf_id, nand_dev_id;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
struct nand_flash_dev *type;
|
|
|
int ret;
|
|
|
|
|
|
- if (chip->flash_node) {
|
|
|
- ret = nand_dt_init(mtd, chip, chip->flash_node);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ ret = nand_dt_init(chip);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ if (!mtd->name && mtd->dev.parent)
|
|
|
+ mtd->name = dev_name(mtd->dev.parent);
|
|
|
|
|
|
/* Set the default functions */
|
|
|
nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
|
|
@@ -4053,7 +4096,7 @@ EXPORT_SYMBOL(nand_scan_ident);
|
|
|
*/
|
|
|
static bool nand_ecc_strength_good(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
|
|
int corr, ds_corr;
|
|
|
|
|
@@ -4082,7 +4125,7 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
|
|
|
int nand_scan_tail(struct mtd_info *mtd)
|
|
|
{
|
|
|
int i;
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
|
|
struct nand_buffers *nbuf;
|
|
|
|
|
@@ -4166,7 +4209,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:
|
|
@@ -4426,7 +4469,7 @@ EXPORT_SYMBOL(nand_scan);
|
|
|
*/
|
|
|
void nand_release(struct mtd_info *mtd)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
+ struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
|
|
|
if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
|
|
|
nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
|