[PATCH v2 3/4] mtd: spinand: Add support continuous read operation
liao jaime
jaimeliao.tw at gmail.com
Thu Apr 27 02:58:10 PDT 2023
Hi Chuanhong
>
> Hi!
>
> On Thu, Feb 9, 2023 at 8:10 PM Jaime Liao <jaimeliao.tw at gmail.com> wrote:
> > [...]
> > +static int spinand_mtd_continuous_read(struct mtd_info *mtd, loff_t from,
> > + struct mtd_oob_ops *ops,
> > + struct nand_io_iter *iter)
> > +{
> > + struct spinand_device *spinand = mtd_to_spinand(mtd);
> > + struct nand_device *nand = mtd_to_nanddev(mtd);
> > + int ret = 0;
> > +
> > + /*
> > + * Continuous read mode could reduce some operation in On-die ECC free
> > + * flash when read page sequentially.
> > + */
> > + iter->req.type = NAND_PAGE_READ;
> > + iter->req.mode = MTD_OPS_RAW;
> > + iter->req.dataoffs = nanddev_offs_to_pos(nand, from, &iter->req.pos);
> > + iter->req.databuf.in = ops->datbuf;
> > + iter->req.datalen = ops->len;
> > +
> > + if (from & (nanddev_page_size(nand) - 1)) {
> > + pr_debug("%s: unaligned address\n", __func__);
> > + return -EINVAL;
> > + }
> > +
> > + ret = spinand_continuous_read_enable(spinand);
> > + if (ret)
> > + return ret;
> > +
> > + spinand->use_continuous_read = true;
> > +
> > + ret = spinand_select_target(spinand, iter->req.pos.target);
> > + if (ret)
> > + return ret;
> > +
> > + /*
> > + * The continuous read operation including: firstly, starting with the
> > + * page read command and the 1 st page data will be read into the cache
> > + * after the read latency tRD. Secondly, Issuing the Read From Cache
> > + * commands (03h/0Bh/3Bh/6Bh/BBh/EBh) to read out the data from cache
> > + * continuously.
> > + *
> > + * The cache is divided into two halves, while one half of the cache is
> > + * outputting the data, the other half will be loaded for the new data;
> > + * therefore, the host can read out the data continuously from page to
> > + * page. Multiple of Read From Cache commands can be issued in one
> > + * continuous read operation, each Read From Cache command is required
> > + * to read multiple 4-byte data exactly; otherwise, the data output will
> > + * be out of sequence from one Read From Cache command to another Read
> > + * From Cache command.
> > + *
> > + * After all the data is read out, the host should pull CS# high to
> > + * terminate this continuous read operation and wait a 6us of tRST for
> > + * the NAND device resets read operation. The data output for each page
> > + * will always start from byte 0 and a full page data should be read out
> > + * for each page.
> > + */
>
> This mode requires the entire read_from_cache op to finish in one command.
> i.e. there can only be one read_from_cache command and the chip-select
> can only be pulled low exactly once.
> There's no guarantee that spinand_read_from_cache_op issues exactly one
> command. spi-mem controllers may have a transfer size limit, requiring an
> operation to be split into multiple read_from_cache requests with different
> column addresses. spi-mem controllers with dirmap support can map a
> memory space to a specific spi-mem read operation, and reading from this
> memory-mapped space also isn't guaranteed to be completed in one
> command. (Controllers may decide to respond to a bus read request using
> multiple spi-mem ops with auto-incremented op addr.)
> So, in order to use this mode, you can't reuse the spinand_read_from_cache_op
> function. Instead, you should write a new function for read_from_cache
> using spi_mem_adjust_op_size and spi_mem_exec_op: When calling
> adjust_op_size, check whether the op size is truncated. If it is, current
> continuous_read request should be aborted and fallback to the normal
> read mode.
As I know, data read could be handle by DMA engine even data length is
greater than
controller limit.
In spi-mem.c, spi_mem_adjust_op_size are using when "no_dirmap" so
that I not sure
that is import for checking before continuous read.
Should I check dirmap mode before enable continuous read?
Thanks your reply.
Jaime
>
> > + ret = spinand_read_page(spinand, &iter->req);
> > + if (ret)
> > + goto continuous_read_error;
> > +
> > + ret = spinand_reset_op(spinand);
> > + if (ret)
> > + goto continuous_read_error;
> > +
>
> --
> Regards,
> Chuanhong Guo
More information about the linux-mtd
mailing list