mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 15:02:32 +00:00
fa4dc86e98
MEMREAD is a new ioctl for MTD character devices that was first included in Linux 6.1. It allows userspace applications to use the Linux kernel's OOB autoplacement mechanism while reading data from NAND devices. The Yafut tool needs this ioctl to do its job. Signed-off-by: Michał Kępień <openwrt@kempniu.pl>
99 lines
3.4 KiB
Diff
99 lines
3.4 KiB
Diff
From eb4a2d282c3c5752211d69be6dff2674119e5583 Mon Sep 17 00:00:00 2001
|
|
From: Miquel Raynal <miquel.raynal@bootlin.com>
|
|
Date: Thu, 27 Jan 2022 10:18:03 +0100
|
|
Subject: [PATCH 09/15] mtd: spinand: Create direct mapping descriptors for ECC
|
|
operations
|
|
|
|
In order for pipelined ECC engines to be able to enable/disable the ECC
|
|
engine only when needed and avoid races when future parallel-operations
|
|
will be supported, we need to provide the information about the use of
|
|
the ECC engine in the direct mapping hooks. As direct mapping
|
|
configurations are meant to be static, it is best to create two new
|
|
mappings: one for regular 'raw' accesses and one for accesses involving
|
|
correction. It is up to the driver to use or not the new ECC enable
|
|
boolean contained in the spi-mem operation.
|
|
|
|
As dirmaps are not free (they consume a few pages of MMIO address space)
|
|
and because these extra entries are only meant to be used by pipelined
|
|
engines, let's limit their use to this specific type of engine and save
|
|
a bit of memory with all the other setups.
|
|
|
|
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
|
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
|
|
Link: https://lore.kernel.org/linux-mtd/20220127091808.1043392-9-miquel.raynal@bootlin.com
|
|
(cherry picked from commit f9d7c7265bcff7d9a17425a8cddf702e8fe159c2)
|
|
---
|
|
drivers/mtd/nand/spi/core.c | 35 +++++++++++++++++++++++++++++++++--
|
|
include/linux/mtd/spinand.h | 2 ++
|
|
2 files changed, 35 insertions(+), 2 deletions(-)
|
|
|
|
--- a/drivers/mtd/nand/spi/core.c
|
|
+++ b/drivers/mtd/nand/spi/core.c
|
|
@@ -381,7 +381,10 @@ static int spinand_read_from_cache_op(st
|
|
}
|
|
}
|
|
|
|
- rdesc = spinand->dirmaps[req->pos.plane].rdesc;
|
|
+ if (req->mode == MTD_OPS_RAW)
|
|
+ rdesc = spinand->dirmaps[req->pos.plane].rdesc;
|
|
+ else
|
|
+ rdesc = spinand->dirmaps[req->pos.plane].rdesc_ecc;
|
|
|
|
while (nbytes) {
|
|
ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf);
|
|
@@ -452,7 +455,10 @@ static int spinand_write_to_cache_op(str
|
|
req->ooblen);
|
|
}
|
|
|
|
- wdesc = spinand->dirmaps[req->pos.plane].wdesc;
|
|
+ if (req->mode == MTD_OPS_RAW)
|
|
+ wdesc = spinand->dirmaps[req->pos.plane].wdesc;
|
|
+ else
|
|
+ wdesc = spinand->dirmaps[req->pos.plane].wdesc_ecc;
|
|
|
|
while (nbytes) {
|
|
ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf);
|
|
@@ -875,6 +881,31 @@ static int spinand_create_dirmap(struct
|
|
|
|
spinand->dirmaps[plane].rdesc = desc;
|
|
|
|
+ if (nand->ecc.engine->integration != NAND_ECC_ENGINE_INTEGRATION_PIPELINED) {
|
|
+ spinand->dirmaps[plane].wdesc_ecc = spinand->dirmaps[plane].wdesc;
|
|
+ spinand->dirmaps[plane].rdesc_ecc = spinand->dirmaps[plane].rdesc;
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ info.op_tmpl = *spinand->op_templates.update_cache;
|
|
+ info.op_tmpl.data.ecc = true;
|
|
+ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
|
|
+ spinand->spimem, &info);
|
|
+ if (IS_ERR(desc))
|
|
+ return PTR_ERR(desc);
|
|
+
|
|
+ spinand->dirmaps[plane].wdesc_ecc = desc;
|
|
+
|
|
+ info.op_tmpl = *spinand->op_templates.read_cache;
|
|
+ info.op_tmpl.data.ecc = true;
|
|
+ desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
|
|
+ spinand->spimem, &info);
|
|
+ if (IS_ERR(desc))
|
|
+ return PTR_ERR(desc);
|
|
+
|
|
+ spinand->dirmaps[plane].rdesc_ecc = desc;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--- a/include/linux/mtd/spinand.h
|
|
+++ b/include/linux/mtd/spinand.h
|
|
@@ -392,6 +392,8 @@ struct spinand_info {
|
|
struct spinand_dirmap {
|
|
struct spi_mem_dirmap_desc *wdesc;
|
|
struct spi_mem_dirmap_desc *rdesc;
|
|
+ struct spi_mem_dirmap_desc *wdesc_ecc;
|
|
+ struct spi_mem_dirmap_desc *rdesc_ecc;
|
|
};
|
|
|
|
/**
|