blob: 42467b625404975c2d7c0113330ca0b7eadc8709 [file] [log] [blame]
developer5d148cb2023-06-02 13:08:11 +08001From 2c71a01b9363f44ca077ec0e27b6a06a15617497 Mon Sep 17 00:00:00 2001
2From: Sam Shih <sam.shih@mediatek.com>
3Date: Fri, 2 Jun 2023 13:06:14 +0800
4Subject: [PATCH]
5 [spi-and-storage][999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch]
6
7---
8 drivers/mtd/nand/spi/winbond.c | 129 ++++++++++++++++++++++++++++++++-
9 1 file changed, 127 insertions(+), 2 deletions(-)
10
11diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
12index 766844283..6473b0367 100644
developerd2bdfc32022-03-18 21:25:39 +080013--- a/drivers/mtd/nand/spi/winbond.c
14+++ b/drivers/mtd/nand/spi/winbond.c
developer6207d3c2022-12-08 19:06:30 +080015@@ -15,6 +15,23 @@
developerd2bdfc32022-03-18 21:25:39 +080016
17 #define WINBOND_CFG_BUF_READ BIT(3)
18
19+#define W25N02_N04KV_STATUS_ECC_MASK (3 << 4)
20+#define W25N02_N04KV_STATUS_ECC_NO_BITFLIPS (0 << 4)
21+#define W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS (1 << 4)
22+#define W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4)
23+#define W25N02_N04KV_STATUS_ECC_UNCOR_ERROR (2 << 4)
24+
25+#define W25N01_M02GV_STATUS_ECC_MASK (3 << 4)
26+#define W25N01_M02GV_STATUS_ECC_NO_BITFLIPS (0 << 4)
27+#define W25N01_M02GV_STATUS_ECC_1_BITFLIPS (1 << 4)
28+#define W25N01_M02GV_STATUS_ECC_UNCOR_ERROR (2 << 4)
29+
developerd2bdfc32022-03-18 21:25:39 +080030+#define W25N01KV_STATUS_ECC_MASK (3 << 4)
31+#define W25N01KV_STATUS_ECC_NO_BITFLIPS (0 << 4)
32+#define W25N01KV_STATUS_ECC_1_3_BITFLIPS (1 << 4)
33+#define W25N01KV_STATUS_ECC_4_BITFLIPS (3 << 4)
34+#define W25N01KV_STATUS_ECC_UNCOR_ERROR (2 << 4)
developerd2bdfc32022-03-18 21:25:39 +080035+
36 static SPINAND_OP_VARIANTS(read_cache_variants,
37 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
38 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
developer5d148cb2023-06-02 13:08:11 +080039@@ -31,6 +48,29 @@ static SPINAND_OP_VARIANTS(update_cache_variants,
developerd2bdfc32022-03-18 21:25:39 +080040 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
41 SPINAND_PROG_LOAD(false, 0, NULL, 0));
42
43+static int w25n02kv_n04kv_ooblayout_ecc(struct mtd_info *mtd, int section,
44+ struct mtd_oob_region *region)
45+{
46+ return -ERANGE;
47+}
48+
49+static int w25n02kv_n04kv_ooblayout_free(struct mtd_info *mtd, int section,
50+ struct mtd_oob_region *region)
51+{
52+ if (section > 3)
53+ return -ERANGE;
54+
55+ region->offset = (16 * section) + 2;
56+ region->length = 14;
57+
58+ return 0;
59+}
60+
61+static const struct mtd_ooblayout_ops w25n02kv_n04kv_ooblayout = {
62+ .ecc = w25n02kv_n04kv_ooblayout_ecc,
63+ .free = w25n02kv_n04kv_ooblayout_free,
64+};
65+
66 static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
67 struct mtd_oob_region *region)
68 {
developer5d148cb2023-06-02 13:08:11 +080069@@ -74,9 +114,61 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
developerd2bdfc32022-03-18 21:25:39 +080070 return spi_mem_exec_op(spinand->spimem, &op);
71 }
72
developerd2bdfc32022-03-18 21:25:39 +080073+static int w25n01kv_ecc_get_status(struct spinand_device *spinand,
74+ u8 status)
75+{
76+ switch (status & W25N01KV_STATUS_ECC_MASK) {
77+ case W25N01KV_STATUS_ECC_NO_BITFLIPS:
78+ return 0;
79+
80+ case W25N01KV_STATUS_ECC_1_3_BITFLIPS:
81+ return 3;
82+
83+ case W25N01KV_STATUS_ECC_4_BITFLIPS:
84+ return 4;
85+
86+ case W25N01KV_STATUS_ECC_UNCOR_ERROR:
87+ return -EBADMSG;
88+
89+ default:
90+ break;
91+ }
92+
93+ return -EINVAL;
94+}
developerd2bdfc32022-03-18 21:25:39 +080095+
96+static int w25n02kv_n04kv_ecc_get_status(struct spinand_device *spinand,
97+ u8 status)
98+{
99+ switch (status & W25N02_N04KV_STATUS_ECC_MASK) {
100+ case W25N02_N04KV_STATUS_ECC_NO_BITFLIPS:
101+ return 0;
102+
103+ case W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS:
104+ return 3;
105+
106+ case W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS:
107+ return 4;
108+
109+ /* W25N02_N04KV_use internal 8bit ECC algorithm.
110+ * But the ECC strength is 4 bit requried.
111+ * Return 3 if the bit bit flip count less than 5.
112+ * Return 4 if the bit bit flip count more than 5 to 8.
113+ */
114+
115+ case W25N02_N04KV_STATUS_ECC_UNCOR_ERROR:
116+ return -EBADMSG;
117+
118+ default:
119+ break;
120+ }
121+
122+ return -EINVAL;
123+}
124+
125 static const struct spinand_info winbond_spinand_table[] = {
126 SPINAND_INFO("W25M02GV",
127- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
128+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
129 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
130 NAND_ECCREQ(1, 512),
131 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
developer5d148cb2023-06-02 13:08:11 +0800132@@ -85,8 +177,18 @@ static const struct spinand_info winbond_spinand_table[] = {
developerd2bdfc32022-03-18 21:25:39 +0800133 0,
134 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
135 SPINAND_SELECT_TARGET(w25m02gv_select_target)),
developerd2bdfc32022-03-18 21:25:39 +0800136+ SPINAND_INFO("W25N01KV",
developer6207d3c2022-12-08 19:06:30 +0800137+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
138+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
developerd2bdfc32022-03-18 21:25:39 +0800139+ NAND_ECCREQ(4, 512),
140+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
141+ &write_cache_variants,
142+ &update_cache_variants),
143+ 0,
144+ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
145+ w25n01kv_ecc_get_status)),
developerd2bdfc32022-03-18 21:25:39 +0800146 SPINAND_INFO("W25N01GV",
147- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
148+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
149 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
150 NAND_ECCREQ(1, 512),
151 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
developer5d148cb2023-06-02 13:08:11 +0800152@@ -94,6 +196,29 @@ static const struct spinand_info winbond_spinand_table[] = {
developerd2bdfc32022-03-18 21:25:39 +0800153 &update_cache_variants),
154 0,
155 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
developerd2bdfc32022-03-18 21:25:39 +0800156+ SPINAND_INFO("W25N02KV",
157+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
158+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
developercd6f9cf2023-04-17 14:25:27 +0800159+ NAND_ECCREQ(8, 512),
developerd2bdfc32022-03-18 21:25:39 +0800160+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
161+ &write_cache_variants,
162+ &update_cache_variants),
163+ 0,
164+ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
165+ w25n02kv_n04kv_ecc_get_status)),
166+ /* W25N04KV has 2-die(lun), however, it can select die automatically.
167+ * Treat it as single die here and double block size.
168+ */
169+ SPINAND_INFO("W25N04KV",
170+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
171+ NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
developercd6f9cf2023-04-17 14:25:27 +0800172+ NAND_ECCREQ(8, 512),
developerd2bdfc32022-03-18 21:25:39 +0800173+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
174+ &write_cache_variants,
175+ &update_cache_variants),
176+ 0,
177+ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
178+ w25n02kv_n04kv_ecc_get_status)),
179 };
180
181 static int winbond_spinand_init(struct spinand_device *spinand)
developer5d148cb2023-06-02 13:08:11 +0800182--
1832.34.1
184