1b98ac5e2SFrieder Schrempf // SPDX-License-Identifier: GPL-2.0
2b98ac5e2SFrieder Schrempf /*
3b98ac5e2SFrieder Schrempf * Copyright (c) 2017 exceet electronics GmbH
4b98ac5e2SFrieder Schrempf *
5b98ac5e2SFrieder Schrempf * Authors:
6b98ac5e2SFrieder Schrempf * Frieder Schrempf <frieder.schrempf@exceet.de>
7b98ac5e2SFrieder Schrempf * Boris Brezillon <boris.brezillon@bootlin.com>
8b98ac5e2SFrieder Schrempf */
9b98ac5e2SFrieder Schrempf
10b98ac5e2SFrieder Schrempf #ifndef __UBOOT__
11b98ac5e2SFrieder Schrempf #include <linux/device.h>
12b98ac5e2SFrieder Schrempf #include <linux/kernel.h>
13b98ac5e2SFrieder Schrempf #endif
14b98ac5e2SFrieder Schrempf #include <linux/mtd/spinand.h>
15b98ac5e2SFrieder Schrempf
16b98ac5e2SFrieder Schrempf #define SPINAND_MFR_WINBOND 0xEF
17b98ac5e2SFrieder Schrempf
18b98ac5e2SFrieder Schrempf #define WINBOND_CFG_BUF_READ BIT(3)
19b98ac5e2SFrieder Schrempf
20b98ac5e2SFrieder Schrempf static SPINAND_OP_VARIANTS(read_cache_variants,
21b98ac5e2SFrieder Schrempf SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
22b98ac5e2SFrieder Schrempf SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
23b98ac5e2SFrieder Schrempf SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
24b98ac5e2SFrieder Schrempf SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
25b98ac5e2SFrieder Schrempf SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
26b98ac5e2SFrieder Schrempf SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
27b98ac5e2SFrieder Schrempf
28b1a0aa40SJon Lin #ifdef CONFIG_SPI_NAND_WINBOND_CONT_READ
29b1a0aa40SJon Lin static SPINAND_OP_VARIANTS(read_cache_variants_cont,
30b1a0aa40SJon Lin SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
31b1a0aa40SJon Lin SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
32b1a0aa40SJon Lin SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
33b1a0aa40SJon Lin SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
34b1a0aa40SJon Lin SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
35b1a0aa40SJon Lin SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
36b1a0aa40SJon Lin #endif
37b1a0aa40SJon Lin
38b98ac5e2SFrieder Schrempf static SPINAND_OP_VARIANTS(write_cache_variants,
39b98ac5e2SFrieder Schrempf SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
40b98ac5e2SFrieder Schrempf SPINAND_PROG_LOAD(true, 0, NULL, 0));
41b98ac5e2SFrieder Schrempf
42b98ac5e2SFrieder Schrempf static SPINAND_OP_VARIANTS(update_cache_variants,
43b98ac5e2SFrieder Schrempf SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
44b98ac5e2SFrieder Schrempf SPINAND_PROG_LOAD(false, 0, NULL, 0));
45b98ac5e2SFrieder Schrempf
w25m02gv_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)46b98ac5e2SFrieder Schrempf static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
47b98ac5e2SFrieder Schrempf struct mtd_oob_region *region)
48b98ac5e2SFrieder Schrempf {
49b98ac5e2SFrieder Schrempf if (section > 3)
50b98ac5e2SFrieder Schrempf return -ERANGE;
51b98ac5e2SFrieder Schrempf
52b98ac5e2SFrieder Schrempf region->offset = (16 * section) + 8;
53b98ac5e2SFrieder Schrempf region->length = 8;
54b98ac5e2SFrieder Schrempf
55b98ac5e2SFrieder Schrempf return 0;
56b98ac5e2SFrieder Schrempf }
57b98ac5e2SFrieder Schrempf
w25m02gv_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)58b98ac5e2SFrieder Schrempf static int w25m02gv_ooblayout_free(struct mtd_info *mtd, int section,
59b98ac5e2SFrieder Schrempf struct mtd_oob_region *region)
60b98ac5e2SFrieder Schrempf {
61b98ac5e2SFrieder Schrempf if (section > 3)
62b98ac5e2SFrieder Schrempf return -ERANGE;
63b98ac5e2SFrieder Schrempf
64b98ac5e2SFrieder Schrempf region->offset = (16 * section) + 2;
65b98ac5e2SFrieder Schrempf region->length = 6;
66b98ac5e2SFrieder Schrempf
67b98ac5e2SFrieder Schrempf return 0;
68b98ac5e2SFrieder Schrempf }
69b98ac5e2SFrieder Schrempf
70b98ac5e2SFrieder Schrempf static const struct mtd_ooblayout_ops w25m02gv_ooblayout = {
71b98ac5e2SFrieder Schrempf .ecc = w25m02gv_ooblayout_ecc,
72301f8dd1SSimon Glass .rfree = w25m02gv_ooblayout_free,
73b98ac5e2SFrieder Schrempf };
74b98ac5e2SFrieder Schrempf
w25m02gv_select_target(struct spinand_device * spinand,unsigned int target)75b98ac5e2SFrieder Schrempf static int w25m02gv_select_target(struct spinand_device *spinand,
76b98ac5e2SFrieder Schrempf unsigned int target)
77b98ac5e2SFrieder Schrempf {
78b98ac5e2SFrieder Schrempf struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0xc2, 1),
79b98ac5e2SFrieder Schrempf SPI_MEM_OP_NO_ADDR,
80b98ac5e2SFrieder Schrempf SPI_MEM_OP_NO_DUMMY,
81b98ac5e2SFrieder Schrempf SPI_MEM_OP_DATA_OUT(1,
82b98ac5e2SFrieder Schrempf spinand->scratchbuf,
83b98ac5e2SFrieder Schrempf 1));
84b98ac5e2SFrieder Schrempf
85b98ac5e2SFrieder Schrempf *spinand->scratchbuf = target;
86b98ac5e2SFrieder Schrempf return spi_mem_exec_op(spinand->slave, &op);
87b98ac5e2SFrieder Schrempf }
88b98ac5e2SFrieder Schrempf
w25n02kv_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)8922edf958SJon Lin static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section,
9022edf958SJon Lin struct mtd_oob_region *region)
9122edf958SJon Lin {
9222edf958SJon Lin if (section)
9322edf958SJon Lin return -ERANGE;
9422edf958SJon Lin
9522edf958SJon Lin region->offset = 64;
9622edf958SJon Lin region->length = 64;
9722edf958SJon Lin
9822edf958SJon Lin return 0;
9922edf958SJon Lin }
10022edf958SJon Lin
w25n02kv_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)10122edf958SJon Lin static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section,
10222edf958SJon Lin struct mtd_oob_region *region)
10322edf958SJon Lin {
10422edf958SJon Lin if (section)
10522edf958SJon Lin return -ERANGE;
10622edf958SJon Lin
10722edf958SJon Lin /* Reserve 2 bytes for the BBM. */
10822edf958SJon Lin region->offset = 2;
10922edf958SJon Lin region->length = 62;
11022edf958SJon Lin
11122edf958SJon Lin return 0;
11222edf958SJon Lin }
11322edf958SJon Lin
11422edf958SJon Lin static const struct mtd_ooblayout_ops w25n02kv_ooblayout = {
11522edf958SJon Lin .ecc = w25n02kv_ooblayout_ecc,
11622edf958SJon Lin .rfree = w25n02kv_ooblayout_free,
11722edf958SJon Lin };
11822edf958SJon Lin
w25n02kv_ecc_get_status(struct spinand_device * spinand,u8 status)11922edf958SJon Lin static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
12022edf958SJon Lin u8 status)
12122edf958SJon Lin {
12222edf958SJon Lin struct nand_device *nand = spinand_to_nand(spinand);
12322edf958SJon Lin
12422edf958SJon Lin switch (status & STATUS_ECC_MASK) {
12522edf958SJon Lin case STATUS_ECC_NO_BITFLIPS:
12622edf958SJon Lin return 0;
12722edf958SJon Lin
12822edf958SJon Lin case STATUS_ECC_UNCOR_ERROR:
12922edf958SJon Lin return -EBADMSG;
13022edf958SJon Lin
13122edf958SJon Lin case STATUS_ECC_HAS_BITFLIPS:
1329dd597e7SJon Lin return 1;
13322edf958SJon Lin
13422edf958SJon Lin default:
1359dd597e7SJon Lin return nand->eccreq.strength;
13622edf958SJon Lin }
13722edf958SJon Lin
13822edf958SJon Lin return -EINVAL;
13922edf958SJon Lin }
14022edf958SJon Lin
w25n04lw_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)141*302a7e19SJon Lin static int w25n04lw_ooblayout_ecc(struct mtd_info *mtd, int section,
142*302a7e19SJon Lin struct mtd_oob_region *region)
143*302a7e19SJon Lin {
144*302a7e19SJon Lin if (section)
145*302a7e19SJon Lin return -ERANGE;
146*302a7e19SJon Lin
147*302a7e19SJon Lin region->offset = mtd->oobsize / 2;
148*302a7e19SJon Lin region->length = mtd->oobsize / 2;
149*302a7e19SJon Lin
150*302a7e19SJon Lin return 0;
151*302a7e19SJon Lin }
152*302a7e19SJon Lin
w25n04lw_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)153*302a7e19SJon Lin static int w25n04lw_ooblayout_free(struct mtd_info *mtd, int section,
154*302a7e19SJon Lin struct mtd_oob_region *region)
155*302a7e19SJon Lin {
156*302a7e19SJon Lin if (section)
157*302a7e19SJon Lin return -ERANGE;
158*302a7e19SJon Lin
159*302a7e19SJon Lin region->offset = 2;
160*302a7e19SJon Lin region->length = mtd->oobsize / 2 - 2;
161*302a7e19SJon Lin
162*302a7e19SJon Lin return 0;
163*302a7e19SJon Lin }
164*302a7e19SJon Lin
165*302a7e19SJon Lin static const struct mtd_ooblayout_ops w25n04lw_ooblayout = {
166*302a7e19SJon Lin .ecc = w25n04lw_ooblayout_ecc,
167*302a7e19SJon Lin .rfree = w25n04lw_ooblayout_free,
168*302a7e19SJon Lin };
169*302a7e19SJon Lin
17081afcfe1SJon Lin /* Another set for the same id[2] devices in one series */
171b98ac5e2SFrieder Schrempf static const struct spinand_info winbond_spinand_table[] = {
17281afcfe1SJon Lin SPINAND_INFO("W25M02GV",
17381afcfe1SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAB),
174b98ac5e2SFrieder Schrempf NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 2),
175b98ac5e2SFrieder Schrempf NAND_ECCREQ(1, 512),
176b98ac5e2SFrieder Schrempf SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
177b98ac5e2SFrieder Schrempf &write_cache_variants,
178b98ac5e2SFrieder Schrempf &update_cache_variants),
179b98ac5e2SFrieder Schrempf 0,
180b98ac5e2SFrieder Schrempf SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
181b98ac5e2SFrieder Schrempf SPINAND_SELECT_TARGET(w25m02gv_select_target)),
18281afcfe1SJon Lin SPINAND_INFO("W25N512GV",
18381afcfe1SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAA, 0x20),
184527cb271SJon Lin NAND_MEMORG(1, 2048, 64, 64, 512, 1, 1, 1),
185527cb271SJon Lin NAND_ECCREQ(1, 512),
186527cb271SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
187527cb271SJon Lin &write_cache_variants,
188527cb271SJon Lin &update_cache_variants),
189527cb271SJon Lin 0,
190527cb271SJon Lin SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
191527cb271SJon Lin SPINAND_SELECT_TARGET(w25m02gv_select_target)),
19281afcfe1SJon Lin SPINAND_INFO("W25N01GV",
19381afcfe1SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAA, 0x21),
1942ec05489SJon Lin NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
1952ec05489SJon Lin NAND_ECCREQ(1, 512),
196b1a0aa40SJon Lin #ifdef CONFIG_SPI_NAND_WINBOND_CONT_READ
197b1a0aa40SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants_cont,
198b1a0aa40SJon Lin &write_cache_variants,
199b1a0aa40SJon Lin &update_cache_variants),
200b1a0aa40SJon Lin #else
2012ec05489SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
2022ec05489SJon Lin &write_cache_variants,
2032ec05489SJon Lin &update_cache_variants),
204b1a0aa40SJon Lin #endif
2052ec05489SJon Lin 0,
206b2ee20d3SJason Zhu SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
207b2ee20d3SJason Zhu SPINAND_SELECT_TARGET(w25m02gv_select_target)),
20881afcfe1SJon Lin SPINAND_INFO("W25N02KV",
20981afcfe1SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAA, 0x22),
2109dd597e7SJon Lin NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
21122edf958SJon Lin NAND_ECCREQ(8, 512),
21222edf958SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
21322edf958SJon Lin &write_cache_variants,
21422edf958SJon Lin &update_cache_variants),
21522edf958SJon Lin 0,
21622edf958SJon Lin SPINAND_ECCINFO(&w25n02kv_ooblayout,
21722edf958SJon Lin w25n02kv_ecc_get_status)),
21881afcfe1SJon Lin SPINAND_INFO("W25N04KV",
21981afcfe1SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAA, 0x23),
2209dd597e7SJon Lin NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1),
221027a4716SJon Lin NAND_ECCREQ(8, 512),
222027a4716SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
223027a4716SJon Lin &write_cache_variants,
224027a4716SJon Lin &update_cache_variants),
225027a4716SJon Lin 0,
226027a4716SJon Lin SPINAND_ECCINFO(&w25n02kv_ooblayout,
227027a4716SJon Lin w25n02kv_ecc_get_status)),
22881afcfe1SJon Lin SPINAND_INFO("W25N01GW",
22981afcfe1SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBA, 0x21),
23081afcfe1SJon Lin NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
23181afcfe1SJon Lin NAND_ECCREQ(1, 512),
23281afcfe1SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
23381afcfe1SJon Lin &write_cache_variants,
23481afcfe1SJon Lin &update_cache_variants),
23581afcfe1SJon Lin 0,
23681afcfe1SJon Lin SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
23781afcfe1SJon Lin SPINAND_SELECT_TARGET(w25m02gv_select_target)),
238f9e45ef5SJon Lin SPINAND_INFO("W25N02KW",
239f9e45ef5SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBA, 0x22),
2409dd597e7SJon Lin NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
241f9e45ef5SJon Lin NAND_ECCREQ(8, 512),
242f9e45ef5SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
243f9e45ef5SJon Lin &write_cache_variants,
244f9e45ef5SJon Lin &update_cache_variants),
245f9e45ef5SJon Lin 0,
246f9e45ef5SJon Lin SPINAND_ECCINFO(&w25n02kv_ooblayout,
247f9e45ef5SJon Lin w25n02kv_ecc_get_status)),
2489dd597e7SJon Lin SPINAND_INFO("W25N01KV",
2499dd597e7SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAE, 0x21),
2509dd597e7SJon Lin NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
2519dd597e7SJon Lin NAND_ECCREQ(4, 512),
2529dd597e7SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
2539dd597e7SJon Lin &write_cache_variants,
2549dd597e7SJon Lin &update_cache_variants),
2559dd597e7SJon Lin 0,
2569dd597e7SJon Lin SPINAND_ECCINFO(&w25n02kv_ooblayout,
2579dd597e7SJon Lin w25n02kv_ecc_get_status)),
258473de4c4SJon Lin SPINAND_INFO("W25N01JWZEIG",
25950dac400SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBC, 0x21),
260473de4c4SJon Lin NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
261473de4c4SJon Lin NAND_ECCREQ(1, 512),
262473de4c4SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
263473de4c4SJon Lin &write_cache_variants,
264473de4c4SJon Lin &update_cache_variants),
265473de4c4SJon Lin SPINAND_HAS_QE_BIT,
266473de4c4SJon Lin SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
2677512998aSJon Lin SPINAND_INFO("W25N01KWZPIG",
26850dac400SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBE, 0x21),
2697512998aSJon Lin NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
2707512998aSJon Lin NAND_ECCREQ(4, 512),
2717512998aSJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
2727512998aSJon Lin &write_cache_variants,
2737512998aSJon Lin &update_cache_variants),
2747512998aSJon Lin 0,
2757512998aSJon Lin SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
276*302a7e19SJon Lin SPINAND_INFO("W25N04LW2EIG",
277*302a7e19SJon Lin SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xB2, 0x23),
278*302a7e19SJon Lin NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
279*302a7e19SJon Lin NAND_ECCREQ(8, 512),
280*302a7e19SJon Lin SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
281*302a7e19SJon Lin &write_cache_variants,
282*302a7e19SJon Lin &update_cache_variants),
283*302a7e19SJon Lin SPINAND_HAS_QE_BIT,
284*302a7e19SJon Lin SPINAND_ECCINFO(&w25n04lw_ooblayout, w25n02kv_ecc_get_status)),
28522edf958SJon Lin };
28622edf958SJon Lin
winbond_spinand_init(struct spinand_device * spinand)287b98ac5e2SFrieder Schrempf static int winbond_spinand_init(struct spinand_device *spinand)
288b98ac5e2SFrieder Schrempf {
289b98ac5e2SFrieder Schrempf struct nand_device *nand = spinand_to_nand(spinand);
290b98ac5e2SFrieder Schrempf unsigned int i;
291b98ac5e2SFrieder Schrempf
292b98ac5e2SFrieder Schrempf /*
293b98ac5e2SFrieder Schrempf * Make sure all dies are in buffer read mode and not continuous read
294b98ac5e2SFrieder Schrempf * mode.
295b98ac5e2SFrieder Schrempf */
296b98ac5e2SFrieder Schrempf for (i = 0; i < nand->memorg.ntargets; i++) {
297b98ac5e2SFrieder Schrempf spinand_select_target(spinand, i);
298b98ac5e2SFrieder Schrempf spinand_upd_cfg(spinand, WINBOND_CFG_BUF_READ,
299b98ac5e2SFrieder Schrempf WINBOND_CFG_BUF_READ);
300b98ac5e2SFrieder Schrempf }
301b98ac5e2SFrieder Schrempf
3024857d1caSJon Lin /* W25N01JWZEIG enable continuous read */
303fc61dde5SJon Lin #ifdef CONFIG_SPI_NAND_WINBOND_CONT_READ
3044857d1caSJon Lin if (spinand->id.data[1] == 0xaa && spinand->id.data[2] == 0x21) {
3054857d1caSJon Lin spinand->support_cont_read = true;
3064857d1caSJon Lin spinand_upd_cfg(spinand, CFG_BUF_ENABLE, 0);
3074857d1caSJon Lin printf("Support cont_read\n");
3084857d1caSJon Lin }
3094857d1caSJon Lin #endif
3104857d1caSJon Lin
311b98ac5e2SFrieder Schrempf return 0;
312b98ac5e2SFrieder Schrempf }
313b98ac5e2SFrieder Schrempf
314b98ac5e2SFrieder Schrempf static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
315b98ac5e2SFrieder Schrempf .init = winbond_spinand_init,
316b98ac5e2SFrieder Schrempf };
317b98ac5e2SFrieder Schrempf
318b98ac5e2SFrieder Schrempf const struct spinand_manufacturer winbond_spinand_manufacturer = {
319b98ac5e2SFrieder Schrempf .id = SPINAND_MFR_WINBOND,
320b98ac5e2SFrieder Schrempf .name = "Winbond",
32181afcfe1SJon Lin .chips = winbond_spinand_table,
32281afcfe1SJon Lin .nchips = ARRAY_SIZE(winbond_spinand_table),
323b98ac5e2SFrieder Schrempf .ops = &winbond_spinand_manuf_ops,
324b98ac5e2SFrieder Schrempf };
325