1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Author: Ahmed Naseef <naseefkm@gmail.com> 4 */ 5 6 #include <linux/device.h> 7 #include <linux/kernel.h> 8 #include <linux/mtd/spinand.h> 9 10 #define SPINAND_MFR_DOSILICON 0xE5 11 12 static SPINAND_OP_VARIANTS(read_cache_variants, 13 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0), 14 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0), 15 SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0), 16 SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0)); 17 18 static SPINAND_OP_VARIANTS(write_cache_variants, 19 SPINAND_PROG_LOAD_1S_1S_4S_OP(true, 0, NULL, 0), 20 SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0)); 21 22 static SPINAND_OP_VARIANTS(update_cache_variants, 23 SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0), 24 SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0)); 25 26 static int ds35xx_ooblayout_ecc(struct mtd_info *mtd, int section, 27 struct mtd_oob_region *region) 28 { 29 if (section > 3) 30 return -ERANGE; 31 32 region->offset = 8 + (section * 16); 33 region->length = 8; 34 35 return 0; 36 } 37 38 static int ds35xx_ooblayout_free(struct mtd_info *mtd, int section, 39 struct mtd_oob_region *region) 40 { 41 if (section > 3) 42 return -ERANGE; 43 44 if (section == 0) { 45 /* reserve 2 bytes for the BBM */ 46 region->offset = 2; 47 region->length = 6; 48 } else { 49 region->offset = section * 16; 50 region->length = 8; 51 } 52 53 return 0; 54 } 55 56 static const struct mtd_ooblayout_ops ds35xx_ooblayout = { 57 .ecc = ds35xx_ooblayout_ecc, 58 .free = ds35xx_ooblayout_free, 59 }; 60 61 static const struct spinand_info dosilicon_spinand_table[] = { 62 SPINAND_INFO("DS35Q1GA", 63 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x71), 64 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 65 NAND_ECCREQ(4, 512), 66 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 67 &write_cache_variants, 68 &update_cache_variants), 69 SPINAND_HAS_QE_BIT, 70 SPINAND_ECCINFO(&ds35xx_ooblayout, NULL)), 71 SPINAND_INFO("DS35M1GA", 72 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x21), 73 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 74 NAND_ECCREQ(4, 512), 75 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 76 &write_cache_variants, 77 &update_cache_variants), 78 SPINAND_HAS_QE_BIT, 79 SPINAND_ECCINFO(&ds35xx_ooblayout, NULL)), 80 }; 81 82 static const struct spinand_manufacturer_ops dosilicon_spinand_manuf_ops = { 83 }; 84 85 const struct spinand_manufacturer dosilicon_spinand_manufacturer = { 86 .id = SPINAND_MFR_DOSILICON, 87 .name = "Dosilicon", 88 .chips = dosilicon_spinand_table, 89 .nchips = ARRAY_SIZE(dosilicon_spinand_table), 90 .ops = &dosilicon_spinand_manuf_ops, 91 }; 92