Commit ced80966 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

updated to current version

parent fd4f2e1d
...@@ -36,9 +36,10 @@ ...@@ -36,9 +36,10 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/nmi.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h> #include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h> #include <linux/mtd/nand_ecc.h>
#include <linux/mtd/nand_bch.h> #include <linux/mtd/nand_bch.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -69,8 +70,14 @@ static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section, ...@@ -69,8 +70,14 @@ static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
if (!section) { if (!section) {
oobregion->offset = 0; oobregion->offset = 0;
oobregion->length = 4; if (mtd->oobsize == 16)
oobregion->length = 4;
else
oobregion->length = 3;
} else { } else {
if (mtd->oobsize == 8)
return -ERANGE;
oobregion->offset = 6; oobregion->offset = 6;
oobregion->length = ecc->total - 4; oobregion->length = ecc->total - 4;
} }
...@@ -143,6 +150,74 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = { ...@@ -143,6 +150,74 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
}; };
EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);
/*
* Support the old "large page" layout used for 1-bit Hamming ECC where ECC
* are placed at a fixed offset.
*/
static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_ecc_ctrl *ecc = &chip->ecc;
if (section)
return -ERANGE;
switch (mtd->oobsize) {
case 64:
oobregion->offset = 40;
break;
case 128:
oobregion->offset = 80;
break;
default:
return -EINVAL;
}
oobregion->length = ecc->total;
if (oobregion->offset + oobregion->length > mtd->oobsize)
return -ERANGE;
return 0;
}
static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_ecc_ctrl *ecc = &chip->ecc;
int ecc_offset = 0;
if (section < 0 || section > 1)
return -ERANGE;
switch (mtd->oobsize) {
case 64:
ecc_offset = 40;
break;
case 128:
ecc_offset = 80;
break;
default:
return -EINVAL;
}
if (section == 0) {
oobregion->offset = 2;
oobregion->length = ecc_offset - 2;
} else {
oobregion->offset = ecc_offset + ecc->total;
oobregion->length = mtd->oobsize - oobregion->offset;
}
return 0;
}
static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
.ecc = nand_ooblayout_ecc_lp_hamming,
.free = nand_ooblayout_free_lp_hamming,
};
static int check_offs_len(struct mtd_info *mtd, static int check_offs_len(struct mtd_info *mtd,
loff_t ofs, uint64_t len) loff_t ofs, uint64_t len)
{ {
...@@ -360,40 +435,32 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) ...@@ -360,40 +435,32 @@ 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) static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
{ {
int page, res = 0, i = 0; int page, page_end, res;
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
u16 bad; u8 bad;
if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
ofs += mtd->erasesize - mtd->writesize; ofs += mtd->erasesize - mtd->writesize;
page = (int)(ofs >> chip->page_shift) & chip->pagemask; page = (int)(ofs >> chip->page_shift) & chip->pagemask;
page_end = page + (chip->bbt_options & NAND_BBT_SCAN2NDPAGE ? 2 : 1);
do { for (; page < page_end; page++) {
if (chip->options & NAND_BUSWIDTH_16) { res = chip->ecc.read_oob(mtd, chip, page);
chip->cmdfunc(mtd, NAND_CMD_READOOB, if (res)
chip->badblockpos & 0xFE, page); return res;
bad = cpu_to_le16(chip->read_word(mtd));
if (chip->badblockpos & 0x1) bad = chip->oob_poi[chip->badblockpos];
bad >>= 8;
else
bad &= 0xFF;
} else {
chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
page);
bad = chip->read_byte(mtd);
}
if (likely(chip->badblockbits == 8)) if (likely(chip->badblockbits == 8))
res = bad != 0xFF; res = bad != 0xFF;
else else
res = hweight8(bad) < chip->badblockbits; res = hweight8(bad) < chip->badblockbits;
ofs += mtd->writesize; if (res)
page = (int)(ofs >> chip->page_shift) & chip->pagemask; return res;
i++; }
} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
return res; return 0;
} }
/** /**
...@@ -448,10 +515,12 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) ...@@ -448,10 +515,12 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
* specify how to write bad block markers to OOB (chip->block_markbad). * specify how to write bad block markers to OOB (chip->block_markbad).
* *
* We try operations in the following order: * We try operations in the following order:
*
* (1) erase the affected block, to allow OOB marker to be written cleanly * (1) erase the affected block, to allow OOB marker to be written cleanly
* (2) write bad block marker to OOB area of affected block (unless flag * (2) write bad block marker to OOB area of affected block (unless flag
* NAND_BBT_NO_OOB_BBM is present) * NAND_BBT_NO_OOB_BBM is present)
* (3) update the BBT * (3) update the BBT
*
* Note that we retain the first error encountered in (2) or (3), finish the * Note that we retain the first error encountered in (2) or (3), finish the
* procedures, and dump the error in the end. * procedures, and dump the error in the end.
*/ */
...@@ -682,6 +751,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, ...@@ -682,6 +751,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
case NAND_CMD_ERASE2: case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN: case NAND_CMD_SEQIN:
case NAND_CMD_STATUS: case NAND_CMD_STATUS:
case NAND_CMD_READID:
case NAND_CMD_SET_FEATURES:
return; return;
case NAND_CMD_RESET: case NAND_CMD_RESET:
...@@ -697,6 +768,16 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, ...@@ -697,6 +768,16 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
return; return;
/* This applies to read commands */ /* This applies to read commands */
case NAND_CMD_READ0:
/*
* READ0 is sometimes used to exit GET STATUS mode. When this
* is the case no address cycles are requested, and we can use
* this information to detect that we should not wait for the
* device to be ready.
*/
if (column == -1 && page_addr == -1)
return;
default: default:
/* /*
* If we don't have access to the busy pin, we apply the given * If we don't have access to the busy pin, we apply the given
...@@ -716,6 +797,25 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, ...@@ -716,6 +797,25 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
nand_wait_ready(mtd); nand_wait_ready(mtd);
} }
static void nand_ccs_delay(struct nand_chip *chip)
{
/*
* The controller already takes care of waiting for tCCS when the RNDIN
* or RNDOUT command is sent, return directly.
*/
if (!(chip->options & NAND_WAIT_TCCS))
return;
/*
* Wait tCCS_min if it is correctly defined, otherwise wait 500ns
* (which should be safe for all NANDs).
*/
if (chip->data_interface && chip->data_interface->timings.sdr.tCCS_min)
ndelay(chip->data_interface->timings.sdr.tCCS_min / 1000);
else
ndelay(500);
}
/** /**
* nand_command_lp - [DEFAULT] Send command to NAND large page device * nand_command_lp - [DEFAULT] Send command to NAND large page device
* @mtd: MTD device structure * @mtd: MTD device structure
...@@ -780,8 +880,13 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, ...@@ -780,8 +880,13 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
case NAND_CMD_ERASE1: case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2: case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN: case NAND_CMD_SEQIN:
case NAND_CMD_RNDIN:
case NAND_CMD_STATUS: case NAND_CMD_STATUS:
case NAND_CMD_READID:
case NAND_CMD_SET_FEATURES:
return;
case NAND_CMD_RNDIN:
nand_ccs_delay(chip);
return; return;
case NAND_CMD_RESET: case NAND_CMD_RESET:
...@@ -802,9 +907,20 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, ...@@ -802,9 +907,20 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
chip->cmd_ctrl(mtd, NAND_CMD_NONE, chip->cmd_ctrl(mtd, NAND_CMD_NONE,
NAND_NCE | NAND_CTRL_CHANGE); NAND_NCE | NAND_CTRL_CHANGE);
nand_ccs_delay(chip);
return; return;
case NAND_CMD_READ0: case NAND_CMD_READ0:
/*
* READ0 is sometimes used to exit GET STATUS mode. When this
* is the case no address cycles are requested, and we can use
* this information to detect that READSTART should not be
* issued.
*/
if (column == -1 && page_addr == -1)
return;
chip->cmd_ctrl(mtd, NAND_CMD_READSTART, chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
chip->cmd_ctrl(mtd, NAND_CMD_NONE, chip->cmd_ctrl(mtd, NAND_CMD_NONE,
...@@ -962,12 +1078,13 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) ...@@ -962,12 +1078,13 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
/** /**
* nand_reset_data_interface - Reset data interface and timings * nand_reset_data_interface - Reset data interface and timings
* @chip: The NAND chip * @chip: The NAND chip
* @chipnr: Internal die id
* *
* Reset the Data interface and timings to ONFI mode 0. * Reset the Data interface and timings to ONFI mode 0.
* *
* Returns 0 for success or negative error code otherwise. * Returns 0 for success or negative error code otherwise.
*/ */
static int nand_reset_data_interface(struct nand_chip *chip) static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
{ {
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
const struct nand_data_interface *conf; const struct nand_data_interface *conf;
...@@ -991,7 +1108,7 @@ static int nand_reset_data_interface(struct nand_chip *chip) ...@@ -991,7 +1108,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
*/ */
conf = nand_get_default_data_interface(); conf = nand_get_default_data_interface();
ret = chip->setup_data_interface(mtd, conf, false); ret = chip->setup_data_interface(mtd, chipnr, conf);
if (ret) if (ret)
pr_err("Failed to configure data interface to SDR timing mode 0\n"); pr_err("Failed to configure data interface to SDR timing mode 0\n");
...@@ -1001,6 +1118,7 @@ static int nand_reset_data_interface(struct nand_chip *chip) ...@@ -1001,6 +1118,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
/** /**
* nand_setup_data_interface - Setup the best data interface and timings * nand_setup_data_interface - Setup the best data interface and timings
* @chip: The NAND chip * @chip: The NAND chip
* @chipnr: Internal die id
* *
* Find and configure the best data interface and NAND timings supported by * Find and configure the best data interface and NAND timings supported by
* the chip and the driver. * the chip and the driver.
...@@ -1010,7 +1128,7 @@ static int nand_reset_data_interface(struct nand_chip *chip) ...@@ -1010,7 +1128,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
* *
* Returns 0 for success or negative error code otherwise. * Returns 0 for success or negative error code otherwise.
*/ */
static int nand_setup_data_interface(struct nand_chip *chip) static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
{ {
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
int ret; int ret;
...@@ -1022,7 +1140,9 @@ static int nand_setup_data_interface(struct nand_chip *chip) ...@@ -1022,7 +1140,9 @@ static int nand_setup_data_interface(struct nand_chip *chip)
* Ensure the timing mode has been changed on the chip side * Ensure the timing mode has been changed on the chip side
* before changing timings on the controller side. * before changing timings on the controller side.
*/ */
if (chip->onfi_version) { if (chip->onfi_version &&
(le16_to_cpu(chip->onfi_params.opt_cmd) &
ONFI_OPT_CMD_SET_GET_FEATURES)) {
u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = { u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
chip->onfi_timing_mode_default, chip->onfi_timing_mode_default,
}; };
...@@ -1034,7 +1154,7 @@ static int nand_setup_data_interface(struct nand_chip *chip) ...@@ -1034,7 +1154,7 @@ static int nand_setup_data_interface(struct nand_chip *chip)
goto err; goto err;
} }
ret = chip->setup_data_interface(mtd, chip->data_interface, false); ret = chip->setup_data_interface(mtd, chipnr, chip->data_interface);
err: err:
return ret; return ret;
} }
...@@ -1085,8 +1205,10 @@ static int nand_init_data_interface(struct nand_chip *chip) ...@@ -1085,8 +1205,10 @@ static int nand_init_data_interface(struct nand_chip *chip)
if (ret) if (ret)
continue; continue;
ret = chip->setup_data_interface(mtd, chip->data_interface, /* Pass -1 to only */
true); ret = chip->setup_data_interface(mtd,
NAND_DATA_IFACE_CHECK_ONLY,
chip->data_interface);
if (!ret) { if (!ret) {
chip->onfi_timing_mode_default = mode; chip->onfi_timing_mode_default = mode;
break; break;
...@@ -1113,7 +1235,7 @@ int nand_reset(struct nand_chip *chip, int chipnr) ...@@ -1113,7 +1235,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
int ret; int ret;
ret = nand_reset_data_interface(chip); ret = nand_reset_data_interface(chip, chipnr);
if (ret) if (ret)
return ret; return ret;
...@@ -1126,7 +1248,7 @@ int nand_reset(struct nand_chip *chip, int chipnr) ...@@ -1126,7 +1248,7 @@ int nand_reset(struct nand_chip *chip, int chipnr)
chip->select_chip(mtd, -1); chip->select_chip(mtd, -1);
chip->select_chip(mtd, chipnr); chip->select_chip(mtd, chipnr);
ret = nand_setup_data_interface(chip); ret = nand_setup_data_interface(chip, chipnr);
chip->select_chip(mtd, -1); chip->select_chip(mtd, -1);
if (ret) if (ret)
return ret; return ret;
...@@ -1134,178 +1256,6 @@ int nand_reset(struct nand_chip *chip, int chipnr) ...@@ -1134,178 +1256,6 @@ int nand_reset(struct nand_chip *chip, int chipnr)
return 0; return 0;
} }
/**
* __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
* @mtd: mtd info
* @ofs: offset to start unlock from
* @len: length to unlock
* @invert: when = 0, unlock the range of blocks within the lower and
* upper boundary address
* when = 1, unlock the range of blocks outside the boundaries
* of the lower and upper boundary address
*
* Returs unlock status.
*/
static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
uint64_t len, int invert)
{
int ret = 0;
int status, page;
struct nand_chip *chip = mtd_to_nand(mtd);
/* Submit address of first page to unlock */
page = ofs >> chip->page_shift;
chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask);
/* Submit address of last page to unlock */
page = (ofs + len) >> chip->page_shift;
chip->cmdfunc(mtd, NAND_CMD_UNLOCK2, -1,
(page | invert) & chip->pagemask);
/* Call wait ready function */
status = chip->waitfunc(mtd, chip);
/* See if device thinks it succeeded */
if (status & NAND_STATUS_FAIL) {
pr_debug("%s: error status = 0x%08x\n",
__func__, status);
ret = -EIO;
}
return ret;
}
/**
* nand_unlock - [REPLACEABLE] unlocks specified locked blocks
* @mtd: mtd info
* @ofs: offset to start unlock from
* @len: length to unlock
*
* Returns unlock status.
*/
int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret = 0;
int chipnr;
struct nand_chip *chip = mtd_to_nand(mtd);
pr_debug("%s: start = 0x%012llx, len = %llu\n",
__func__, (unsigned long long)ofs, len);
if (check_offs_len(mtd, ofs, len))
return -EINVAL;
/* Align to last block address if size addresses end of the device */
if (ofs + len == mtd->size)
len -= mtd->erasesize;
nand_get_device(mtd, FL_UNLOCKING);
/* Shift to get chip number */
chipnr = ofs >> chip->chip_shift;
/*
* Reset the chip.
* If we want to check the WP through READ STATUS and check the bit 7
* we must reset the chip
* some operation can also clear the bit 7 of status register
* eg. erase/program a locked block
*/
nand_reset(chip, chipnr);
chip->select_chip(mtd, chipnr);
/* Check, if it is write protected */
if (nand_check_wp(mtd)) {
pr_debug("%s: device is write protected!\n",
__func__);
ret = -EIO;
goto out;
}
ret = __nand_unlock(mtd, ofs, len, 0);
out:
chip->select_chip(mtd, -1);
nand_release_device(mtd);
return ret;
}
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
*
* 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)
{
int ret = 0;
int chipnr, status, page;
struct nand_chip *chip = mtd_to_nand(mtd);
pr_debug("%s: start = 0x%012llx, len = %llu\n",
__func__, (unsigned long long)ofs, len);
if (check_offs_len(mtd, ofs, len))
return -EINVAL;
nand_get_device(mtd, FL_LOCKING);
/* Shift to get chip number */
chipnr = ofs >> chip->chip_shift;
/*
* Reset the chip.
* If we want to check the WP through READ STATUS and check the bit 7
* we must reset the chip
* some operation can also clear the bit 7 of status register
* eg. erase/program a locked block
*/
nand_reset(chip, chipnr);
chip->select_chip(mtd, chipnr);
/* Check, if it is write protected */
if (nand_check_wp(mtd)) {
pr_debug("%s: device is write protected!\n",
__func__);
status = MTD_ERASE_FAILED;
ret = -EIO;
goto out;
}
/* Submit address of first page to lock */
page = ofs >> chip->page_shift;
chip->cmdfunc(mtd, NAND_CMD_LOCK, -1, page & chip->pagemask);
/* Call wait ready function */
status = chip->waitfunc(mtd, chip);
/* See if device thinks it succeeded */
if (status & NAND_STATUS_FAIL) {
pr_debug("%s: error status = 0x%08x\n",
__func__, status);
ret = -EIO;
goto out;
}
ret = __nand_unlock(mtd, ofs, len, 0x1);
out:
chip->select_chip(mtd, -1);
nand_release_device(mtd);
return ret;
}
EXPORT_SYMBOL(nand_lock);
/** /**
* nand_check_erased_buf - check if a buffer contains (almost) only 0xff data * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
* @buf: buffer to test * @buf: buffer to test
...@@ -1341,7 +1291,10 @@ static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold) ...@@ -1341,7 +1291,10 @@ static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold)
for (; len >= sizeof(long); for (; len >= sizeof(long);
len -= sizeof(long), bitmap += sizeof(long)) { len -= sizeof(long), bitmap += sizeof(long)) {
weight = hweight_long(*((unsigned long *)bitmap)); unsigned long d = *((unsigned long *)bitmap);
if (d == ~0UL)
continue;
weight = hweight_long(d);
bitflips += BITS_PER_LONG - weight; bitflips += BITS_PER_LONG - weight;
if (unlikely(bitflips > bitflips_threshold)) if (unlikely(bitflips > bitflips_threshold))
return -EBADMSG; return -EBADMSG;
...@@ -1444,14 +1397,15 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chunk); ...@@ -1444,14 +1397,15 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chunk);
* *
* 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, int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page) uint8_t *buf, int oob_required, int page)
{ {
chip->read_buf(mtd, buf, mtd->writesize); chip->read_buf(mtd, buf, mtd->writesize);
if (oob_required) if (oob_required)
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
return 0; return 0;
} }
EXPORT_SYMBOL(nand_read_page_raw);
/** /**
* nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc
...@@ -1944,7 +1898,9 @@ int nand_do_read_ops(struct mtd_info *mtd, loff_t from, ...@@ -1944,7 +1898,9 @@ int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
if (!aligned) if (!aligned)
use_bufpoi = 1; use_bufpoi = 1;
else if (chip->options & NAND_USE_BOUNCE_BUFFER) else if (chip->options & NAND_USE_BOUNCE_BUFFER)
use_bufpoi = !virt_addr_valid(buf); use_bufpoi = !virt_addr_valid(buf) ||
!IS_ALIGNED((unsigned long)buf,
chip->buf_align);
else else
use_bufpoi = 0; use_bufpoi = 0;
...@@ -1957,7 +1913,8 @@ int nand_do_read_ops(struct mtd_info *mtd, loff_t from, ...@@ -1957,7 +1913,8 @@ int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
__func__, buf); __func__, buf);
read_retry: read_retry:
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); if (nand_standard_page_accessors(&chip->ecc))
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
/* /*
* Now read the page into the buffer. Absent an error, * Now read the page into the buffer. Absent an error,
...@@ -1982,8 +1939,6 @@ read_retry: ...@@ -1982,8 +1939,6 @@ read_retry:
break; break;
} }
max_bitflips = max_t(unsigned int, max_bitflips, ret);
/* Transfer not aligned data */ /* Transfer not aligned data */
if (use_bufpoi) { if (use_bufpoi) {
if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
...@@ -2034,6 +1989,7 @@ read_retry: ...@@ -2034,6 +1989,7 @@ read_retry:
} }
buf += bytes; buf += bytes;
max_bitflips = max_t(unsigned int, max_bitflips, ret);
} else { } else {
memcpy(buf, chip->buffers->databuf + col, bytes); memcpy(buf, chip->buffers->databuf + col, bytes);
buf += bytes; buf += bytes;
...@@ -2389,8 +2345,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, ...@@ -2389,8 +2345,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
* *
* 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_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 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); chip->write_buf(mtd, buf, mtd->writesize);
if (oob_required) if (oob_required)
...@@ -2398,6 +2354,7 @@ static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2398,6 +2354,7 @@ static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
return 0; return 0;
} }
EXPORT_SYMBOL(nand_write_page_raw);
/** /**
* nand_write_page_raw_syndrome - [INTERN] raw page write function * nand_write_page_raw_syndrome - [INTERN] raw page write function
...@@ -2622,7 +2579,7 @@ static int nand_write_page_syndrome(struct mtd_info *mtd, ...@@ -2622,7 +2579,7 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
} }
/** /**
* nand_write_page - [REPLACEABLE] write one page * nand_write_page - write one page
* @mtd: MTD device structure * @mtd: MTD device structure
* @chip: NAND chip descriptor * @chip: NAND chip descriptor
* @offset: address offset within the page * @offset: address offset within the page
...@@ -2630,12 +2587,11 @@ static int nand_write_page_syndrome(struct mtd_info *mtd, ...@@ -2630,12 +2587,11 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
* @buf: the data to write * @buf: the data to write
* @oob_required: must write chip->oob_poi to OOB * @oob_required: must write chip->oob_poi to OOB
* @page: page number to write * @page: page number to write
* @cached: cached programming
* @raw: use _raw version of write_page * @raw: use _raw version of write_page
*/ */
static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offset, int data_len, const uint8_t *buf, uint32_t offset, int data_len, const uint8_t *buf,
int oob_required, int page, int cached, int raw) int oob_required, int page, int raw)
{ {
int status, subpage; int status, subpage;
...@@ -2645,7 +2601,8 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2645,7 +2601,8 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
else else
subpage = 0; subpage = 0;
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (nand_standard_page_accessors(&chip->ecc))
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
if (unlikely(raw)) if (unlikely(raw))
status = chip->ecc.write_page_raw(mtd, chip, buf, status = chip->ecc.write_page_raw(mtd, chip, buf,
...@@ -2660,29 +2617,12 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -2660,29 +2617,12 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
if (status < 0) if (status < 0)
return status; return status;
/* if (nand_standard_page_accessors(&chip->ecc)) {
* Cached progamming disabled for now. Not sure if it's worth the
* trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).
*/
cached = 0;
if (!cached || !NAND_HAS_CACHEPROG(chip)) {
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
status = chip->waitfunc(mtd, chip);
/*
* See if operation failed and additional status checks are
* available.
*/
if ((status & NAND_STATUS_FAIL) && (chip->errstat))
status = chip->errstat(mtd, chip, FL_WRITING, status,
page);
status = chip->waitfunc(mtd, chip);
if (status & NAND_STATUS_FAIL) if (status & NAND_STATUS_FAIL)
return -EIO; return -EIO;
} else {
chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
status = chip->waitfunc(mtd, chip);
} }
return 0; return 0;
...@@ -2742,7 +2682,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len, ...@@ -2742,7 +2682,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
int nand_do_write_ops(struct mtd_info *mtd, loff_t to, int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
{ {
int chipnr, realpage, page, blockmask, column; int chipnr, realpage, page, column;
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
uint32_t writelen = ops->len; uint32_t writelen = ops->len;
...@@ -2778,7 +2718,6 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2778,7 +2718,6 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
realpage = (int)(to >> chip->page_shift); realpage = (int)(to >> chip->page_shift);
page = realpage & chip->pagemask; page = realpage & chip->pagemask;
blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
/* Invalidate the page cache, when we write to the cached page */ /* Invalidate the page cache, when we write to the cached page */
if (to <= ((loff_t)chip->pagebuf << chip->page_shift) && if (to <= ((loff_t)chip->pagebuf << chip->page_shift) &&
...@@ -2793,7 +2732,6 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2793,7 +2732,6 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
while (1) { while (1) {
int bytes = mtd->writesize; int bytes = mtd->writesize;
int cached = writelen > bytes && page != blockmask;
uint8_t *wbuf = buf; uint8_t *wbuf = buf;
int use_bufpoi; int use_bufpoi;
int part_pagewr = (column || writelen < mtd->writesize); int part_pagewr = (column || writelen < mtd->writesize);
...@@ -2801,7 +2739,9 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2801,7 +2739,9 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
if (part_pagewr) if (part_pagewr)
use_bufpoi = 1; use_bufpoi = 1;
else if (chip->options & NAND_USE_BOUNCE_BUFFER) else if (chip->options & NAND_USE_BOUNCE_BUFFER)
use_bufpoi = !virt_addr_valid(buf); use_bufpoi = !virt_addr_valid(buf) ||
!IS_ALIGNED((unsigned long)buf,
chip->buf_align);
else else
use_bufpoi = 0; use_bufpoi = 0;
...@@ -2809,7 +2749,6 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2809,7 +2749,6 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
if (use_bufpoi) { if (use_bufpoi) {
pr_debug("%s: using write bounce buffer for buf@%p\n", pr_debug("%s: using write bounce buffer for buf@%p\n",
__func__, buf); __func__, buf);
cached = 0;
if (part_pagewr) if (part_pagewr)
bytes = min_t(int, bytes - column, writelen); bytes = min_t(int, bytes - column, writelen);
chip->pagebuf = -1; chip->pagebuf = -1;
...@@ -2826,9 +2765,10 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to, ...@@ -2826,9 +2765,10 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
/* We still need to erase leftover OOB data */ /* We still need to erase leftover OOB data */
memset(chip->oob_poi, 0xff, mtd->oobsize); memset(chip->oob_poi, 0xff, mtd->oobsize);
} }
ret = chip->write_page(mtd, chip, column, bytes, wbuf,
oob_required, page, cached, ret = nand_write_page(mtd, chip, column, bytes, wbuf,
(ops->mode == MTD_OPS_RAW)); oob_required, page,
(ops->mode == MTD_OPS_RAW));
if (ret) if (ret)
break; break;
...@@ -3153,14 +3093,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, ...@@ -3153,14 +3093,6 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
status = chip->erase(mtd, page & chip->pagemask); status = chip->erase(mtd, page & chip->pagemask);
/*
* See if operation failed and additional status checks are
* available
*/
if ((status & NAND_STATUS_FAIL) && (chip->errstat))
status = chip->errstat(mtd, chip, FL_ERASING,
status, page);
/* See if block erase succeeded */ /* See if block erase succeeded */
if (status & NAND_STATUS_FAIL) { if (status & NAND_STATUS_FAIL) {
pr_debug("%s: failed erase, page 0x%08x\n", pr_debug("%s: failed erase, page 0x%08x\n",
...@@ -3259,6 +3191,42 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) ...@@ -3259,6 +3191,42 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
return nand_block_markbad_lowlevel(mtd, ofs); return nand_block_markbad_lowlevel(mtd, ofs);
} }
/**
* nand_max_bad_blocks - [MTD Interface] Max number of bad blocks for an mtd
* @mtd: MTD device structure
* @ofs: offset relative to mtd start
* @len: length of mtd
*/
static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
{
struct nand_chip *chip = mtd_to_nand(mtd);
u32 part_start_block;
u32 part_end_block;
u32 part_start_die;
u32 part_end_die;
/*
* max_bb_per_die and blocks_per_die used to determine
* the maximum bad block count.
*/
if (!chip->max_bb_per_die || !chip->blocks_per_die)
return -ENOTSUPP;
/* Get the start and end of the partition in erase blocks. */
part_start_block = mtd_div_by_eb(ofs, mtd);
part_end_block = mtd_div_by_eb(len, mtd) + part_start_block - 1;
/* Get the start and end LUNs of the partition. */
part_start_die = part_start_block / chip->blocks_per_die;
part_end_die = part_end_block / chip->blocks_per_die;
/*
* Look up the bad blocks per unit and multiply by the number of units
* that the partition spans.
*/
return chip->max_bb_per_die * (part_end_die - part_start_die + 1);
}
/** /**
* nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand * nand_onfi_set_features- [REPLACEABLE] set features for ONFI nand
* @mtd: MTD device structure * @mtd: MTD device structure
...@@ -3310,6 +3278,25 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -3310,6 +3278,25 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
return 0; return 0;
} }
/**
* nand_onfi_get_set_features_notsupp - set/get features stub returning
* -ENOTSUPP
* @mtd: MTD device structure
* @chip: nand chip info structure
* @addr: feature address.
* @subfeature_param: the subfeature parameters, a four bytes array.
*
* Should be used by NAND controller drivers that do not support the SET/GET
* FEATURES operations.
*/
int nand_onfi_get_set_features_notsupp(struct mtd_info *mtd,
struct nand_chip *chip, int addr,
u8 *subfeature_param)
{
return -ENOTSUPP;
}
EXPORT_SYMBOL(nand_onfi_get_set_features_notsupp);
/** /**
* nand_suspend - [MTD Interface] Suspend the NAND flash * nand_suspend - [MTD Interface] Suspend the NAND flash
* @mtd: MTD device structure * @mtd: MTD device structure
...@@ -3345,8 +3332,10 @@ static void nand_shutdown(struct mtd_info *mtd) ...@@ -3345,8 +3332,10 @@ static void nand_shutdown(struct mtd_info *mtd)
} }
/* Set default functions */ /* Set default functions */
static void nand_set_defaults(struct nand_chip *chip, int busw) static void nand_set_defaults(struct nand_chip *chip)
{ {
unsigned int busw = chip->options & NAND_BUSWIDTH_16;
/* check for proper chip_delay setup, set 20us if not */ /* check for proper chip_delay setup, set 20us if not */
if (!chip->chip_delay) if (!chip->chip_delay)
chip->chip_delay = 20; chip->chip_delay = 20;
...@@ -3391,6 +3380,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) ...@@ -3391,6 +3380,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
nand_hw_control_init(chip->controller); nand_hw_control_init(chip->controller);
} }
if (!chip->buf_align)
chip->buf_align = 1;
} }
/* Sanitize ONFI strings so we can safely print them */ /* Sanitize ONFI strings so we can safely print them */
...@@ -3424,9 +3415,10 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) ...@@ -3424,9 +3415,10 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
} }
/* Parse the Extended Parameter Page. */ /* Parse the Extended Parameter Page. */
static int nand_flash_detect_ext_param_page(struct mtd_info *mtd, static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
struct nand_chip *chip, struct nand_onfi_params *p) struct nand_onfi_params *p)
{ {
struct mtd_info *mtd = nand_to_mtd(chip);
struct onfi_ext_param_page *ep; struct onfi_ext_param_page *ep;
struct onfi_ext_section *s; struct onfi_ext_section *s;
struct onfi_ext_ecc_info *ecc; struct onfi_ext_ecc_info *ecc;
...@@ -3494,36 +3486,12 @@ ext_out: ...@@ -3494,36 +3486,12 @@ ext_out:
return ret; return ret;
} }
static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
{
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,
feature);
}
/*
* Configure chip properties from Micron vendor-specific ONFI table
*/
static void nand_onfi_detect_micron(struct nand_chip *chip,
struct nand_onfi_params *p)
{
struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
if (le16_to_cpu(p->vendor_revision) < 1)
return;
chip->read_retries = micron->read_retry_options;
chip->setup_read_retry = nand_setup_read_retry_micron;
}
/* /*
* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
*/ */
static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, static int nand_flash_detect_onfi(struct nand_chip *chip)
int *busw)
{ {
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_onfi_params *p = &chip->onfi_params; struct nand_onfi_params *p = &chip->onfi_params;
int i, j; int i, j;
int val; int val;
...@@ -3595,10 +3563,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -3595,10 +3563,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
chip->bits_per_cell = p->bits_per_cell; chip->bits_per_cell = p->bits_per_cell;
chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun);
chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun);
if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS) if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
*busw = NAND_BUSWIDTH_16; chip->options |= NAND_BUSWIDTH_16;
else
*busw = 0;
if (p->ecc_bits != 0xff) { if (p->ecc_bits != 0xff) {
chip->ecc_strength_ds = p->ecc_bits; chip->ecc_strength_ds = p->ecc_bits;
...@@ -3616,24 +3585,21 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -3616,24 +3585,21 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
chip->cmdfunc = nand_command_lp; chip->cmdfunc = nand_command_lp;
/* The Extended Parameter Page is supported since ONFI 2.1. */ /* The Extended Parameter Page is supported since ONFI 2.1. */
if (nand_flash_detect_ext_param_page(mtd, chip, p)) if (nand_flash_detect_ext_param_page(chip, p))
pr_warn("Failed to detect ONFI extended param page\n"); pr_warn("Failed to detect ONFI extended param page\n");
} else { } else {
pr_warn("Could not retrieve ONFI ECC requirements\n"); pr_warn("Could not retrieve ONFI ECC requirements\n");
} }
if (p->jedec_id == NAND_MFR_MICRON)
nand_onfi_detect_micron(chip, p);
return 1; return 1;
} }
/* /*
* Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise.
*/ */
static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip, static int nand_flash_detect_jedec(struct nand_chip *chip)
int *busw)
{ {
struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_jedec_params *p = &chip->jedec_params; struct nand_jedec_params *p = &chip->jedec_params;
struct jedec_ecc_info *ecc; struct jedec_ecc_info *ecc;
int val; int val;
...@@ -3692,9 +3658,7 @@ static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -3692,9 +3658,7 @@ static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip,
chip->bits_per_cell = p->bits_per_cell; chip->bits_per_cell = p->bits_per_cell;
if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS) if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS)
*busw = NAND_BUSWIDTH_16; chip->options |= NAND_BUSWIDTH_16;
else
*busw = 0;
/* ECC info */ /* ECC info */
ecc = &p->ecc_info[0]; ecc = &p->ecc_info[0];
...@@ -3783,165 +3747,46 @@ static int nand_get_bits_per_cell(u8 cellinfo) ...@@ -3783,165 +3747,46 @@ static int nand_get_bits_per_cell(u8 cellinfo)
* chip. The rest of the parameters must be decoded according to generic or * chip. The rest of the parameters must be decoded according to generic or
* manufacturer-specific "extended ID" decoding patterns. * manufacturer-specific "extended ID" decoding patterns.
*/ */
static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, void nand_decode_ext_id(struct nand_chip *chip)
u8 id_data[8], int *busw)
{ {
int extid, id_len; struct mtd_info *mtd = nand_to_mtd(chip);
int extid;
u8 *id_data = chip->id.data;
/* The 3rd id byte holds MLC / multichip data */ /* The 3rd id byte holds MLC / multichip data */
chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
/* The 4th id byte is the important one */ /* The 4th id byte is the important one */
extid = id_data[3]; extid = id_data[3];
id_len = nand_id_len(id_data, 8); /* Calc pagesize */
mtd->writesize = 1024 << (extid & 0x03);
/* extid >>= 2;
* Field definitions are in the following datasheets: /* Calc oobsize */
* Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) extid >>= 2;
* Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) /* Calc blocksize. Blocksize is multiples of 64KiB */
* mtd->erasesize = (64 * 1024) << (extid & 0x03);
* Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung extid >>= 2;
* ID to decide what to do. /* Get buswidth information */
*/ if (extid & 0x1)
if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && chip->options |= NAND_BUSWIDTH_16;
!nand_is_slc(chip) && id_data[5] != 0x00) {
/* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2;
/* Calc oobsize */
switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
case 1:
mtd->oobsize = 128;
break;
case 2:
mtd->oobsize = 218;
break;
case 3:
mtd->oobsize = 400;
break;
case 4:
mtd->oobsize = 436;
break;
case 5:
mtd->oobsize = 512;
break;
case 6:
mtd->oobsize = 640;
break;
case 7:
default: /* Other cases are "reserved" (unknown) */
mtd->oobsize = 1024;
break;
}
extid >>= 2;
/* Calc blocksize */
mtd->erasesize = (128 * 1024) <<
(((extid >> 1) & 0x04) | (extid & 0x03));
*busw = 0;
} else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
!nand_is_slc(chip)) {
unsigned int tmp;
/* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2;
/* Calc oobsize */
switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
case 0:
mtd->oobsize = 128;
break;
case 1:
mtd->oobsize = 224;
break;
case 2:
mtd->oobsize = 448;
break;
case 3:
mtd->oobsize = 64;
break;
case 4:
mtd->oobsize = 32;
break;
case 5:
mtd->oobsize = 16;
break;
default:
mtd->oobsize = 640;
break;
}
extid >>= 2;
/* Calc blocksize */
tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
if (tmp < 0x03)
mtd->erasesize = (128 * 1024) << tmp;
else if (tmp == 0x03)
mtd->erasesize = 768 * 1024;
else
mtd->erasesize = (64 * 1024) << tmp;
*busw = 0;
} else {
/* Calc pagesize */
mtd->writesize = 1024 << (extid & 0x03);
extid >>= 2;
/* Calc oobsize */
mtd->oobsize = (8 << (extid & 0x01)) *
(mtd->writesize >> 9);
extid >>= 2;
/* Calc blocksize. Blocksize is multiples of 64KiB */
mtd->erasesize = (64 * 1024) << (extid & 0x03);
extid >>= 2;
/* Get buswidth information */
*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
/*
* Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
* 512B page. For Toshiba SLC, we decode the 5th/6th byte as
* follows:
* - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
* 110b -> 24nm
* - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC
*/
if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
nand_is_slc(chip) &&
(id_data[5] & 0x7) == 0x6 /* 24nm */ &&
!(id_data[4] & 0x80) /* !BENAND */) {
mtd->oobsize = 32 * mtd->writesize >> 9;
}
}
} }
EXPORT_SYMBOL_GPL(nand_decode_ext_id);
/* /*
* Old devices have chip data hardcoded in the device ID table. nand_decode_id * Old devices have chip data hardcoded in the device ID table. nand_decode_id
* decodes a matching ID table entry and assigns the MTD size parameters for * decodes a matching ID table entry and assigns the MTD size parameters for
* the chip. * the chip.
*/ */
static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
struct nand_flash_dev *type, u8 id_data[8],
int *busw)
{ {
int maf_id = id_data[0]; struct mtd_info *mtd = nand_to_mtd(chip);
mtd->erasesize = type->erasesize; mtd->erasesize = type->erasesize;
mtd->writesize = type->pagesize; mtd->writesize = type->pagesize;
mtd->oobsize = mtd->writesize / 32; mtd->oobsize = mtd->writesize / 32;
*busw = type->options & NAND_BUSWIDTH_16;
/* All legacy ID NAND are small-page, SLC */ /* All legacy ID NAND are small-page, SLC */
chip->bits_per_cell = 1; chip->bits_per_cell = 1;
/*
* Check for Spansion/AMD ID + repeating 5th, 6th byte since
* some Spansion chips have erasesize that conflicts with size
* 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 && id_data[5] == 0x00
&& id_data[6] == 0x00 && id_data[7] == 0x00
&& mtd->writesize == 512) {
mtd->erasesize = 128 * 1024;
mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
}
} }
/* /*
...@@ -3949,36 +3794,15 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -3949,36 +3794,15 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
* heuristic patterns using various detected parameters (e.g., manufacturer, * heuristic patterns using various detected parameters (e.g., manufacturer,
* page size, cell-type information). * page size, cell-type information).
*/ */
static void nand_decode_bbm_options(struct mtd_info *mtd, static void nand_decode_bbm_options(struct nand_chip *chip)
struct nand_chip *chip, u8 id_data[8])
{ {
int maf_id = id_data[0]; struct mtd_info *mtd = nand_to_mtd(chip);
/* Set the bad block position */ /* Set the bad block position */
if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16)) if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
chip->badblockpos = NAND_LARGE_BADBLOCK_POS; chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
else else
chip->badblockpos = NAND_SMALL_BADBLOCK_POS; chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
/*
* Bad block marker is stored in the last page of each block on Samsung
* and Hynix MLC devices; stored in first two pages of each block on
* Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
* AMD/Spansion, and Macronix. All others scan only the first page.
*/
if (!nand_is_slc(chip) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX))
chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
else if ((nand_is_slc(chip) &&
(maf_id == NAND_MFR_SAMSUNG ||
maf_id == NAND_MFR_HYNIX ||
maf_id == NAND_MFR_TOSHIBA ||
maf_id == NAND_MFR_AMD ||
maf_id == NAND_MFR_MACRONIX)) ||
(mtd->writesize == 2048 &&
maf_id == NAND_MFR_MICRON))
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
} }
static inline bool is_full_id_nand(struct nand_flash_dev *type) static inline bool is_full_id_nand(struct nand_flash_dev *type)
...@@ -3986,9 +3810,12 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type) ...@@ -3986,9 +3810,12 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type)
return type->id_len; return type->id_len;
} }
static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, static bool find_full_id_nand(struct nand_chip *chip,
struct nand_flash_dev *type, u8 *id_data, int *busw) struct nand_flash_dev *type)
{ {
struct mtd_info *mtd = nand_to_mtd(chip);
u8 *id_data = chip->id.data;
if (!strncmp(type->id, id_data, type->id_len)) { if (!strncmp(type->id, id_data, type->id_len)) {
mtd->writesize = type->pagesize; mtd->writesize = type->pagesize;
mtd->erasesize = type->erasesize; mtd->erasesize = type->erasesize;
...@@ -4002,8 +3829,6 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -4002,8 +3829,6 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
chip->onfi_timing_mode_default = chip->onfi_timing_mode_default =
type->onfi_timing_mode_default; type->onfi_timing_mode_default;
*busw = type->options & NAND_BUSWIDTH_16;
if (!mtd->name) if (!mtd->name)
mtd->name = type->name; mtd->name = type->name;
...@@ -4012,17 +3837,67 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, ...@@ -4012,17 +3837,67 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
return false; return false;
} }
/*
* Manufacturer detection. Only used when the NAND is not ONFI or JEDEC
* compliant and does not have a full-id or legacy-id entry in the nand_ids
* table.
*/
static void nand_manufacturer_detect(struct nand_chip *chip)
{
/*
* Try manufacturer detection if available and use
* nand_decode_ext_id() otherwise.
*/
if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
chip->manufacturer.desc->ops->detect) {
/* The 3rd id byte holds MLC / multichip data */
chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
chip->manufacturer.desc->ops->detect(chip);
} else {
nand_decode_ext_id(chip);
}
}
/*
* Manufacturer initialization. This function is called for all NANDs including
* ONFI and JEDEC compliant ones.
* Manufacturer drivers should put all their specific initialization code in
* their ->init() hook.
*/
static int nand_manufacturer_init(struct nand_chip *chip)
{
if (!chip->manufacturer.desc || !chip->manufacturer.desc->ops ||
!chip->manufacturer.desc->ops->init)
return 0;
return chip->manufacturer.desc->ops->init(chip);
}
/*
* Manufacturer cleanup. This function is called for all NANDs including
* ONFI and JEDEC compliant ones.
* Manufacturer drivers should put all their specific cleanup code in their
* ->cleanup() hook.
*/
static void nand_manufacturer_cleanup(struct nand_chip *chip)
{
/* Release manufacturer private data */
if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
chip->manufacturer.desc->ops->cleanup)
chip->manufacturer.desc->ops->cleanup(chip);
}
/* /*
* Get the flash and manufacturer id and lookup if the type is supported. * Get the flash and manufacturer id and lookup if the type is supported.
*/ */
static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
struct nand_chip *chip,
int *maf_id, int *dev_id,
struct nand_flash_dev *type)
{ {
const struct nand_manufacturer *manufacturer;
struct mtd_info *mtd = nand_to_mtd(chip);
int busw; int busw;
int i, maf_idx; int i;
u8 id_data[8]; u8 *id_data = chip->id.data;
u8 maf_id, dev_id;
/* /*
* Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
...@@ -4037,8 +3912,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, ...@@ -4037,8 +3912,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read manufacturer and device IDs */ /* Read manufacturer and device IDs */
*maf_id = chip->read_byte(mtd); maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd); dev_id = chip->read_byte(mtd);
/* /*
* Try again to make sure, as some systems the bus-hold or other * Try again to make sure, as some systems the bus-hold or other
...@@ -4050,23 +3925,44 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, ...@@ -4050,23 +3925,44 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
/* Read entire ID string */ /* Read entire ID string */
for (i = 0; i < 8; i++) for (i = 0; i < ARRAY_SIZE(chip->id.data); i++)
id_data[i] = chip->read_byte(mtd); id_data[i] = chip->read_byte(mtd);
if (id_data[0] != *maf_id || id_data[1] != *dev_id) { if (id_data[0] != maf_id || id_data[1] != dev_id) {
pr_info("second ID read did not match %02x,%02x against %02x,%02x\n", pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
*maf_id, *dev_id, id_data[0], id_data[1]); maf_id, dev_id, id_data[0], id_data[1]);
return ERR_PTR(-ENODEV); return -ENODEV;
} }
chip->id.len = nand_id_len(id_data, ARRAY_SIZE(chip->id.data));
/* Try to identify manufacturer */
manufacturer = nand_get_manufacturer(maf_id);
chip->manufacturer.desc = manufacturer;
if (!type) if (!type)
type = nand_flash_ids; type = nand_flash_ids;
/*
* Save the NAND_BUSWIDTH_16 flag before letting auto-detection logic
* override it.
* This is required to make sure initial NAND bus width set by the
* NAND controller driver is coherent with the real NAND bus width
* (extracted by auto-detection code).
*/
busw = chip->options & NAND_BUSWIDTH_16;
/*
* The flag is only set (never cleared), reset it to its default value
* before starting auto-detection.
*/
chip->options &= ~NAND_BUSWIDTH_16;
for (; type->name != NULL; type++) { for (; type->name != NULL; type++) {
if (is_full_id_nand(type)) { if (is_full_id_nand(type)) {
if (find_full_id_nand(mtd, chip, type, id_data, &busw)) if (find_full_id_nand(chip, type))
goto ident_done; goto ident_done;
} else if (*dev_id == type->dev_id) { } else if (dev_id == type->dev_id) {
break; break;
} }
} }
...@@ -4074,64 +3970,50 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, ...@@ -4074,64 +3970,50 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->onfi_version = 0; chip->onfi_version = 0;
if (!type->name || !type->pagesize) { if (!type->name || !type->pagesize) {
/* Check if the chip is ONFI compliant */ /* Check if the chip is ONFI compliant */
if (nand_flash_detect_onfi(mtd, chip, &busw)) if (nand_flash_detect_onfi(chip))
goto ident_done; goto ident_done;
/* Check if the chip is JEDEC compliant */ /* Check if the chip is JEDEC compliant */
if (nand_flash_detect_jedec(mtd, chip, &busw)) if (nand_flash_detect_jedec(chip))
goto ident_done; goto ident_done;
} }
if (!type->name) if (!type->name)
return ERR_PTR(-ENODEV); return -ENODEV;
if (!mtd->name) if (!mtd->name)
mtd->name = type->name; mtd->name = type->name;
chip->chipsize = (uint64_t)type->chipsize << 20; chip->chipsize = (uint64_t)type->chipsize << 20;
if (!type->pagesize) { if (!type->pagesize)
/* Decode parameters from extended ID */ nand_manufacturer_detect(chip);
nand_decode_ext_id(mtd, chip, id_data, &busw); else
} else { nand_decode_id(chip, type);
nand_decode_id(mtd, chip, type, id_data, &busw);
}
/* Get chip options */ /* Get chip options */
chip->options |= type->options; chip->options |= type->options;
/*
* 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: ident_done:
/* Try to identify manufacturer */
for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
if (nand_manuf_ids[maf_idx].id == *maf_id)
break;
}
if (chip->options & NAND_BUSWIDTH_AUTO) { if (chip->options & NAND_BUSWIDTH_AUTO) {
WARN_ON(chip->options & NAND_BUSWIDTH_16); WARN_ON(busw & NAND_BUSWIDTH_16);
chip->options |= busw; nand_set_defaults(chip);
nand_set_defaults(chip, busw);
} else if (busw != (chip->options & NAND_BUSWIDTH_16)) { } else if (busw != (chip->options & NAND_BUSWIDTH_16)) {
/* /*
* Check, if buswidth is correct. Hardware drivers should set * Check, if buswidth is correct. Hardware drivers should set
* chip correct! * chip correct!
*/ */
pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
*maf_id, *dev_id); maf_id, dev_id);
pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name); pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
pr_warn("bus width %d instead %d bit\n", mtd->name);
(chip->options & NAND_BUSWIDTH_16) ? 16 : 8, pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8,
busw ? 16 : 8); (chip->options & NAND_BUSWIDTH_16) ? 16 : 8);
return ERR_PTR(-EINVAL); return -EINVAL;
} }
nand_decode_bbm_options(mtd, chip, id_data); nand_decode_bbm_options(chip);
/* Calculate the address shift from the page size */ /* Calculate the address shift from the page size */
chip->page_shift = ffs(mtd->writesize) - 1; chip->page_shift = ffs(mtd->writesize) - 1;
...@@ -4154,25 +4036,23 @@ ident_done: ...@@ -4154,25 +4036,23 @@ ident_done:
if (mtd->writesize > 512 && chip->cmdfunc == nand_command) if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
chip->cmdfunc = nand_command_lp; chip->cmdfunc = nand_command_lp;
if (*maf_id == NAND_MFR_MICRON) nandchip_micron_init(mtd, *dev_id);
pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
*maf_id, *dev_id); maf_id, dev_id);
if (chip->onfi_version) if (chip->onfi_version)
pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
chip->onfi_params.model); chip->onfi_params.model);
else if (chip->jedec_version) else if (chip->jedec_version)
pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
chip->jedec_params.model); chip->jedec_params.model);
else else
pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
type->name); type->name);
pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
mtd->erasesize >> 10, mtd->writesize, mtd->oobsize); mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
return type; return 0;
} }
static const char * const nand_ecc_modes[] = { static const char * const nand_ecc_modes[] = {
...@@ -4181,6 +4061,7 @@ static const char * const nand_ecc_modes[] = { ...@@ -4181,6 +4061,7 @@ static const char * const nand_ecc_modes[] = {
[NAND_ECC_HW] = "hw", [NAND_ECC_HW] = "hw",
[NAND_ECC_HW_SYNDROME] = "hw_syndrome", [NAND_ECC_HW_SYNDROME] = "hw_syndrome",
[NAND_ECC_HW_OOB_FIRST] = "hw_oob_first", [NAND_ECC_HW_OOB_FIRST] = "hw_oob_first",
[NAND_ECC_ON_DIE] = "on-die",
}; };
static int of_get_nand_ecc_mode(struct device_node *np) static int of_get_nand_ecc_mode(struct device_node *np)
...@@ -4299,12 +4180,6 @@ static int nand_dt_init(struct nand_chip *chip) ...@@ -4299,12 +4180,6 @@ static int nand_dt_init(struct nand_chip *chip)
ecc_strength = of_get_nand_ecc_strength(dn); ecc_strength = of_get_nand_ecc_strength(dn);
ecc_step = of_get_nand_ecc_step_size(dn); ecc_step = of_get_nand_ecc_step_size(dn);
if ((ecc_step >= 0 && !(ecc_strength >= 0)) ||
(!(ecc_step >= 0) && ecc_strength >= 0)) {
pr_err("must set both strength and step size in DT\n");
return -EINVAL;
}
if (ecc_mode >= 0) if (ecc_mode >= 0)
chip->ecc.mode = ecc_mode; chip->ecc.mode = ecc_mode;
...@@ -4338,7 +4213,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, ...@@ -4338,7 +4213,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
{ {
int i, nand_maf_id, nand_dev_id; int i, nand_maf_id, nand_dev_id;
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_flash_dev *type;
int ret; int ret;
ret = nand_dt_init(chip); ret = nand_dt_init(chip);
...@@ -4358,35 +4232,19 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, ...@@ -4358,35 +4232,19 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
return -EINVAL; return -EINVAL;
} }
/* Set the default functions */ /* Set the default functions */
nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); nand_set_defaults(chip);
/* Read the flash type */ /* Read the flash type */
type = nand_get_flash_type(mtd, chip, &nand_maf_id, ret = nand_detect(chip, table);
&nand_dev_id, table); if (ret) {
if (IS_ERR(type)) {
if (!(chip->options & NAND_SCAN_SILENT_NODEV)) if (!(chip->options & NAND_SCAN_SILENT_NODEV))
pr_warn("No NAND device found\n"); pr_warn("No NAND device found\n");
chip->select_chip(mtd, -1); chip->select_chip(mtd, -1);
return PTR_ERR(type); return ret;
} }
/* Initialize the ->data_interface field. */ nand_maf_id = chip->id.data[0];
ret = nand_init_data_interface(chip); nand_dev_id = chip->id.data[1];
if (ret)
return ret;
/*
* Setup the data interface correctly on the chip and controller side.
* This explicit call to nand_setup_data_interface() is only required
* for the first die, because nand_reset() has been called before
* ->data_interface and ->default_onfi_timing_mode were set.
* For the other dies, nand_reset() will automatically switch to the
* best mode for us.
*/
ret = nand_setup_data_interface(chip);
if (ret)
return ret;
chip->select_chip(mtd, -1); chip->select_chip(mtd, -1);
...@@ -4513,6 +4371,226 @@ static int nand_set_ecc_soft_ops(struct mtd_info *mtd) ...@@ -4513,6 +4371,226 @@ static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
} }
} }
/**
* nand_check_ecc_caps - check the sanity of preset ECC settings
* @chip: nand chip info structure
* @caps: ECC caps info structure
* @oobavail: OOB size that the ECC engine can use
*
* When ECC step size and strength are already set, check if they are supported
* by the controller and the calculated ECC bytes fit within the chip's OOB.
* On success, the calculated ECC bytes is set.
*/
int nand_check_ecc_caps(struct nand_chip *chip,
const struct nand_ecc_caps *caps, int oobavail)
{
struct mtd_info *mtd = nand_to_mtd(chip);
const struct nand_ecc_step_info *stepinfo;
int preset_step = chip->ecc.size;
int preset_strength = chip->ecc.strength;
int nsteps, ecc_bytes;
int i, j;
if (WARN_ON(oobavail < 0))
return -EINVAL;
if (!preset_step || !preset_strength)
return -ENODATA;
nsteps = mtd->writesize / preset_step;
for (i = 0; i < caps->nstepinfos; i++) {
stepinfo = &caps->stepinfos[i];
if (stepinfo->stepsize != preset_step)
continue;
for (j = 0; j < stepinfo->nstrengths; j++) {
if (stepinfo->strengths[j] != preset_strength)
continue;
ecc_bytes = caps->calc_ecc_bytes(preset_step,
preset_strength);
if (WARN_ON_ONCE(ecc_bytes < 0))
return ecc_bytes;
if (ecc_bytes * nsteps > oobavail) {
pr_err("ECC (step, strength) = (%d, %d) does not fit in OOB",
preset_step, preset_strength);
return -ENOSPC;
}
chip->ecc.bytes = ecc_bytes;
return 0;
}
}
pr_err("ECC (step, strength) = (%d, %d) not supported on this controller",
preset_step, preset_strength);
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(nand_check_ecc_caps);
/**
* nand_match_ecc_req - meet the chip's requirement with least ECC bytes
* @chip: nand chip info structure
* @caps: ECC engine caps info structure
* @oobavail: OOB size that the ECC engine can use
*
* If a chip's ECC requirement is provided, try to meet it with the least
* number of ECC bytes (i.e. with the largest number of OOB-free bytes).
* On success, the chosen ECC settings are set.
*/
int nand_match_ecc_req(struct nand_chip *chip,
const struct nand_ecc_caps *caps, int oobavail)
{
struct mtd_info *mtd = nand_to_mtd(chip);
const struct nand_ecc_step_info *stepinfo;
int req_step = chip->ecc_step_ds;
int req_strength = chip->ecc_strength_ds;
int req_corr, step_size, strength, nsteps, ecc_bytes, ecc_bytes_total;
int best_step, best_strength, best_ecc_bytes;
int best_ecc_bytes_total = INT_MAX;
int i, j;
if (WARN_ON(oobavail < 0))
return -EINVAL;
/* No information provided by the NAND chip */
if (!req_step || !req_strength)
return -ENOTSUPP;
/* number of correctable bits the chip requires in a page */
req_corr = mtd->writesize / req_step * req_strength;
for (i = 0; i < caps->nstepinfos; i++) {
stepinfo = &caps->stepinfos[i];
step_size = stepinfo->stepsize;
for (j = 0; j < stepinfo->nstrengths; j++) {
strength = stepinfo->strengths[j];
/*
* If both step size and strength are smaller than the
* chip's requirement, it is not easy to compare the
* resulted reliability.
*/
if (step_size < req_step && strength < req_strength)
continue;
if (mtd->writesize % step_size)
continue;
nsteps = mtd->writesize / step_size;
ecc_bytes = caps->calc_ecc_bytes(step_size, strength);
if (WARN_ON_ONCE(ecc_bytes < 0))
continue;
ecc_bytes_total = ecc_bytes * nsteps;
if (ecc_bytes_total > oobavail ||
strength * nsteps < req_corr)
continue;
/*
* We assume the best is to meet the chip's requrement
* with the least number of ECC bytes.
*/
if (ecc_bytes_total < best_ecc_bytes_total) {
best_ecc_bytes_total = ecc_bytes_total;
best_step = step_size;
best_strength = strength;
best_ecc_bytes = ecc_bytes;
}
}
}
if (best_ecc_bytes_total == INT_MAX)
return -ENOTSUPP;
chip->ecc.size = best_step;
chip->ecc.strength = best_strength;
chip->ecc.bytes = best_ecc_bytes;
return 0;
}
EXPORT_SYMBOL_GPL(nand_match_ecc_req);
/**
* nand_maximize_ecc - choose the max ECC strength available
* @chip: nand chip info structure
* @caps: ECC engine caps info structure
* @oobavail: OOB size that the ECC engine can use
*
* Choose the max ECC strength that is supported on the controller, and can fit
* within the chip's OOB. On success, the chosen ECC settings are set.
*/
int nand_maximize_ecc(struct nand_chip *chip,
const struct nand_ecc_caps *caps, int oobavail)
{
struct mtd_info *mtd = nand_to_mtd(chip);
const struct nand_ecc_step_info *stepinfo;
int step_size, strength, nsteps, ecc_bytes, corr;
int best_corr = 0;
int best_step = 0;
int best_strength, best_ecc_bytes;
int i, j;
if (WARN_ON(oobavail < 0))
return -EINVAL;
for (i = 0; i < caps->nstepinfos; i++) {
stepinfo = &caps->stepinfos[i];
step_size = stepinfo->stepsize;
/* If chip->ecc.size is already set, respect it */
if (chip->ecc.size && step_size != chip->ecc.size)
continue;
for (j = 0; j < stepinfo->nstrengths; j++) {
strength = stepinfo->strengths[j];
if (mtd->writesize % step_size)
continue;
nsteps = mtd->writesize / step_size;
ecc_bytes = caps->calc_ecc_bytes(step_size, strength);
if (WARN_ON_ONCE(ecc_bytes < 0))
continue;
if (ecc_bytes * nsteps > oobavail)
continue;
corr = strength * nsteps;
/*
* If the number of correctable bits is the same,
* bigger step_size has more reliability.
*/
if (corr > best_corr ||
(corr == best_corr && step_size > best_step)) {
best_corr = corr;
best_step = step_size;
best_strength = strength;
best_ecc_bytes = ecc_bytes;
}
}
}
if (!best_corr)
return -ENOTSUPP;
chip->ecc.size = best_step;
chip->ecc.strength = best_strength;
chip->ecc.bytes = best_ecc_bytes;
return 0;
}
EXPORT_SYMBOL_GPL(nand_maximize_ecc);
/* /*
* Check if the chip configuration meet the datasheet requirements. * Check if the chip configuration meet the datasheet requirements.
...@@ -4547,6 +4625,26 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd) ...@@ -4547,6 +4625,26 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds; return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds;
} }
static bool invalid_ecc_page_accessors(struct nand_chip *chip)
{
struct nand_ecc_ctrl *ecc = &chip->ecc;
if (nand_standard_page_accessors(ecc))
return false;
/*
* NAND_ECC_CUSTOM_PAGE_ACCESS flag is set, make sure the NAND
* controller driver implements all the page accessors because
* default helpers are not suitable when the core does not
* send the READ0/PAGEPROG commands.
*/
return (!ecc->read_page || !ecc->write_page ||
!ecc->read_page_raw || !ecc->write_page_raw ||
(NAND_HAS_SUBPAGE_READ(chip) && !ecc->read_subpage) ||
(NAND_HAS_SUBPAGE_WRITE(chip) && !ecc->write_subpage &&
ecc->hwctl && ecc->calculate));
}
/** /**
* nand_scan_tail - [NAND Interface] Scan for the NAND device * nand_scan_tail - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure * @mtd: MTD device structure
...@@ -4559,29 +4657,61 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4559,29 +4657,61 @@ int nand_scan_tail(struct mtd_info *mtd)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_ecc_ctrl *ecc = &chip->ecc;
struct nand_buffers *nbuf; struct nand_buffers *nbuf = NULL;
int ret; int ret, i;
/* New bad blocks should be marked in OOB, flash-based BBT, or both */ /* New bad blocks should be marked in OOB, flash-based BBT, or both */
if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
!(chip->bbt_options & NAND_BBT_USE_FLASH))) !(chip->bbt_options & NAND_BBT_USE_FLASH))) {
return -EINVAL;
}
if (invalid_ecc_page_accessors(chip)) {
pr_err("Invalid ECC page accessors setup\n");
return -EINVAL; return -EINVAL;
}
if (!(chip->options & NAND_OWN_BUFFERS)) { if (!(chip->options & NAND_OWN_BUFFERS)) {
nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
+ mtd->oobsize * 3, GFP_KERNEL);
if (!nbuf) if (!nbuf)
return -ENOMEM; return -ENOMEM;
nbuf->ecccalc = (uint8_t *)(nbuf + 1);
nbuf->ecccode = nbuf->ecccalc + mtd->oobsize; nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
nbuf->databuf = nbuf->ecccode + mtd->oobsize; if (!nbuf->ecccalc) {
ret = -ENOMEM;
goto err_free_nbuf;
}
nbuf->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
if (!nbuf->ecccode) {
ret = -ENOMEM;
goto err_free_nbuf;
}
nbuf->databuf = kmalloc(mtd->writesize + mtd->oobsize,
GFP_KERNEL);
if (!nbuf->databuf) {
ret = -ENOMEM;
goto err_free_nbuf;
}
chip->buffers = nbuf; chip->buffers = nbuf;
} else { } else if (!chip->buffers) {
if (!chip->buffers) return -ENOMEM;
return -ENOMEM;
} }
/*
* FIXME: some NAND manufacturer drivers expect the first die to be
* selected when manufacturer->init() is called. They should be fixed
* to explictly select the relevant die when interacting with the NAND
* chip.
*/
chip->select_chip(mtd, 0);
ret = nand_manufacturer_init(chip);
chip->select_chip(mtd, -1);
if (ret)
goto err_free_nbuf;
/* Set the internal oob buffer location, just after the page data */ /* Set the internal oob buffer location, just after the page data */
chip->oob_poi = chip->buffers->databuf + mtd->writesize; chip->oob_poi = chip->buffers->databuf + mtd->writesize;
...@@ -4597,19 +4727,16 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4597,19 +4727,16 @@ int nand_scan_tail(struct mtd_info *mtd)
break; break;
case 64: case 64:
case 128: case 128:
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
break; break;
default: default:
WARN(1, "No oob scheme defined for oobsize %d\n", WARN(1, "No oob scheme defined for oobsize %d\n",
mtd->oobsize); mtd->oobsize);
ret = -EINVAL; ret = -EINVAL;
goto err_free; goto err_nand_manuf_cleanup;
} }
} }
if (!chip->write_page)
chip->write_page = nand_write_page;
/* /*
* Check ECC mode, default to software if 3byte/512byte hardware ECC is * Check ECC mode, default to software if 3byte/512byte hardware ECC is
* selected and we have 256 byte pagesize fallback to software ECC * selected and we have 256 byte pagesize fallback to software ECC
...@@ -4621,7 +4748,7 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4621,7 +4748,7 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!ecc->calculate || !ecc->correct || !ecc->hwctl) { if (!ecc->calculate || !ecc->correct || !ecc->hwctl) {
WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); WARN(1, "No ECC functions supplied; hardware ECC not possible\n");
ret = -EINVAL; ret = -EINVAL;
goto err_free; goto err_nand_manuf_cleanup;
} }
if (!ecc->read_page) if (!ecc->read_page)
ecc->read_page = nand_read_page_hwecc_oob_first; ecc->read_page = nand_read_page_hwecc_oob_first;
...@@ -4653,7 +4780,7 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4653,7 +4780,7 @@ int nand_scan_tail(struct mtd_info *mtd)
ecc->write_page == nand_write_page_hwecc)) { ecc->write_page == nand_write_page_hwecc)) {
WARN(1, "No ECC functions supplied; hardware ECC not possible\n"); WARN(1, "No ECC functions supplied; hardware ECC not possible\n");
ret = -EINVAL; ret = -EINVAL;
goto err_free; goto err_nand_manuf_cleanup;
} }
/* Use standard syndrome read/write page function? */ /* Use standard syndrome read/write page function? */
if (!ecc->read_page) if (!ecc->read_page)
...@@ -4673,7 +4800,7 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4673,7 +4800,7 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!ecc->strength) { if (!ecc->strength) {
WARN(1, "Driver must set ecc.strength when using hardware ECC\n"); WARN(1, "Driver must set ecc.strength when using hardware ECC\n");
ret = -EINVAL; ret = -EINVAL;
goto err_free; goto err_nand_manuf_cleanup;
} }
break; break;
} }
...@@ -4686,8 +4813,20 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4686,8 +4813,20 @@ int nand_scan_tail(struct mtd_info *mtd)
ret = nand_set_ecc_soft_ops(mtd); ret = nand_set_ecc_soft_ops(mtd);
if (ret) { if (ret) {
ret = -EINVAL; ret = -EINVAL;
goto err_free; goto err_nand_manuf_cleanup;
}
break;
case NAND_ECC_ON_DIE:
if (!ecc->read_page || !ecc->write_page) {
WARN(1, "No ECC functions supplied; on-die ECC not possible\n");
ret = -EINVAL;
goto err_nand_manuf_cleanup;
} }
if (!ecc->read_oob)
ecc->read_oob = nand_read_oob_std;
if (!ecc->write_oob)
ecc->write_oob = nand_write_oob_std;
break; break;
case NAND_ECC_NONE: case NAND_ECC_NONE:
...@@ -4706,7 +4845,7 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4706,7 +4845,7 @@ int nand_scan_tail(struct mtd_info *mtd)
default: default:
WARN(1, "Invalid NAND_ECC_MODE %d\n", ecc->mode); WARN(1, "Invalid NAND_ECC_MODE %d\n", ecc->mode);
ret = -EINVAL; ret = -EINVAL;
goto err_free; goto err_nand_manuf_cleanup;
} }
/* For many systems, the standard OOB write also works for raw */ /* For many systems, the standard OOB write also works for raw */
...@@ -4727,9 +4866,14 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4727,9 +4866,14 @@ int nand_scan_tail(struct mtd_info *mtd)
if (ecc->steps * ecc->size != mtd->writesize) { if (ecc->steps * ecc->size != mtd->writesize) {
WARN(1, "Invalid ECC parameters\n"); WARN(1, "Invalid ECC parameters\n");
ret = -EINVAL; ret = -EINVAL;
goto err_free; goto err_nand_manuf_cleanup;
} }
ecc->total = ecc->steps * ecc->bytes; ecc->total = ecc->steps * ecc->bytes;
if (ecc->total > mtd->oobsize) {
WARN(1, "Total number of ECC bytes exceeded oobsize\n");
ret = -EINVAL;
goto err_nand_manuf_cleanup;
}
/* /*
* The number of bytes available for a client to place data into * The number of bytes available for a client to place data into
...@@ -4799,6 +4943,7 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4799,6 +4943,7 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->_block_isreserved = nand_block_isreserved; mtd->_block_isreserved = nand_block_isreserved;
mtd->_block_isbad = nand_block_isbad; mtd->_block_isbad = nand_block_isbad;
mtd->_block_markbad = nand_block_markbad; mtd->_block_markbad = nand_block_markbad;
mtd->_max_bad_blocks = nand_max_bad_blocks;
mtd->writebufsize = mtd->writesize; mtd->writebufsize = mtd->writesize;
/* /*
...@@ -4809,15 +4954,46 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4809,15 +4954,46 @@ int nand_scan_tail(struct mtd_info *mtd)
if (!mtd->bitflip_threshold) if (!mtd->bitflip_threshold)
mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4); mtd->bitflip_threshold = DIV_ROUND_UP(mtd->ecc_strength * 3, 4);
/* Initialize the ->data_interface field. */
ret = nand_init_data_interface(chip);
if (ret)
goto err_nand_manuf_cleanup;
/* Enter fastest possible mode on all dies. */
for (i = 0; i < chip->numchips; i++) {
chip->select_chip(mtd, i);
ret = nand_setup_data_interface(chip, i);
chip->select_chip(mtd, -1);
if (ret)
goto err_nand_data_iface_cleanup;
}
/* Check, if we should skip the bad block table scan */ /* Check, if we should skip the bad block table scan */
if (chip->options & NAND_SKIP_BBTSCAN) if (chip->options & NAND_SKIP_BBTSCAN)
return 0; return 0;
/* Build bad block table */ /* Build bad block table */
return chip->scan_bbt(mtd); ret = chip->scan_bbt(mtd);
err_free: if (ret)
if (!(chip->options & NAND_OWN_BUFFERS)) goto err_nand_data_iface_cleanup;
kfree(chip->buffers);
return 0;
err_nand_data_iface_cleanup:
nand_release_data_interface(chip);
err_nand_manuf_cleanup:
nand_manufacturer_cleanup(chip);
err_free_nbuf:
if (nbuf) {
kfree(nbuf->databuf);
kfree(nbuf->ecccode);
kfree(nbuf->ecccalc);
kfree(nbuf);
}
return ret; return ret;
} }
EXPORT_SYMBOL(nand_scan_tail); EXPORT_SYMBOL(nand_scan_tail);
...@@ -4868,13 +5044,20 @@ void nand_cleanup(struct nand_chip *chip) ...@@ -4868,13 +5044,20 @@ void nand_cleanup(struct nand_chip *chip)
/* Free bad block table memory */ /* Free bad block table memory */
kfree(chip->bbt); kfree(chip->bbt);
if (!(chip->options & NAND_OWN_BUFFERS)) if (!(chip->options & NAND_OWN_BUFFERS) && chip->buffers) {
kfree(chip->buffers->databuf);
kfree(chip->buffers->ecccode);
kfree(chip->buffers->ecccalc);
kfree(chip->buffers); kfree(chip->buffers);
}
/* Free bad block descriptor memory */ /* Free bad block descriptor memory */
if (chip->badblock_pattern && chip->badblock_pattern->options if (chip->badblock_pattern && chip->badblock_pattern->options
& NAND_BBT_DYNAMICSTRUCT) & NAND_BBT_DYNAMICSTRUCT)
kfree(chip->badblock_pattern); kfree(chip->badblock_pattern);
/* Free manufacturer priv data. */
nand_manufacturer_cleanup(chip);
} }
EXPORT_SYMBOL_GPL(nand_cleanup); EXPORT_SYMBOL_GPL(nand_cleanup);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment