Commit d16b9d22 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-20170807' of git://git.infradead.org/linux-mtd

Pull MTD fixes from Brian Norris:
 "I missed getting these out for rc4, but here are some MTD fixes.

  Just NAND fixes (in both the core handling, and a few drivers). Notes
  stolen from Boris:

  Core fixes:

   - fix data interface setup for ONFI NANDs that do not support the SET
     FEATURES command

   - fix a kernel doc header

   - fix potential integer overflow when retrieving timing information
     from the parameter page

   - fix wrong OOB layout for small page NANDs

  Driver fixes:

   - fix potential division-by-zero bug

   - fix backward compat with old atmel-nand DT bindings

   - fix ->setup_data_interface() in the atmel NAND driver"

* tag 'for-linus-20170807' of git://git.infradead.org/linux-mtd:
  mtd: nand: atmel: Fix EDO mode check
  mtd: nand: Declare tBERS, tR and tPROG as u64 to avoid integer overflow
  mtd: nand: Fix timing setup for NANDs that do not support SET FEATURES
  mtd: nand: Fix a docs build warning
  mtd: nand: sunxi: fix potential divide-by-zero error
  nand: fix wrong default oob layout for small pages using soft ecc
  mtd: nand: atmel: Fix DT backward compatibility in pmecc.c
parents 1742c0f0 33983675
...@@ -1201,7 +1201,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, ...@@ -1201,7 +1201,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
* tRC < 30ns implies EDO mode. This controller does not support this * tRC < 30ns implies EDO mode. This controller does not support this
* mode. * mode.
*/ */
if (conf->timings.sdr.tRC_min < 30) if (conf->timings.sdr.tRC_min < 30000)
return -ENOTSUPP; return -ENOTSUPP;
atmel_smc_cs_conf_init(smcconf); atmel_smc_cs_conf_init(smcconf);
......
...@@ -945,6 +945,7 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev) ...@@ -945,6 +945,7 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev)
*/ */
struct platform_device *pdev = to_platform_device(userdev); struct platform_device *pdev = to_platform_device(userdev);
const struct atmel_pmecc_caps *caps; const struct atmel_pmecc_caps *caps;
const struct of_device_id *match;
/* No PMECC engine available. */ /* No PMECC engine available. */
if (!of_property_read_bool(userdev->of_node, if (!of_property_read_bool(userdev->of_node,
...@@ -953,21 +954,11 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev) ...@@ -953,21 +954,11 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev)
caps = &at91sam9g45_caps; caps = &at91sam9g45_caps;
/* /* Find the caps associated to the NAND dev node. */
* Try to find the NFC subnode and extract the associated caps match = of_match_node(atmel_pmecc_legacy_match,
* from there. userdev->of_node);
*/ if (match && match->data)
np = of_find_compatible_node(userdev->of_node, NULL, caps = match->data;
"atmel,sama5d3-nfc");
if (np) {
const struct of_device_id *match;
match = of_match_node(atmel_pmecc_legacy_match, np);
if (match && match->data)
caps = match->data;
of_node_put(np);
}
pmecc = atmel_pmecc_create(pdev, caps, 1, 2); pmecc = atmel_pmecc_create(pdev, caps, 1, 2);
} }
......
...@@ -65,8 +65,14 @@ static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section, ...@@ -65,8 +65,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;
} }
...@@ -1125,7 +1131,9 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr) ...@@ -1125,7 +1131,9 @@ static int nand_setup_data_interface(struct nand_chip *chip, int chipnr)
* 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,
}; };
...@@ -2741,7 +2749,6 @@ static int nand_write_page_syndrome(struct mtd_info *mtd, ...@@ -2741,7 +2749,6 @@ 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,
......
...@@ -311,9 +311,9 @@ int onfi_init_data_interface(struct nand_chip *chip, ...@@ -311,9 +311,9 @@ int onfi_init_data_interface(struct nand_chip *chip,
struct nand_sdr_timings *timings = &iface->timings.sdr; struct nand_sdr_timings *timings = &iface->timings.sdr;
/* microseconds -> picoseconds */ /* microseconds -> picoseconds */
timings->tPROG_max = 1000000UL * le16_to_cpu(params->t_prog); timings->tPROG_max = 1000000ULL * le16_to_cpu(params->t_prog);
timings->tBERS_max = 1000000UL * le16_to_cpu(params->t_bers); timings->tBERS_max = 1000000ULL * le16_to_cpu(params->t_bers);
timings->tR_max = 1000000UL * le16_to_cpu(params->t_r); timings->tR_max = 1000000ULL * le16_to_cpu(params->t_r);
/* nanoseconds -> picoseconds */ /* nanoseconds -> picoseconds */
timings->tCCS_min = 1000UL * le16_to_cpu(params->t_ccs); timings->tCCS_min = 1000UL * le16_to_cpu(params->t_ccs);
......
...@@ -1728,6 +1728,10 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline, ...@@ -1728,6 +1728,10 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline,
*/ */
chip->clk_rate = NSEC_PER_SEC / min_clk_period; chip->clk_rate = NSEC_PER_SEC / min_clk_period;
real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate); real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
if (real_clk_rate <= 0) {
dev_err(nfc->dev, "Unable to round clk %lu\n", chip->clk_rate);
return -EINVAL;
}
/* /*
* ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
......
...@@ -681,10 +681,10 @@ struct nand_buffers { ...@@ -681,10 +681,10 @@ struct nand_buffers {
* @tWW_min: WP# transition to WE# low * @tWW_min: WP# transition to WE# low
*/ */
struct nand_sdr_timings { struct nand_sdr_timings {
u32 tBERS_max; u64 tBERS_max;
u32 tCCS_min; u32 tCCS_min;
u32 tPROG_max; u64 tPROG_max;
u32 tR_max; u64 tR_max;
u32 tALH_min; u32 tALH_min;
u32 tADL_min; u32 tADL_min;
u32 tALS_min; u32 tALS_min;
......
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