1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2018 Stefan Roese <sr@denx.de> 4 * 5 * Derived from drivers/mtd/nand/spi/micron.c 6 * Copyright (c) 2016-2017 Micron Technology, Inc. 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_GIGADEVICE 0xC8 16 17 #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS (1 << 4) 18 #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS (3 << 4) 19 20 #define GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS (1 << 4) 21 #define GD5FXGQ5XE_STATUS_ECC_4_BITFLIPS (3 << 4) 22 23 #define GD5FXGQXXEXXG_REG_STATUS2 0xf0 24 25 #define GD5FXGQ4UXFXXG_STATUS_ECC_MASK (7 << 4) 26 #define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS (0 << 4) 27 #define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS (1 << 4) 28 #define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR (7 << 4) 29 30 static SPINAND_OP_VARIANTS(read_cache_variants, 31 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), 32 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 33 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 34 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 35 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), 36 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); 37 38 static SPINAND_OP_VARIANTS(read_cache_variants_f, 39 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), 40 SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0), 41 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 42 SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0), 43 SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0), 44 SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0)); 45 46 static SPINAND_OP_VARIANTS(read_cache_variants_1gq5, 47 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), 48 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 49 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 50 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 51 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), 52 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); 53 54 static SPINAND_OP_VARIANTS(read_cache_variants_2gq5, 55 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0), 56 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 57 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0), 58 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 59 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), 60 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); 61 62 static SPINAND_OP_VARIANTS(write_cache_variants, 63 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), 64 SPINAND_PROG_LOAD(true, 0, NULL, 0)); 65 66 static SPINAND_OP_VARIANTS(update_cache_variants, 67 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), 68 SPINAND_PROG_LOAD(false, 0, NULL, 0)); 69 70 static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section, 71 struct mtd_oob_region *region) 72 { 73 if (section > 3) 74 return -ERANGE; 75 76 region->offset = (16 * section) + 8; 77 region->length = 8; 78 79 return 0; 80 } 81 82 static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section, 83 struct mtd_oob_region *region) 84 { 85 if (section > 3) 86 return -ERANGE; 87 88 if (section) { 89 region->offset = 16 * section; 90 region->length = 8; 91 } else { 92 /* section 0 has one byte reserved for bad block mark */ 93 region->offset = 1; 94 region->length = 7; 95 } 96 return 0; 97 } 98 99 static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = { 100 .ecc = gd5fxgq4xa_ooblayout_ecc, 101 .rfree = gd5fxgq4xa_ooblayout_free, 102 }; 103 104 static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand, 105 u8 status) 106 { 107 switch (status & STATUS_ECC_MASK) { 108 case STATUS_ECC_NO_BITFLIPS: 109 return 0; 110 111 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS: 112 /* 1-7 bits are flipped. return the maximum. */ 113 return 7; 114 115 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS: 116 return 8; 117 118 case STATUS_ECC_UNCOR_ERROR: 119 return -EBADMSG; 120 121 default: 122 break; 123 } 124 125 return -EINVAL; 126 } 127 128 static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section, 129 struct mtd_oob_region *region) 130 { 131 if (section) 132 return -ERANGE; 133 134 region->offset = 64; 135 region->length = 64; 136 137 return 0; 138 } 139 140 static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section, 141 struct mtd_oob_region *region) 142 { 143 if (section) 144 return -ERANGE; 145 146 /* Reserve 1 bytes for the BBM. */ 147 region->offset = 1; 148 region->length = 63; 149 150 return 0; 151 } 152 153 /* Valid for Q4/Q5 and Q6 (untested) devices */ 154 static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = { 155 .ecc = gd5fxgqx_variant2_ooblayout_ecc, 156 .rfree = gd5fxgqx_variant2_ooblayout_free, 157 }; 158 159 static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section, 160 struct mtd_oob_region *oobregion) 161 { 162 if (section) 163 return -ERANGE; 164 165 oobregion->offset = 128; 166 oobregion->length = 128; 167 168 return 0; 169 } 170 171 static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section, 172 struct mtd_oob_region *oobregion) 173 { 174 if (section) 175 return -ERANGE; 176 177 oobregion->offset = 1; 178 oobregion->length = 127; 179 180 return 0; 181 } 182 183 static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = { 184 .ecc = gd5fxgq4xc_ooblayout_256_ecc, 185 .rfree = gd5fxgq4xc_ooblayout_256_free, 186 }; 187 188 static int gd5fxgqx_variant3_ooblayout_ecc(struct mtd_info *mtd, int section, 189 struct mtd_oob_region *region) 190 { 191 return -ERANGE; 192 } 193 194 static int gd5fxgqx_variant3_ooblayout_free(struct mtd_info *mtd, int section, 195 struct mtd_oob_region *region) 196 { 197 if (section) 198 return -ERANGE; 199 200 /* Reserve 1 bytes for the BBM. */ 201 region->offset = 1; 202 region->length = 63; 203 204 return 0; 205 } 206 207 static const struct mtd_ooblayout_ops gd5fxgqx_variant3_ooblayout = { 208 .ecc = gd5fxgqx_variant3_ooblayout_ecc, 209 .rfree = gd5fxgqx_variant3_ooblayout_free, 210 }; 211 212 static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand, 213 u8 status) 214 { 215 u8 status2; 216 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2, 217 &status2); 218 int ret; 219 220 switch (status & STATUS_ECC_MASK) { 221 case STATUS_ECC_NO_BITFLIPS: 222 return 0; 223 224 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS: 225 /* 226 * Read status2 register to determine a more fine grained 227 * bit error status 228 */ 229 ret = spi_mem_exec_op(spinand->slave, &op); 230 if (ret) 231 return ret; 232 233 /* 234 * 4 ... 7 bits are flipped (1..4 can't be detected, so 235 * report the maximum of 4 in this case 236 */ 237 /* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */ 238 return ((status & STATUS_ECC_MASK) >> 2) | 239 ((status2 & STATUS_ECC_MASK) >> 4); 240 241 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS: 242 return 8; 243 244 case STATUS_ECC_UNCOR_ERROR: 245 return -EBADMSG; 246 247 default: 248 break; 249 } 250 251 return -EINVAL; 252 } 253 254 static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand, 255 u8 status) 256 { 257 u8 status2; 258 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2, 259 &status2); 260 int ret; 261 262 switch (status & STATUS_ECC_MASK) { 263 case STATUS_ECC_NO_BITFLIPS: 264 return 0; 265 266 case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS: 267 /* 268 * Read status2 register to determine a more fine grained 269 * bit error status 270 */ 271 ret = spi_mem_exec_op(spinand->slave, &op); 272 if (ret) 273 return ret; 274 275 /* 276 * 1 ... 4 bits are flipped (and corrected) 277 */ 278 /* bits sorted this way (1...0): ECCSE1, ECCSE0 */ 279 return ((status2 & STATUS_ECC_MASK) >> 4) + 1; 280 281 case STATUS_ECC_UNCOR_ERROR: 282 return -EBADMSG; 283 284 default: 285 break; 286 } 287 288 return -EINVAL; 289 } 290 291 static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand, 292 u8 status) 293 { 294 switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) { 295 case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS: 296 return 0; 297 298 case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS: 299 return 3; 300 301 case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR: 302 return -EBADMSG; 303 304 default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */ 305 return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2; 306 } 307 308 return -EINVAL; 309 } 310 311 static const struct spinand_info gigadevice_spinand_table[] = { 312 SPINAND_INFO("GD5F1GQ4xA", 313 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1), 314 NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), 315 NAND_ECCREQ(8, 512), 316 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 317 &write_cache_variants, 318 &update_cache_variants), 319 SPINAND_HAS_QE_BIT, 320 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, 321 gd5fxgq4xa_ecc_get_status)), 322 SPINAND_INFO("GD5F2GQ4xA", 323 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2), 324 NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), 325 NAND_ECCREQ(8, 512), 326 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 327 &write_cache_variants, 328 &update_cache_variants), 329 SPINAND_HAS_QE_BIT, 330 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, 331 gd5fxgq4xa_ecc_get_status)), 332 SPINAND_INFO("GD5F4GQ4xA", 333 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4), 334 NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1), 335 NAND_ECCREQ(8, 512), 336 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 337 &write_cache_variants, 338 &update_cache_variants), 339 SPINAND_HAS_QE_BIT, 340 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, 341 gd5fxgq4xa_ecc_get_status)), 342 SPINAND_INFO("GD5F4GQ4RC", 343 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68), 344 NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), 345 NAND_ECCREQ(8, 512), 346 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, 347 &write_cache_variants, 348 &update_cache_variants), 349 SPINAND_HAS_QE_BIT, 350 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops, 351 gd5fxgq4ufxxg_ecc_get_status)), 352 SPINAND_INFO("GD5F4GQ4UC", 353 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68), 354 NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), 355 NAND_ECCREQ(8, 512), 356 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, 357 &write_cache_variants, 358 &update_cache_variants), 359 SPINAND_HAS_QE_BIT, 360 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops, 361 gd5fxgq4ufxxg_ecc_get_status)), 362 SPINAND_INFO("GD5F1GQ4UExxG", 363 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1), 364 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 365 NAND_ECCREQ(8, 512), 366 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 367 &write_cache_variants, 368 &update_cache_variants), 369 SPINAND_HAS_QE_BIT, 370 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 371 gd5fxgq4uexxg_ecc_get_status)), 372 SPINAND_INFO("GD5F1GQ4RExxG", 373 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1), 374 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 375 NAND_ECCREQ(8, 512), 376 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 377 &write_cache_variants, 378 &update_cache_variants), 379 SPINAND_HAS_QE_BIT, 380 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 381 gd5fxgq4uexxg_ecc_get_status)), 382 SPINAND_INFO("GD5F2GQ4UExxG", 383 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2), 384 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 385 NAND_ECCREQ(8, 512), 386 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 387 &write_cache_variants, 388 &update_cache_variants), 389 SPINAND_HAS_QE_BIT, 390 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 391 gd5fxgq4uexxg_ecc_get_status)), 392 SPINAND_INFO("GD5F2GQ4RExxG", 393 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2), 394 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 395 NAND_ECCREQ(8, 512), 396 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 397 &write_cache_variants, 398 &update_cache_variants), 399 SPINAND_HAS_QE_BIT, 400 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 401 gd5fxgq4uexxg_ecc_get_status)), 402 SPINAND_INFO("GD5F1GQ4UFxxG", 403 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48), 404 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 405 NAND_ECCREQ(8, 512), 406 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, 407 &write_cache_variants, 408 &update_cache_variants), 409 SPINAND_HAS_QE_BIT, 410 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 411 gd5fxgq4ufxxg_ecc_get_status)), 412 SPINAND_INFO("GD5F1GQ5UExxG", 413 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51), 414 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 415 NAND_ECCREQ(4, 512), 416 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 417 &write_cache_variants, 418 &update_cache_variants), 419 SPINAND_HAS_QE_BIT, 420 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 421 gd5fxgq5xexxg_ecc_get_status)), 422 SPINAND_INFO("GD5F1GQ5RExxG", 423 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41, 0xC8), 424 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 425 NAND_ECCREQ(4, 512), 426 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, 427 &write_cache_variants, 428 &update_cache_variants), 429 SPINAND_HAS_QE_BIT, 430 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 431 gd5fxgq5xexxg_ecc_get_status)), 432 SPINAND_INFO("GD5F2GQ5UExxG", 433 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52), 434 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 435 NAND_ECCREQ(4, 512), 436 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, 437 &write_cache_variants, 438 &update_cache_variants), 439 SPINAND_HAS_QE_BIT, 440 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 441 gd5fxgq5xexxg_ecc_get_status)), 442 SPINAND_INFO("GD5F2GQ5RExxG", 443 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42), 444 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 445 NAND_ECCREQ(4, 512), 446 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, 447 &write_cache_variants, 448 &update_cache_variants), 449 SPINAND_HAS_QE_BIT, 450 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 451 gd5fxgq5xexxg_ecc_get_status)), 452 SPINAND_INFO("GD5F4GQ6UExxG", 453 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55), 454 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 2, 1), 455 NAND_ECCREQ(4, 512), 456 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, 457 &write_cache_variants, 458 &update_cache_variants), 459 SPINAND_HAS_QE_BIT, 460 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 461 gd5fxgq5xexxg_ecc_get_status)), 462 SPINAND_INFO("GD5F4GQ6RExxG", 463 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45), 464 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 2, 1), 465 NAND_ECCREQ(4, 512), 466 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, 467 &write_cache_variants, 468 &update_cache_variants), 469 SPINAND_HAS_QE_BIT, 470 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 471 gd5fxgq5xexxg_ecc_get_status)), 472 SPINAND_INFO("GD5F1GM7UExxG", 473 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91), 474 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 475 NAND_ECCREQ(8, 512), 476 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, 477 &write_cache_variants, 478 &update_cache_variants), 479 SPINAND_HAS_QE_BIT, 480 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 481 gd5fxgq4uexxg_ecc_get_status)), 482 SPINAND_INFO("GD5F1GM7RExxG", 483 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81), 484 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 485 NAND_ECCREQ(8, 512), 486 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, 487 &write_cache_variants, 488 &update_cache_variants), 489 SPINAND_HAS_QE_BIT, 490 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 491 gd5fxgq4uexxg_ecc_get_status)), 492 SPINAND_INFO("GD5F2GM7UExxG", 493 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92), 494 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 495 NAND_ECCREQ(8, 512), 496 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, 497 &write_cache_variants, 498 &update_cache_variants), 499 SPINAND_HAS_QE_BIT, 500 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 501 gd5fxgq4uexxg_ecc_get_status)), 502 SPINAND_INFO("GD5F2GM7RExxG", 503 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82), 504 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 505 NAND_ECCREQ(8, 512), 506 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, 507 &write_cache_variants, 508 &update_cache_variants), 509 SPINAND_HAS_QE_BIT, 510 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 511 gd5fxgq4uexxg_ecc_get_status)), 512 SPINAND_INFO("GD5F4GM8UExxG", 513 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95), 514 NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1), 515 NAND_ECCREQ(8, 512), 516 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, 517 &write_cache_variants, 518 &update_cache_variants), 519 SPINAND_HAS_QE_BIT, 520 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 521 gd5fxgq4uexxg_ecc_get_status)), 522 SPINAND_INFO("GD5F4GM8RExxG", 523 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85), 524 NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1), 525 NAND_ECCREQ(8, 512), 526 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, 527 &write_cache_variants, 528 &update_cache_variants), 529 SPINAND_HAS_QE_BIT, 530 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 531 gd5fxgq4uexxg_ecc_get_status)), 532 SPINAND_INFO("GD5F1GQ4UExxH", 533 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd9), 534 NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), 535 NAND_ECCREQ(8, 512), 536 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 537 &write_cache_variants, 538 &update_cache_variants), 539 SPINAND_HAS_QE_BIT, 540 SPINAND_ECCINFO(&gd5fxgqx_variant3_ooblayout, 541 gd5fxgq4xa_ecc_get_status)), 542 SPINAND_INFO("GD5F1GM9UEYIGY", 543 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91), 544 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 545 NAND_ECCREQ(8, 512), 546 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 547 &write_cache_variants, 548 &update_cache_variants), 549 SPINAND_HAS_QE_BIT, 550 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, gd5fxgq4xa_ecc_get_status)), 551 }; 552 553 static int gigadevice_spinand_set_ds(struct spinand_device *spinand, u8 ds_io) 554 { 555 struct spi_mem_op op = SPINAND_SET_FEATURE_OP(0xD0, 556 spinand->scratchbuf); 557 558 *spinand->scratchbuf = (ds_io & 0x3) << 5; 559 return spi_mem_exec_op(spinand->slave, &op); 560 } 561 562 static int gigadevice_spinand_init(struct spinand_device *spinand) 563 { 564 /* GD5F1GQ5UExxG */ 565 if (spinand->id.data[1] == 0x51) 566 gigadevice_spinand_set_ds(spinand, 3); 567 568 return 0; 569 } 570 571 static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = { 572 .init = gigadevice_spinand_init, 573 }; 574 575 const struct spinand_manufacturer gigadevice_spinand_manufacturer = { 576 .id = SPINAND_MFR_GIGADEVICE, 577 .name = "GigaDevice", 578 .chips = gigadevice_spinand_table, 579 .nchips = ARRAY_SIZE(gigadevice_spinand_table), 580 .ops = &gigadevice_spinand_manuf_ops, 581 }; 582