1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2016-2017 Micron Technology, Inc. 4 * 5 * Authors: 6 * Peter Pan <peterpandong@micron.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_MICRON 0x2c 16 17 #define MICRON_STATUS_ECC_MASK GENMASK(7, 4) 18 #define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4) 19 #define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4) 20 #define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4) 21 #define MICRON_STATUS_ECC_7TO8_BITFLIPS (5 << 4) 22 23 static SPINAND_OP_VARIANTS(read_cache_variants, 24 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), 25 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 26 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 27 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 28 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), 29 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); 30 31 static SPINAND_OP_VARIANTS(write_cache_variants, 32 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), 33 SPINAND_PROG_LOAD(true, 0, NULL, 0)); 34 35 static SPINAND_OP_VARIANTS(update_cache_variants, 36 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), 37 SPINAND_PROG_LOAD(false, 0, NULL, 0)); 38 39 static int mt29f2g01abagd_ooblayout_ecc(struct mtd_info *mtd, int section, 40 struct mtd_oob_region *region) 41 { 42 if (section) 43 return -ERANGE; 44 45 region->offset = 64; 46 region->length = 64; 47 48 return 0; 49 } 50 51 static int mt29f2g01abagd_ooblayout_free(struct mtd_info *mtd, int section, 52 struct mtd_oob_region *region) 53 { 54 if (section) 55 return -ERANGE; 56 57 /* Reserve 2 bytes for the BBM. */ 58 region->offset = 2; 59 region->length = 62; 60 61 return 0; 62 } 63 64 static const struct mtd_ooblayout_ops mt29f2g01abagd_ooblayout = { 65 .ecc = mt29f2g01abagd_ooblayout_ecc, 66 .rfree = mt29f2g01abagd_ooblayout_free, 67 }; 68 69 static int mt29f2g01abagd_ecc_get_status(struct spinand_device *spinand, 70 u8 status) 71 { 72 switch (status & MICRON_STATUS_ECC_MASK) { 73 case STATUS_ECC_NO_BITFLIPS: 74 return 0; 75 76 case STATUS_ECC_UNCOR_ERROR: 77 return -EBADMSG; 78 79 case MICRON_STATUS_ECC_1TO3_BITFLIPS: 80 return 3; 81 82 case MICRON_STATUS_ECC_4TO6_BITFLIPS: 83 return 6; 84 85 case MICRON_STATUS_ECC_7TO8_BITFLIPS: 86 return 8; 87 88 default: 89 break; 90 } 91 92 return -EINVAL; 93 } 94 95 static int mt29f4g01abafd_ooblayout_ecc(struct mtd_info *mtd, int section, 96 struct mtd_oob_region *region) 97 { 98 if (section) 99 return -ERANGE; 100 101 region->offset = mtd->oobsize / 2; 102 region->length = mtd->oobsize / 2; 103 104 return 0; 105 } 106 107 static int mt29f4g01abafd_ooblayout_free(struct mtd_info *mtd, int section, 108 struct mtd_oob_region *region) 109 { 110 if (section) 111 return -ERANGE; 112 113 region->offset = 2; 114 region->length = mtd->oobsize / 2 - 2; 115 116 return 0; 117 } 118 119 static const struct mtd_ooblayout_ops mt29f4g01abafd_ooblayout = { 120 .ecc = mt29f4g01abafd_ooblayout_ecc, 121 .rfree = mt29f4g01abafd_ooblayout_free, 122 }; 123 124 /* 125 * ecc bits: 0xC0[4,6] 126 * [0b000], No bit errors were detected; 127 * [0b001] and [0b011], 1~6 Bit errors were detected and corrected. Not 128 * reach Flipping Bits; 129 * [0b101], Bit error count equals the bit flip 130 * detection threshold 131 * [0b010], Multiple bit errors were detected and 132 * not corrected. 133 * others, Reserved. 134 */ 135 static int mt29f4g01abafd_ecc_ecc_get_status(struct spinand_device *spinand, 136 u8 status) 137 { 138 struct nand_device *nand = spinand_to_nand(spinand); 139 u8 eccsr = (status & GENMASK(6, 4)) >> 4; 140 141 if (eccsr <= 1 || eccsr == 3) 142 return eccsr; 143 else if (eccsr == 5) 144 return nand->eccreq.strength; 145 else 146 return -EBADMSG; 147 } 148 149 static const struct spinand_info micron_spinand_table[] = { 150 SPINAND_INFO("MT29F2G01ABAGD", 151 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), 152 NAND_MEMORG(1, 2048, 128, 64, 2048, 2, 1, 1), 153 NAND_ECCREQ(8, 512), 154 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 155 &write_cache_variants, 156 &update_cache_variants), 157 0, 158 SPINAND_ECCINFO(&mt29f2g01abagd_ooblayout, 159 mt29f2g01abagd_ecc_get_status)), 160 SPINAND_INFO("MT29F1G01ABAGD", 161 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), 162 NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), 163 NAND_ECCREQ(8, 512), 164 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 165 &write_cache_variants, 166 &update_cache_variants), 167 0, 168 SPINAND_ECCINFO(&mt29f2g01abagd_ooblayout, 169 mt29f2g01abagd_ecc_get_status)), 170 SPINAND_INFO("MT29F4G01ABAFD", 171 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34), 172 NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), 173 NAND_ECCREQ(8, 512), 174 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 175 &write_cache_variants, 176 &update_cache_variants), 177 0, 178 SPINAND_ECCINFO(&mt29f4g01abafd_ooblayout, mt29f4g01abafd_ecc_ecc_get_status)), 179 }; 180 181 static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = { 182 }; 183 184 const struct spinand_manufacturer micron_spinand_manufacturer = { 185 .id = SPINAND_MFR_MICRON, 186 .name = "Micron", 187 .chips = micron_spinand_table, 188 .nchips = ARRAY_SIZE(micron_spinand_table), 189 .ops = µn_spinand_manuf_ops, 190 }; 191