blob: 374531b815aa7c84e5546dd11da48cba4a88c683 [file] [log] [blame]
developerd82d9fc2022-06-23 19:03:51 +08001From 6bd88d34cb5a5cb1d7c544c9f5b430105b000308 Mon Sep 17 00:00:00 2001
2From: "SkyLake.Huang" <skylake.huang@mediatek.com>
3Date: Thu, 23 Jun 2022 18:39:56 +0800
4Subject: [PATCH] drivers: mtd: spinand: Add calibration support for spinand
5
6Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
7---
8 drivers/mtd/nand/spi/core.c | 58 +++++++++++++++++++++++++++++++++++++
9 1 file changed, 58 insertions(+)
10
11diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
12index 9f5f95ff7..b346c7a8a 100644
13--- a/drivers/mtd/nand/spi/core.c
14+++ b/drivers/mtd/nand/spi/core.c
15@@ -789,6 +789,60 @@ static int spinand_manufacturer_match(struct spinand_device *spinand,
16 return -ENOTSUPP;
17 }
18
19+int spinand_cal_read(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen) {
20+ int ret;
21+ u8 status;
22+ struct spinand_device *spinand = (struct spinand_device *)priv;
23+ struct device *dev = &spinand->spimem->spi->dev;
24+
25+ typedef struct nand_pos my_pos;
26+ my_pos pos;
27+ typedef struct nand_page_io_req my_req;
28+ my_req req;
29+
30+ if(addrlen != sizeof(struct nand_addr)/sizeof(unsigned int)) {
31+ dev_err(dev, "Must provide correct addr(length) for spinand calibration\n");
32+ return -EINVAL;
33+ }
34+
35+ ret = spinand_reset_op(spinand);
36+ if (ret)
37+ return ret;
38+
39+ /* We should store our golden data in first target because
40+ * we can't switch target at this moment.
41+ */
42+ pos = (my_pos){
43+ .target = 0,
44+ .lun = *addr,
45+ .plane = *(addr+1),
46+ .eraseblock = *(addr+2),
47+ .page = *(addr+3),
48+ };
49+
50+ req = (my_req){
51+ .pos = pos,
52+ .dataoffs = *(addr+4),
53+ .datalen = readlen,
54+ .databuf.in = buf,
55+ .mode = MTD_OPS_AUTO_OOB,
56+ };
57+
58+ ret = spinand_load_page_op(spinand, &req);
59+ if (ret)
60+ return ret;
61+
62+ ret = spinand_wait(spinand, &status);
63+ if (ret < 0)
64+ return ret;
65+
66+ struct spi_mem_op op = SPINAND_PAGE_READ_FROM_CACHE_OP(
67+ false, 0, 1, buf, readlen);
68+ ret = spi_mem_exec_op(spinand->spimem, &op);
69+
70+ return 0;
71+}
72+
73 static int spinand_id_detect(struct spinand_device *spinand)
74 {
75 u8 *id = spinand->id.data;
76@@ -1004,6 +1058,10 @@ static int spinand_init(struct spinand_device *spinand)
77 if (!spinand->scratchbuf)
78 return -ENOMEM;
79
80+ ret = spi_mem_do_calibration(spinand->spimem, spinand_cal_read, spinand);
81+ if (ret)
82+ dev_err(dev, "Failed to calibrate SPI-NAND (err = %d)\n", ret);
83+
84 ret = spinand_detect(spinand);
85 if (ret)
86 goto err_free_bufs;
87--
882.18.0
89