blob: ba9b72cb5538ba8cffb122d6a6d241fe4d29c1d2 [file] [log] [blame]
developerd2bdfc32022-03-18 21:25:39 +08001--- a/drivers/mtd/nand/spi/winbond.c
2+++ b/drivers/mtd/nand/spi/winbond.c
3@@ -15,6 +15,25 @@
4
5 #define WINBOND_CFG_BUF_READ BIT(3)
6
7+#define W25N02_N04KV_STATUS_ECC_MASK (3 << 4)
8+#define W25N02_N04KV_STATUS_ECC_NO_BITFLIPS (0 << 4)
9+#define W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS (1 << 4)
10+#define W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4)
11+#define W25N02_N04KV_STATUS_ECC_UNCOR_ERROR (2 << 4)
12+
13+#define W25N01_M02GV_STATUS_ECC_MASK (3 << 4)
14+#define W25N01_M02GV_STATUS_ECC_NO_BITFLIPS (0 << 4)
15+#define W25N01_M02GV_STATUS_ECC_1_BITFLIPS (1 << 4)
16+#define W25N01_M02GV_STATUS_ECC_UNCOR_ERROR (2 << 4)
17+
18+#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV)
19+#define W25N01KV_STATUS_ECC_MASK (3 << 4)
20+#define W25N01KV_STATUS_ECC_NO_BITFLIPS (0 << 4)
21+#define W25N01KV_STATUS_ECC_1_3_BITFLIPS (1 << 4)
22+#define W25N01KV_STATUS_ECC_4_BITFLIPS (3 << 4)
23+#define W25N01KV_STATUS_ECC_UNCOR_ERROR (2 << 4)
24+#endif
25+
26 static SPINAND_OP_VARIANTS(read_cache_variants,
27 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
28 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
29@@ -31,6 +50,29 @@ static SPINAND_OP_VARIANTS(update_cache_
30 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
31 SPINAND_PROG_LOAD(false, 0, NULL, 0));
32
33+static int w25n02kv_n04kv_ooblayout_ecc(struct mtd_info *mtd, int section,
34+ struct mtd_oob_region *region)
35+{
36+ return -ERANGE;
37+}
38+
39+static int w25n02kv_n04kv_ooblayout_free(struct mtd_info *mtd, int section,
40+ struct mtd_oob_region *region)
41+{
42+ if (section > 3)
43+ return -ERANGE;
44+
45+ region->offset = (16 * section) + 2;
46+ region->length = 14;
47+
48+ return 0;
49+}
50+
51+static const struct mtd_ooblayout_ops w25n02kv_n04kv_ooblayout = {
52+ .ecc = w25n02kv_n04kv_ooblayout_ecc,
53+ .free = w25n02kv_n04kv_ooblayout_free,
54+};
55+
56 static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
57 struct mtd_oob_region *region)
58 {
59@@ -74,9 +116,63 @@ static int w25m02gv_select_target(struct
60 return spi_mem_exec_op(spinand->spimem, &op);
61 }
62
63+#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV)
64+static int w25n01kv_ecc_get_status(struct spinand_device *spinand,
65+ u8 status)
66+{
67+ switch (status & W25N01KV_STATUS_ECC_MASK) {
68+ case W25N01KV_STATUS_ECC_NO_BITFLIPS:
69+ return 0;
70+
71+ case W25N01KV_STATUS_ECC_1_3_BITFLIPS:
72+ return 3;
73+
74+ case W25N01KV_STATUS_ECC_4_BITFLIPS:
75+ return 4;
76+
77+ case W25N01KV_STATUS_ECC_UNCOR_ERROR:
78+ return -EBADMSG;
79+
80+ default:
81+ break;
82+ }
83+
84+ return -EINVAL;
85+}
86+#endif
87+
88+static int w25n02kv_n04kv_ecc_get_status(struct spinand_device *spinand,
89+ u8 status)
90+{
91+ switch (status & W25N02_N04KV_STATUS_ECC_MASK) {
92+ case W25N02_N04KV_STATUS_ECC_NO_BITFLIPS:
93+ return 0;
94+
95+ case W25N02_N04KV_STATUS_ECC_1_4_BITFLIPS:
96+ return 3;
97+
98+ case W25N02_N04KV_STATUS_ECC_5_8_BITFLIPS:
99+ return 4;
100+
101+ /* W25N02_N04KV_use internal 8bit ECC algorithm.
102+ * But the ECC strength is 4 bit requried.
103+ * Return 3 if the bit bit flip count less than 5.
104+ * Return 4 if the bit bit flip count more than 5 to 8.
105+ */
106+
107+ case W25N02_N04KV_STATUS_ECC_UNCOR_ERROR:
108+ return -EBADMSG;
109+
110+ default:
111+ break;
112+ }
113+
114+ return -EINVAL;
115+}
116+
117 static const struct spinand_info winbond_spinand_table[] = {
118 SPINAND_INFO("W25M02GV",
119- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
120+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
121 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
122 NAND_ECCREQ(1, 512),
123 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
124@@ -85,8 +181,20 @@ static const struct spinand_info winbond
125 0,
126 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
127 SPINAND_SELECT_TARGET(w25m02gv_select_target)),
128+#if IS_ENABLED(CONFIG_MTD_SPI_NAND_W25N01KV)
129+ SPINAND_INFO("W25N01KV",
130+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
131+ NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1),
132+ NAND_ECCREQ(4, 512),
133+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
134+ &write_cache_variants,
135+ &update_cache_variants),
136+ 0,
137+ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
138+ w25n01kv_ecc_get_status)),
139+#else
140 SPINAND_INFO("W25N01GV",
141- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
142+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
143 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
144 NAND_ECCREQ(1, 512),
145 SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
146@@ -94,6 +202,30 @@ static const struct spinand_info winbond
147 &update_cache_variants),
148 0,
149 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
150+#endif
151+ SPINAND_INFO("W25N02KV",
152+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
153+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
154+ NAND_ECCREQ(4, 512),
155+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
156+ &write_cache_variants,
157+ &update_cache_variants),
158+ 0,
159+ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
160+ w25n02kv_n04kv_ecc_get_status)),
161+ /* W25N04KV has 2-die(lun), however, it can select die automatically.
162+ * Treat it as single die here and double block size.
163+ */
164+ SPINAND_INFO("W25N04KV",
165+ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23),
166+ NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1),
167+ NAND_ECCREQ(4, 512),
168+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
169+ &write_cache_variants,
170+ &update_cache_variants),
171+ 0,
172+ SPINAND_ECCINFO(&w25n02kv_n04kv_ooblayout,
173+ w25n02kv_n04kv_ecc_get_status)),
174 };
175
176 static int winbond_spinand_init(struct spinand_device *spinand)
177--- a/drivers/mtd/nand/spi/Kconfig
178+++ b/drivers/mtd/nand/spi/Kconfig
179@@ -6,3 +6,11 @@ menuconfig MTD_SPI_NAND
180 select SPI_MEM
181 help
182 This is the framework for the SPI NAND device drivers.
183+
184+config MTD_SPI_NAND_W25N01KV
185+ tristate "Winbond W25N01KV Support"
186+ select MTD_SPI_NAND
187+ help
188+ Winbond W25N01KV share the same ID with W25N01GV. However, they have
189+ different attributes.
190+