1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Author: 4 * Felix Matouschek <felix@matouschek.org> 5 */ 6 7 #include <linux/bitfield.h> 8 #include <linux/device.h> 9 #include <linux/kernel.h> 10 #include <linux/mtd/spinand.h> 11 12 #define SPINAND_MFR_XTX 0x0B 13 14 #define XT26G0XA_STATUS_ECC_MASK GENMASK(5, 2) 15 #define XT26G0XA_STATUS_ECC_NO_DETECTED (0 << 2) 16 #define XT26G0XA_STATUS_ECC_8_CORRECTED (3 << 4) 17 #define XT26G0XA_STATUS_ECC_UNCOR_ERROR (2 << 4) 18 19 #define XT26XXXD_STATUS_ECC3_ECC2_MASK GENMASK(7, 6) 20 #define XT26XXXD_STATUS_ECC_NO_DETECTED (0) 21 #define XT26XXXD_STATUS_ECC_1_7_CORRECTED (1) 22 #define XT26XXXD_STATUS_ECC_8_CORRECTED (3) 23 #define XT26XXXD_STATUS_ECC_UNCOR_ERROR (2) 24 25 static SPINAND_OP_VARIANTS(read_cache_variants, 26 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), 27 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 28 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 29 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 30 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), 31 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); 32 33 static SPINAND_OP_VARIANTS(write_cache_variants, 34 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), 35 SPINAND_PROG_LOAD(true, 0, NULL, 0)); 36 37 static SPINAND_OP_VARIANTS(update_cache_variants, 38 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), 39 SPINAND_PROG_LOAD(false, 0, NULL, 0)); 40 41 static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section, 42 struct mtd_oob_region *region) 43 { 44 if (section) 45 return -ERANGE; 46 47 region->offset = 48; 48 region->length = 16; 49 50 return 0; 51 } 52 53 static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section, 54 struct mtd_oob_region *region) 55 { 56 if (section) 57 return -ERANGE; 58 59 region->offset = 1; 60 region->length = 47; 61 62 return 0; 63 } 64 65 static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = { 66 .ecc = xt26g0xa_ooblayout_ecc, 67 .free = xt26g0xa_ooblayout_free, 68 }; 69 70 static int xt26g0xa_ecc_get_status(struct spinand_device *spinand, 71 u8 status) 72 { 73 status = status & XT26G0XA_STATUS_ECC_MASK; 74 75 switch (status) { 76 case XT26G0XA_STATUS_ECC_NO_DETECTED: 77 return 0; 78 case XT26G0XA_STATUS_ECC_8_CORRECTED: 79 return 8; 80 case XT26G0XA_STATUS_ECC_UNCOR_ERROR: 81 return -EBADMSG; 82 default: 83 break; 84 } 85 86 /* At this point values greater than (2 << 4) are invalid */ 87 if (status > XT26G0XA_STATUS_ECC_UNCOR_ERROR) 88 return -EINVAL; 89 90 /* (1 << 2) through (7 << 2) are 1-7 corrected errors */ 91 return status >> 2; 92 } 93 94 static int xt26xxxd_ooblayout_ecc(struct mtd_info *mtd, int section, 95 struct mtd_oob_region *region) 96 { 97 if (section) 98 return -ERANGE; 99 100 region->offset = mtd->oobsize / 2; 101 region->length = mtd->oobsize / 2; 102 103 return 0; 104 } 105 106 static int xt26xxxd_ooblayout_free(struct mtd_info *mtd, int section, 107 struct mtd_oob_region *region) 108 { 109 if (section) 110 return -ERANGE; 111 112 region->offset = 2; 113 region->length = mtd->oobsize / 2 - 2; 114 115 return 0; 116 } 117 118 static const struct mtd_ooblayout_ops xt26xxxd_ooblayout = { 119 .ecc = xt26xxxd_ooblayout_ecc, 120 .free = xt26xxxd_ooblayout_free, 121 }; 122 123 static int xt26xxxd_ecc_get_status(struct spinand_device *spinand, 124 u8 status) 125 { 126 switch (FIELD_GET(STATUS_ECC_MASK, status)) { 127 case XT26XXXD_STATUS_ECC_NO_DETECTED: 128 return 0; 129 case XT26XXXD_STATUS_ECC_UNCOR_ERROR: 130 return -EBADMSG; 131 case XT26XXXD_STATUS_ECC_1_7_CORRECTED: 132 return 4 + FIELD_GET(XT26XXXD_STATUS_ECC3_ECC2_MASK, status); 133 case XT26XXXD_STATUS_ECC_8_CORRECTED: 134 return 8; 135 default: 136 break; 137 } 138 139 return -EINVAL; 140 } 141 static const struct spinand_info xtx_spinand_table[] = { 142 SPINAND_INFO("XT26G01A", 143 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE1), 144 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 145 NAND_ECCREQ(8, 512), 146 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 147 &write_cache_variants, 148 &update_cache_variants), 149 SPINAND_HAS_QE_BIT, 150 SPINAND_ECCINFO(&xt26g0xa_ooblayout, 151 xt26g0xa_ecc_get_status)), 152 SPINAND_INFO("XT26G02A", 153 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE2), 154 NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), 155 NAND_ECCREQ(8, 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(&xt26g0xa_ooblayout, 161 xt26g0xa_ecc_get_status)), 162 SPINAND_INFO("XT26G04A", 163 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE3), 164 NAND_MEMORG(1, 2048, 64, 128, 2048, 40, 1, 1, 1), 165 NAND_ECCREQ(8, 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(&xt26g0xa_ooblayout, 171 xt26g0xa_ecc_get_status)), 172 SPINAND_INFO("XT26G01D", 173 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x31), 174 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), 175 NAND_ECCREQ(8, 512), 176 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 177 &write_cache_variants, 178 &update_cache_variants), 179 0, 180 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 181 xt26xxxd_ecc_get_status)), 182 SPINAND_INFO("XT26G11D", 183 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x34), 184 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), 185 NAND_ECCREQ(8, 512), 186 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 187 &write_cache_variants, 188 &update_cache_variants), 189 0, 190 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 191 xt26xxxd_ecc_get_status)), 192 SPINAND_INFO("XT26Q01D", 193 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51), 194 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), 195 NAND_ECCREQ(8, 512), 196 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 197 &write_cache_variants, 198 &update_cache_variants), 199 0, 200 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 201 xt26xxxd_ecc_get_status)), 202 SPINAND_INFO("XT26G02D", 203 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x32), 204 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), 205 NAND_ECCREQ(8, 512), 206 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 207 &write_cache_variants, 208 &update_cache_variants), 209 0, 210 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 211 xt26xxxd_ecc_get_status)), 212 SPINAND_INFO("XT26G12D", 213 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x35), 214 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), 215 NAND_ECCREQ(8, 512), 216 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 217 &write_cache_variants, 218 &update_cache_variants), 219 0, 220 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 221 xt26xxxd_ecc_get_status)), 222 SPINAND_INFO("XT26Q02D", 223 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52), 224 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), 225 NAND_ECCREQ(8, 512), 226 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 227 &write_cache_variants, 228 &update_cache_variants), 229 0, 230 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 231 xt26xxxd_ecc_get_status)), 232 SPINAND_INFO("XT26G04D", 233 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x33), 234 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), 235 NAND_ECCREQ(8, 512), 236 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 237 &write_cache_variants, 238 &update_cache_variants), 239 0, 240 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 241 xt26xxxd_ecc_get_status)), 242 SPINAND_INFO("XT26Q04D", 243 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x53), 244 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), 245 NAND_ECCREQ(8, 512), 246 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 247 &write_cache_variants, 248 &update_cache_variants), 249 0, 250 SPINAND_ECCINFO(&xt26xxxd_ooblayout, 251 xt26xxxd_ecc_get_status)), 252 }; 253 254 static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = { 255 }; 256 257 const struct spinand_manufacturer xtx_spinand_manufacturer = { 258 .id = SPINAND_MFR_XTX, 259 .name = "XTX", 260 .chips = xtx_spinand_table, 261 .nchips = ARRAY_SIZE(xtx_spinand_table), 262 .ops = &xtx_spinand_manuf_ops, 263 }; 264