X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fmtd%2Fnand%2Fnand_base.c;h=c4619e3ac4ab2194947c253de81f5a054401857e;hb=5844feeaa4154d1c46d3462c7a4653d22356d8b4;hp=d4cec2f8a0162a7e5bad7c9deb5cd699c9cbcdb7;hpb=0ec56dc4a1489d5b1d23d1c019b76a69ce153805;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index d4cec2f8a016..c4619e3ac4ab 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -48,6 +48,7 @@ #include #include #include +#include /* Define default oob placement schemes for large and small page devices */ static struct nand_ecclayout nand_oob_8 = { @@ -565,6 +566,25 @@ void nand_wait_ready(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(nand_wait_ready); +/** + * nand_wait_status_ready - [GENERIC] Wait for the ready status after commands. + * @mtd: MTD device structure + * @timeo: Timeout in ms + * + * Wait for status ready (i.e. command done) or timeout. + */ +static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) +{ + register struct nand_chip *chip = mtd->priv; + + timeo = jiffies + msecs_to_jiffies(timeo); + do { + if ((chip->read_byte(mtd) & NAND_STATUS_READY)) + break; + touch_softlockup_watchdog(); + } while (time_before(jiffies, timeo)); +}; + /** * nand_command - [DEFAULT] Send command to NAND device * @mtd: MTD device structure @@ -643,8 +663,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, NAND_CTRL_CLE | NAND_CTRL_CHANGE); chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) - ; + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); return; /* This applies to read commands */ @@ -740,8 +760,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) - ; + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); return; case NAND_CMD_RNDOUT: @@ -2124,7 +2144,7 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, /** - * nand_write_subpage_hwecc - [REPLACABLE] hardware ECC based subpage write + * nand_write_subpage_hwecc - [REPLACEABLE] hardware ECC based subpage write * @mtd: mtd info structure * @chip: nand chip info structure * @offset: column address of subpage within the page @@ -2909,9 +2929,6 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, & ONFI_OPT_CMD_SET_GET_FEATURES)) return -EINVAL; - /* clear the sub feature parameters */ - memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN); - chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) *subfeature_param++ = chip->read_byte(mtd); @@ -3779,6 +3796,39 @@ ident_done: return type; } +static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, + struct device_node *dn) +{ + int ecc_mode, ecc_strength, ecc_step; + + if (of_get_nand_bus_width(dn) == 16) + chip->options |= NAND_BUSWIDTH_16; + + if (of_get_nand_on_flash_bbt(dn)) + chip->bbt_options |= NAND_BBT_USE_FLASH; + + ecc_mode = of_get_nand_ecc_mode(dn); + ecc_strength = of_get_nand_ecc_strength(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) + chip->ecc.mode = ecc_mode; + + if (ecc_strength >= 0) + chip->ecc.strength = ecc_strength; + + if (ecc_step > 0) + chip->ecc.size = ecc_step; + + return 0; +} + /** * nand_scan_ident - [NAND Interface] Scan for the NAND device * @mtd: MTD device structure @@ -3796,6 +3846,13 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, int i, nand_maf_id, nand_dev_id; struct nand_chip *chip = mtd->priv; struct nand_flash_dev *type; + int ret; + + if (chip->dn) { + ret = nand_dt_init(mtd, chip, chip->dn); + if (ret) + return ret; + } /* Set the default functions */ nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);