/**
* nand_reset_data_interface - Reset data interface and timings
* @chip: The NAND chip
+ * @chipnr: Internal die id
*
* 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)
+static int nand_reset_data_interface(struct nand_chip *chip, int chipnr)
{
struct mtd_info *mtd = nand_to_mtd(chip);
const struct nand_data_interface *conf;
*/
conf = nand_get_default_data_interface();
- ret = chip->setup_data_interface(mtd, conf, false);
+ ret = chip->setup_data_interface(mtd, chipnr, conf);
if (ret)
pr_err("Failed to configure data interface to SDR timing mode 0\n");
/**
* nand_setup_data_interface - Setup the best data interface and timings
* @chip: The NAND chip
+ * @chipnr: Internal die id
*
* Find and configure the best data interface and NAND timings supported by
* the chip and the driver.
*
* 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);
int ret;
goto err;
}
- ret = chip->setup_data_interface(mtd, chip->data_interface, false);
+ ret = chip->setup_data_interface(mtd, chipnr, chip->data_interface);
err:
return ret;
}
if (ret)
continue;
- ret = chip->setup_data_interface(mtd, chip->data_interface,
- true);
+ /* Pass -1 to only */
+ ret = chip->setup_data_interface(mtd,
+ NAND_DATA_IFACE_CHECK_ONLY,
+ chip->data_interface);
if (!ret) {
chip->onfi_timing_mode_default = mode;
break;
struct mtd_info *mtd = nand_to_mtd(chip);
int ret;
- ret = nand_reset_data_interface(chip);
+ ret = nand_reset_data_interface(chip, chipnr);
if (ret)
return ret;
chip->select_chip(mtd, -1);
chip->select_chip(mtd, chipnr);
- ret = nand_setup_data_interface(chip);
+ ret = nand_setup_data_interface(chip, chipnr);
chip->select_chip(mtd, -1);
if (ret)
return ret;
for (; len >= 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;
if (unlikely(bitflips > bitflips_threshold))
return -EBADMSG;
*
* Not for syndrome calculating ECC controllers, which use a special oob layout.
*/
-static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
+int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
{
chip->read_buf(mtd, buf, mtd->writesize);
if (oob_required)
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
return 0;
}
+EXPORT_SYMBOL(nand_read_page_raw);
/**
* nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc
*
* Not for syndrome calculating ECC controllers, which use a special oob layout.
*/
-static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required, int page)
+int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required, int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
if (oob_required)
return 0;
}
+EXPORT_SYMBOL(nand_write_page_raw);
/**
* nand_write_page_raw_syndrome - [INTERN] raw page write function
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
* @mtd: MTD device structure
[NAND_ECC_HW] = "hw",
[NAND_ECC_HW_SYNDROME] = "hw_syndrome",
[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)
* For the other dies, nand_reset() will automatically switch to the
* best mode for us.
*/
- ret = nand_setup_data_interface(chip);
+ ret = nand_setup_data_interface(chip, 0);
if (ret)
return ret;
}
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_free;
+ }
+ if (!ecc->read_oob)
+ ecc->read_oob = nand_read_oob_std;
+ if (!ecc->write_oob)
+ ecc->write_oob = nand_write_oob_std;
+ break;
+
case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n");
ecc->read_page = nand_read_page_raw;