1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2005, Intec Automation Inc. 4 * Copyright (C) 2014, Freescale Semiconductor, Inc. 5 */ 6 7 #include <linux/mtd/spi-nor.h> 8 9 #include "core.h" 10 11 #define WINBOND_NOR_OP_RDEAR 0xc8 /* Read Extended Address Register */ 12 #define WINBOND_NOR_OP_WREAR 0xc5 /* Write Extended Address Register */ 13 #define WINBOND_NOR_OP_SELDIE 0xc2 /* Select active die */ 14 15 #define WINBOND_NOR_WREAR_OP(buf) \ 16 SPI_MEM_OP(SPI_MEM_OP_CMD(WINBOND_NOR_OP_WREAR, 0), \ 17 SPI_MEM_OP_NO_ADDR, \ 18 SPI_MEM_OP_NO_DUMMY, \ 19 SPI_MEM_OP_DATA_OUT(1, buf, 0)) 20 21 #define WINBOND_NOR_SELDIE_OP(buf) \ 22 SPI_MEM_OP(SPI_MEM_OP_CMD(WINBOND_NOR_OP_SELDIE, 0), \ 23 SPI_MEM_OP_NO_ADDR, \ 24 SPI_MEM_OP_NO_DUMMY, \ 25 SPI_MEM_OP_DATA_OUT(1, buf, 0)) 26 27 static int 28 w25q128_post_bfpt_fixups(struct spi_nor *nor, 29 const struct sfdp_parameter_header *bfpt_header, 30 const struct sfdp_bfpt *bfpt) 31 { 32 /* 33 * Zetta ZD25Q128C is a clone of the Winbond device. But the encoded 34 * size is really wrong. It seems that they confused Mbit with MiB. 35 * Thus the flash is discovered as a 2MiB device. 36 */ 37 if (bfpt_header->major == SFDP_JESD216_MAJOR && 38 bfpt_header->minor == SFDP_JESD216_MINOR && 39 nor->params->size == SZ_2M && 40 nor->params->erase_map.regions[0].size == SZ_2M) { 41 nor->params->size = SZ_16M; 42 nor->params->erase_map.regions[0].size = SZ_16M; 43 } 44 45 return 0; 46 } 47 48 static const struct spi_nor_fixups w25q128_fixups = { 49 .post_bfpt = w25q128_post_bfpt_fixups, 50 }; 51 52 static int 53 w25q256_post_bfpt_fixups(struct spi_nor *nor, 54 const struct sfdp_parameter_header *bfpt_header, 55 const struct sfdp_bfpt *bfpt) 56 { 57 /* 58 * W25Q256JV supports 4B opcodes but W25Q256FV does not. 59 * Unfortunately, Winbond has re-used the same JEDEC ID for both 60 * variants which prevents us from defining a new entry in the parts 61 * table. 62 * To differentiate between W25Q256JV and W25Q256FV check SFDP header 63 * version: only JV has JESD216A compliant structure (version 5). 64 */ 65 if (bfpt_header->major == SFDP_JESD216_MAJOR && 66 bfpt_header->minor == SFDP_JESD216A_MINOR) 67 nor->flags |= SNOR_F_4B_OPCODES; 68 69 return 0; 70 } 71 72 static const struct spi_nor_fixups w25q256_fixups = { 73 .post_bfpt = w25q256_post_bfpt_fixups, 74 }; 75 76 /** 77 * winbond_nor_select_die() - Set active die. 78 * @nor: pointer to 'struct spi_nor'. 79 * @die: die to set active. 80 * 81 * Certain Winbond chips feature more than a single die. This is mostly hidden 82 * to the user, except that some chips may experience time deviation when 83 * modifying the status bits between dies, which in some corner cases may 84 * produce problematic races. Being able to explicitly select a die to check its 85 * state in this case may be useful. 86 * 87 * Return: 0 on success, -errno otherwise. 88 */ 89 static int winbond_nor_select_die(struct spi_nor *nor, u8 die) 90 { 91 int ret; 92 93 nor->bouncebuf[0] = die; 94 95 if (nor->spimem) { 96 struct spi_mem_op op = WINBOND_NOR_SELDIE_OP(nor->bouncebuf); 97 98 spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); 99 100 ret = spi_mem_exec_op(nor->spimem, &op); 101 } else { 102 ret = spi_nor_controller_ops_write_reg(nor, 103 WINBOND_NOR_OP_SELDIE, 104 nor->bouncebuf, 1); 105 } 106 107 if (ret) 108 dev_dbg(nor->dev, "error %d selecting die %d\n", ret, die); 109 110 return ret; 111 } 112 113 static int winbond_nor_multi_die_ready(struct spi_nor *nor) 114 { 115 int ret, i; 116 117 for (i = 0; i < nor->params->n_dice; i++) { 118 ret = winbond_nor_select_die(nor, i); 119 if (ret) 120 return ret; 121 122 ret = spi_nor_sr_ready(nor); 123 if (ret <= 0) 124 return ret; 125 } 126 127 return 1; 128 } 129 130 static int 131 winbond_nor_multi_die_post_sfdp_fixups(struct spi_nor *nor) 132 { 133 /* 134 * SFDP supports dice numbers, but this information is only available in 135 * optional additional tables which are not provided by these chips. 136 * Dice number has an impact though, because these devices need extra 137 * care when reading the busy bit. 138 */ 139 nor->params->n_dice = nor->params->size / SZ_64M; 140 nor->params->ready = winbond_nor_multi_die_ready; 141 142 return 0; 143 } 144 145 static const struct spi_nor_fixups winbond_nor_multi_die_fixups = { 146 .post_sfdp = winbond_nor_multi_die_post_sfdp_fixups, 147 }; 148 149 static const struct flash_info winbond_nor_parts[] = { 150 { 151 .id = SNOR_ID(0xef, 0x30, 0x10), 152 .name = "w25x05", 153 .size = SZ_64K, 154 .no_sfdp_flags = SECT_4K, 155 }, { 156 .id = SNOR_ID(0xef, 0x30, 0x11), 157 .name = "w25x10", 158 .size = SZ_128K, 159 .no_sfdp_flags = SECT_4K, 160 }, { 161 .id = SNOR_ID(0xef, 0x30, 0x12), 162 .name = "w25x20", 163 .size = SZ_256K, 164 .no_sfdp_flags = SECT_4K, 165 }, { 166 .id = SNOR_ID(0xef, 0x30, 0x13), 167 .name = "w25x40", 168 .size = SZ_512K, 169 .no_sfdp_flags = SECT_4K, 170 }, { 171 .id = SNOR_ID(0xef, 0x30, 0x14), 172 .name = "w25x80", 173 .size = SZ_1M, 174 .no_sfdp_flags = SECT_4K, 175 }, { 176 .id = SNOR_ID(0xef, 0x30, 0x15), 177 .name = "w25x16", 178 .size = SZ_2M, 179 .no_sfdp_flags = SECT_4K, 180 }, { 181 .id = SNOR_ID(0xef, 0x30, 0x16), 182 .name = "w25x32", 183 .size = SZ_4M, 184 .no_sfdp_flags = SECT_4K, 185 }, { 186 .id = SNOR_ID(0xef, 0x30, 0x17), 187 .name = "w25x64", 188 .size = SZ_8M, 189 .no_sfdp_flags = SECT_4K, 190 }, { 191 .id = SNOR_ID(0xef, 0x40, 0x12), 192 .name = "w25q20cl", 193 .size = SZ_256K, 194 .no_sfdp_flags = SECT_4K, 195 }, { 196 .id = SNOR_ID(0xef, 0x40, 0x14), 197 .name = "w25q80bl", 198 .size = SZ_1M, 199 .no_sfdp_flags = SECT_4K, 200 }, { 201 .id = SNOR_ID(0xef, 0x40, 0x16), 202 .name = "w25q32", 203 .size = SZ_4M, 204 .no_sfdp_flags = SECT_4K, 205 }, { 206 .id = SNOR_ID(0xef, 0x40, 0x17), 207 .name = "w25q64", 208 .size = SZ_8M, 209 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 210 }, { 211 .id = SNOR_ID(0xef, 0x40, 0x18), 212 /* Flavors w/ and w/o SFDP. */ 213 .name = "w25q128", 214 .size = SZ_16M, 215 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 216 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 217 .fixups = &w25q128_fixups, 218 }, { 219 .id = SNOR_ID(0xef, 0x40, 0x19), 220 .name = "w25q256", 221 .size = SZ_32M, 222 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 223 .fixups = &w25q256_fixups, 224 }, { 225 .id = SNOR_ID(0xef, 0x40, 0x20), 226 .name = "w25q512jvq", 227 .size = SZ_64M, 228 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 229 }, { 230 /* W25Q01JV */ 231 .id = SNOR_ID(0xef, 0x40, 0x21), 232 .fixups = &winbond_nor_multi_die_fixups, 233 }, { 234 .id = SNOR_ID(0xef, 0x50, 0x12), 235 .name = "w25q20bw", 236 .size = SZ_256K, 237 .no_sfdp_flags = SECT_4K, 238 }, { 239 .id = SNOR_ID(0xef, 0x50, 0x14), 240 .name = "w25q80", 241 .size = SZ_1M, 242 .no_sfdp_flags = SECT_4K, 243 }, { 244 .id = SNOR_ID(0xef, 0x60, 0x12), 245 .name = "w25q20ew", 246 .size = SZ_256K, 247 .no_sfdp_flags = SECT_4K, 248 }, { 249 .id = SNOR_ID(0xef, 0x60, 0x15), 250 .name = "w25q16dw", 251 .size = SZ_2M, 252 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 253 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 254 }, { 255 .id = SNOR_ID(0xef, 0x60, 0x16), 256 .name = "w25q32dw", 257 .size = SZ_4M, 258 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 259 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 260 .otp = SNOR_OTP(256, 3, 0x1000, 0x1000), 261 }, { 262 .id = SNOR_ID(0xef, 0x60, 0x17), 263 .name = "w25q64dw", 264 .size = SZ_8M, 265 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 266 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 267 }, { 268 .id = SNOR_ID(0xef, 0x60, 0x18), 269 .name = "w25q128fw", 270 .size = SZ_16M, 271 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 272 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 273 }, { 274 .id = SNOR_ID(0xef, 0x60, 0x19), 275 .name = "w25q256jw", 276 .size = SZ_32M, 277 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 278 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 279 }, { 280 .id = SNOR_ID(0xef, 0x60, 0x20), 281 .name = "w25q512nwq", 282 .otp = SNOR_OTP(256, 3, 0x1000, 0x1000), 283 }, { 284 .id = SNOR_ID(0xef, 0x70, 0x15), 285 .name = "w25q16jv-im/jm", 286 .size = SZ_2M, 287 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 288 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 289 }, { 290 .id = SNOR_ID(0xef, 0x70, 0x16), 291 .name = "w25q32jv", 292 .size = SZ_4M, 293 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 294 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 295 }, { 296 .id = SNOR_ID(0xef, 0x70, 0x17), 297 .name = "w25q64jvm", 298 .size = SZ_8M, 299 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 300 .no_sfdp_flags = SECT_4K, 301 }, { 302 .id = SNOR_ID(0xef, 0x70, 0x18), 303 .name = "w25q128jv", 304 .size = SZ_16M, 305 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 306 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 307 }, { 308 .id = SNOR_ID(0xef, 0x70, 0x19), 309 .name = "w25q256jvm", 310 }, { 311 /* W25Q02JV */ 312 .id = SNOR_ID(0xef, 0x70, 0x22), 313 .fixups = &winbond_nor_multi_die_fixups, 314 }, { 315 .id = SNOR_ID(0xef, 0x71, 0x19), 316 .name = "w25m512jv", 317 .size = SZ_64M, 318 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 319 }, { 320 .id = SNOR_ID(0xef, 0x80, 0x16), 321 .name = "w25q32jwm", 322 .size = SZ_4M, 323 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 324 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 325 .otp = SNOR_OTP(256, 3, 0x1000, 0x1000), 326 }, { 327 .id = SNOR_ID(0xef, 0x80, 0x17), 328 .name = "w25q64jwm", 329 .size = SZ_8M, 330 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 331 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 332 }, { 333 .id = SNOR_ID(0xef, 0x80, 0x18), 334 .name = "w25q128jwm", 335 .size = SZ_16M, 336 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, 337 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 338 }, { 339 .id = SNOR_ID(0xef, 0x80, 0x19), 340 .name = "w25q256jwm", 341 .size = SZ_32M, 342 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 343 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, 344 }, { 345 .id = SNOR_ID(0xef, 0x80, 0x20), 346 .name = "w25q512nwm", 347 .otp = SNOR_OTP(256, 3, 0x1000, 0x1000), 348 }, { 349 /* W25Q01NWxxIQ */ 350 .id = SNOR_ID(0xef, 0x60, 0x21), 351 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 352 }, { 353 /* W25Q01NWxxIM */ 354 .id = SNOR_ID(0xef, 0x80, 0x21), 355 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 356 }, { 357 /* W25Q02NWxxIM */ 358 .id = SNOR_ID(0xef, 0x80, 0x22), 359 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 360 }, { 361 /* W25H512NWxxAM */ 362 .id = SNOR_ID(0xef, 0xa0, 0x20), 363 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 364 }, { 365 /* W25H01NWxxAM */ 366 .id = SNOR_ID(0xef, 0xa0, 0x21), 367 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 368 }, { 369 /* W25H02NWxxAM */ 370 .id = SNOR_ID(0xef, 0xa0, 0x22), 371 .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP, 372 }, 373 }; 374 375 /** 376 * winbond_nor_write_ear() - Write Extended Address Register. 377 * @nor: pointer to 'struct spi_nor'. 378 * @ear: value to write to the Extended Address Register. 379 * 380 * Return: 0 on success, -errno otherwise. 381 */ 382 static int winbond_nor_write_ear(struct spi_nor *nor, u8 ear) 383 { 384 int ret; 385 386 nor->bouncebuf[0] = ear; 387 388 if (nor->spimem) { 389 struct spi_mem_op op = WINBOND_NOR_WREAR_OP(nor->bouncebuf); 390 391 spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); 392 393 ret = spi_mem_exec_op(nor->spimem, &op); 394 } else { 395 ret = spi_nor_controller_ops_write_reg(nor, 396 WINBOND_NOR_OP_WREAR, 397 nor->bouncebuf, 1); 398 } 399 400 if (ret) 401 dev_dbg(nor->dev, "error %d writing EAR\n", ret); 402 403 return ret; 404 } 405 406 /** 407 * winbond_nor_set_4byte_addr_mode() - Set 4-byte address mode for Winbond 408 * flashes. 409 * @nor: pointer to 'struct spi_nor'. 410 * @enable: true to enter the 4-byte address mode, false to exit the 4-byte 411 * address mode. 412 * 413 * Return: 0 on success, -errno otherwise. 414 */ 415 static int winbond_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable) 416 { 417 int ret; 418 419 ret = spi_nor_set_4byte_addr_mode_en4b_ex4b(nor, enable); 420 if (ret || enable) 421 return ret; 422 423 /* 424 * On Winbond W25Q256FV, leaving 4byte mode causes the Extended Address 425 * Register to be set to 1, so all 3-byte-address reads come from the 426 * second 16M. We must clear the register to enable normal behavior. 427 */ 428 ret = spi_nor_write_enable(nor); 429 if (ret) 430 return ret; 431 432 ret = winbond_nor_write_ear(nor, 0); 433 if (ret) 434 return ret; 435 436 return spi_nor_write_disable(nor); 437 } 438 439 static const struct spi_nor_otp_ops winbond_nor_otp_ops = { 440 .read = spi_nor_otp_read_secr, 441 .write = spi_nor_otp_write_secr, 442 .erase = spi_nor_otp_erase_secr, 443 .lock = spi_nor_otp_lock_sr2, 444 .is_locked = spi_nor_otp_is_locked_sr2, 445 }; 446 447 static int winbond_nor_late_init(struct spi_nor *nor) 448 { 449 struct spi_nor_flash_parameter *params = nor->params; 450 451 if (params->otp.org) 452 params->otp.ops = &winbond_nor_otp_ops; 453 454 /* 455 * Winbond seems to require that the Extended Address Register to be set 456 * to zero when exiting the 4-Byte Address Mode, at least for W25Q256FV. 457 * This requirement is not described in the JESD216 SFDP standard, thus 458 * it is Winbond specific. Since we do not know if other Winbond flashes 459 * have the same requirement, play safe and overwrite the method parsed 460 * from BFPT, if any. 461 */ 462 params->set_4byte_addr_mode = winbond_nor_set_4byte_addr_mode; 463 464 return 0; 465 } 466 467 static const struct spi_nor_fixups winbond_nor_fixups = { 468 .late_init = winbond_nor_late_init, 469 }; 470 471 const struct spi_nor_manufacturer spi_nor_winbond = { 472 .name = "winbond", 473 .parts = winbond_nor_parts, 474 .nparts = ARRAY_SIZE(winbond_nor_parts), 475 .fixups = &winbond_nor_fixups, 476 }; 477