[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