From: Boris Brezillon <boris.brezillon@bootlin.com>
To: Sam Lefebvre <sam.lefebvre@essensium.com>
Cc: linux-mtd@lists.infradead.org, Han Xu <han.xu@nxp.com>,
"Arnout Vandecappelle \(Essensium/Mind\)" <arnout@mind.be>
Subject: Re: [PATCH 10/18] mtd: rawnand: factor nand_command_lp() into nand_command()
Date: Fri, 20 Apr 2018 22:34:54 +0200 [thread overview]
Message-ID: <20180420223454.445a1858@bbrezillon> (raw)
In-Reply-To: <20180420081946.16088-11-sam.lefebvre@essensium.com>
Hi Sam, Arnout,
On Fri, 20 Apr 2018 10:19:38 +0200
Sam Lefebvre <sam.lefebvre@essensium.com> wrote:
> From: "Arnout Vandecappelle (Essensium/Mind)" <arnout@mind.be>
>
> The nand_command() and nand_command_lp() functions are very similar.
> Factor them into a single function, and use conditions on writesize to
> identify the differences.
>
> is_lp checks are added everywhere to make sure the behaviour is exactly
> the same as before. Most likely, the checks in CACHEDPROG, RNDIN and
> RNDOUT are not needed since these commands are only valid for LP
> devices. But since I'm not sure of that, I'm leaving it as is.
>
> The only side effect of this patch is that the large-page behaviour is
> activated a little bit earlier: as soon as writesize is set. However,
> only SEQIN, READOOB, READ0, CACHEDPROG, RNDIN and RNDOUT behave
> differently between small and large page. Of these, only RNDOUT is used
> in nand_detect(). RNDOUT is used by nand_change_read_column_op() which
> is called by nand_flash_detect_ext_param_page(). Before this patch, the
> switch to nand_command_lp was already made just before calling that
> function so the behaviour doesn't change.
>
> Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
> ---
> Note that I don't have access to a small-page device, so only tested on
> large-page devices. Also only tested on i.MX6Q (gpmi-nand).
>
> I only verified the lack of change in behaviour during nand_detect by
> reading the code, so it's possible that I missed something. Testing on
> various devices (ONFI, JEDEC, non-ONFI/JEDEC) is needed to be really
> sure that nothing breaks.
>
> Note that this patch can be removed from the series without affecting
> the rest.
Hm, I don't want to risk any regression, so I'm gonna pass on this
patch, especially since we're trying to get rid of ->cmdfunc() in favor
or ->exec_op().
The same goes for patch 9, sorry.
Regards,
Boris
> ---
> drivers/mtd/nand/raw/nand_base.c | 236 ++++++++++++---------------------------
> 1 file changed, 70 insertions(+), 166 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index bcc0344b1f27..320efbe41bd6 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -747,121 +747,6 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
> };
> EXPORT_SYMBOL_GPL(nand_soft_waitrdy);
>
> -/**
> - * nand_command - [DEFAULT] Send command to NAND device
> - * @mtd: MTD device structure
> - * @command: the command to be sent
> - * @column: the column address for this command, -1 if none
> - * @page_addr: the page address for this command, -1 if none
> - *
> - * Send command to NAND device. This function is used for small page devices
> - * (512 Bytes per page).
> - */
> -static void nand_command(struct mtd_info *mtd, unsigned int command,
> - int column, int page_addr)
> -{
> - register struct nand_chip *chip = mtd_to_nand(mtd);
> - int ctrl = NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE;
> -
> - /* Write out the command to the device */
> - if (command == NAND_CMD_SEQIN) {
> - int readcmd;
> -
> - if (column >= mtd->writesize) {
> - /* OOB area */
> - column -= mtd->writesize;
> - readcmd = NAND_CMD_READOOB;
> - } else if (column < 256) {
> - /* First 256 bytes --> READ0 */
> - readcmd = NAND_CMD_READ0;
> - } else {
> - column -= 256;
> - readcmd = NAND_CMD_READ1;
> - }
> - chip->cmd_ctrl(mtd, readcmd, ctrl);
> - ctrl &= ~NAND_CTRL_CHANGE;
> - }
> - if (command != NAND_CMD_NONE)
> - chip->cmd_ctrl(mtd, command, ctrl);
> -
> - /* Address cycle, when necessary */
> - ctrl = NAND_NCE | NAND_ALE | NAND_CTRL_CHANGE;
> - /* Serially input address */
> - if (column != -1) {
> - /* Adjust columns for 16 bit buswidth */
> - if (chip->options & NAND_BUSWIDTH_16 &&
> - !nand_opcode_8bits(command))
> - column >>= 1;
> - chip->cmd_ctrl(mtd, column, ctrl);
> - ctrl &= ~NAND_CTRL_CHANGE;
> - }
> - if (page_addr != -1) {
> - chip->cmd_ctrl(mtd, page_addr, ctrl);
> - ctrl &= ~NAND_CTRL_CHANGE;
> - chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
> - if (chip->options & NAND_ROW_ADDR_3)
> - chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
> - }
> - chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
> -
> - /*
> - * Program and erase have their own busy handlers status and sequential
> - * in needs no delay
> - */
> - switch (command) {
> -
> - case NAND_CMD_NONE:
> - case NAND_CMD_PAGEPROG:
> - case NAND_CMD_ERASE1:
> - case NAND_CMD_ERASE2:
> - case NAND_CMD_SEQIN:
> - case NAND_CMD_STATUS:
> - case NAND_CMD_READID:
> - case NAND_CMD_SET_FEATURES:
> - return;
> -
> - case NAND_CMD_RESET:
> - if (chip->dev_ready)
> - break;
> - udelay(chip->chip_delay);
> - chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
> - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
> - chip->cmd_ctrl(mtd, NAND_CMD_NONE,
> - NAND_NCE | NAND_CTRL_CHANGE);
> - /* EZ-NAND can take upto 250ms as per ONFi v4.0 */
> - nand_wait_status_ready(mtd, 250);
> - return;
> -
> - /* This applies to read commands */
> - case NAND_CMD_READ0:
> - /*
> - * READ0 is sometimes used to exit GET STATUS mode. When this
> - * is the case no address cycles are requested, and we can use
> - * this information to detect that we should not wait for the
> - * device to be ready.
> - */
> - if (column == -1 && page_addr == -1)
> - return;
> -
> - default:
> - /*
> - * If we don't have access to the busy pin, we apply the given
> - * command delay
> - */
> - if (!chip->dev_ready) {
> - udelay(chip->chip_delay);
> - return;
> - }
> - }
> - /*
> - * Apply this short delay always to ensure that we do wait tWB in
> - * any case on any machine.
> - */
> - ndelay(100);
> -
> - nand_wait_ready(mtd);
> -}
> -
> static void nand_ccs_delay(struct nand_chip *chip)
> {
> /*
> @@ -882,26 +767,48 @@ static void nand_ccs_delay(struct nand_chip *chip)
> }
>
> /**
> - * nand_command_lp - [DEFAULT] Send command to NAND large page device
> + * nand_command - [DEFAULT] Send command to NAND device
> * @mtd: MTD device structure
> * @command: the command to be sent
> * @column: the column address for this command, -1 if none
> * @page_addr: the page address for this command, -1 if none
> *
> - * Send command to NAND device. This is the version for the new large page
> - * devices. We don't have the separate regions as we have in the small page
> - * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
> + * Send command to NAND device.
> */
> -static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
> +static void nand_command(struct mtd_info *mtd, unsigned int command,
> int column, int page_addr)
> {
> register struct nand_chip *chip = mtd_to_nand(mtd);
> int ctrl = NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE;
> + /* Large page devices (> 512 bytes) behave slightly differently. */
> + bool is_lp = mtd->writesize > 512;
>
> - /* Emulate NAND_CMD_READOOB */
> - if (command == NAND_CMD_READOOB) {
> - column += mtd->writesize;
> - command = NAND_CMD_READ0;
> + if (is_lp) {
> + /* Large page devices don't have the separate regions as we
> + * have in the small page devices. We must emulate
> + * NAND_CMD_READOOB to keep the code compatible.
> + */
> + if (command == NAND_CMD_READOOB) {
> + column += mtd->writesize;
> + command = NAND_CMD_READ0;
> + }
> + } else if (command == NAND_CMD_SEQIN) {
> + /* Write out the command to the device */
> + int readcmd;
> +
> + if (column >= mtd->writesize) {
> + /* OOB area */
> + column -= mtd->writesize;
> + readcmd = NAND_CMD_READOOB;
> + } else if (column < 256) {
> + /* First 256 bytes --> READ0 */
> + readcmd = NAND_CMD_READ0;
> + } else {
> + column -= 256;
> + readcmd = NAND_CMD_READ1;
> + }
> + chip->cmd_ctrl(mtd, readcmd, ctrl);
> + ctrl &= ~NAND_CTRL_CHANGE;
> }
>
> /* Command latch cycle */
> @@ -920,7 +827,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
> ctrl &= ~NAND_CTRL_CHANGE;
>
> /* Only output a single addr cycle for 8bits opcodes. */
> - if (!nand_opcode_8bits(command))
> + if (is_lp && !nand_opcode_8bits(command))
> chip->cmd_ctrl(mtd, column >> 8, ctrl);
> }
> if (page_addr != -1) {
> @@ -939,7 +846,6 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
> switch (command) {
>
> case NAND_CMD_NONE:
> - case NAND_CMD_CACHEDPROG:
> case NAND_CMD_PAGEPROG:
> case NAND_CMD_ERASE1:
> case NAND_CMD_ERASE2:
> @@ -949,9 +855,17 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
> case NAND_CMD_SET_FEATURES:
> return;
>
> + case NAND_CMD_CACHEDPROG:
> + if (is_lp)
> + return;
> + break;
> +
> case NAND_CMD_RNDIN:
> - nand_ccs_delay(chip);
> - return;
> + if (is_lp) {
> + nand_ccs_delay(chip);
> + return;
> + }
> + break;
>
> case NAND_CMD_RESET:
> if (chip->dev_ready)
> @@ -966,40 +880,44 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
> return;
>
> case NAND_CMD_RNDOUT:
> - /* No ready / busy check necessary */
> - chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
> - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
> - chip->cmd_ctrl(mtd, NAND_CMD_NONE,
> - NAND_NCE | NAND_CTRL_CHANGE);
> -
> - nand_ccs_delay(chip);
> - return;
> + if (is_lp) {
> + /* No ready / busy check necessary */
> + chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
> + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
> + chip->cmd_ctrl(mtd, NAND_CMD_NONE,
> + NAND_NCE | NAND_CTRL_CHANGE);
> +
> + nand_ccs_delay(chip);
> + return;
> + }
> + break;
>
> case NAND_CMD_READ0:
> /*
> * READ0 is sometimes used to exit GET STATUS mode. When this
> * is the case no address cycles are requested, and we can use
> - * this information to detect that READSTART should not be
> - * issued.
> + * this information to detect that that we should not wait for
> + * the device to be ready and READSTART should not be issued.
> */
> if (column == -1 && page_addr == -1)
> return;
>
> - chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
> - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
> - chip->cmd_ctrl(mtd, NAND_CMD_NONE,
> - NAND_NCE | NAND_CTRL_CHANGE);
> -
> - /* This applies to read commands */
> - default:
> - /*
> - * If we don't have access to the busy pin, we apply the given
> - * command delay.
> - */
> - if (!chip->dev_ready) {
> - udelay(chip->chip_delay);
> - return;
> + if (is_lp) {
> + chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
> + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
> + chip->cmd_ctrl(mtd, NAND_CMD_NONE,
> + NAND_NCE | NAND_CTRL_CHANGE);
> }
> + /* Read commands must wait */
> + break;
> + }
> + /*
> + * If we don't have access to the busy pin, we apply the given command
> + * delay.
> + */
> + if (!chip->dev_ready) {
> + udelay(chip->chip_delay);
> + return;
> }
>
> /*
> @@ -5180,16 +5098,6 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
> chip->ecc_step_ds = 512;
> } else if (chip->parameters.onfi.version >= 21 &&
> (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
> -
> - /*
> - * The nand_flash_detect_ext_param_page() uses the
> - * Change Read Column command which maybe not supported
> - * by the chip->cmdfunc. So try to update the chip->cmdfunc
> - * now. We do not replace user supplied command function.
> - */
> - if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
> - chip->cmdfunc = nand_command_lp;
> -
> /* The Extended Parameter Page is supported since ONFI 2.1. */
> if (nand_flash_detect_ext_param_page(chip, p))
> pr_warn("Failed to detect ONFI extended param page\n");
> @@ -5686,10 +5594,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
> chip->badblockbits = 8;
> chip->erase = single_erase;
>
> - /* Do not replace user supplied command function! */
> - if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
> - chip->cmdfunc = nand_command_lp;
> -
> pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
> maf_id, dev_id);
> pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
next prev parent reply other threads:[~2018-04-20 20:35 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-20 8:19 Reducing the number of interrupts by page reads, part 1 Sam Lefebvre
2018-04-20 8:19 ` [PATCH 01/18] mtd: nand: gpmi: drop dma_ops_type Sam Lefebvre
2018-04-20 8:19 ` [PATCH 02/18] mtd: nand: gpmi: pass buffer and len around Sam Lefebvre
2018-04-20 8:19 ` [PATCH 03/18] mtd: nand: gpmi: put only once used functions inline Sam Lefebvre
2018-04-20 8:19 ` [PATCH 04/18] mtd: nand: gpmi: remove direct_dma_map_ok from driver data struct Sam Lefebvre
2018-04-20 8:19 ` [PATCH 05/18] mtd: nand: gpmi: return valid value from bch_set_geometry() Sam Lefebvre
2018-04-20 8:19 ` [PATCH 06/18] mtd: nand: gpmi: remove unnecessary variables Sam Lefebvre
2018-04-20 8:19 ` [PATCH 07/18] mtd: rawnand: gpmi: return generated errors in gpmi_ecc_read_oob() Sam Lefebvre
2018-04-20 22:40 ` Boris Brezillon
2018-04-20 8:19 ` [PATCH 08/18] mtd: rawnand: gpmi: set aggregate ready/busy signalling Sam Lefebvre
2018-04-20 8:19 ` [PATCH 09/18] mtd: rawnand: make nand_command() and nand_command_lp() more similar Sam Lefebvre
2018-04-20 8:19 ` [PATCH 10/18] mtd: rawnand: factor nand_command_lp() into nand_command() Sam Lefebvre
2018-04-20 20:34 ` Boris Brezillon [this message]
2018-04-23 7:16 ` Arnout Vandecappelle
2018-04-20 8:19 ` [PATCH 11/18] mtd: rawnand: gpmi: instantiate cmdfunc Sam Lefebvre
2018-04-20 20:38 ` Boris Brezillon
2018-04-23 7:43 ` Arnout Vandecappelle
2018-04-23 10:05 ` Boris Brezillon
2018-04-20 8:19 ` [PATCH 12/18] mtd: rawnand: gpmi: gpmi_ccs_delay() is not needed Sam Lefebvre
2018-04-20 8:19 ` [PATCH 13/18] mtd: rawnand: gpmi: explicit delays are " Sam Lefebvre
2018-04-20 8:19 ` [PATCH 14/18] mtd: rawnand: gpmi: no explicit wait is needed after sending a command Sam Lefebvre
2018-04-20 8:19 ` [PATCH 15/18] mtd: rawnand: gpmi: cmd_ctrl is no longer needed Sam Lefebvre
2018-04-20 8:19 ` [PATCH 16/18] mtd: rawnand: gpmi: inline gpmi_cmd_ctrl() Sam Lefebvre
2018-04-20 8:19 ` [PATCH 17/18] mtd: rawnand: gpmi: gpmi_nand_command(): use separate sgl for the two commands Sam Lefebvre
2018-04-20 8:19 ` [PATCH 18/18] mtd: rawnand: gpmi: issue two commands in a single DMA chain Sam Lefebvre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180420223454.445a1858@bbrezillon \
--to=boris.brezillon@bootlin.com \
--cc=arnout@mind.be \
--cc=han.xu@nxp.com \
--cc=linux-mtd@lists.infradead.org \
--cc=sam.lefebvre@essensium.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox