[PATCH v2 3/4] mtd: spinand: Add support continuous read operation

Chuanhong Guo gch981213 at gmail.com
Tue Feb 14 22:51:15 PST 2023


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.

> +       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