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>
82 lines
2.2 KiB
Diff
82 lines
2.2 KiB
Diff
From 7670ec4a14891a1a182b98a9c403ffbf6b49e4b1 Mon Sep 17 00:00:00 2001
|
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
|
Date: Thu, 23 Jun 2022 18:39:56 +0800
|
|
Subject: [PATCH 5/6] drivers: mtd: spinand: Add calibration support for
|
|
spinand
|
|
|
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
|
---
|
|
drivers/mtd/nand/spi/core.c | 54 +++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 54 insertions(+)
|
|
|
|
--- a/drivers/mtd/nand/spi/core.c
|
|
+++ b/drivers/mtd/nand/spi/core.c
|
|
@@ -977,6 +977,56 @@ static int spinand_manufacturer_match(st
|
|
return -ENOTSUPP;
|
|
}
|
|
|
|
+int spinand_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) {
|
|
+ struct spinand_device *spinand = (struct spinand_device *)priv;
|
|
+ struct device *dev = &spinand->spimem->spi->dev;
|
|
+ struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, buf, readlen);
|
|
+ struct nand_pos pos;
|
|
+ struct nand_page_io_req req;
|
|
+ u8 status;
|
|
+ int ret;
|
|
+
|
|
+ if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) {
|
|
+ dev_err(dev, "Must provide correct addr(length) for spinand calibration\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ ret = spinand_reset_op(spinand);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* We should store our golden data in first target because
|
|
+ * we can't switch target at this moment.
|
|
+ */
|
|
+ pos = (struct nand_pos){
|
|
+ .target = 0,
|
|
+ .lun = *addr,
|
|
+ .plane = *(addr+1),
|
|
+ .eraseblock = *(addr+2),
|
|
+ .page = *(addr+3),
|
|
+ };
|
|
+
|
|
+ req = (struct nand_page_io_req){
|
|
+ .pos = pos,
|
|
+ .dataoffs = *(addr+4),
|
|
+ .datalen = readlen,
|
|
+ .databuf.in = buf,
|
|
+ .mode = MTD_OPS_AUTO_OOB,
|
|
+ };
|
|
+
|
|
+ ret = spinand_load_page_op(spinand, &req);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = spinand_wait(spinand, &status);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ ret = spi_mem_exec_op(spinand->spimem, &op);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int spinand_id_detect(struct spinand_device *spinand)
|
|
{
|
|
u8 *id = spinand->id.data;
|
|
@@ -1227,6 +1277,10 @@ static int spinand_init(struct spinand_d
|
|
if (!spinand->scratchbuf)
|
|
return -ENOMEM;
|
|
|
|
+ ret = spi_mem_do_calibration(spinand->spimem, spinand_cal_read, spinand);
|
|
+ if (ret)
|
|
+ dev_err(dev, "Failed to calibrate SPI-NAND (err = %d)\n", ret);
|
|
+
|
|
ret = spinand_detect(spinand);
|
|
if (ret)
|
|
goto err_free_bufs;
|