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 #include <linux/device.h> 10 #include <linux/kernel.h> 11 #include <linux/mtd/spinand.h> 12 13 #define SPINAND_MFR_MICRON 0x2c 14 15 #define MICRON_STATUS_ECC_MASK GENMASK(7, 4) 16 #define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4) 17 #define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4) 18 #define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4) 19 #define MICRON_STATUS_ECC_7TO8_BITFLIPS (5 << 4) 20 21 #define MICRON_CFG_CR BIT(0) 22 23 /* 24 * As per datasheet, die selection is done by the 6th bit of Die 25 * Select Register (Address 0xD0). 26 */ 27 #define MICRON_DIE_SELECT_REG 0xD0 28 29 #define MICRON_SELECT_DIE(x) ((x) << 6) 30 31 static SPINAND_OP_VARIANTS(read_cache_variants, 32 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), 33 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 34 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 35 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 36 SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), 37 SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); 38 39 static SPINAND_OP_VARIANTS(write_cache_variants, 40 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), 41 SPINAND_PROG_LOAD(true, 0, NULL, 0)); 42 43 static SPINAND_OP_VARIANTS(update_cache_variants, 44 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), 45 SPINAND_PROG_LOAD(false, 0, NULL, 0)); 46 47 static int micron_8_ooblayout_ecc(struct mtd_info *mtd, int section, 48 struct mtd_oob_region *region) 49 { 50 if (section) 51 return -ERANGE; 52 53 region->offset = mtd->oobsize / 2; 54 region->length = mtd->oobsize / 2; 55 56 return 0; 57 } 58 59 static int micron_8_ooblayout_free(struct mtd_info *mtd, int section, 60 struct mtd_oob_region *region) 61 { 62 if (section) 63 return -ERANGE; 64 65 /* Reserve 2 bytes for the BBM. */ 66 region->offset = 2; 67 region->length = (mtd->oobsize / 2) - 2; 68 69 return 0; 70 } 71 72 static const struct mtd_ooblayout_ops micron_8_ooblayout = { 73 .ecc = micron_8_ooblayout_ecc, 74 .free = micron_8_ooblayout_free, 75 }; 76 77 static int micron_select_target(struct spinand_device *spinand, 78 unsigned int target) 79 { 80 struct spi_mem_op op = SPINAND_SET_FEATURE_OP(MICRON_DIE_SELECT_REG, 81 spinand->scratchbuf); 82 83 if (target > 1) 84 return -EINVAL; 85 86 *spinand->scratchbuf = MICRON_SELECT_DIE(target); 87 88 return spi_mem_exec_op(spinand->spimem, &op); 89 } 90 91 static int micron_8_ecc_get_status(struct spinand_device *spinand, 92 u8 status) 93 { 94 switch (status & MICRON_STATUS_ECC_MASK) { 95 case STATUS_ECC_NO_BITFLIPS: 96 return 0; 97 98 case STATUS_ECC_UNCOR_ERROR: 99 return -EBADMSG; 100 101 case MICRON_STATUS_ECC_1TO3_BITFLIPS: 102 return 3; 103 104 case MICRON_STATUS_ECC_4TO6_BITFLIPS: 105 return 6; 106 107 case MICRON_STATUS_ECC_7TO8_BITFLIPS: 108 return 8; 109 110 default: 111 break; 112 } 113 114 return -EINVAL; 115 } 116 117 static const struct spinand_info micron_spinand_table[] = { 118 /* M79A 2Gb 3.3V */ 119 SPINAND_INFO("MT29F2G01ABAGD", 120 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), 121 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), 122 NAND_ECCREQ(8, 512), 123 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 124 &write_cache_variants, 125 &update_cache_variants), 126 0, 127 SPINAND_ECCINFO(µn_8_ooblayout, 128 micron_8_ecc_get_status)), 129 /* M79A 2Gb 1.8V */ 130 SPINAND_INFO("MT29F2G01ABBGD", 131 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), 132 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), 133 NAND_ECCREQ(8, 512), 134 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 135 &write_cache_variants, 136 &update_cache_variants), 137 0, 138 SPINAND_ECCINFO(µn_8_ooblayout, 139 micron_8_ecc_get_status)), 140 /* M78A 1Gb 3.3V */ 141 SPINAND_INFO("MT29F1G01ABAFD", 142 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), 143 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), 144 NAND_ECCREQ(8, 512), 145 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 146 &write_cache_variants, 147 &update_cache_variants), 148 0, 149 SPINAND_ECCINFO(µn_8_ooblayout, 150 micron_8_ecc_get_status)), 151 /* M78A 1Gb 1.8V */ 152 SPINAND_INFO("MT29F1G01ABAFD", 153 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), 154 NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 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 0, 160 SPINAND_ECCINFO(µn_8_ooblayout, 161 micron_8_ecc_get_status)), 162 /* M79A 4Gb 3.3V */ 163 SPINAND_INFO("MT29F4G01ADAGD", 164 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x36), 165 NAND_MEMORG(1, 2048, 128, 64, 2048, 80, 2, 1, 2), 166 NAND_ECCREQ(8, 512), 167 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 168 &write_cache_variants, 169 &update_cache_variants), 170 0, 171 SPINAND_ECCINFO(µn_8_ooblayout, 172 micron_8_ecc_get_status), 173 SPINAND_SELECT_TARGET(micron_select_target)), 174 /* M70A 4Gb 3.3V */ 175 SPINAND_INFO("MT29F4G01ABAFD", 176 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x34), 177 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), 178 NAND_ECCREQ(8, 512), 179 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 180 &write_cache_variants, 181 &update_cache_variants), 182 SPINAND_HAS_CR_FEAT_BIT, 183 SPINAND_ECCINFO(µn_8_ooblayout, 184 micron_8_ecc_get_status)), 185 /* M70A 4Gb 1.8V */ 186 SPINAND_INFO("MT29F4G01ABBFD", 187 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), 188 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), 189 NAND_ECCREQ(8, 512), 190 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 191 &write_cache_variants, 192 &update_cache_variants), 193 SPINAND_HAS_CR_FEAT_BIT, 194 SPINAND_ECCINFO(µn_8_ooblayout, 195 micron_8_ecc_get_status)), 196 /* M70A 8Gb 3.3V */ 197 SPINAND_INFO("MT29F8G01ADAFD", 198 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x46), 199 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2), 200 NAND_ECCREQ(8, 512), 201 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 202 &write_cache_variants, 203 &update_cache_variants), 204 SPINAND_HAS_CR_FEAT_BIT, 205 SPINAND_ECCINFO(µn_8_ooblayout, 206 micron_8_ecc_get_status), 207 SPINAND_SELECT_TARGET(micron_select_target)), 208 /* M70A 8Gb 1.8V */ 209 SPINAND_INFO("MT29F8G01ADBFD", 210 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x47), 211 NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 2), 212 NAND_ECCREQ(8, 512), 213 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 214 &write_cache_variants, 215 &update_cache_variants), 216 SPINAND_HAS_CR_FEAT_BIT, 217 SPINAND_ECCINFO(µn_8_ooblayout, 218 micron_8_ecc_get_status), 219 SPINAND_SELECT_TARGET(micron_select_target)), 220 }; 221 222 static int micron_spinand_init(struct spinand_device *spinand) 223 { 224 /* 225 * M70A device series enable Continuous Read feature at Power-up, 226 * which is not supported. Disable this bit to avoid any possible 227 * failure. 228 */ 229 if (spinand->flags & SPINAND_HAS_CR_FEAT_BIT) 230 return spinand_upd_cfg(spinand, MICRON_CFG_CR, 0); 231 232 return 0; 233 } 234 235 static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = { 236 .init = micron_spinand_init, 237 }; 238 239 const struct spinand_manufacturer micron_spinand_manufacturer = { 240 .id = SPINAND_MFR_MICRON, 241 .name = "Micron", 242 .chips = micron_spinand_table, 243 .nchips = ARRAY_SIZE(micron_spinand_table), 244 .ops = µn_spinand_manuf_ops, 245 }; 246