xref: /OK3568_Linux_fs/u-boot/drivers/mtd/nand/spi/hyf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd
4  *
5  * Authors:
6  *	Dingqiang Lin <jon.lin@rock-chips.com>
7  */
8 
9 #ifndef __UBOOT__
10 #include <linux/device.h>
11 #include <linux/kernel.h>
12 #endif
13 #include <linux/mtd/spinand.h>
14 
15 #define SPINAND_MFR_HYF		0xC9
16 
17 static SPINAND_OP_VARIANTS(read_cache_variants,
18 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
19 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
20 		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
21 		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
22 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
23 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
24 
25 static SPINAND_OP_VARIANTS(write_cache_variants,
26 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
27 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
28 
29 static SPINAND_OP_VARIANTS(update_cache_variants,
30 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
31 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
32 
hyf1gq4upacae_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)33 static int hyf1gq4upacae_ooblayout_ecc(struct mtd_info *mtd, int section,
34 				       struct mtd_oob_region *region)
35 {
36 	if (section)
37 		return -ERANGE;
38 
39 	region->offset = 64;
40 	region->length = 64;
41 
42 	return 0;
43 }
44 
hyf1gq4upacae_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)45 static int hyf1gq4upacae_ooblayout_free(struct mtd_info *mtd, int section,
46 					struct mtd_oob_region *region)
47 {
48 	if (section)
49 		return -ERANGE;
50 
51 	region->offset = 1;
52 	region->length = 63;
53 
54 	return 0;
55 }
56 
57 static const struct mtd_ooblayout_ops hyf1gq4upacae_ooblayout = {
58 	.ecc = hyf1gq4upacae_ooblayout_ecc,
59 	.rfree = hyf1gq4upacae_ooblayout_free,
60 };
61 
hyf1gq4udacae_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)62 static int hyf1gq4udacae_ooblayout_ecc(struct mtd_info *mtd, int section,
63 				       struct mtd_oob_region *region)
64 {
65 	if (section > 3)
66 		return -ERANGE;
67 
68 	region->offset = (16 * section) + 8;
69 	region->length = 8;
70 
71 	return 0;
72 }
73 
hyf1gq4udacae_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)74 static int hyf1gq4udacae_ooblayout_free(struct mtd_info *mtd, int section,
75 					struct mtd_oob_region *region)
76 {
77 	if (section > 3)
78 		return -ERANGE;
79 
80 	region->offset = (16 * section) + 4;
81 	region->length = 4;
82 
83 	return 0;
84 }
85 
86 static const struct mtd_ooblayout_ops hyf1gq4udacae_ooblayout = {
87 	.ecc = hyf1gq4udacae_ooblayout_ecc,
88 	.rfree = hyf1gq4udacae_ooblayout_free,
89 };
90 
hyf2gq4uaacae_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)91 static int hyf2gq4uaacae_ooblayout_ecc(struct mtd_info *mtd, int section,
92 				       struct mtd_oob_region *region)
93 {
94 	if (section > 3)
95 		return -ERANGE;
96 
97 	region->offset = (32 * section) + 8;
98 	region->length = 24;
99 
100 	return 0;
101 }
102 
hyf2gq4uaacae_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)103 static int hyf2gq4uaacae_ooblayout_free(struct mtd_info *mtd, int section,
104 					struct mtd_oob_region *region)
105 {
106 	if (section > 3)
107 		return -ERANGE;
108 
109 	region->offset = 32 * section;
110 	region->length = 8;
111 
112 	return 0;
113 }
114 
115 static const struct mtd_ooblayout_ops hyf2gq4uaacae_ooblayout = {
116 	.ecc = hyf2gq4uaacae_ooblayout_ecc,
117 	.rfree = hyf2gq4uaacae_ooblayout_free,
118 };
119 
hyf1gq4udacae_ecc_get_status(struct spinand_device * spinand,u8 status)120 static int hyf1gq4udacae_ecc_get_status(struct spinand_device *spinand,
121 					u8 status)
122 {
123 	struct nand_device *nand = spinand_to_nand(spinand);
124 
125 	switch (status & STATUS_ECC_MASK) {
126 	case STATUS_ECC_NO_BITFLIPS:
127 		return 0;
128 
129 	case STATUS_ECC_UNCOR_ERROR:
130 		return -EBADMSG;
131 
132 	case STATUS_ECC_HAS_BITFLIPS:
133 		return 1;
134 
135 	default:
136 		return nand->eccreq.strength;
137 	}
138 
139 	return -EINVAL;
140 }
141 
142 static const struct spinand_info hyf_spinand_table[] = {
143 	SPINAND_INFO("HYF1GQ4UPACAE",
144 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xA1),
145 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
146 		     NAND_ECCREQ(1, 512),
147 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
148 					      &write_cache_variants,
149 					      &update_cache_variants),
150 		     SPINAND_HAS_QE_BIT,
151 		     SPINAND_ECCINFO(&hyf1gq4upacae_ooblayout, NULL)),
152 	SPINAND_INFO("HYF1GQ4UDACAE",
153 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x21),
154 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
155 		     NAND_ECCREQ(4, 512),
156 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
157 					      &write_cache_variants,
158 					      &update_cache_variants),
159 		     SPINAND_HAS_QE_BIT,
160 		     SPINAND_ECCINFO(&hyf1gq4udacae_ooblayout,
161 				     hyf1gq4udacae_ecc_get_status)),
162 	SPINAND_INFO("HYF1GQ4UDACAE",
163 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x22),
164 		     NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1),
165 		     NAND_ECCREQ(4, 512),
166 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
167 					      &write_cache_variants,
168 					      &update_cache_variants),
169 		     SPINAND_HAS_QE_BIT,
170 		     SPINAND_ECCINFO(&hyf1gq4udacae_ooblayout,
171 				     hyf1gq4udacae_ecc_get_status)),
172 	SPINAND_INFO("HYF2GQ4UAACAE",
173 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52),
174 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
175 		     NAND_ECCREQ(14, 512),
176 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
177 					      &write_cache_variants,
178 					      &update_cache_variants),
179 		     SPINAND_HAS_QE_BIT,
180 		     SPINAND_ECCINFO(&hyf2gq4uaacae_ooblayout,
181 				     hyf1gq4udacae_ecc_get_status)),
182 	SPINAND_INFO("HYF2GQ4UHCCAE",
183 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x5A),
184 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
185 		     NAND_ECCREQ(14, 512),
186 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
187 					      &write_cache_variants,
188 					      &update_cache_variants),
189 		     SPINAND_HAS_QE_BIT,
190 		     SPINAND_ECCINFO(&hyf2gq4uaacae_ooblayout,
191 				     hyf1gq4udacae_ecc_get_status)),
192 	SPINAND_INFO("HYF4GQ4UAACBE",
193 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xD4),
194 		     NAND_MEMORG(1, 4096, 128, 64, 2048, 1, 1, 1),
195 		     NAND_ECCREQ(4, 512),
196 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
197 					      &write_cache_variants,
198 					      &update_cache_variants),
199 		     SPINAND_HAS_QE_BIT,
200 		     SPINAND_ECCINFO(&hyf2gq4uaacae_ooblayout,
201 				     hyf1gq4udacae_ecc_get_status)),
202 	SPINAND_INFO("HYF2GQ4IAACAE",
203 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x82),
204 		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
205 		     NAND_ECCREQ(14, 512),
206 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
207 					      &write_cache_variants,
208 					      &update_cache_variants),
209 		     SPINAND_HAS_QE_BIT,
210 		     SPINAND_ECCINFO(&hyf2gq4uaacae_ooblayout,
211 				     hyf1gq4udacae_ecc_get_status)),
212 	SPINAND_INFO("HYF1GQ4IDACAE",
213 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x81),
214 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1),
215 		     NAND_ECCREQ(4, 512),
216 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
217 					      &write_cache_variants,
218 					      &update_cache_variants),
219 		     SPINAND_HAS_QE_BIT,
220 		     SPINAND_ECCINFO(&hyf1gq4udacae_ooblayout,
221 				     hyf1gq4udacae_ecc_get_status)),
222 };
223 
224 static const struct spinand_manufacturer_ops hyf_spinand_manuf_ops = {
225 };
226 
227 const struct spinand_manufacturer hyf_spinand_manufacturer = {
228 	.id = SPINAND_MFR_HYF,
229 	.name = "hyf",
230 	.chips = hyf_spinand_table,
231 	.nchips = ARRAY_SIZE(hyf_spinand_table),
232 	.ops = &hyf_spinand_manuf_ops,
233 };
234