1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2017 exceet electronics GmbH 4 * 5 * Authors: 6 * Frieder Schrempf <frieder.schrempf@exceet.de> 7 * Boris Brezillon <boris.brezillon@bootlin.com> 8 */ 9 10 #include <linux/device.h> 11 #include <linux/kernel.h> 12 #include <linux/mtd/spinand.h> 13 #include <linux/units.h> 14 15 #define SPINAND_MFR_WINBOND 0xEF 16 17 #define WINBOND_CFG_BUF_READ BIT(3) 18 19 #define W25N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4) 20 21 /* 22 * "X2" in the core is equivalent to "dual output" in the datasheets, 23 * "X4" in the core is equivalent to "quad output" in the datasheets. 24 */ 25 26 static SPINAND_OP_VARIANTS(read_cache_dtr_variants, 27 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_DTR_OP(0, 8, NULL, 0, 80 * HZ_PER_MHZ), 28 SPINAND_PAGE_READ_FROM_CACHE_X4_DTR_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ), 29 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), 30 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 31 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_DTR_OP(0, 4, NULL, 0, 80 * HZ_PER_MHZ), 32 SPINAND_PAGE_READ_FROM_CACHE_X2_DTR_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ), 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_DTR_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ), 36 SPINAND_PAGE_READ_FROM_CACHE_FAST_OP(0, 1, NULL, 0), 37 SPINAND_PAGE_READ_FROM_CACHE_OP(0, 1, NULL, 0, 54 * HZ_PER_MHZ)); 38 39 static SPINAND_OP_VARIANTS(read_cache_variants, 40 SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), 41 SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), 42 SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), 43 SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), 44 SPINAND_PAGE_READ_FROM_CACHE_FAST_OP(0, 1, NULL, 0), 45 SPINAND_PAGE_READ_FROM_CACHE_OP(0, 1, NULL, 0)); 46 47 static SPINAND_OP_VARIANTS(write_cache_variants, 48 SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), 49 SPINAND_PROG_LOAD(true, 0, NULL, 0)); 50 51 static SPINAND_OP_VARIANTS(update_cache_variants, 52 SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), 53 SPINAND_PROG_LOAD(false, 0, NULL, 0)); 54 55 static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section, 56 struct mtd_oob_region *region) 57 { 58 if (section > 3) 59 return -ERANGE; 60 61 region->offset = (16 * section) + 8; 62 region->length = 8; 63 64 return 0; 65 } 66 67 static int w25m02gv_ooblayout_free(struct mtd_info *mtd, int section, 68 struct mtd_oob_region *region) 69 { 70 if (section > 3) 71 return -ERANGE; 72 73 region->offset = (16 * section) + 2; 74 region->length = 6; 75 76 return 0; 77 } 78 79 static const struct mtd_ooblayout_ops w25m02gv_ooblayout = { 80 .ecc = w25m02gv_ooblayout_ecc, 81 .free = w25m02gv_ooblayout_free, 82 }; 83 84 static int w25m02gv_select_target(struct spinand_device *spinand, 85 unsigned int target) 86 { 87 struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0xc2, 1), 88 SPI_MEM_OP_NO_ADDR, 89 SPI_MEM_OP_NO_DUMMY, 90 SPI_MEM_OP_DATA_OUT(1, 91 spinand->scratchbuf, 92 1)); 93 94 *spinand->scratchbuf = target; 95 return spi_mem_exec_op(spinand->spimem, &op); 96 } 97 98 static int w25n01kv_ooblayout_ecc(struct mtd_info *mtd, int section, 99 struct mtd_oob_region *region) 100 { 101 if (section > 3) 102 return -ERANGE; 103 104 region->offset = 64 + (8 * section); 105 region->length = 7; 106 107 return 0; 108 } 109 110 static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section, 111 struct mtd_oob_region *region) 112 { 113 if (section > 3) 114 return -ERANGE; 115 116 region->offset = 64 + (16 * section); 117 region->length = 13; 118 119 return 0; 120 } 121 122 static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section, 123 struct mtd_oob_region *region) 124 { 125 if (section > 3) 126 return -ERANGE; 127 128 region->offset = (16 * section) + 2; 129 region->length = 14; 130 131 return 0; 132 } 133 134 static const struct mtd_ooblayout_ops w25n01kv_ooblayout = { 135 .ecc = w25n01kv_ooblayout_ecc, 136 .free = w25n02kv_ooblayout_free, 137 }; 138 139 static const struct mtd_ooblayout_ops w25n02kv_ooblayout = { 140 .ecc = w25n02kv_ooblayout_ecc, 141 .free = w25n02kv_ooblayout_free, 142 }; 143 144 static int w25n02kv_ecc_get_status(struct spinand_device *spinand, 145 u8 status) 146 { 147 struct nand_device *nand = spinand_to_nand(spinand); 148 u8 mbf = 0; 149 struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); 150 151 switch (status & STATUS_ECC_MASK) { 152 case STATUS_ECC_NO_BITFLIPS: 153 return 0; 154 155 case STATUS_ECC_UNCOR_ERROR: 156 return -EBADMSG; 157 158 case STATUS_ECC_HAS_BITFLIPS: 159 case W25N04KV_STATUS_ECC_5_8_BITFLIPS: 160 /* 161 * Let's try to retrieve the real maximum number of bitflips 162 * in order to avoid forcing the wear-leveling layer to move 163 * data around if it's not necessary. 164 */ 165 if (spi_mem_exec_op(spinand->spimem, &op)) 166 return nanddev_get_ecc_conf(nand)->strength; 167 168 mbf = *(spinand->scratchbuf) >> 4; 169 170 if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) 171 return nanddev_get_ecc_conf(nand)->strength; 172 173 return mbf; 174 175 default: 176 break; 177 } 178 179 return -EINVAL; 180 } 181 182 static const struct spinand_info winbond_spinand_table[] = { 183 /* 512M-bit densities */ 184 SPINAND_INFO("W25N512GW", /* 1.8V */ 185 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x20), 186 NAND_MEMORG(1, 2048, 64, 64, 512, 10, 1, 1, 1), 187 NAND_ECCREQ(1, 512), 188 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 189 &write_cache_variants, 190 &update_cache_variants), 191 0, 192 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), 193 /* 1G-bit densities */ 194 SPINAND_INFO("W25N01GV", /* 3.3V */ 195 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21), 196 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 197 NAND_ECCREQ(1, 512), 198 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 199 &write_cache_variants, 200 &update_cache_variants), 201 0, 202 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), 203 SPINAND_INFO("W25N01GW", /* 1.8V */ 204 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x21), 205 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 206 NAND_ECCREQ(1, 512), 207 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 208 &write_cache_variants, 209 &update_cache_variants), 210 0, 211 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), 212 SPINAND_INFO("W25N01JW", /* high-speed 1.8V */ 213 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbc, 0x21), 214 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), 215 NAND_ECCREQ(1, 512), 216 SPINAND_INFO_OP_VARIANTS(&read_cache_dtr_variants, 217 &write_cache_variants, 218 &update_cache_variants), 219 0, 220 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), 221 SPINAND_INFO("W25N01KV", /* 3.3V */ 222 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21), 223 NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1), 224 NAND_ECCREQ(4, 512), 225 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 226 &write_cache_variants, 227 &update_cache_variants), 228 0, 229 SPINAND_ECCINFO(&w25n01kv_ooblayout, w25n02kv_ecc_get_status)), 230 /* 2G-bit densities */ 231 SPINAND_INFO("W25M02GV", /* 2x1G-bit 3.3V */ 232 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), 233 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2), 234 NAND_ECCREQ(1, 512), 235 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 236 &write_cache_variants, 237 &update_cache_variants), 238 0, 239 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), 240 SPINAND_SELECT_TARGET(w25m02gv_select_target)), 241 SPINAND_INFO("W25N02JW", /* high-speed 1.8V */ 242 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbf, 0x22), 243 NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 2, 1), 244 NAND_ECCREQ(1, 512), 245 SPINAND_INFO_OP_VARIANTS(&read_cache_dtr_variants, 246 &write_cache_variants, 247 &update_cache_variants), 248 0, 249 SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), 250 SPINAND_INFO("W25N02KV", /* 3.3V */ 251 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22), 252 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), 253 NAND_ECCREQ(8, 512), 254 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 255 &write_cache_variants, 256 &update_cache_variants), 257 0, 258 SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), 259 SPINAND_INFO("W25N02KW", /* 1.8V */ 260 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x22), 261 NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), 262 NAND_ECCREQ(8, 512), 263 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 264 &write_cache_variants, 265 &update_cache_variants), 266 0, 267 SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), 268 /* 4G-bit densities */ 269 SPINAND_INFO("W25N04KV", /* 3.3V */ 270 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), 271 NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1), 272 NAND_ECCREQ(8, 512), 273 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 274 &write_cache_variants, 275 &update_cache_variants), 276 0, 277 SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), 278 SPINAND_INFO("W25N04KW", /* 1.8V */ 279 SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xba, 0x23), 280 NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 1, 1, 1), 281 NAND_ECCREQ(8, 512), 282 SPINAND_INFO_OP_VARIANTS(&read_cache_variants, 283 &write_cache_variants, 284 &update_cache_variants), 285 0, 286 SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), 287 }; 288 289 static int winbond_spinand_init(struct spinand_device *spinand) 290 { 291 struct nand_device *nand = spinand_to_nand(spinand); 292 unsigned int i; 293 294 /* 295 * Make sure all dies are in buffer read mode and not continuous read 296 * mode. 297 */ 298 for (i = 0; i < nand->memorg.ntargets; i++) { 299 spinand_select_target(spinand, i); 300 spinand_upd_cfg(spinand, WINBOND_CFG_BUF_READ, 301 WINBOND_CFG_BUF_READ); 302 } 303 304 return 0; 305 } 306 307 static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = { 308 .init = winbond_spinand_init, 309 }; 310 311 const struct spinand_manufacturer winbond_spinand_manufacturer = { 312 .id = SPINAND_MFR_WINBOND, 313 .name = "Winbond", 314 .chips = winbond_spinand_table, 315 .nchips = ARRAY_SIZE(winbond_spinand_table), 316 .ops = &winbond_spinand_manuf_ops, 317 }; 318