[RFC PATCH v2 1/6] mtd: nand: provide several helpers to do common NAND operations

Boris Brezillon boris.brezillon at free-electrons.com
Thu Nov 30 00:18:30 PST 2017


Hi Masahiro,

On Thu, 30 Nov 2017 16:44:35 +0900
Masahiro Yamada <yamada.masahiro at socionext.com> wrote:

> 2017-11-07 23:54 GMT+09:00 Miquel Raynal <miquel.raynal at free-electrons.com>:
> 
> > diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
> > index 5124f8ae8c04..ca8d3414d252 100644
> > --- a/drivers/mtd/nand/denali.c
> > +++ b/drivers/mtd/nand/denali.c
> > @@ -645,8 +645,6 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
> >                             int page, int write)
> >  {
> >         struct denali_nand_info *denali = mtd_to_denali(mtd);
> > -       unsigned int start_cmd = write ? NAND_CMD_SEQIN : NAND_CMD_READ0;
> > -       unsigned int rnd_cmd = write ? NAND_CMD_RNDIN : NAND_CMD_RNDOUT;
> >         int writesize = mtd->writesize;
> >         int oobsize = mtd->oobsize;
> >         uint8_t *bufpoi = chip->oob_poi;
> > @@ -658,11 +656,11 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
> >         int i, pos, len;
> >
> >         /* BBM at the beginning of the OOB area */
> > -       chip->cmdfunc(mtd, start_cmd, writesize, page);
> >         if (write)
> > -               chip->write_buf(mtd, bufpoi, oob_skip);
> > +               nand_prog_page_begin_op(chip, page, writesize, bufpoi,
> > +                                       oob_skip);
> >         else
> > -               chip->read_buf(mtd, bufpoi, oob_skip);
> > +               nand_read_page_op(chip, page, writesize, bufpoi, oob_skip);
> >         bufpoi += oob_skip;
> >
> >         /* OOB ECC */
> > @@ -675,30 +673,35 @@ static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip,
> >                 else if (pos + len > writesize)
> >                         len = writesize - pos;
> >
> > -               chip->cmdfunc(mtd, rnd_cmd, pos, -1);
> >                 if (write)
> > -                       chip->write_buf(mtd, bufpoi, len);
> > +                       nand_change_write_column_op(chip, pos, bufpoi, len,
> > +                                                   false);
> >                 else
> > -                       chip->read_buf(mtd, bufpoi, len);
> > +                       nand_change_read_column_op(chip, pos, bufpoi, len,
> > +                                                  false);
> >                 bufpoi += len;
> >                 if (len < ecc_bytes) {
> >                         len = ecc_bytes - len;
> > -                       chip->cmdfunc(mtd, rnd_cmd, writesize + oob_skip, -1);
> >                         if (write)
> > -                               chip->write_buf(mtd, bufpoi, len);
> > +                               nand_change_write_column_op(chip, writesize +
> > +                                                           oob_skip, bufpoi,
> > +                                                           len, false);
> >                         else
> > -                               chip->read_buf(mtd, bufpoi, len);
> > +                               nand_change_read_column_op(chip, writesize +
> > +                                                          oob_skip, bufpoi,
> > +                                                          len, false);
> >                         bufpoi += len;
> >                 }
> >         }
> >
> >         /* OOB free */
> >         len = oobsize - (bufpoi - chip->oob_poi);
> > -       chip->cmdfunc(mtd, rnd_cmd, size - len, -1);
> >         if (write)
> > -               chip->write_buf(mtd, bufpoi, len);
> > +               nand_change_write_column_op(chip, size - len, bufpoi, len,
> > +                                           false);
> >         else
> > -               chip->read_buf(mtd, bufpoi, len);
> > +               nand_change_read_column_op(chip, size - len, bufpoi, len,
> > +                                          false);
> >  }
> >
> >  static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
> > @@ -788,16 +791,12 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
> >                             int page)
> >  {
> >         struct denali_nand_info *denali = mtd_to_denali(mtd);
> > -       int status;
> >
> >         denali_reset_irq(denali);
> >
> >         denali_oob_xfer(mtd, chip, page, 1);
> >
> > -       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
> > -       status = chip->waitfunc(mtd, chip);
> > -
> > -       return status & NAND_STATUS_FAIL ? -EIO : 0;
> > +       return nand_prog_page_end_op(chip);
> >  }
> >
> >  static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
> > @@ -951,7 +950,7 @@ static int denali_erase(struct mtd_info *mtd, int page)
> >         irq_status = denali_wait_for_irq(denali,
> >                                          INTR__ERASE_COMP | INTR__ERASE_FAIL);
> >
> > -       return irq_status & INTR__ERASE_COMP ? 0 : NAND_STATUS_FAIL;
> > +       return irq_status & INTR__ERASE_FAIL ? -EIO : 0;
> >  }  
> 
> Does this change keep the equivalent behavior?

Yep, because the core is patched accordingly, and all implementers of
->erase() (docg4, nand_base and denali) are now returning 0 in case of
success and -EERROR in case of failure.

> 
> Changing NAND_STATUS_FAIL to -EIO is OK
> (but, not mentioned in the git-log)

You're right, we should probably move this change in a separate patch.

> 
> I am not 100% sure about
>   INTR__ERASE_COMP  ->  INTR__ERASE_FAIL.

We'll keep the old test then:

	return irq_status & INTR__ERASE_COMP ? 0 : -EIO;

> 
> 
> Theoretically, there could be three cases:
>   [1] INTR__ERASE_COMP interrupt is asserted
>   [2] INTR__ERASE_FAIL interrupt is asserted
>   [3] Nothing is asserted (bailout by timeout)

Well, ideally we should have something like:

	if (irq_status & INTR__ERASE_COMP)
		return 0;
	else if (irq_status & INTR__ERASE_FAIL)
		return -EIO;

	return -ETIMEDOUT;

But let's keep the existing behavior (return -EIO in case of timeout).

Thanks,

Boris

> 
> 
> If you change this, I must consult our hardware engineers
> whether [3] happens or not in erase operation.
> 
> 




More information about the linux-mtd mailing list