Message ID | 20230515094440.3552094-2-AVKrasnov@sberdevices.ru |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp6792991vqo; Mon, 15 May 2023 02:50:25 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5Nxo5z8KQOqc5O8mwW1jQVkneSNTVeUzasWpfhyLNHtcaaUGwDJdbDpKWJ99/R2qguR2wn X-Received: by 2002:a05:6a20:9184:b0:100:d4ee:ba80 with SMTP id v4-20020a056a20918400b00100d4eeba80mr21944734pzd.27.1684144224872; Mon, 15 May 2023 02:50:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684144224; cv=none; d=google.com; s=arc-20160816; b=i6Ya7CNiTlSPtQCBoqvkxTi6PYXM/gRz8DHKsxJMshvbI2e4dJcxm3VwTbNTeOJtL5 vIiBgBGRf4bsSqDjCyXbEMFmnWwFVqLU/tocrnAv1nOzhzqnElT2wOsZ0WItGB9Aka8N 5FcBvdC7T/C6UjYYjnU2uv2qnJgSeZfCv9SaHEXp7r/38AijieXGTS0oTFlzxDDpDNyx oODwyD1rTMBpEbvd7e1Sw5a0d4t2SP6RIYEygqagWL1c+S5Uy5b0zHJXjrNgpr7Lr5fF spxp+SVx8KbtRMKkni12hLA5/8/+2VTtda0BTdi0yAWe55YV19/rF5YUbBiPCg0eIS9R 7GSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Dmj6MVlJqsj8zojvHjdvVHURJoWIYhagZNM7JaN5Dds=; b=SKw28i5eNGnPZHHA70abBkZXWYm3JqAqMxvjbwSZmatwgp0AnOF+fUGYqUVrO9Uyz4 u1eFojYjE12gr69D6B+0dZXharuh4SE8PeOIBsZ/1Q9uFWS5EKwCvNECUT1k5nSvMLJl CZqN4PNZLP2am7FTJtjgQv4UaUtZS48URj5VhHLWa398zu1D/5WcSY47Hdj3YkFnfY7v qmn3XWpiHSq6J/r2KgzVn1cjStimfHuqHmNcMRw+k2ECJNCSMLS2QNEzUgpMhSYWW9R8 CPh7epk5+frS5Vg8yaKuMAu8XODN03VkyjKOwHPwU9G9w6bB8xWk0befbUzw4vtKSPZN zyHA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sberdevices.ru header.s=mail header.b="Uf/IsyLU"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=sberdevices.ru Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j13-20020a63cf0d000000b005133f65dc69si15767995pgg.219.2023.05.15.02.50.11; Mon, 15 May 2023 02:50:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@sberdevices.ru header.s=mail header.b="Uf/IsyLU"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=sberdevices.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231829AbjEOJtv (ORCPT <rfc822;peekingduck44@gmail.com> + 99 others); Mon, 15 May 2023 05:49:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53890 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236794AbjEOJts (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 15 May 2023 05:49:48 -0400 Received: from mx.sberdevices.ru (mx.sberdevices.ru [45.89.227.171]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4C7DA7 for <linux-kernel@vger.kernel.org>; Mon, 15 May 2023 02:49:44 -0700 (PDT) Received: from s-lin-edge02.sberdevices.ru (localhost [127.0.0.1]) by mx.sberdevices.ru (Postfix) with ESMTP id 915EE5FD16; Mon, 15 May 2023 12:49:41 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sberdevices.ru; s=mail; t=1684144181; bh=Dmj6MVlJqsj8zojvHjdvVHURJoWIYhagZNM7JaN5Dds=; h=From:To:Subject:Date:Message-ID:MIME-Version:Content-Type; b=Uf/IsyLUdE2c+v5zkfr9jL/h4IMMipF+j4vKH5XLB675lh5wbPAcDL2sN8H3UJLtp xlpIzpPQTpsqwkFr7iVB2tU8JB6Bm3v6gTiF2Emg1kI27sWm+or+dg2kOie66s6sSM nrMUu76TljNs6mZocS7M/ybbzUAqeJ+DqVdk8F7GDKmK+H3MpPO2676qvGwO6U0wF+ kBaCR6iRUe98WX1HlfeDgMKl6NckIRQzd9yLp8zXmym2w8Bdz6zFcXqk8TaGgt+mr2 KX51MxCd7d/0UQY8C8zC8EkLWsJ7AxpQTZm0Mtl+sH1rOyVuH1UYyphQSd3KhzuaZ8 /GaTuToSVdESg== Received: from S-MS-EXCH01.sberdevices.ru (S-MS-EXCH01.sberdevices.ru [172.16.1.4]) by mx.sberdevices.ru (Postfix) with ESMTP; Mon, 15 May 2023 12:49:41 +0300 (MSK) From: Arseniy Krasnov <AVKrasnov@sberdevices.ru> To: Liang Yang <liang.yang@amlogic.com>, Miquel Raynal <miquel.raynal@bootlin.com>, Richard Weinberger <richard@nod.at>, Vignesh Raghavendra <vigneshr@ti.com>, Neil Armstrong <neil.armstrong@linaro.org>, Kevin Hilman <khilman@baylibre.com>, Jerome Brunet <jbrunet@baylibre.com>, Martin Blumenstingl <martin.blumenstingl@googlemail.com>, Yixun Lan <yixun.lan@amlogic.com>, Jianxin Pan <jianxin.pan@amlogic.com> CC: <oxffffaa@gmail.com>, <kernel@sberdevices.ru>, Arseniy Krasnov <AVKrasnov@sberdevices.ru>, <linux-mtd@lists.infradead.org>, <linux-arm-kernel@lists.infradead.org>, <linux-amlogic@lists.infradead.org>, <linux-kernel@vger.kernel.org> Subject: [PATCH v4 1/5] mtd: rawnand: meson: fix command sequence for read/write Date: Mon, 15 May 2023 12:44:35 +0300 Message-ID: <20230515094440.3552094-2-AVKrasnov@sberdevices.ru> X-Mailer: git-send-email 2.35.0 In-Reply-To: <20230515094440.3552094-1-AVKrasnov@sberdevices.ru> References: <20230515094440.3552094-1-AVKrasnov@sberdevices.ru> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [172.16.1.6] X-ClientProxiedBy: S-MS-EXCH01.sberdevices.ru (172.16.1.4) To S-MS-EXCH01.sberdevices.ru (172.16.1.4) X-KSMG-Rule-ID: 4 X-KSMG-Message-Action: clean X-KSMG-AntiSpam-Status: not scanned, disabled by settings X-KSMG-AntiSpam-Interceptor-Info: not scanned X-KSMG-AntiPhishing: not scanned, disabled by settings X-KSMG-AntiVirus: Kaspersky Secure Mail Gateway, version 1.1.2.30, bases: 2023/05/15 04:03:00 #21308474 X-KSMG-AntiVirus-Status: Clean, skipped X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765953215058071081?= X-GMAIL-MSGID: =?utf-8?q?1765953215058071081?= |
Series |
refactoring and fix for Meson NAND
|
|
Commit Message
Arseniy Krasnov
May 15, 2023, 9:44 a.m. UTC
This fixes read/write functionality by:
1) Changing NFC_CMD_RB_INT bit value.
2) Adding extra NAND_CMD_STATUS command on each r/w request.
3) Adding extra idle commands during r/w request.
4) Adding extra NAND_CMD_READ0 on each read request.
Without this patch driver works unstable, for example there are a lot
of ECC errors.
Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller")
Suggested-by: Liang Yang <liang.yang@amlogic.com>
Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
---
drivers/mtd/nand/raw/meson_nand.c | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
Comments
Hi Arseniy, AVKrasnov@sberdevices.ru wrote on Mon, 15 May 2023 12:44:35 +0300: > This fixes read/write functionality by: > 1) Changing NFC_CMD_RB_INT bit value. I guess this is a separate fix > 2) Adding extra NAND_CMD_STATUS command on each r/w request. Is this really needed? Looks like you're delaying the next op only. Is using a delay enough? If yes, then it's probably the wrong approach. > 3) Adding extra idle commands during r/w request. Question about this below, might also be a patch on its own? > 4) Adding extra NAND_CMD_READ0 on each read request. > > Without this patch driver works unstable, for example there are a lot > of ECC errors. I believe all the fixes should be Cc'ed to stable, please add in your commits: Cc: stable@... > > Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller") > Suggested-by: Liang Yang <liang.yang@amlogic.com> > Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> > --- > drivers/mtd/nand/raw/meson_nand.c | 30 +++++++++++++++++++++--------- > 1 file changed, 21 insertions(+), 9 deletions(-) > > diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c > index 074e14225c06..2f4d8c84186b 100644 > --- a/drivers/mtd/nand/raw/meson_nand.c > +++ b/drivers/mtd/nand/raw/meson_nand.c > @@ -37,7 +37,7 @@ > #define NFC_CMD_SCRAMBLER_ENABLE BIT(19) > #define NFC_CMD_SCRAMBLER_DISABLE 0 > #define NFC_CMD_SHORTMODE_DISABLE 0 > -#define NFC_CMD_RB_INT BIT(14) > +#define NFC_CMD_RB_INT ((0xb << 10) | BIT(18) | BIT(16)) > > #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) > > @@ -392,7 +392,7 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand, > } > } > > -static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) > +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, int cmd_read0) > { > u32 cmd, cfg; > int ret = 0; > @@ -407,17 +407,29 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) > > reinit_completion(&nfc->completion); > > + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; > + writel(cmd, nfc->reg_base + NFC_REG_CMD); > + meson_nfc_cmd_idle(nfc, 5); Why 5 and 2 below? They look like magic values. Is this totally experimental? > + > /* use the max erase time as the maximum clock for waiting R/B */ > - cmd = NFC_CMD_RB | NFC_CMD_RB_INT > - | nfc->param.chip_select | nfc->timing.tbers_max; This is not documented in the commit log, is it? > + cmd = NFC_CMD_RB | NFC_CMD_RB_INT | nfc->timing.tbers_max; > writel(cmd, nfc->reg_base + NFC_REG_CMD); > + meson_nfc_cmd_idle(nfc, 2); > > ret = wait_for_completion_timeout(&nfc->completion, > msecs_to_jiffies(timeout_ms)); > if (ret == 0) > - ret = -1; > + return -1; Please use real error codes, such as ETIMEDOUT. > > - return ret; > + if (!cmd_read0) > + return 0; > + > + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0; This looks really wrong, I don't get why you would need to send an expensive READ0 command. > + writel(cmd, nfc->reg_base + NFC_REG_CMD); > + meson_nfc_drain_cmd(nfc); > + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); > + > + return 0; > } > > static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) > @@ -623,7 +635,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, > if (in) { > nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART; > writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD); > - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max)); > + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), 1); > } else { > meson_nfc_cmd_idle(nfc, nfc->timing.tadl); > } > @@ -669,7 +681,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, > > cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; > writel(cmd, nfc->reg_base + NFC_REG_CMD); > - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max)); > + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), 0); > > meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); > > @@ -952,7 +964,7 @@ static int meson_nfc_exec_op(struct nand_chip *nand, > break; > > case NAND_OP_WAITRDY_INSTR: > - meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms); > + meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms, 1); > if (instr->delay_ns) > meson_nfc_cmd_idle(nfc, delay_idle); > break; Thanks, Miquèl
Hello Miquel, Liang On 22.05.2023 18:05, Miquel Raynal wrote: > Hi Arseniy, > > AVKrasnov@sberdevices.ru wrote on Mon, 15 May 2023 12:44:35 +0300: > >> This fixes read/write functionality by: >> 1) Changing NFC_CMD_RB_INT bit value. > > I guess this is a separate fix > Ok, I'll move it to separate patch >> 2) Adding extra NAND_CMD_STATUS command on each r/w request. > > Is this really needed? Looks like you're delaying the next op only. Is > using a delay enough? If yes, then it's probably the wrong approach. > >> 3) Adding extra idle commands during r/w request. > > Question about this below, might also be a patch on its own? > >> 4) Adding extra NAND_CMD_READ0 on each read request. >> >> Without this patch driver works unstable, for example there are a lot >> of ECC errors. > > I believe all the fixes should be Cc'ed to stable, please add in your > commits: > > Cc: stable@... > Ack, after everything will be clear with this patch :) >> >> Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller") >> Suggested-by: Liang Yang <liang.yang@amlogic.com> >> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> >> --- >> drivers/mtd/nand/raw/meson_nand.c | 30 +++++++++++++++++++++--------- >> 1 file changed, 21 insertions(+), 9 deletions(-) >> >> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c >> index 074e14225c06..2f4d8c84186b 100644 >> --- a/drivers/mtd/nand/raw/meson_nand.c >> +++ b/drivers/mtd/nand/raw/meson_nand.c >> @@ -37,7 +37,7 @@ >> #define NFC_CMD_SCRAMBLER_ENABLE BIT(19) >> #define NFC_CMD_SCRAMBLER_DISABLE 0 >> #define NFC_CMD_SHORTMODE_DISABLE 0 >> -#define NFC_CMD_RB_INT BIT(14) >> +#define NFC_CMD_RB_INT ((0xb << 10) | BIT(18) | BIT(16)) >> >> #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) >> >> @@ -392,7 +392,7 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand, >> } >> } >> >> -static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) >> +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, int cmd_read0) >> { >> u32 cmd, cfg; >> int ret = 0; >> @@ -407,17 +407,29 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) >> >> reinit_completion(&nfc->completion); >> >> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; >> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >> + meson_nfc_cmd_idle(nfc, 5); > > Why 5 and 2 below? They look like magic values. Is this totally > experimental? @Liang, may be change it to defines ? > >> + >> /* use the max erase time as the maximum clock for waiting R/B */ >> - cmd = NFC_CMD_RB | NFC_CMD_RB_INT >> - | nfc->param.chip_select | nfc->timing.tbers_max; > > This is not documented in the commit log, is it? > >> + cmd = NFC_CMD_RB | NFC_CMD_RB_INT | nfc->timing.tbers_max; >> writel(cmd, nfc->reg_base + NFC_REG_CMD); >> + meson_nfc_cmd_idle(nfc, 2); >> >> ret = wait_for_completion_timeout(&nfc->completion, >> msecs_to_jiffies(timeout_ms)); >> if (ret == 0) >> - ret = -1; >> + return -1; > > Please use real error codes, such as ETIMEDOUT. Ack > >> >> - return ret; >> + if (!cmd_read0) >> + return 0; >> + >> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0; > > This looks really wrong, I don't get why you would need to send an > expensive READ0 command. This logic was suggested by @Liang Yang here to fix this driver (suggested as patch): https://lore.kernel.org/linux-mtd/8537e736-44a8-d17b-7923-25d5bd406dcc@sberdevices.ru/T/#m0df09d2ab2cac98431fb268a4ce3c00dc5c7a69e @Liang, could You please give us more details? Thanks, Arseniy > >> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >> + meson_nfc_drain_cmd(nfc); >> + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); >> + >> + return 0; >> } >> >> static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) >> @@ -623,7 +635,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, >> if (in) { >> nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART; >> writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD); >> - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max)); >> + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), 1); >> } else { >> meson_nfc_cmd_idle(nfc, nfc->timing.tadl); >> } >> @@ -669,7 +681,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, >> >> cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; >> writel(cmd, nfc->reg_base + NFC_REG_CMD); >> - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max)); >> + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), 0); >> >> meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); >> >> @@ -952,7 +964,7 @@ static int meson_nfc_exec_op(struct nand_chip *nand, >> break; >> >> case NAND_OP_WAITRDY_INSTR: >> - meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms); >> + meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms, 1); >> if (instr->delay_ns) >> meson_nfc_cmd_idle(nfc, delay_idle); >> break; > > > Thanks, > Miquèl
On 23.05.2023 12:12, Arseniy Krasnov wrote: > Hello Miquel, Liang > > On 22.05.2023 18:05, Miquel Raynal wrote: >> Hi Arseniy, >> >> AVKrasnov@sberdevices.ru wrote on Mon, 15 May 2023 12:44:35 +0300: >> >>> This fixes read/write functionality by: >>> 1) Changing NFC_CMD_RB_INT bit value. >> >> I guess this is a separate fix >> > > Ok, I'll move it to separate patch > >>> 2) Adding extra NAND_CMD_STATUS command on each r/w request. >> >> Is this really needed? Looks like you're delaying the next op only. Is >> using a delay enough? If yes, then it's probably the wrong approach. Hi Miquel, small update, I found some details from @Liang's message in v1 talks from the last month: * After sending NAND_CMD_READ0, address, NAND_CMD_READSTART and read status(NAND_CMD_STATUS = 0x70) commands, it should send NAND_CMD_READ0 command for exiting the read status mode from the datasheet from NAND device. but previous meson_nfc_queue_rb() only checks the Ready/Busy pin and it doesn't send read status(NAND_CMD_STATUS = 0x70) command. i think there is something wrong with the Ready/Busy pin(please check the hardware whether this Ready/Busy pin is connected with SOC) or the source code. i have the board without Ready/Busy pin and prefer to use the nfc command called RB_IO6. it sends NAND_CMD_STATUS command and checks bit6 of the status register of NAND device from the data bus and generate IRQ if ready. * I guess, that sequence of commands from this patch is described in datasheet (unfortunately I don't have it and relied on the old driver). Yesterday I tried to remove sending of NAND_CMD_STATUS from this patch, but it broke current driver - i had ECC errors, so it looks like "shot in the dark" situation, to understand this logic. Thanks, Arseniy >> >>> 3) Adding extra idle commands during r/w request. >> >> Question about this below, might also be a patch on its own? >> >>> 4) Adding extra NAND_CMD_READ0 on each read request. >>> >>> Without this patch driver works unstable, for example there are a lot >>> of ECC errors. >> >> I believe all the fixes should be Cc'ed to stable, please add in your >> commits: >> >> Cc: stable@... >> > > Ack, after everything will be clear with this patch :) > >>> >>> Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller") >>> Suggested-by: Liang Yang <liang.yang@amlogic.com> >>> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> >>> --- >>> drivers/mtd/nand/raw/meson_nand.c | 30 +++++++++++++++++++++--------- >>> 1 file changed, 21 insertions(+), 9 deletions(-) >>> >>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c >>> index 074e14225c06..2f4d8c84186b 100644 >>> --- a/drivers/mtd/nand/raw/meson_nand.c >>> +++ b/drivers/mtd/nand/raw/meson_nand.c >>> @@ -37,7 +37,7 @@ >>> #define NFC_CMD_SCRAMBLER_ENABLE BIT(19) >>> #define NFC_CMD_SCRAMBLER_DISABLE 0 >>> #define NFC_CMD_SHORTMODE_DISABLE 0 >>> -#define NFC_CMD_RB_INT BIT(14) >>> +#define NFC_CMD_RB_INT ((0xb << 10) | BIT(18) | BIT(16)) >>> >>> #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) >>> >>> @@ -392,7 +392,7 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand, >>> } >>> } >>> >>> -static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) >>> +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, int cmd_read0) >>> { >>> u32 cmd, cfg; >>> int ret = 0; >>> @@ -407,17 +407,29 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) >>> >>> reinit_completion(&nfc->completion); >>> >>> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; >>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >>> + meson_nfc_cmd_idle(nfc, 5); >> >> Why 5 and 2 below? They look like magic values. Is this totally >> experimental? > > @Liang, may be change it to defines ? > >> >>> + >>> /* use the max erase time as the maximum clock for waiting R/B */ >>> - cmd = NFC_CMD_RB | NFC_CMD_RB_INT >>> - | nfc->param.chip_select | nfc->timing.tbers_max; >> >> This is not documented in the commit log, is it? >> >>> + cmd = NFC_CMD_RB | NFC_CMD_RB_INT | nfc->timing.tbers_max; >>> writel(cmd, nfc->reg_base + NFC_REG_CMD); >>> + meson_nfc_cmd_idle(nfc, 2); >>> >>> ret = wait_for_completion_timeout(&nfc->completion, >>> msecs_to_jiffies(timeout_ms)); >>> if (ret == 0) >>> - ret = -1; >>> + return -1; >> >> Please use real error codes, such as ETIMEDOUT. > > Ack > >> >>> >>> - return ret; >>> + if (!cmd_read0) >>> + return 0; >>> + >>> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0; >> >> This looks really wrong, I don't get why you would need to send an >> expensive READ0 command. > > This logic was suggested by @Liang Yang here to fix this driver (suggested as patch): > https://lore.kernel.org/linux-mtd/8537e736-44a8-d17b-7923-25d5bd406dcc@sberdevices.ru/T/#m0df09d2ab2cac98431fb268a4ce3c00dc5c7a69e > @Liang, could You please give us more details? > > Thanks, Arseniy > >> >>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >>> + meson_nfc_drain_cmd(nfc); >>> + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); >>> + >>> + return 0; >>> } >>> >>> static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) >>> @@ -623,7 +635,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, >>> if (in) { >>> nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART; >>> writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD); >>> - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max)); >>> + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), 1); >>> } else { >>> meson_nfc_cmd_idle(nfc, nfc->timing.tadl); >>> } >>> @@ -669,7 +681,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, >>> >>> cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; >>> writel(cmd, nfc->reg_base + NFC_REG_CMD); >>> - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max)); >>> + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), 0); >>> >>> meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); >>> >>> @@ -952,7 +964,7 @@ static int meson_nfc_exec_op(struct nand_chip *nand, >>> break; >>> >>> case NAND_OP_WAITRDY_INSTR: >>> - meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms); >>> + meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms, 1); >>> if (instr->delay_ns) >>> meson_nfc_cmd_idle(nfc, delay_idle); >>> break; >> >> >> Thanks, >> Miquèl
Hi Arseniy, avkrasnov@sberdevices.ru wrote on Wed, 24 May 2023 12:05:47 +0300: > On 23.05.2023 12:12, Arseniy Krasnov wrote: > > Hello Miquel, Liang > > > > On 22.05.2023 18:05, Miquel Raynal wrote: > >> Hi Arseniy, > >> > >> AVKrasnov@sberdevices.ru wrote on Mon, 15 May 2023 12:44:35 +0300: > >> > >>> This fixes read/write functionality by: > >>> 1) Changing NFC_CMD_RB_INT bit value. > >> > >> I guess this is a separate fix > >> > > > > Ok, I'll move it to separate patch > > > >>> 2) Adding extra NAND_CMD_STATUS command on each r/w request. > >> > >> Is this really needed? Looks like you're delaying the next op only. Is > >> using a delay enough? If yes, then it's probably the wrong approach. > > Hi Miquel, small update, I found some details from @Liang's message in v1 talks from the last month: > > * > After sending NAND_CMD_READ0, address, NAND_CMD_READSTART and read status(NAND_CMD_STATUS = 0x70) commands, it should send > NAND_CMD_READ0 command for exiting the read status mode from the datasheet from NAND device. That is true. > but previous meson_nfc_queue_rb() > only checks the Ready/Busy pin and it doesn't send read status(NAND_CMD_STATUS = 0x70) command. > i think there is something wrong with the Ready/Busy pin(please check the hardware whether this > Ready/Busy pin is connected with SOC) or the source code. i have the board without Ready/Busy pin and prefer to use the > nfc command called RB_IO6. it sends NAND_CMD_STATUS command and checks bit6 of the status register of NAND device from the > data bus and generate IRQ if ready. > * > > I guess, that sequence of commands from this patch is described in datasheet (unfortunately I don't have it and relied on the old driver). > Yesterday I tried to remove sending of NAND_CMD_STATUS from this patch, but it broke current driver - i had ECC errors, so it looks like > "shot in the dark" situation, to understand this logic. When an operation on the NAND array happens (eg. read, prog, erase), you need to wait "some time" before accessing the internal sram or even the chip which is "busy" until it gets "ready" again. You can probe the ready/busy pin (that's the hardware way, fast and reliable) or you can poll a status with NAND_CMD_STATUS. The chips are designed so they can actually process that command while they are doing time consuming tasks to update the host. But IIRC every byte read will return the status until you send READ0 again, which means "I'm done with the status read" somehow. Please see nand_soft_waitrdy() in order to understand how this is supposed to work. You can even use that helper (which is exported) instead of open-coding it in your driver. See atmel or sunxi implementations for instance. As using the native RB pin is better, you would need to identify whether you have one or not at probe time and then either poll the relevant bit of your controller if there is one, or fallback to the soft read (which should fallback on exec_op in the end). Thanks, Miquèl
On 26.05.2023 20:22, Miquel Raynal wrote: > Hi Arseniy, > > avkrasnov@sberdevices.ru wrote on Wed, 24 May 2023 12:05:47 +0300: > >> On 23.05.2023 12:12, Arseniy Krasnov wrote: >>> Hello Miquel, Liang >>> >>> On 22.05.2023 18:05, Miquel Raynal wrote: >>>> Hi Arseniy, >>>> >>>> AVKrasnov@sberdevices.ru wrote on Mon, 15 May 2023 12:44:35 +0300: >>>> >>>>> This fixes read/write functionality by: >>>>> 1) Changing NFC_CMD_RB_INT bit value. >>>> >>>> I guess this is a separate fix >>>> >>> >>> Ok, I'll move it to separate patch >>> >>>>> 2) Adding extra NAND_CMD_STATUS command on each r/w request. >>>> >>>> Is this really needed? Looks like you're delaying the next op only. Is >>>> using a delay enough? If yes, then it's probably the wrong approach. >> >> Hi Miquel, small update, I found some details from @Liang's message in v1 talks from the last month: >> >> * >> After sending NAND_CMD_READ0, address, NAND_CMD_READSTART and read status(NAND_CMD_STATUS = 0x70) commands, it should send >> NAND_CMD_READ0 command for exiting the read status mode from the datasheet from NAND device. > > That is true. > >> but previous meson_nfc_queue_rb() >> only checks the Ready/Busy pin and it doesn't send read status(NAND_CMD_STATUS = 0x70) command. >> i think there is something wrong with the Ready/Busy pin(please check the hardware whether this >> Ready/Busy pin is connected with SOC) or the source code. i have the board without Ready/Busy pin and prefer to use the >> nfc command called RB_IO6. it sends NAND_CMD_STATUS command and checks bit6 of the status register of NAND device from the >> data bus and generate IRQ if ready. >> * >> >> I guess, that sequence of commands from this patch is described in datasheet (unfortunately I don't have it and relied on the old driver). >> Yesterday I tried to remove sending of NAND_CMD_STATUS from this patch, but it broke current driver - i had ECC errors, so it looks like >> "shot in the dark" situation, to understand this logic. > > When an operation on the NAND array happens (eg. read, prog, erase), > you need to wait "some time" before accessing the internal sram or even > the chip which is "busy" until it gets "ready" again. You can probe the > ready/busy pin (that's the hardware way, fast and reliable) or you can > poll a status with NAND_CMD_STATUS. The chips are designed so they can > actually process that command while they are doing time consuming tasks > to update the host. But IIRC every byte read will return the status > until you send READ0 again, which means "I'm done with the status > read" somehow. > > Please see nand_soft_waitrdy() in order to understand how this is > supposed to work. You can even use that helper (which is exported) > instead of open-coding it in your driver. See atmel or sunxi > implementations for instance. > > As using the native RB pin is better, you would need to identify > whether you have one or not at probe time and then either poll the > relevant bit of your controller if there is one, or fallback to the > soft read (which should fallback on exec_op in the end). Thanks for this information! I'll use 'nand_soft_waitrdy()' at least, because i guess that there is no RB pin on my device. Thanks, Arseniy > > Thanks, > Miquèl
Hi Arseniy, avkrasnov@sberdevices.ru wrote on Tue, 30 May 2023 14:19:08 +0300: > On 26.05.2023 20:22, Miquel Raynal wrote: > > Hi Arseniy, > > > > avkrasnov@sberdevices.ru wrote on Wed, 24 May 2023 12:05:47 +0300: > > > >> On 23.05.2023 12:12, Arseniy Krasnov wrote: > >>> Hello Miquel, Liang > >>> > >>> On 22.05.2023 18:05, Miquel Raynal wrote: > >>>> Hi Arseniy, > >>>> > >>>> AVKrasnov@sberdevices.ru wrote on Mon, 15 May 2023 12:44:35 +0300: > >>>> > >>>>> This fixes read/write functionality by: > >>>>> 1) Changing NFC_CMD_RB_INT bit value. > >>>> > >>>> I guess this is a separate fix > >>>> > >>> > >>> Ok, I'll move it to separate patch > >>> > >>>>> 2) Adding extra NAND_CMD_STATUS command on each r/w request. > >>>> > >>>> Is this really needed? Looks like you're delaying the next op only. Is > >>>> using a delay enough? If yes, then it's probably the wrong approach. > >> > >> Hi Miquel, small update, I found some details from @Liang's message in v1 talks from the last month: > >> > >> * > >> After sending NAND_CMD_READ0, address, NAND_CMD_READSTART and read status(NAND_CMD_STATUS = 0x70) commands, it should send > >> NAND_CMD_READ0 command for exiting the read status mode from the datasheet from NAND device. > > > > That is true. > > > >> but previous meson_nfc_queue_rb() > >> only checks the Ready/Busy pin and it doesn't send read status(NAND_CMD_STATUS = 0x70) command. > >> i think there is something wrong with the Ready/Busy pin(please check the hardware whether this > >> Ready/Busy pin is connected with SOC) or the source code. i have the board without Ready/Busy pin and prefer to use the > >> nfc command called RB_IO6. it sends NAND_CMD_STATUS command and checks bit6 of the status register of NAND device from the > >> data bus and generate IRQ if ready. > >> * > >> > >> I guess, that sequence of commands from this patch is described in datasheet (unfortunately I don't have it and relied on the old driver). > >> Yesterday I tried to remove sending of NAND_CMD_STATUS from this patch, but it broke current driver - i had ECC errors, so it looks like > >> "shot in the dark" situation, to understand this logic. > > > > When an operation on the NAND array happens (eg. read, prog, erase), > > you need to wait "some time" before accessing the internal sram or even > > the chip which is "busy" until it gets "ready" again. You can probe the > > ready/busy pin (that's the hardware way, fast and reliable) or you can > > poll a status with NAND_CMD_STATUS. The chips are designed so they can > > actually process that command while they are doing time consuming tasks > > to update the host. But IIRC every byte read will return the status > > until you send READ0 again, which means "I'm done with the status > > read" somehow. > > > > Please see nand_soft_waitrdy() in order to understand how this is > > supposed to work. You can even use that helper (which is exported) > > instead of open-coding it in your driver. See atmel or sunxi > > implementations for instance. > > > > As using the native RB pin is better, you would need to identify > > whether you have one or not at probe time and then either poll the > > relevant bit of your controller if there is one, or fallback to the > > soft read (which should fallback on exec_op in the end). > > Thanks for this information! I'll use 'nand_soft_waitrdy()' at least, because i guess that > there is no RB pin on my device. Currently there is only support for the physical pin IIRC. This means you cannot just drop it. You need to support both. Thanks, Miquèl
On 30.05.2023 16:05, Miquel Raynal wrote: > Hi Arseniy, > > avkrasnov@sberdevices.ru wrote on Tue, 30 May 2023 14:19:08 +0300: > >> On 26.05.2023 20:22, Miquel Raynal wrote: >>> Hi Arseniy, >>> >>> avkrasnov@sberdevices.ru wrote on Wed, 24 May 2023 12:05:47 +0300: >>> >>>> On 23.05.2023 12:12, Arseniy Krasnov wrote: >>>>> Hello Miquel, Liang >>>>> >>>>> On 22.05.2023 18:05, Miquel Raynal wrote: >>>>>> Hi Arseniy, >>>>>> >>>>>> AVKrasnov@sberdevices.ru wrote on Mon, 15 May 2023 12:44:35 +0300: >>>>>> >>>>>>> This fixes read/write functionality by: >>>>>>> 1) Changing NFC_CMD_RB_INT bit value. >>>>>> >>>>>> I guess this is a separate fix >>>>>> >>>>> >>>>> Ok, I'll move it to separate patch >>>>> >>>>>>> 2) Adding extra NAND_CMD_STATUS command on each r/w request. >>>>>> >>>>>> Is this really needed? Looks like you're delaying the next op only. Is >>>>>> using a delay enough? If yes, then it's probably the wrong approach. >>>> >>>> Hi Miquel, small update, I found some details from @Liang's message in v1 talks from the last month: >>>> >>>> * >>>> After sending NAND_CMD_READ0, address, NAND_CMD_READSTART and read status(NAND_CMD_STATUS = 0x70) commands, it should send >>>> NAND_CMD_READ0 command for exiting the read status mode from the datasheet from NAND device. >>> >>> That is true. >>> >>>> but previous meson_nfc_queue_rb() >>>> only checks the Ready/Busy pin and it doesn't send read status(NAND_CMD_STATUS = 0x70) command. >>>> i think there is something wrong with the Ready/Busy pin(please check the hardware whether this >>>> Ready/Busy pin is connected with SOC) or the source code. i have the board without Ready/Busy pin and prefer to use the >>>> nfc command called RB_IO6. it sends NAND_CMD_STATUS command and checks bit6 of the status register of NAND device from the >>>> data bus and generate IRQ if ready. >>>> * >>>> >>>> I guess, that sequence of commands from this patch is described in datasheet (unfortunately I don't have it and relied on the old driver). >>>> Yesterday I tried to remove sending of NAND_CMD_STATUS from this patch, but it broke current driver - i had ECC errors, so it looks like >>>> "shot in the dark" situation, to understand this logic. >>> >>> When an operation on the NAND array happens (eg. read, prog, erase), >>> you need to wait "some time" before accessing the internal sram or even >>> the chip which is "busy" until it gets "ready" again. You can probe the >>> ready/busy pin (that's the hardware way, fast and reliable) or you can >>> poll a status with NAND_CMD_STATUS. The chips are designed so they can >>> actually process that command while they are doing time consuming tasks >>> to update the host. But IIRC every byte read will return the status >>> until you send READ0 again, which means "I'm done with the status >>> read" somehow. >>> >>> Please see nand_soft_waitrdy() in order to understand how this is >>> supposed to work. You can even use that helper (which is exported) >>> instead of open-coding it in your driver. See atmel or sunxi >>> implementations for instance. >>> >>> As using the native RB pin is better, you would need to identify >>> whether you have one or not at probe time and then either poll the >>> relevant bit of your controller if there is one, or fallback to the >>> soft read (which should fallback on exec_op in the end). >> >> Thanks for this information! I'll use 'nand_soft_waitrdy()' at least, because i guess that >> there is no RB pin on my device. > > Currently there is only support for the physical pin IIRC. This means > you cannot just drop it. You need to support both. Yes, i'm not going to drop RB pin support, but as I don't have device to test it(i guess), i'll add 'nand_sort_waitrdy()' anyway. Thanks, Arseniy > > Thanks, > Miquèl УВЕДОМЛЕНИЕ О КОНФИДЕНЦИАЛЬНОСТИ: Это электронное сообщение и любые документы, приложенные к нему, содержат конфиденциальную информацию. Настоящим уведомляем Вас о том, что если это сообщение не предназначено Вам, использование, копирование, распространение информации, содержащейся в настоящем сообщении, а также осуществление любых действий на основе этой информации, строго запрещено. Если Вы получили это сообщение по ошибке, пожалуйста, сообщите об этом отправителю по электронной почте и удалите это сообщение. CONFIDENTIALITY NOTICE: This email and any files attached to it are confidential. If you are not the intended recipient you are notified that using, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited. If you have received this email in error please notify the sender and delete this email.
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 074e14225c06..2f4d8c84186b 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -37,7 +37,7 @@ #define NFC_CMD_SCRAMBLER_ENABLE BIT(19) #define NFC_CMD_SCRAMBLER_DISABLE 0 #define NFC_CMD_SHORTMODE_DISABLE 0 -#define NFC_CMD_RB_INT BIT(14) +#define NFC_CMD_RB_INT ((0xb << 10) | BIT(18) | BIT(16)) #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) @@ -392,7 +392,7 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand, } } -static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, int cmd_read0) { u32 cmd, cfg; int ret = 0; @@ -407,17 +407,29 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) reinit_completion(&nfc->completion); + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + meson_nfc_cmd_idle(nfc, 5); + /* use the max erase time as the maximum clock for waiting R/B */ - cmd = NFC_CMD_RB | NFC_CMD_RB_INT - | nfc->param.chip_select | nfc->timing.tbers_max; + cmd = NFC_CMD_RB | NFC_CMD_RB_INT | nfc->timing.tbers_max; writel(cmd, nfc->reg_base + NFC_REG_CMD); + meson_nfc_cmd_idle(nfc, 2); ret = wait_for_completion_timeout(&nfc->completion, msecs_to_jiffies(timeout_ms)); if (ret == 0) - ret = -1; + return -1; - return ret; + if (!cmd_read0) + return 0; + + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); + + return 0; } static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) @@ -623,7 +635,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, if (in) { nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART; writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD); - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max)); + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), 1); } else { meson_nfc_cmd_idle(nfc, nfc->timing.tadl); } @@ -669,7 +681,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; writel(cmd, nfc->reg_base + NFC_REG_CMD); - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max)); + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), 0); meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); @@ -952,7 +964,7 @@ static int meson_nfc_exec_op(struct nand_chip *nand, break; case NAND_OP_WAITRDY_INSTR: - meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms); + meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms, 1); if (instr->delay_ns) meson_nfc_cmd_idle(nfc, delay_idle); break;