Commit 90f4ad03 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mtd/fixes-for-6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull mtd fixes from Miquel Raynal:

 - Rockchip NAND controller driver was not checking the timings properly
   and the introduction of NV-DDR support broke it.

 - The core was also misbehaving in some very specific cases: in case of
   (unlikely) bitflips in the parameter page, the fallback might have
   failed as well but for software reasons.

 - Finally, the chosen ECC configuration was no longer properly
   propagated to upper layers, mostly failing an info message at probe
   time.

* tag 'mtd/fixes-for-6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: rawnand: rockchip: ensure NVDDR timings are rejected
  mtd: rawnand: Bypass a couple of sanity checks during NAND identification
  mtd: rawnand: Fix the nand_read_data_op() early check
  mtd: rawnand: Ensure ECC configuration is propagated to upper layers
parents 9b458a26 b27d8946
...@@ -1093,28 +1093,32 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs, ...@@ -1093,28 +1093,32 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
unsigned int offset_in_page) unsigned int offset_in_page)
{ {
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
bool ident_stage = !mtd->writesize;
/* Make sure the offset is less than the actual page size. */ /* Bypass all checks during NAND identification */
if (offset_in_page > mtd->writesize + mtd->oobsize) if (likely(!ident_stage)) {
return -EINVAL; /* Make sure the offset is less than the actual page size. */
if (offset_in_page > mtd->writesize + mtd->oobsize)
return -EINVAL;
/* /*
* On small page NANDs, there's a dedicated command to access the OOB * On small page NANDs, there's a dedicated command to access the OOB
* area, and the column address is relative to the start of the OOB * area, and the column address is relative to the start of the OOB
* area, not the start of the page. Asjust the address accordingly. * area, not the start of the page. Asjust the address accordingly.
*/ */
if (mtd->writesize <= 512 && offset_in_page >= mtd->writesize) if (mtd->writesize <= 512 && offset_in_page >= mtd->writesize)
offset_in_page -= mtd->writesize; offset_in_page -= mtd->writesize;
/* /*
* The offset in page is expressed in bytes, if the NAND bus is 16-bit * The offset in page is expressed in bytes, if the NAND bus is 16-bit
* wide, then it must be divided by 2. * wide, then it must be divided by 2.
*/ */
if (chip->options & NAND_BUSWIDTH_16) { if (chip->options & NAND_BUSWIDTH_16) {
if (WARN_ON(offset_in_page % 2)) if (WARN_ON(offset_in_page % 2))
return -EINVAL; return -EINVAL;
offset_in_page /= 2; offset_in_page /= 2;
}
} }
addrs[0] = offset_in_page; addrs[0] = offset_in_page;
...@@ -1123,7 +1127,7 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs, ...@@ -1123,7 +1127,7 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
* Small page NANDs use 1 cycle for the columns, while large page NANDs * Small page NANDs use 1 cycle for the columns, while large page NANDs
* need 2 * need 2
*/ */
if (mtd->writesize <= 512) if (!ident_stage && mtd->writesize <= 512)
return 1; return 1;
addrs[1] = offset_in_page >> 8; addrs[1] = offset_in_page >> 8;
...@@ -1436,16 +1440,19 @@ int nand_change_read_column_op(struct nand_chip *chip, ...@@ -1436,16 +1440,19 @@ int nand_change_read_column_op(struct nand_chip *chip,
unsigned int len, bool force_8bit) unsigned int len, bool force_8bit)
{ {
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
bool ident_stage = !mtd->writesize;
if (len && !buf) if (len && !buf)
return -EINVAL; return -EINVAL;
if (offset_in_page + len > mtd->writesize + mtd->oobsize) if (!ident_stage) {
return -EINVAL; if (offset_in_page + len > mtd->writesize + mtd->oobsize)
return -EINVAL;
/* Small page NANDs do not support column change. */ /* Small page NANDs do not support column change. */
if (mtd->writesize <= 512) if (mtd->writesize <= 512)
return -ENOTSUPP; return -ENOTSUPP;
}
if (nand_has_exec_op(chip)) { if (nand_has_exec_op(chip)) {
const struct nand_interface_config *conf = const struct nand_interface_config *conf =
...@@ -2173,7 +2180,7 @@ EXPORT_SYMBOL_GPL(nand_reset_op); ...@@ -2173,7 +2180,7 @@ EXPORT_SYMBOL_GPL(nand_reset_op);
int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
bool force_8bit, bool check_only) bool force_8bit, bool check_only)
{ {
if (!len || !buf) if (!len || (!check_only && !buf))
return -EINVAL; return -EINVAL;
if (nand_has_exec_op(chip)) { if (nand_has_exec_op(chip)) {
...@@ -6301,6 +6308,7 @@ static const struct nand_ops rawnand_ops = { ...@@ -6301,6 +6308,7 @@ static const struct nand_ops rawnand_ops = {
static int nand_scan_tail(struct nand_chip *chip) static int nand_scan_tail(struct nand_chip *chip)
{ {
struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_info *mtd = nand_to_mtd(chip);
struct nand_device *base = &chip->base;
struct nand_ecc_ctrl *ecc = &chip->ecc; struct nand_ecc_ctrl *ecc = &chip->ecc;
int ret, i; int ret, i;
...@@ -6445,9 +6453,13 @@ static int nand_scan_tail(struct nand_chip *chip) ...@@ -6445,9 +6453,13 @@ static int nand_scan_tail(struct nand_chip *chip)
if (!ecc->write_oob_raw) if (!ecc->write_oob_raw)
ecc->write_oob_raw = ecc->write_oob; ecc->write_oob_raw = ecc->write_oob;
/* propagate ecc info to mtd_info */ /* Propagate ECC info to the generic NAND and MTD layers */
mtd->ecc_strength = ecc->strength; mtd->ecc_strength = ecc->strength;
if (!base->ecc.ctx.conf.strength)
base->ecc.ctx.conf.strength = ecc->strength;
mtd->ecc_step_size = ecc->size; mtd->ecc_step_size = ecc->size;
if (!base->ecc.ctx.conf.step_size)
base->ecc.ctx.conf.step_size = ecc->size;
/* /*
* Set the number of read / write steps for one page depending on ECC * Set the number of read / write steps for one page depending on ECC
...@@ -6455,6 +6467,8 @@ static int nand_scan_tail(struct nand_chip *chip) ...@@ -6455,6 +6467,8 @@ static int nand_scan_tail(struct nand_chip *chip)
*/ */
if (!ecc->steps) if (!ecc->steps)
ecc->steps = mtd->writesize / ecc->size; ecc->steps = mtd->writesize / ecc->size;
if (!base->ecc.ctx.nsteps)
base->ecc.ctx.nsteps = ecc->steps;
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;
......
...@@ -420,13 +420,13 @@ static int rk_nfc_setup_interface(struct nand_chip *chip, int target, ...@@ -420,13 +420,13 @@ static int rk_nfc_setup_interface(struct nand_chip *chip, int target,
u32 rate, tc2rw, trwpw, trw2c; u32 rate, tc2rw, trwpw, trw2c;
u32 temp; u32 temp;
if (target < 0)
return 0;
timings = nand_get_sdr_timings(conf); timings = nand_get_sdr_timings(conf);
if (IS_ERR(timings)) if (IS_ERR(timings))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (target < 0)
return 0;
if (IS_ERR(nfc->nfc_clk)) if (IS_ERR(nfc->nfc_clk))
rate = clk_get_rate(nfc->ahb_clk); rate = clk_get_rate(nfc->ahb_clk);
else else
......
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