* [PATCH v3 0/2] Meson NAND: waiting w/o wired ready/busy pin
@ 2023-06-08 4:47 Arseniy Krasnov
2023-06-08 4:47 ` [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property Arseniy Krasnov
2023-06-08 4:47 ` [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin Arseniy Krasnov
0 siblings, 2 replies; 12+ messages in thread
From: Arseniy Krasnov @ 2023-06-08 4:47 UTC (permalink / raw)
To: Liang Yang, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl
Cc: oxffffaa, kernel, Arseniy Krasnov, linux-mtd, devicetree,
linux-arm-kernel, linux-amlogic, linux-kernel
Main thing that this patchset adds is support for waiting for command
completion when there is no wired ready/busy pin. This is implemented
by using Meson specific command which operates without wired pin, but
supports interrupt driven waiting (default way for waiting without
hardware pin is 'nand_soft_waitrdy()' which uses software loop instead
of interrupt). To select which mode to use during driver initialization,
common NAND controller property is used - 'nand-rb'. It is described in
'nand-controller.yaml'. But for Meson, its description was missed in
'amlogic,meson-nand.yaml', so this patchset also adds support for it.
Patch for bindings was tested with dt_binding_check and dtbs_check.
Links:
v1 (as two separate patches):
https://lore.kernel.org/linux-mtd/20230606193507.35024-1-AVKrasnov@sberdevices.ru/
https://lore.kernel.org/linux-mtd/20230607073015.1280085-1-AVKrasnov@sberdevices.ru/
v2 (tagged as v1, but consider it as v2):
https://lore.kernel.org/linux-mtd/20230607145026.2899547-1-AVKrasnov@sberdevices.ru/
Changelog:
v1 -> v2:
* Two separate patches:
For bindings: https://lore.kernel.org/linux-mtd/20230606193507.35024-1-AVKrasnov@sberdevices.ru/
For driver: https://lore.kernel.org/linux-mtd/20230607073015.1280085-1-AVKrasnov@sberdevices.ru/
Now fixed/updated and combined to this patchset with v1 version.
* In binding patch:
* Invalid type of 'nand-rb' is fixed, it was 'bool', now it is 'uint32 array' as required. Also
new declaration of 'nand-rb' contains several restrictions like number of elements and min/max
value of elements.
* Location of 'nand-rb' is moved from the controller object to the chip object as required.
* In driver patch:
* Update comment which describes when it is needed to send NAND_CMD_READ0 to
leave command waiting loop.
* Change type of 'no_rb_pin' to 'bool' as in v1. Now it is just a flag which selects
mode to wait for command completion.
v2 -> v3:
* In binding patch:
* 'minimum' property is dropped, because 'nand-rb' is unsigned.
* In driver patch:
* Logic of 'no_rb_pin' parsing is reworked a little bit. For example to return error
code from 'of_property_read_u32()'.
Arseniy Krasnov (2):
dt-bindings: nand: meson: Fix 'nand-rb' property
mtd: rawnand: meson: waiting w/o wired ready/busy pin
.../bindings/mtd/amlogic,meson-nand.yaml | 6 ++
drivers/mtd/nand/raw/meson_nand.c | 77 ++++++++++++++++++-
2 files changed, 79 insertions(+), 4 deletions(-)
--
2.35.0
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property 2023-06-08 4:47 [PATCH v3 0/2] Meson NAND: waiting w/o wired ready/busy pin Arseniy Krasnov @ 2023-06-08 4:47 ` Arseniy Krasnov 2023-06-08 12:01 ` Krzysztof Kozlowski 2023-06-09 15:25 ` Miquel Raynal 2023-06-08 4:47 ` [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin Arseniy Krasnov 1 sibling, 2 replies; 12+ messages in thread From: Arseniy Krasnov @ 2023-06-08 4:47 UTC (permalink / raw) To: Liang Yang, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl Cc: oxffffaa, kernel, Arseniy Krasnov, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel Add description of 'nand-rb' property. Use "Fixes" because this property must be supported since the beginning. Fixes: fbc00b5e746f ("dt-bindings: nand: meson: convert txt to yaml") Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> --- .../devicetree/bindings/mtd/amlogic,meson-nand.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml b/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml index 28fb9a7dd70f..3bec8af91bbb 100644 --- a/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml +++ b/Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml @@ -58,6 +58,11 @@ patternProperties: meson-gxl-nfc 8, 16, 24, 30, 40, 50, 60 meson-axg-nfc 8 + nand-rb: + maxItems: 1 + items: + maximum: 0 + required: - compatible - reg @@ -87,6 +92,7 @@ examples: nand@0 { reg = <0>; + nand-rb = <0>; }; }; -- 2.35.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property 2023-06-08 4:47 ` [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property Arseniy Krasnov @ 2023-06-08 12:01 ` Krzysztof Kozlowski 2023-06-09 15:25 ` Miquel Raynal 1 sibling, 0 replies; 12+ messages in thread From: Krzysztof Kozlowski @ 2023-06-08 12:01 UTC (permalink / raw) To: Arseniy Krasnov, Liang Yang, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl Cc: oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel On 08/06/2023 06:47, Arseniy Krasnov wrote: > Add description of 'nand-rb' property. Use "Fixes" because this property > must be supported since the beginning. > > Fixes: fbc00b5e746f ("dt-bindings: nand: meson: convert txt to yaml") > Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Best regards, Krzysztof ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property 2023-06-08 4:47 ` [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property Arseniy Krasnov 2023-06-08 12:01 ` Krzysztof Kozlowski @ 2023-06-09 15:25 ` Miquel Raynal 1 sibling, 0 replies; 12+ messages in thread From: Miquel Raynal @ 2023-06-09 15:25 UTC (permalink / raw) To: Arseniy Krasnov, Liang Yang, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl Cc: oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel On Thu, 2023-06-08 at 04:47:27 UTC, Arseniy Krasnov wrote: > Add description of 'nand-rb' property. Use "Fixes" because this property > must be supported since the beginning. > > Fixes: fbc00b5e746f ("dt-bindings: nand: meson: convert txt to yaml") > Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> > Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks. Miquel ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-06-08 4:47 [PATCH v3 0/2] Meson NAND: waiting w/o wired ready/busy pin Arseniy Krasnov 2023-06-08 4:47 ` [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property Arseniy Krasnov @ 2023-06-08 4:47 ` Arseniy Krasnov 2023-06-09 15:24 ` Miquel Raynal 2023-07-04 12:43 ` Miquel Raynal 1 sibling, 2 replies; 12+ messages in thread From: Arseniy Krasnov @ 2023-06-08 4:47 UTC (permalink / raw) To: Liang Yang, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl Cc: oxffffaa, kernel, Arseniy Krasnov, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel If there is no wired ready/busy pin, classic way to wait for command completion is to use function 'nand_soft_waitrdy()'. Meson NAND has special command which allows to wait for NAND_STATUS_READY bit without reading status in a software loop (as 'nand_soft_waitrdy()' does). To use it send this command along with NAND_CMD_STATUS, then wait for an interrupt, and after interrupt send NAND_CMD_READ0. So this feature allows to use interrupt driven waiting without wired ready/busy pin. Suggested-by: Liang Yang <liang.yang@amlogic.com> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> --- drivers/mtd/nand/raw/meson_nand.c | 77 +++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 074e14225c06..9f05e113b4ea 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -38,6 +38,7 @@ #define NFC_CMD_SCRAMBLER_DISABLE 0 #define NFC_CMD_SHORTMODE_DISABLE 0 #define NFC_CMD_RB_INT BIT(14) +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) @@ -179,6 +180,7 @@ struct meson_nfc { u32 info_bytes; unsigned long assigned_cs; + bool no_rb_pin; }; enum { @@ -392,7 +394,42 @@ 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_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, + bool need_cmd_read0) +{ + u32 cmd, cfg; + + meson_nfc_cmd_idle(nfc, nfc->timing.twb); + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); + + cfg = readl(nfc->reg_base + NFC_REG_CFG); + cfg |= NFC_RB_IRQ_EN; + writel(cfg, nfc->reg_base + NFC_REG_CFG); + + reinit_completion(&nfc->completion); + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + /* use the max erase time as the maximum clock for waiting R/B */ + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + if (!wait_for_completion_timeout(&nfc->completion, + msecs_to_jiffies(timeout_ms))) + return -ETIMEDOUT; + + if (need_cmd_read0) { + 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 int meson_nfc_wait_rb_pin(struct meson_nfc *nfc, int timeout_ms) { u32 cmd, cfg; int ret = 0; @@ -420,6 +457,27 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) return ret; } +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, + bool need_cmd_read0) +{ + if (nfc->no_rb_pin) { + /* This mode is used when there is no wired R/B pin. + * It works like 'nand_soft_waitrdy()', but instead of + * polling NAND_CMD_STATUS bit in the software loop, + * it will wait for interrupt - controllers checks IO + * bus and when it detects NAND_CMD_STATUS on it, it + * raises interrupt. After interrupt, NAND_CMD_READ0 is + * sent as terminator of the ready waiting procedure if + * needed (for all cases except page programming - this + * is reason of 'need_cmd_read0' flag). + */ + return meson_nfc_wait_no_rb_pin(nfc, timeout_ms, + need_cmd_read0); + } else { + return meson_nfc_wait_rb_pin(nfc, timeout_ms); + } +} + static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) { struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); @@ -623,7 +681,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), true); } else { meson_nfc_cmd_idle(nfc, nfc->timing.tadl); } @@ -669,7 +727,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), false); meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); @@ -952,7 +1010,8 @@ 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, + true); if (instr->delay_ns) meson_nfc_cmd_idle(nfc, delay_idle); break; @@ -1248,6 +1307,7 @@ meson_nfc_nand_chip_init(struct device *dev, struct mtd_info *mtd; int ret, i; u32 tmp, nsels; + u32 nand_rb_val = 0; nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); if (!nsels || nsels > MAX_CE_NUM) { @@ -1287,6 +1347,15 @@ meson_nfc_nand_chip_init(struct device *dev, mtd->owner = THIS_MODULE; mtd->dev.parent = dev; + ret = of_property_read_u32(np, "nand-rb", &nand_rb_val); + if (ret == -EINVAL) + nfc->no_rb_pin = true; + else if (ret) + return ret; + + if (nand_rb_val) + return -EINVAL; + ret = nand_scan(nand, nsels); if (ret) return ret; -- 2.35.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-06-08 4:47 ` [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin Arseniy Krasnov @ 2023-06-09 15:24 ` Miquel Raynal 2023-07-04 12:43 ` Miquel Raynal 1 sibling, 0 replies; 12+ messages in thread From: Miquel Raynal @ 2023-06-09 15:24 UTC (permalink / raw) To: Arseniy Krasnov, Liang Yang, Miquel Raynal, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl Cc: oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel On Thu, 2023-06-08 at 04:47:28 UTC, Arseniy Krasnov wrote: > If there is no wired ready/busy pin, classic way to wait for command > completion is to use function 'nand_soft_waitrdy()'. Meson NAND has > special command which allows to wait for NAND_STATUS_READY bit without > reading status in a software loop (as 'nand_soft_waitrdy()' does). To > use it send this command along with NAND_CMD_STATUS, then wait for an > interrupt, and after interrupt send NAND_CMD_READ0. So this feature > allows to use interrupt driven waiting without wired ready/busy pin. > > Suggested-by: Liang Yang <liang.yang@amlogic.com> > Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks. Miquel ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-06-08 4:47 ` [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin Arseniy Krasnov 2023-06-09 15:24 ` Miquel Raynal @ 2023-07-04 12:43 ` Miquel Raynal 2023-07-04 12:46 ` Arseniy Krasnov 1 sibling, 1 reply; 12+ messages in thread From: Miquel Raynal @ 2023-07-04 12:43 UTC (permalink / raw) To: Arseniy Krasnov Cc: Liang Yang, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl, oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel Hi Arseniy, AVKrasnov@sberdevices.ru wrote on Thu, 8 Jun 2023 07:47:28 +0300: > If there is no wired ready/busy pin, classic way to wait for command > completion is to use function 'nand_soft_waitrdy()'. Meson NAND has > special command which allows to wait for NAND_STATUS_READY bit without > reading status in a software loop (as 'nand_soft_waitrdy()' does). To > use it send this command along with NAND_CMD_STATUS, then wait for an > interrupt, and after interrupt send NAND_CMD_READ0. So this feature > allows to use interrupt driven waiting without wired ready/busy pin. > > Suggested-by: Liang Yang <liang.yang@amlogic.com> > Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> > --- > drivers/mtd/nand/raw/meson_nand.c | 77 +++++++++++++++++++++++++++++-- > 1 file changed, 73 insertions(+), 4 deletions(-) > > diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c > index 074e14225c06..9f05e113b4ea 100644 > --- a/drivers/mtd/nand/raw/meson_nand.c > +++ b/drivers/mtd/nand/raw/meson_nand.c > @@ -38,6 +38,7 @@ > #define NFC_CMD_SCRAMBLER_DISABLE 0 > #define NFC_CMD_SHORTMODE_DISABLE 0 > #define NFC_CMD_RB_INT BIT(14) > +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) > > #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) > > @@ -179,6 +180,7 @@ struct meson_nfc { > u32 info_bytes; > > unsigned long assigned_cs; > + bool no_rb_pin; > }; > > enum { > @@ -392,7 +394,42 @@ 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_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, > + bool need_cmd_read0) > +{ > + u32 cmd, cfg; > + > + meson_nfc_cmd_idle(nfc, nfc->timing.twb); > + meson_nfc_drain_cmd(nfc); > + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); > + > + cfg = readl(nfc->reg_base + NFC_REG_CFG); > + cfg |= NFC_RB_IRQ_EN; > + writel(cfg, nfc->reg_base + NFC_REG_CFG); > + > + reinit_completion(&nfc->completion); > + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; > + writel(cmd, nfc->reg_base + NFC_REG_CMD); > + > + /* use the max erase time as the maximum clock for waiting R/B */ > + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; > + writel(cmd, nfc->reg_base + NFC_REG_CMD); > + > + if (!wait_for_completion_timeout(&nfc->completion, > + msecs_to_jiffies(timeout_ms))) > + return -ETIMEDOUT; > + > + if (need_cmd_read0) { > + 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); > + } I forgot about this, you should avoid open coding core helpers, can you please send a followup patch to use nand_status_op() and nand_exit_status_op() ? > + > + return 0; > +} > + > +static int meson_nfc_wait_rb_pin(struct meson_nfc *nfc, int timeout_ms) > { > u32 cmd, cfg; > int ret = 0; > @@ -420,6 +457,27 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) > return ret; > } > > +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, > + bool need_cmd_read0) > +{ > + if (nfc->no_rb_pin) { > + /* This mode is used when there is no wired R/B pin. > + * It works like 'nand_soft_waitrdy()', but instead of > + * polling NAND_CMD_STATUS bit in the software loop, > + * it will wait for interrupt - controllers checks IO > + * bus and when it detects NAND_CMD_STATUS on it, it > + * raises interrupt. After interrupt, NAND_CMD_READ0 is > + * sent as terminator of the ready waiting procedure if > + * needed (for all cases except page programming - this > + * is reason of 'need_cmd_read0' flag). > + */ > + return meson_nfc_wait_no_rb_pin(nfc, timeout_ms, > + need_cmd_read0); > + } else { > + return meson_nfc_wait_rb_pin(nfc, timeout_ms); > + } > +} > + > static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) > { > struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); > @@ -623,7 +681,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), true); > } else { > meson_nfc_cmd_idle(nfc, nfc->timing.tadl); > } > @@ -669,7 +727,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), false); > > meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); > > @@ -952,7 +1010,8 @@ 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, > + true); > if (instr->delay_ns) > meson_nfc_cmd_idle(nfc, delay_idle); > break; > @@ -1248,6 +1307,7 @@ meson_nfc_nand_chip_init(struct device *dev, > struct mtd_info *mtd; > int ret, i; > u32 tmp, nsels; > + u32 nand_rb_val = 0; > > nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); > if (!nsels || nsels > MAX_CE_NUM) { > @@ -1287,6 +1347,15 @@ meson_nfc_nand_chip_init(struct device *dev, > mtd->owner = THIS_MODULE; > mtd->dev.parent = dev; > > + ret = of_property_read_u32(np, "nand-rb", &nand_rb_val); > + if (ret == -EINVAL) > + nfc->no_rb_pin = true; > + else if (ret) > + return ret; > + > + if (nand_rb_val) > + return -EINVAL; > + > ret = nand_scan(nand, nsels); > if (ret) > return ret; Thanks, Miquèl ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-07-04 12:43 ` Miquel Raynal @ 2023-07-04 12:46 ` Arseniy Krasnov 2023-07-04 13:12 ` Miquel Raynal 0 siblings, 1 reply; 12+ messages in thread From: Arseniy Krasnov @ 2023-07-04 12:46 UTC (permalink / raw) To: Miquel Raynal Cc: Liang Yang, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl, oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel On 04.07.2023 15:43, Miquel Raynal wrote: > Hi Arseniy, > > AVKrasnov@sberdevices.ru wrote on Thu, 8 Jun 2023 07:47:28 +0300: > >> If there is no wired ready/busy pin, classic way to wait for command >> completion is to use function 'nand_soft_waitrdy()'. Meson NAND has >> special command which allows to wait for NAND_STATUS_READY bit without >> reading status in a software loop (as 'nand_soft_waitrdy()' does). To >> use it send this command along with NAND_CMD_STATUS, then wait for an >> interrupt, and after interrupt send NAND_CMD_READ0. So this feature >> allows to use interrupt driven waiting without wired ready/busy pin. >> >> Suggested-by: Liang Yang <liang.yang@amlogic.com> >> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> >> --- >> drivers/mtd/nand/raw/meson_nand.c | 77 +++++++++++++++++++++++++++++-- >> 1 file changed, 73 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c >> index 074e14225c06..9f05e113b4ea 100644 >> --- a/drivers/mtd/nand/raw/meson_nand.c >> +++ b/drivers/mtd/nand/raw/meson_nand.c >> @@ -38,6 +38,7 @@ >> #define NFC_CMD_SCRAMBLER_DISABLE 0 >> #define NFC_CMD_SHORTMODE_DISABLE 0 >> #define NFC_CMD_RB_INT BIT(14) >> +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) >> >> #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) >> >> @@ -179,6 +180,7 @@ struct meson_nfc { >> u32 info_bytes; >> >> unsigned long assigned_cs; >> + bool no_rb_pin; >> }; >> >> enum { >> @@ -392,7 +394,42 @@ 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_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, >> + bool need_cmd_read0) >> +{ >> + u32 cmd, cfg; >> + >> + meson_nfc_cmd_idle(nfc, nfc->timing.twb); >> + meson_nfc_drain_cmd(nfc); >> + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); >> + >> + cfg = readl(nfc->reg_base + NFC_REG_CFG); >> + cfg |= NFC_RB_IRQ_EN; >> + writel(cfg, nfc->reg_base + NFC_REG_CFG); >> + >> + reinit_completion(&nfc->completion); >> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; >> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >> + >> + /* use the max erase time as the maximum clock for waiting R/B */ >> + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; >> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >> + >> + if (!wait_for_completion_timeout(&nfc->completion, >> + msecs_to_jiffies(timeout_ms))) >> + return -ETIMEDOUT; >> + >> + if (need_cmd_read0) { >> + 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); >> + } > > I forgot about this, you should avoid open coding core helpers, can you > please send a followup patch to use nand_status_op() and > nand_exit_status_op() ? A ok, so: 1) Sending NAND_CMD_STATUS goes to nand_status_op() 2) Sending NAND_CMD_READ0 goes to nand_exit_status_op() Ok, no problem! I'll prepare and send it on this week! Thanks, Arseniy > >> + >> + return 0; >> +} >> + >> +static int meson_nfc_wait_rb_pin(struct meson_nfc *nfc, int timeout_ms) >> { >> u32 cmd, cfg; >> int ret = 0; >> @@ -420,6 +457,27 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) >> return ret; >> } >> >> +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, >> + bool need_cmd_read0) >> +{ >> + if (nfc->no_rb_pin) { >> + /* This mode is used when there is no wired R/B pin. >> + * It works like 'nand_soft_waitrdy()', but instead of >> + * polling NAND_CMD_STATUS bit in the software loop, >> + * it will wait for interrupt - controllers checks IO >> + * bus and when it detects NAND_CMD_STATUS on it, it >> + * raises interrupt. After interrupt, NAND_CMD_READ0 is >> + * sent as terminator of the ready waiting procedure if >> + * needed (for all cases except page programming - this >> + * is reason of 'need_cmd_read0' flag). >> + */ >> + return meson_nfc_wait_no_rb_pin(nfc, timeout_ms, >> + need_cmd_read0); >> + } else { >> + return meson_nfc_wait_rb_pin(nfc, timeout_ms); >> + } >> +} >> + >> static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) >> { >> struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); >> @@ -623,7 +681,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), true); >> } else { >> meson_nfc_cmd_idle(nfc, nfc->timing.tadl); >> } >> @@ -669,7 +727,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), false); >> >> meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); >> >> @@ -952,7 +1010,8 @@ 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, >> + true); >> if (instr->delay_ns) >> meson_nfc_cmd_idle(nfc, delay_idle); >> break; >> @@ -1248,6 +1307,7 @@ meson_nfc_nand_chip_init(struct device *dev, >> struct mtd_info *mtd; >> int ret, i; >> u32 tmp, nsels; >> + u32 nand_rb_val = 0; >> >> nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); >> if (!nsels || nsels > MAX_CE_NUM) { >> @@ -1287,6 +1347,15 @@ meson_nfc_nand_chip_init(struct device *dev, >> mtd->owner = THIS_MODULE; >> mtd->dev.parent = dev; >> >> + ret = of_property_read_u32(np, "nand-rb", &nand_rb_val); >> + if (ret == -EINVAL) >> + nfc->no_rb_pin = true; >> + else if (ret) >> + return ret; >> + >> + if (nand_rb_val) >> + return -EINVAL; >> + >> ret = nand_scan(nand, nsels); >> if (ret) >> return ret; > > > Thanks, > Miquèl ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-07-04 12:46 ` Arseniy Krasnov @ 2023-07-04 13:12 ` Miquel Raynal 2023-07-04 13:07 ` Arseniy Krasnov 0 siblings, 1 reply; 12+ messages in thread From: Miquel Raynal @ 2023-07-04 13:12 UTC (permalink / raw) To: Arseniy Krasnov Cc: Liang Yang, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl, oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel Hi Arseniy, avkrasnov@sberdevices.ru wrote on Tue, 4 Jul 2023 15:46:18 +0300: > On 04.07.2023 15:43, Miquel Raynal wrote: > > Hi Arseniy, > > > > AVKrasnov@sberdevices.ru wrote on Thu, 8 Jun 2023 07:47:28 +0300: > > > >> If there is no wired ready/busy pin, classic way to wait for command > >> completion is to use function 'nand_soft_waitrdy()'. Meson NAND has > >> special command which allows to wait for NAND_STATUS_READY bit without > >> reading status in a software loop (as 'nand_soft_waitrdy()' does). To > >> use it send this command along with NAND_CMD_STATUS, then wait for an > >> interrupt, and after interrupt send NAND_CMD_READ0. So this feature > >> allows to use interrupt driven waiting without wired ready/busy pin. > >> > >> Suggested-by: Liang Yang <liang.yang@amlogic.com> > >> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> > >> --- > >> drivers/mtd/nand/raw/meson_nand.c | 77 +++++++++++++++++++++++++++++-- > >> 1 file changed, 73 insertions(+), 4 deletions(-) > >> > >> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c > >> index 074e14225c06..9f05e113b4ea 100644 > >> --- a/drivers/mtd/nand/raw/meson_nand.c > >> +++ b/drivers/mtd/nand/raw/meson_nand.c > >> @@ -38,6 +38,7 @@ > >> #define NFC_CMD_SCRAMBLER_DISABLE 0 > >> #define NFC_CMD_SHORTMODE_DISABLE 0 > >> #define NFC_CMD_RB_INT BIT(14) > >> +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) > >> > >> #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) > >> > >> @@ -179,6 +180,7 @@ struct meson_nfc { > >> u32 info_bytes; > >> > >> unsigned long assigned_cs; > >> + bool no_rb_pin; > >> }; > >> > >> enum { > >> @@ -392,7 +394,42 @@ 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_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, > >> + bool need_cmd_read0) > >> +{ > >> + u32 cmd, cfg; > >> + > >> + meson_nfc_cmd_idle(nfc, nfc->timing.twb); > >> + meson_nfc_drain_cmd(nfc); > >> + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); > >> + > >> + cfg = readl(nfc->reg_base + NFC_REG_CFG); > >> + cfg |= NFC_RB_IRQ_EN; > >> + writel(cfg, nfc->reg_base + NFC_REG_CFG); > >> + > >> + reinit_completion(&nfc->completion); > >> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; > >> + writel(cmd, nfc->reg_base + NFC_REG_CMD); > >> + > >> + /* use the max erase time as the maximum clock for waiting R/B */ > >> + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; > >> + writel(cmd, nfc->reg_base + NFC_REG_CMD); > >> + > >> + if (!wait_for_completion_timeout(&nfc->completion, > >> + msecs_to_jiffies(timeout_ms))) > >> + return -ETIMEDOUT; > >> + > >> + if (need_cmd_read0) { > >> + 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); > >> + } > > > > I forgot about this, you should avoid open coding core helpers, can you > > please send a followup patch to use nand_status_op() and > > nand_exit_status_op() ? > > A ok, so: > 1) Sending NAND_CMD_STATUS goes to nand_status_op() > 2) Sending NAND_CMD_READ0 goes to nand_exit_status_op() > > Ok, no problem! I'll prepare and send it on this week! Exactly. Sorry I had this in mind but I likely forgot to write it down. Thanks, Miquèl ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-07-04 13:12 ` Miquel Raynal @ 2023-07-04 13:07 ` Arseniy Krasnov 2023-07-04 17:32 ` Arseniy Krasnov 0 siblings, 1 reply; 12+ messages in thread From: Arseniy Krasnov @ 2023-07-04 13:07 UTC (permalink / raw) To: Miquel Raynal Cc: Liang Yang, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl, oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel On 04.07.2023 16:12, Miquel Raynal wrote: > Hi Arseniy, > > avkrasnov@sberdevices.ru wrote on Tue, 4 Jul 2023 15:46:18 +0300: > >> On 04.07.2023 15:43, Miquel Raynal wrote: >>> Hi Arseniy, >>> >>> AVKrasnov@sberdevices.ru wrote on Thu, 8 Jun 2023 07:47:28 +0300: >>> >>>> If there is no wired ready/busy pin, classic way to wait for command >>>> completion is to use function 'nand_soft_waitrdy()'. Meson NAND has >>>> special command which allows to wait for NAND_STATUS_READY bit without >>>> reading status in a software loop (as 'nand_soft_waitrdy()' does). To >>>> use it send this command along with NAND_CMD_STATUS, then wait for an >>>> interrupt, and after interrupt send NAND_CMD_READ0. So this feature >>>> allows to use interrupt driven waiting without wired ready/busy pin. >>>> >>>> Suggested-by: Liang Yang <liang.yang@amlogic.com> >>>> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> >>>> --- >>>> drivers/mtd/nand/raw/meson_nand.c | 77 +++++++++++++++++++++++++++++-- >>>> 1 file changed, 73 insertions(+), 4 deletions(-) >>>> >>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c >>>> index 074e14225c06..9f05e113b4ea 100644 >>>> --- a/drivers/mtd/nand/raw/meson_nand.c >>>> +++ b/drivers/mtd/nand/raw/meson_nand.c >>>> @@ -38,6 +38,7 @@ >>>> #define NFC_CMD_SCRAMBLER_DISABLE 0 >>>> #define NFC_CMD_SHORTMODE_DISABLE 0 >>>> #define NFC_CMD_RB_INT BIT(14) >>>> +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) >>>> >>>> #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) >>>> >>>> @@ -179,6 +180,7 @@ struct meson_nfc { >>>> u32 info_bytes; >>>> >>>> unsigned long assigned_cs; >>>> + bool no_rb_pin; >>>> }; >>>> >>>> enum { >>>> @@ -392,7 +394,42 @@ 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_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, >>>> + bool need_cmd_read0) >>>> +{ >>>> + u32 cmd, cfg; >>>> + >>>> + meson_nfc_cmd_idle(nfc, nfc->timing.twb); >>>> + meson_nfc_drain_cmd(nfc); >>>> + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); >>>> + >>>> + cfg = readl(nfc->reg_base + NFC_REG_CFG); >>>> + cfg |= NFC_RB_IRQ_EN; >>>> + writel(cfg, nfc->reg_base + NFC_REG_CFG); >>>> + >>>> + reinit_completion(&nfc->completion); >>>> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; >>>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >>>> + >>>> + /* use the max erase time as the maximum clock for waiting R/B */ >>>> + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; >>>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >>>> + >>>> + if (!wait_for_completion_timeout(&nfc->completion, >>>> + msecs_to_jiffies(timeout_ms))) >>>> + return -ETIMEDOUT; >>>> + >>>> + if (need_cmd_read0) { >>>> + 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); >>>> + } >>> >>> I forgot about this, you should avoid open coding core helpers, can you >>> please send a followup patch to use nand_status_op() and >>> nand_exit_status_op() ? >> >> A ok, so: >> 1) Sending NAND_CMD_STATUS goes to nand_status_op() >> 2) Sending NAND_CMD_READ0 goes to nand_exit_status_op() >> >> Ok, no problem! I'll prepare and send it on this week! > > Exactly. Sorry I had this in mind but I likely forgot to write it > down. Ok, got it! Thanks, Arseniy > > Thanks, > Miquèl ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-07-04 13:07 ` Arseniy Krasnov @ 2023-07-04 17:32 ` Arseniy Krasnov 2023-07-05 7:07 ` Miquel Raynal 0 siblings, 1 reply; 12+ messages in thread From: Arseniy Krasnov @ 2023-07-04 17:32 UTC (permalink / raw) To: Miquel Raynal Cc: Liang Yang, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl, oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel On 04.07.2023 16:07, Arseniy Krasnov wrote: > > > On 04.07.2023 16:12, Miquel Raynal wrote: >> Hi Arseniy, >> >> avkrasnov@sberdevices.ru wrote on Tue, 4 Jul 2023 15:46:18 +0300: >> >>> On 04.07.2023 15:43, Miquel Raynal wrote: >>>> Hi Arseniy, >>>> >>>> AVKrasnov@sberdevices.ru wrote on Thu, 8 Jun 2023 07:47:28 +0300: >>>> >>>>> If there is no wired ready/busy pin, classic way to wait for command >>>>> completion is to use function 'nand_soft_waitrdy()'. Meson NAND has >>>>> special command which allows to wait for NAND_STATUS_READY bit without >>>>> reading status in a software loop (as 'nand_soft_waitrdy()' does). To >>>>> use it send this command along with NAND_CMD_STATUS, then wait for an >>>>> interrupt, and after interrupt send NAND_CMD_READ0. So this feature >>>>> allows to use interrupt driven waiting without wired ready/busy pin. >>>>> >>>>> Suggested-by: Liang Yang <liang.yang@amlogic.com> >>>>> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> >>>>> --- >>>>> drivers/mtd/nand/raw/meson_nand.c | 77 +++++++++++++++++++++++++++++-- >>>>> 1 file changed, 73 insertions(+), 4 deletions(-) >>>>> >>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c >>>>> index 074e14225c06..9f05e113b4ea 100644 >>>>> --- a/drivers/mtd/nand/raw/meson_nand.c >>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c >>>>> @@ -38,6 +38,7 @@ >>>>> #define NFC_CMD_SCRAMBLER_DISABLE 0 >>>>> #define NFC_CMD_SHORTMODE_DISABLE 0 >>>>> #define NFC_CMD_RB_INT BIT(14) >>>>> +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) >>>>> >>>>> #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) >>>>> >>>>> @@ -179,6 +180,7 @@ struct meson_nfc { >>>>> u32 info_bytes; >>>>> >>>>> unsigned long assigned_cs; >>>>> + bool no_rb_pin; >>>>> }; >>>>> >>>>> enum { >>>>> @@ -392,7 +394,42 @@ 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_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, >>>>> + bool need_cmd_read0) >>>>> +{ >>>>> + u32 cmd, cfg; >>>>> + >>>>> + meson_nfc_cmd_idle(nfc, nfc->timing.twb); >>>>> + meson_nfc_drain_cmd(nfc); >>>>> + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); >>>>> + >>>>> + cfg = readl(nfc->reg_base + NFC_REG_CFG); >>>>> + cfg |= NFC_RB_IRQ_EN; >>>>> + writel(cfg, nfc->reg_base + NFC_REG_CFG); >>>>> + >>>>> + reinit_completion(&nfc->completion); >>>>> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; >>>>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >>>>> + >>>>> + /* use the max erase time as the maximum clock for waiting R/B */ >>>>> + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; >>>>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); >>>>> + >>>>> + if (!wait_for_completion_timeout(&nfc->completion, >>>>> + msecs_to_jiffies(timeout_ms))) >>>>> + return -ETIMEDOUT; >>>>> + >>>>> + if (need_cmd_read0) { >>>>> + 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); >>>>> + } >>>> >>>> I forgot about this, you should avoid open coding core helpers, can you >>>> please send a followup patch to use nand_status_op() and >>>> nand_exit_status_op() ? >>> >>> A ok, so: >>> 1) Sending NAND_CMD_STATUS goes to nand_status_op() >>> 2) Sending NAND_CMD_READ0 goes to nand_exit_status_op() >>> >>> Ok, no problem! I'll prepare and send it on this week! >> >> Exactly. Sorry I had this in mind but I likely forgot to write it >> down. > > Ok, got it! Hm, seems 'int nand_exit_status_op(struct nand_chip *chip)' is not exported, so I can't use it in the Meson module. While 'nand_status_op()' works ok. May I can export 'nand_exit_status_op()?' Thanks, Arseniy > > Thanks, Arseniy > >> >> Thanks, >> Miquèl ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin 2023-07-04 17:32 ` Arseniy Krasnov @ 2023-07-05 7:07 ` Miquel Raynal 0 siblings, 0 replies; 12+ messages in thread From: Miquel Raynal @ 2023-07-05 7:07 UTC (permalink / raw) To: Arseniy Krasnov Cc: Liang Yang, Richard Weinberger, Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski, Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl, oxffffaa, kernel, linux-mtd, devicetree, linux-arm-kernel, linux-amlogic, linux-kernel Hi Arseniy, avkrasnov@sberdevices.ru wrote on Tue, 4 Jul 2023 20:32:13 +0300: > On 04.07.2023 16:07, Arseniy Krasnov wrote: > > > > > > On 04.07.2023 16:12, Miquel Raynal wrote: > >> Hi Arseniy, > >> > >> avkrasnov@sberdevices.ru wrote on Tue, 4 Jul 2023 15:46:18 +0300: > >> > >>> On 04.07.2023 15:43, Miquel Raynal wrote: > >>>> Hi Arseniy, > >>>> > >>>> AVKrasnov@sberdevices.ru wrote on Thu, 8 Jun 2023 07:47:28 +0300: > >>>> > >>>>> If there is no wired ready/busy pin, classic way to wait for command > >>>>> completion is to use function 'nand_soft_waitrdy()'. Meson NAND has > >>>>> special command which allows to wait for NAND_STATUS_READY bit without > >>>>> reading status in a software loop (as 'nand_soft_waitrdy()' does). To > >>>>> use it send this command along with NAND_CMD_STATUS, then wait for an > >>>>> interrupt, and after interrupt send NAND_CMD_READ0. So this feature > >>>>> allows to use interrupt driven waiting without wired ready/busy pin. > >>>>> > >>>>> Suggested-by: Liang Yang <liang.yang@amlogic.com> > >>>>> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> > >>>>> --- > >>>>> drivers/mtd/nand/raw/meson_nand.c | 77 +++++++++++++++++++++++++++++-- > >>>>> 1 file changed, 73 insertions(+), 4 deletions(-) > >>>>> > >>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c > >>>>> index 074e14225c06..9f05e113b4ea 100644 > >>>>> --- a/drivers/mtd/nand/raw/meson_nand.c > >>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c > >>>>> @@ -38,6 +38,7 @@ > >>>>> #define NFC_CMD_SCRAMBLER_DISABLE 0 > >>>>> #define NFC_CMD_SHORTMODE_DISABLE 0 > >>>>> #define NFC_CMD_RB_INT BIT(14) > >>>>> +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) > >>>>> > >>>>> #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) > >>>>> > >>>>> @@ -179,6 +180,7 @@ struct meson_nfc { > >>>>> u32 info_bytes; > >>>>> > >>>>> unsigned long assigned_cs; > >>>>> + bool no_rb_pin; > >>>>> }; > >>>>> > >>>>> enum { > >>>>> @@ -392,7 +394,42 @@ 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_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, > >>>>> + bool need_cmd_read0) > >>>>> +{ > >>>>> + u32 cmd, cfg; > >>>>> + > >>>>> + meson_nfc_cmd_idle(nfc, nfc->timing.twb); > >>>>> + meson_nfc_drain_cmd(nfc); > >>>>> + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); > >>>>> + > >>>>> + cfg = readl(nfc->reg_base + NFC_REG_CFG); > >>>>> + cfg |= NFC_RB_IRQ_EN; > >>>>> + writel(cfg, nfc->reg_base + NFC_REG_CFG); > >>>>> + > >>>>> + reinit_completion(&nfc->completion); > >>>>> + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; > >>>>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); > >>>>> + > >>>>> + /* use the max erase time as the maximum clock for waiting R/B */ > >>>>> + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; > >>>>> + writel(cmd, nfc->reg_base + NFC_REG_CMD); > >>>>> + > >>>>> + if (!wait_for_completion_timeout(&nfc->completion, > >>>>> + msecs_to_jiffies(timeout_ms))) > >>>>> + return -ETIMEDOUT; > >>>>> + > >>>>> + if (need_cmd_read0) { > >>>>> + 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); > >>>>> + } > >>>> > >>>> I forgot about this, you should avoid open coding core helpers, can you > >>>> please send a followup patch to use nand_status_op() and > >>>> nand_exit_status_op() ? > >>> > >>> A ok, so: > >>> 1) Sending NAND_CMD_STATUS goes to nand_status_op() > >>> 2) Sending NAND_CMD_READ0 goes to nand_exit_status_op() > >>> > >>> Ok, no problem! I'll prepare and send it on this week! > >> > >> Exactly. Sorry I had this in mind but I likely forgot to write it > >> down. > > > > Ok, got it! > > Hm, seems 'int nand_exit_status_op(struct nand_chip *chip)' is not exported, > so I can't use it in the Meson module. While 'nand_status_op()' works ok. > May I can export 'nand_exit_status_op()?' Yes, in a separate patch please. > > Thanks, Arseniy > > > > > > Thanks, Arseniy > > > >> > >> Thanks, > >> Miquèl Thanks, Miquèl ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2023-07-05 7:07 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-06-08 4:47 [PATCH v3 0/2] Meson NAND: waiting w/o wired ready/busy pin Arseniy Krasnov 2023-06-08 4:47 ` [PATCH v3 1/2] dt-bindings: nand: meson: Fix 'nand-rb' property Arseniy Krasnov 2023-06-08 12:01 ` Krzysztof Kozlowski 2023-06-09 15:25 ` Miquel Raynal 2023-06-08 4:47 ` [PATCH v3 2/2] mtd: rawnand: meson: waiting w/o wired ready/busy pin Arseniy Krasnov 2023-06-09 15:24 ` Miquel Raynal 2023-07-04 12:43 ` Miquel Raynal 2023-07-04 12:46 ` Arseniy Krasnov 2023-07-04 13:12 ` Miquel Raynal 2023-07-04 13:07 ` Arseniy Krasnov 2023-07-04 17:32 ` Arseniy Krasnov 2023-07-05 7:07 ` Miquel Raynal
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).