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(write_cache_variants, 47 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), 48 SPINAND_PROG_LOAD(true, 0, NULL, 0)); 49 50 static SPINAND_OP_VARIANTS(update_cache_variants, 51 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), 52 SPINAND_PROG_LOAD(false, 0, NULL, 0)); 53 54 static int gd5fxgq4xa_ooblayout_ecc(struct mtd_info *mtd, int section, 55 struct mtd_oob_region *region) 56 { 57 if (section > 3) 58 return -ERANGE; 59 60 region->offset = (16 * section) + 8; 61 region->length = 8; 62 63 return 0; 64 } 65 66 static int gd5fxgq4xa_ooblayout_free(struct mtd_info *mtd, int section, 67 struct mtd_oob_region *region) 68 { 69 if (section > 3) 70 return -ERANGE; 71 72 if (section) { 73 region->offset = 16 * section; 74 region->length = 8; 75 } else { 76 /* section 0 has one byte reserved for bad block mark */ 77 region->offset = 1; 78 region->length = 7; 79 } 80 return 0; 81 } 82 83 static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = { 84 .ecc = gd5fxgq4xa_ooblayout_ecc, 85 .rfree = gd5fxgq4xa_ooblayout_free, 86 }; 87 88 static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand, 89 u8 status) 90 { 91 switch (status & STATUS_ECC_MASK) { 92 case STATUS_ECC_NO_BITFLIPS: 93 return 0; 94 95 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS: 96 /* 1-7 bits are flipped. return the maximum. */ 97 return 7; 98 99 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS: 100 return 8; 101 102 case STATUS_ECC_UNCOR_ERROR: 103 return -EBADMSG; 104 105 default: 106 break; 107 } 108 109 return -EINVAL; 110 } 111 112 static int gd5fxgqx_variant2_ooblayout_ecc(struct mtd_info *mtd, int section, 113 struct mtd_oob_region *region) 114 { 115 if (section) 116 return -ERANGE; 117 118 region->offset = 64; 119 region->length = 64; 120 121 return 0; 122 } 123 124 static int gd5fxgqx_variant2_ooblayout_free(struct mtd_info *mtd, int section, 125 struct mtd_oob_region *region) 126 { 127 if (section) 128 return -ERANGE; 129 130 /* Reserve 1 bytes for the BBM. */ 131 region->offset = 1; 132 region->length = 63; 133 134 return 0; 135 } 136 137 /* Valid for Q4/Q5 and Q6 (untested) devices */ 138 static const struct mtd_ooblayout_ops gd5fxgqx_variant2_ooblayout = { 139 .ecc = gd5fxgqx_variant2_ooblayout_ecc, 140 .rfree = gd5fxgqx_variant2_ooblayout_free, 141 }; 142 143 static int gd5fxgq4xc_ooblayout_256_ecc(struct mtd_info *mtd, int section, 144 struct mtd_oob_region *oobregion) 145 { 146 if (section) 147 return -ERANGE; 148 149 oobregion->offset = 128; 150 oobregion->length = 128; 151 152 return 0; 153 } 154 155 static int gd5fxgq4xc_ooblayout_256_free(struct mtd_info *mtd, int section, 156 struct mtd_oob_region *oobregion) 157 { 158 if (section) 159 return -ERANGE; 160 161 oobregion->offset = 1; 162 oobregion->length = 127; 163 164 return 0; 165 } 166 167 static const struct mtd_ooblayout_ops gd5fxgq4xc_oob_256_ops = { 168 .ecc = gd5fxgq4xc_ooblayout_256_ecc, 169 .rfree = gd5fxgq4xc_ooblayout_256_free, 170 }; 171 172 static int gd5fxgqx_variant3_ooblayout_ecc(struct mtd_info *mtd, int section, 173 struct mtd_oob_region *region) 174 { 175 return -ERANGE; 176 } 177 178 static int gd5fxgqx_variant3_ooblayout_free(struct mtd_info *mtd, int section, 179 struct mtd_oob_region *region) 180 { 181 if (section) 182 return -ERANGE; 183 184 /* Reserve 1 bytes for the BBM. */ 185 region->offset = 1; 186 region->length = 63; 187 188 return 0; 189 } 190 191 static const struct mtd_ooblayout_ops gd5fxgqx_variant3_ooblayout = { 192 .ecc = gd5fxgqx_variant3_ooblayout_ecc, 193 .rfree = gd5fxgqx_variant3_ooblayout_free, 194 }; 195 196 static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand, 197 u8 status) 198 { 199 u8 status2; 200 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2, 201 &status2); 202 int ret; 203 204 switch (status & STATUS_ECC_MASK) { 205 case STATUS_ECC_NO_BITFLIPS: 206 return 0; 207 208 case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS: 209 /* 210 * Read status2 register to determine a more fine grained 211 * bit error status 212 */ 213 ret = spi_mem_exec_op(spinand->slave, &op); 214 if (ret) 215 return ret; 216 217 /* 218 * 4 ... 7 bits are flipped (1..4 can't be detected, so 219 * report the maximum of 4 in this case 220 */ 221 /* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */ 222 return ((status & STATUS_ECC_MASK) >> 2) | 223 ((status2 & STATUS_ECC_MASK) >> 4); 224 225 case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS: 226 return 8; 227 228 case STATUS_ECC_UNCOR_ERROR: 229 return -EBADMSG; 230 231 default: 232 break; 233 } 234 235 return -EINVAL; 236 } 237 238 static int gd5fxgq5xexxg_ecc_get_status(struct spinand_device *spinand, 239 u8 status) 240 { 241 u8 status2; 242 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQXXEXXG_REG_STATUS2, 243 &status2); 244 int ret; 245 246 switch (status & STATUS_ECC_MASK) { 247 case STATUS_ECC_NO_BITFLIPS: 248 return 0; 249 250 case GD5FXGQ5XE_STATUS_ECC_1_4_BITFLIPS: 251 /* 252 * Read status2 register to determine a more fine grained 253 * bit error status 254 */ 255 ret = spi_mem_exec_op(spinand->slave, &op); 256 if (ret) 257 return ret; 258 259 /* 260 * 1 ... 4 bits are flipped (and corrected) 261 */ 262 /* bits sorted this way (1...0): ECCSE1, ECCSE0 */ 263 return ((status2 & STATUS_ECC_MASK) >> 4) + 1; 264 265 case STATUS_ECC_UNCOR_ERROR: 266 return -EBADMSG; 267 268 default: 269 break; 270 } 271 272 return -EINVAL; 273 } 274 275 static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand, 276 u8 status) 277 { 278 switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) { 279 case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS: 280 return 0; 281 282 case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS: 283 return 3; 284 285 case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR: 286 return -EBADMSG; 287 288 default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */ 289 return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2; 290 } 291 292 return -EINVAL; 293 } 294 295 static const struct spinand_info gigadevice_spinand_table[] = { 296 SPINAND_INFO("GD5F1GQ4xA", 297 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf1), 298 NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), 299 NAND_ECCREQ(8, 512), 300 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 301 &write_cache_variants, 302 &update_cache_variants), 303 SPINAND_HAS_QE_BIT, 304 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, 305 gd5fxgq4xa_ecc_get_status)), 306 SPINAND_INFO("GD5F2GQ4xA", 307 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf2), 308 NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), 309 NAND_ECCREQ(8, 512), 310 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 311 &write_cache_variants, 312 &update_cache_variants), 313 SPINAND_HAS_QE_BIT, 314 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, 315 gd5fxgq4xa_ecc_get_status)), 316 SPINAND_INFO("GD5F4GQ4xA", 317 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xf4), 318 NAND_MEMORG(1, 2048, 64, 64, 4096, 1, 1, 1), 319 NAND_ECCREQ(8, 512), 320 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 321 &write_cache_variants, 322 &update_cache_variants), 323 SPINAND_HAS_QE_BIT, 324 SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout, 325 gd5fxgq4xa_ecc_get_status)), 326 SPINAND_INFO("GD5F4GQ4RC", 327 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xa4, 0x68), 328 NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), 329 NAND_ECCREQ(8, 512), 330 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, 331 &write_cache_variants, 332 &update_cache_variants), 333 SPINAND_HAS_QE_BIT, 334 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops, 335 gd5fxgq4ufxxg_ecc_get_status)), 336 SPINAND_INFO("GD5F4GQ4UC", 337 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb4, 0x68), 338 NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), 339 NAND_ECCREQ(8, 512), 340 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, 341 &write_cache_variants, 342 &update_cache_variants), 343 SPINAND_HAS_QE_BIT, 344 SPINAND_ECCINFO(&gd5fxgq4xc_oob_256_ops, 345 gd5fxgq4ufxxg_ecc_get_status)), 346 SPINAND_INFO("GD5F1GQ4UExxG", 347 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd1), 348 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 349 NAND_ECCREQ(8, 512), 350 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 351 &write_cache_variants, 352 &update_cache_variants), 353 SPINAND_HAS_QE_BIT, 354 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 355 gd5fxgq4uexxg_ecc_get_status)), 356 SPINAND_INFO("GD5F1GQ4UFxxG", 357 SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48), 358 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 359 NAND_ECCREQ(8, 512), 360 SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f, 361 &write_cache_variants, 362 &update_cache_variants), 363 SPINAND_HAS_QE_BIT, 364 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 365 gd5fxgq4ufxxg_ecc_get_status)), 366 SPINAND_INFO("GD5F1GQ5UExxG", 367 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51), 368 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 369 NAND_ECCREQ(4, 512), 370 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 371 &write_cache_variants, 372 &update_cache_variants), 373 SPINAND_HAS_QE_BIT, 374 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 375 gd5fxgq5xexxg_ecc_get_status)), 376 SPINAND_INFO("GD5F2GQ5UExxG", 377 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52), 378 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 379 NAND_ECCREQ(4, 512), 380 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 381 &write_cache_variants, 382 &update_cache_variants), 383 SPINAND_HAS_QE_BIT, 384 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 385 gd5fxgq5xexxg_ecc_get_status)), 386 SPINAND_INFO("GD5F2GQ4UBxxG", 387 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2), 388 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 389 NAND_ECCREQ(8, 512), 390 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 391 &write_cache_variants, 392 &update_cache_variants), 393 SPINAND_HAS_QE_BIT, 394 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 395 gd5fxgq4xa_ecc_get_status)), 396 SPINAND_INFO("GD5F4GQ6UExxG", 397 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x55), 398 NAND_MEMORG(1, 2048, 128, 64, 4096, 1, 1, 1), 399 NAND_ECCREQ(4, 512), 400 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 401 &write_cache_variants, 402 &update_cache_variants), 403 SPINAND_HAS_QE_BIT, 404 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 405 gd5fxgq5xexxg_ecc_get_status)), 406 SPINAND_INFO("GD5F1GQ4UExxH", 407 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd9), 408 NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), 409 NAND_ECCREQ(8, 512), 410 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 411 &write_cache_variants, 412 &update_cache_variants), 413 SPINAND_HAS_QE_BIT, 414 SPINAND_ECCINFO(&gd5fxgqx_variant3_ooblayout, 415 gd5fxgq4xa_ecc_get_status)), 416 SPINAND_INFO("GD5F1GQ5RExxG", 417 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x41), 418 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 419 NAND_ECCREQ(4, 512), 420 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 421 &write_cache_variants, 422 &update_cache_variants), 423 SPINAND_HAS_QE_BIT, 424 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 425 gd5fxgq5xexxg_ecc_get_status)), 426 SPINAND_INFO("GD5F2GQ5RExxG", 427 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x42), 428 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 429 NAND_ECCREQ(4, 512), 430 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 431 &write_cache_variants, 432 &update_cache_variants), 433 SPINAND_HAS_QE_BIT, 434 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 435 gd5fxgq5xexxg_ecc_get_status)), 436 SPINAND_INFO("GD5F2GM7RxG", 437 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x82), 438 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 439 NAND_ECCREQ(8, 512), 440 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 441 &write_cache_variants, 442 &update_cache_variants), 443 SPINAND_HAS_QE_BIT, 444 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 445 gd5fxgq4xa_ecc_get_status)), 446 SPINAND_INFO("GD5F1GM7UxG", 447 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x91), 448 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 449 NAND_ECCREQ(8, 512), 450 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 451 &write_cache_variants, 452 &update_cache_variants), 453 SPINAND_HAS_QE_BIT, 454 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 455 gd5fxgq4xa_ecc_get_status)), 456 SPINAND_INFO("GD5F2GM7UxG", 457 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x92), 458 NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), 459 NAND_ECCREQ(8, 512), 460 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 461 &write_cache_variants, 462 &update_cache_variants), 463 SPINAND_HAS_QE_BIT, 464 SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, 465 gd5fxgq4xa_ecc_get_status)), 466 }; 467 468 static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = { 469 }; 470 471 const struct spinand_manufacturer gigadevice_spinand_manufacturer = { 472 .id = SPINAND_MFR_GIGADEVICE, 473 .name = "GigaDevice", 474 .chips = gigadevice_spinand_table, 475 .nchips = ARRAY_SIZE(gigadevice_spinand_table), 476 .ops = &gigadevice_spinand_manuf_ops, 477 }; 478