|
@@ -745,7 +745,10 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
|
|
|
column >>= 1;
|
|
|
chip->cmd_ctrl(mtd, column, ctrl);
|
|
|
ctrl &= ~NAND_CTRL_CHANGE;
|
|
|
- chip->cmd_ctrl(mtd, column >> 8, ctrl);
|
|
|
+
|
|
|
+ /* Only output a single addr cycle for 8bits opcodes. */
|
|
|
+ if (!nand_opcode_8bits(command))
|
|
|
+ chip->cmd_ctrl(mtd, column >> 8, ctrl);
|
|
|
}
|
|
|
if (page_addr != -1) {
|
|
|
chip->cmd_ctrl(mtd, page_addr, ctrl);
|
|
@@ -947,6 +950,172 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * nand_reset_data_interface - Reset data interface and timings
|
|
|
+ * @chip: The NAND chip
|
|
|
+ *
|
|
|
+ * Reset the Data interface and timings to ONFI mode 0.
|
|
|
+ *
|
|
|
+ * Returns 0 for success or negative error code otherwise.
|
|
|
+ */
|
|
|
+static int nand_reset_data_interface(struct nand_chip *chip)
|
|
|
+{
|
|
|
+ struct mtd_info *mtd = nand_to_mtd(chip);
|
|
|
+ const struct nand_data_interface *conf;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!chip->setup_data_interface)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The ONFI specification says:
|
|
|
+ * "
|
|
|
+ * To transition from NV-DDR or NV-DDR2 to the SDR data
|
|
|
+ * interface, the host shall use the Reset (FFh) command
|
|
|
+ * using SDR timing mode 0. A device in any timing mode is
|
|
|
+ * required to recognize Reset (FFh) command issued in SDR
|
|
|
+ * timing mode 0.
|
|
|
+ * "
|
|
|
+ *
|
|
|
+ * Configure the data interface in SDR mode and set the
|
|
|
+ * timings to timing mode 0.
|
|
|
+ */
|
|
|
+
|
|
|
+ conf = nand_get_default_data_interface();
|
|
|
+ ret = chip->setup_data_interface(mtd, conf, false);
|
|
|
+ if (ret)
|
|
|
+ pr_err("Failed to configure data interface to SDR timing mode 0\n");
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * nand_setup_data_interface - Setup the best data interface and timings
|
|
|
+ * @chip: The NAND chip
|
|
|
+ *
|
|
|
+ * Find and configure the best data interface and NAND timings supported by
|
|
|
+ * the chip and the driver.
|
|
|
+ * First tries to retrieve supported timing modes from ONFI information,
|
|
|
+ * and if the NAND chip does not support ONFI, relies on the
|
|
|
+ * ->onfi_timing_mode_default specified in the nand_ids table.
|
|
|
+ *
|
|
|
+ * Returns 0 for success or negative error code otherwise.
|
|
|
+ */
|
|
|
+static int nand_setup_data_interface(struct nand_chip *chip)
|
|
|
+{
|
|
|
+ struct mtd_info *mtd = nand_to_mtd(chip);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!chip->setup_data_interface || !chip->data_interface)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Ensure the timing mode has been changed on the chip side
|
|
|
+ * before changing timings on the controller side.
|
|
|
+ */
|
|
|
+ if (chip->onfi_version) {
|
|
|
+ u8 tmode_param[ONFI_SUBFEATURE_PARAM_LEN] = {
|
|
|
+ chip->onfi_timing_mode_default,
|
|
|
+ };
|
|
|
+
|
|
|
+ ret = chip->onfi_set_features(mtd, chip,
|
|
|
+ ONFI_FEATURE_ADDR_TIMING_MODE,
|
|
|
+ tmode_param);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = chip->setup_data_interface(mtd, chip->data_interface, false);
|
|
|
+err:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * nand_init_data_interface - find the best data interface and timings
|
|
|
+ * @chip: The NAND chip
|
|
|
+ *
|
|
|
+ * Find the best data interface and NAND timings supported by the chip
|
|
|
+ * and the driver.
|
|
|
+ * First tries to retrieve supported timing modes from ONFI information,
|
|
|
+ * and if the NAND chip does not support ONFI, relies on the
|
|
|
+ * ->onfi_timing_mode_default specified in the nand_ids table. After this
|
|
|
+ * function nand_chip->data_interface is initialized with the best timing mode
|
|
|
+ * available.
|
|
|
+ *
|
|
|
+ * Returns 0 for success or negative error code otherwise.
|
|
|
+ */
|
|
|
+static int nand_init_data_interface(struct nand_chip *chip)
|
|
|
+{
|
|
|
+ struct mtd_info *mtd = nand_to_mtd(chip);
|
|
|
+ int modes, mode, ret;
|
|
|
+
|
|
|
+ if (!chip->setup_data_interface)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * First try to identify the best timings from ONFI parameters and
|
|
|
+ * if the NAND does not support ONFI, fallback to the default ONFI
|
|
|
+ * timing mode.
|
|
|
+ */
|
|
|
+ modes = onfi_get_async_timing_mode(chip);
|
|
|
+ if (modes == ONFI_TIMING_MODE_UNKNOWN) {
|
|
|
+ if (!chip->onfi_timing_mode_default)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ modes = GENMASK(chip->onfi_timing_mode_default, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ chip->data_interface = kzalloc(sizeof(*chip->data_interface),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!chip->data_interface)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ for (mode = fls(modes) - 1; mode >= 0; mode--) {
|
|
|
+ ret = onfi_init_data_interface(chip, chip->data_interface,
|
|
|
+ NAND_SDR_IFACE, mode);
|
|
|
+ if (ret)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ret = chip->setup_data_interface(mtd, chip->data_interface,
|
|
|
+ true);
|
|
|
+ if (!ret) {
|
|
|
+ chip->onfi_timing_mode_default = mode;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void nand_release_data_interface(struct nand_chip *chip)
|
|
|
+{
|
|
|
+ kfree(chip->data_interface);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * nand_reset - Reset and initialize a NAND device
|
|
|
+ * @chip: The NAND chip
|
|
|
+ *
|
|
|
+ * Returns 0 for success or negative error code otherwise
|
|
|
+ */
|
|
|
+int nand_reset(struct nand_chip *chip)
|
|
|
+{
|
|
|
+ struct mtd_info *mtd = nand_to_mtd(chip);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = nand_reset_data_interface(chip);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
|
+
|
|
|
+ ret = nand_setup_data_interface(chip);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
|
|
|
* @mtd: mtd info
|
|
@@ -1025,7 +1194,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
|
* some operation can also clear the bit 7 of status register
|
|
|
* eg. erase/program a locked block
|
|
|
*/
|
|
|
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
|
+ nand_reset(chip);
|
|
|
|
|
|
/* Check, if it is write protected */
|
|
|
if (nand_check_wp(mtd)) {
|
|
@@ -1084,7 +1253,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
|
* some operation can also clear the bit 7 of status register
|
|
|
* eg. erase/program a locked block
|
|
|
*/
|
|
|
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
|
+ nand_reset(chip);
|
|
|
|
|
|
/* Check, if it is write protected */
|
|
|
if (nand_check_wp(mtd)) {
|
|
@@ -2162,7 +2331,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
|
|
|
static int nand_read_oob(struct mtd_info *mtd, loff_t from,
|
|
|
struct mtd_oob_ops *ops)
|
|
|
{
|
|
|
- int ret = -ENOTSUPP;
|
|
|
+ int ret;
|
|
|
|
|
|
ops->retlen = 0;
|
|
|
|
|
@@ -2173,24 +2342,18 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- nand_get_device(mtd, FL_READING);
|
|
|
-
|
|
|
- switch (ops->mode) {
|
|
|
- case MTD_OPS_PLACE_OOB:
|
|
|
- case MTD_OPS_AUTO_OOB:
|
|
|
- case MTD_OPS_RAW:
|
|
|
- break;
|
|
|
+ if (ops->mode != MTD_OPS_PLACE_OOB &&
|
|
|
+ ops->mode != MTD_OPS_AUTO_OOB &&
|
|
|
+ ops->mode != MTD_OPS_RAW)
|
|
|
+ return -ENOTSUPP;
|
|
|
|
|
|
- default:
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ nand_get_device(mtd, FL_READING);
|
|
|
|
|
|
if (!ops->datbuf)
|
|
|
ret = nand_do_read_oob(mtd, from, ops);
|
|
|
else
|
|
|
ret = nand_do_read_ops(mtd, from, ops);
|
|
|
|
|
|
-out:
|
|
|
nand_release_device(mtd);
|
|
|
return ret;
|
|
|
}
|
|
@@ -2788,7 +2951,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
|
|
|
* if we don't do this. I have no clue why, but I seem to have 'fixed'
|
|
|
* it in the doc2000 driver in August 1999. dwmw2.
|
|
|
*/
|
|
|
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
|
+ nand_reset(chip);
|
|
|
|
|
|
/* Check, if it is write protected */
|
|
|
if (nand_check_wp(mtd)) {
|
|
@@ -3191,8 +3354,7 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
|
|
|
|
|
|
if (!chip->controller) {
|
|
|
chip->controller = &chip->hwcontrol;
|
|
|
- spin_lock_init(&chip->controller->lock);
|
|
|
- init_waitqueue_head(&chip->controller->wq);
|
|
|
+ nand_hw_control_init(chip->controller);
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -3829,7 +3991,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
|
|
* Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
|
|
|
* after power-up.
|
|
|
*/
|
|
|
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
|
+ nand_reset(chip);
|
|
|
|
|
|
/* Send the command for reading device ID */
|
|
|
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
|
@@ -4113,6 +4275,9 @@ static int nand_dt_init(struct nand_chip *chip)
|
|
|
if (ecc_step > 0)
|
|
|
chip->ecc.size = ecc_step;
|
|
|
|
|
|
+ if (of_property_read_bool(dn, "nand-ecc-maximize"))
|
|
|
+ chip->ecc.options |= NAND_ECC_MAXIMIZE;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -4141,6 +4306,15 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
|
|
if (!mtd->name && mtd->dev.parent)
|
|
|
mtd->name = dev_name(mtd->dev.parent);
|
|
|
|
|
|
+ if ((!chip->cmdfunc || !chip->select_chip) && !chip->cmd_ctrl) {
|
|
|
+ /*
|
|
|
+ * Default functions assigned for chip_select() and
|
|
|
+ * cmdfunc() both expect cmd_ctrl() to be populated,
|
|
|
+ * so we need to check that that's the case
|
|
|
+ */
|
|
|
+ pr_err("chip.cmd_ctrl() callback is not provided");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
/* Set the default functions */
|
|
|
nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
|
|
|
|
|
@@ -4155,13 +4329,17 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
|
|
return PTR_ERR(type);
|
|
|
}
|
|
|
|
|
|
+ ret = nand_init_data_interface(chip);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
chip->select_chip(mtd, -1);
|
|
|
|
|
|
/* Check for a chip array */
|
|
|
for (i = 1; i < maxchips; i++) {
|
|
|
chip->select_chip(mtd, i);
|
|
|
/* See comment in nand_get_flash_type for reset */
|
|
|
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
|
|
+ nand_reset(chip);
|
|
|
/* Send the command for reading device ID */
|
|
|
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
|
|
/* Read manufacturer and device IDs */
|
|
@@ -4221,6 +4399,7 @@ static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
|
|
|
ecc->write_page_raw = nand_write_page_raw;
|
|
|
ecc->read_oob = nand_read_oob_std;
|
|
|
ecc->write_oob = nand_write_oob_std;
|
|
|
+
|
|
|
/*
|
|
|
* Board driver should supply ecc.size and ecc.strength
|
|
|
* values to select how many bits are correctable.
|
|
@@ -4243,6 +4422,25 @@ static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
|
|
|
}
|
|
|
|
|
|
mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We can only maximize ECC config when the default layout is
|
|
|
+ * used, otherwise we don't know how many bytes can really be
|
|
|
+ * used.
|
|
|
+ */
|
|
|
+ if (mtd->ooblayout == &nand_ooblayout_lp_ops &&
|
|
|
+ ecc->options & NAND_ECC_MAXIMIZE) {
|
|
|
+ int steps, bytes;
|
|
|
+
|
|
|
+ /* Always prefer 1k blocks over 512bytes ones */
|
|
|
+ ecc->size = 1024;
|
|
|
+ steps = mtd->writesize / ecc->size;
|
|
|
+
|
|
|
+ /* Reserve 2 bytes for the BBM */
|
|
|
+ bytes = (mtd->oobsize - 2) / steps;
|
|
|
+ ecc->strength = bytes * 8 / fls(8 * ecc->size);
|
|
|
}
|
|
|
|
|
|
/* See nand_bch_init() for details. */
|
|
@@ -4601,18 +4799,16 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
|
|
|
EXPORT_SYMBOL(nand_scan);
|
|
|
|
|
|
/**
|
|
|
- * nand_release - [NAND Interface] Free resources held by the NAND device
|
|
|
- * @mtd: MTD device structure
|
|
|
+ * nand_cleanup - [NAND Interface] Free resources held by the NAND device
|
|
|
+ * @chip: NAND chip object
|
|
|
*/
|
|
|
-void nand_release(struct mtd_info *mtd)
|
|
|
+void nand_cleanup(struct nand_chip *chip)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd_to_nand(mtd);
|
|
|
-
|
|
|
if (chip->ecc.mode == NAND_ECC_SOFT &&
|
|
|
chip->ecc.algo == NAND_ECC_BCH)
|
|
|
nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
|
|
|
|
|
|
- mtd_device_unregister(mtd);
|
|
|
+ nand_release_data_interface(chip);
|
|
|
|
|
|
/* Free bad block table memory */
|
|
|
kfree(chip->bbt);
|
|
@@ -4624,6 +4820,18 @@ void nand_release(struct mtd_info *mtd)
|
|
|
& NAND_BBT_DYNAMICSTRUCT)
|
|
|
kfree(chip->badblock_pattern);
|
|
|
}
|
|
|
+EXPORT_SYMBOL_GPL(nand_cleanup);
|
|
|
+
|
|
|
+/**
|
|
|
+ * nand_release - [NAND Interface] Unregister the MTD device and free resources
|
|
|
+ * held by the NAND device
|
|
|
+ * @mtd: MTD device structure
|
|
|
+ */
|
|
|
+void nand_release(struct mtd_info *mtd)
|
|
|
+{
|
|
|
+ mtd_device_unregister(mtd);
|
|
|
+ nand_cleanup(mtd_to_nand(mtd));
|
|
|
+}
|
|
|
EXPORT_SYMBOL_GPL(nand_release);
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|