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 /* flash_info mfr_flag. Used to clear sticky prorietary SR bits. */ 12 #define USE_CLSR BIT(0) 13 14 #define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ 15 #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ 16 #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ 17 #define SPINOR_REG_CYPRESS_CFR1V 0x00800002 18 #define SPINOR_REG_CYPRESS_CFR1_QUAD_EN BIT(1) /* Quad Enable */ 19 #define SPINOR_REG_CYPRESS_CFR2V 0x00800003 20 #define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb 21 #define SPINOR_REG_CYPRESS_CFR3V 0x00800004 22 #define SPINOR_REG_CYPRESS_CFR3_PGSZ BIT(4) /* Page size. */ 23 #define SPINOR_REG_CYPRESS_CFR5V 0x00800006 24 #define SPINOR_REG_CYPRESS_CFR5_BIT6 BIT(6) 25 #define SPINOR_REG_CYPRESS_CFR5_DDR BIT(1) 26 #define SPINOR_REG_CYPRESS_CFR5_OPI BIT(0) 27 #define SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN \ 28 (SPINOR_REG_CYPRESS_CFR5_BIT6 | SPINOR_REG_CYPRESS_CFR5_DDR | \ 29 SPINOR_REG_CYPRESS_CFR5_OPI) 30 #define SPINOR_REG_CYPRESS_CFR5_OCT_DTR_DS SPINOR_REG_CYPRESS_CFR5_BIT6 31 #define SPINOR_OP_CYPRESS_RD_FAST 0xee 32 33 /* Cypress SPI NOR flash operations. */ 34 #define CYPRESS_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf) \ 35 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0), \ 36 SPI_MEM_OP_ADDR(naddr, addr, 0), \ 37 SPI_MEM_OP_NO_DUMMY, \ 38 SPI_MEM_OP_DATA_OUT(ndata, buf, 0)) 39 40 #define CYPRESS_NOR_RD_ANY_REG_OP(naddr, addr, buf) \ 41 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0), \ 42 SPI_MEM_OP_ADDR(naddr, addr, 0), \ 43 SPI_MEM_OP_NO_DUMMY, \ 44 SPI_MEM_OP_DATA_IN(1, buf, 0)) 45 46 #define SPANSION_CLSR_OP \ 47 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0), \ 48 SPI_MEM_OP_NO_ADDR, \ 49 SPI_MEM_OP_NO_DUMMY, \ 50 SPI_MEM_OP_NO_DATA) 51 52 static int cypress_nor_octal_dtr_en(struct spi_nor *nor) 53 { 54 struct spi_mem_op op; 55 u8 *buf = nor->bouncebuf; 56 int ret; 57 u8 addr_mode_nbytes = nor->params->addr_mode_nbytes; 58 59 /* Use 24 dummy cycles for memory array reads. */ 60 *buf = SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24; 61 op = (struct spi_mem_op) 62 CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes, 63 SPINOR_REG_CYPRESS_CFR2V, 1, buf); 64 65 ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); 66 if (ret) 67 return ret; 68 69 nor->read_dummy = 24; 70 71 /* Set the octal and DTR enable bits. */ 72 buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN; 73 op = (struct spi_mem_op) 74 CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes, 75 SPINOR_REG_CYPRESS_CFR5V, 1, buf); 76 77 ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); 78 if (ret) 79 return ret; 80 81 /* Read flash ID to make sure the switch was successful. */ 82 ret = spi_nor_read_id(nor, nor->addr_nbytes, 3, buf, 83 SNOR_PROTO_8_8_8_DTR); 84 if (ret) { 85 dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret); 86 return ret; 87 } 88 89 if (memcmp(buf, nor->info->id, nor->info->id_len)) 90 return -EINVAL; 91 92 return 0; 93 } 94 95 static int cypress_nor_octal_dtr_dis(struct spi_nor *nor) 96 { 97 struct spi_mem_op op; 98 u8 *buf = nor->bouncebuf; 99 int ret; 100 101 /* 102 * The register is 1-byte wide, but 1-byte transactions are not allowed 103 * in 8D-8D-8D mode. Since there is no register at the next location, 104 * just initialize the value to 0 and let the transaction go on. 105 */ 106 buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_DS; 107 buf[1] = 0; 108 op = (struct spi_mem_op) 109 CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes, 110 SPINOR_REG_CYPRESS_CFR5V, 2, buf); 111 ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR); 112 if (ret) 113 return ret; 114 115 /* Read flash ID to make sure the switch was successful. */ 116 ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1); 117 if (ret) { 118 dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret); 119 return ret; 120 } 121 122 if (memcmp(buf, nor->info->id, nor->info->id_len)) 123 return -EINVAL; 124 125 return 0; 126 } 127 128 /** 129 * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile 130 * register. 131 * @nor: pointer to a 'struct spi_nor' 132 * 133 * It is recommended to update volatile registers in the field application due 134 * to a risk of the non-volatile registers corruption by power interrupt. This 135 * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable 136 * bit in the CFR1 non-volatile in advance (typically by a Flash programmer 137 * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is 138 * also set during Flash power-up. 139 * 140 * Return: 0 on success, -errno otherwise. 141 */ 142 static int cypress_nor_quad_enable_volatile(struct spi_nor *nor) 143 { 144 struct spi_mem_op op; 145 u8 addr_mode_nbytes = nor->params->addr_mode_nbytes; 146 u8 cfr1v_written; 147 int ret; 148 149 op = (struct spi_mem_op) 150 CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, 151 SPINOR_REG_CYPRESS_CFR1V, 152 nor->bouncebuf); 153 154 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); 155 if (ret) 156 return ret; 157 158 if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1_QUAD_EN) 159 return 0; 160 161 /* Update the Quad Enable bit. */ 162 nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1_QUAD_EN; 163 op = (struct spi_mem_op) 164 CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes, 165 SPINOR_REG_CYPRESS_CFR1V, 1, 166 nor->bouncebuf); 167 ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); 168 if (ret) 169 return ret; 170 171 cfr1v_written = nor->bouncebuf[0]; 172 173 /* Read back and check it. */ 174 op = (struct spi_mem_op) 175 CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, 176 SPINOR_REG_CYPRESS_CFR1V, 177 nor->bouncebuf); 178 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); 179 if (ret) 180 return ret; 181 182 if (nor->bouncebuf[0] != cfr1v_written) { 183 dev_err(nor->dev, "CFR1: Read back test failed\n"); 184 return -EIO; 185 } 186 187 return 0; 188 } 189 190 /** 191 * cypress_nor_set_page_size() - Set page size which corresponds to the flash 192 * configuration. 193 * @nor: pointer to a 'struct spi_nor' 194 * 195 * The BFPT table advertises a 512B or 256B page size depending on part but the 196 * page size is actually configurable (with the default being 256B). Read from 197 * CFR3V[4] and set the correct size. 198 * 199 * Return: 0 on success, -errno otherwise. 200 */ 201 static int cypress_nor_set_page_size(struct spi_nor *nor) 202 { 203 struct spi_mem_op op = 204 CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes, 205 SPINOR_REG_CYPRESS_CFR3V, 206 nor->bouncebuf); 207 int ret; 208 209 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); 210 if (ret) 211 return ret; 212 213 if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR3_PGSZ) 214 nor->params->page_size = 512; 215 else 216 nor->params->page_size = 256; 217 218 return 0; 219 } 220 221 static int 222 s25hx_t_post_bfpt_fixup(struct spi_nor *nor, 223 const struct sfdp_parameter_header *bfpt_header, 224 const struct sfdp_bfpt *bfpt) 225 { 226 /* Replace Quad Enable with volatile version */ 227 nor->params->quad_enable = cypress_nor_quad_enable_volatile; 228 229 return cypress_nor_set_page_size(nor); 230 } 231 232 static void s25hx_t_post_sfdp_fixup(struct spi_nor *nor) 233 { 234 struct spi_nor_erase_type *erase_type = 235 nor->params->erase_map.erase_type; 236 unsigned int i; 237 238 /* 239 * In some parts, 3byte erase opcodes are advertised by 4BAIT. 240 * Convert them to 4byte erase opcodes. 241 */ 242 for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { 243 switch (erase_type[i].opcode) { 244 case SPINOR_OP_SE: 245 erase_type[i].opcode = SPINOR_OP_SE_4B; 246 break; 247 case SPINOR_OP_BE_4K: 248 erase_type[i].opcode = SPINOR_OP_BE_4K_4B; 249 break; 250 default: 251 break; 252 } 253 } 254 } 255 256 static void s25hx_t_late_init(struct spi_nor *nor) 257 { 258 struct spi_nor_flash_parameter *params = nor->params; 259 260 /* Fast Read 4B requires mode cycles */ 261 params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; 262 263 /* The writesize should be ECC data unit size */ 264 params->writesize = 16; 265 } 266 267 static struct spi_nor_fixups s25hx_t_fixups = { 268 .post_bfpt = s25hx_t_post_bfpt_fixup, 269 .post_sfdp = s25hx_t_post_sfdp_fixup, 270 .late_init = s25hx_t_late_init, 271 }; 272 273 /** 274 * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes. 275 * @nor: pointer to a 'struct spi_nor' 276 * @enable: whether to enable or disable Octal DTR 277 * 278 * This also sets the memory access latency cycles to 24 to allow the flash to 279 * run at up to 200MHz. 280 * 281 * Return: 0 on success, -errno otherwise. 282 */ 283 static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable) 284 { 285 return enable ? cypress_nor_octal_dtr_en(nor) : 286 cypress_nor_octal_dtr_dis(nor); 287 } 288 289 static void s28hx_t_post_sfdp_fixup(struct spi_nor *nor) 290 { 291 /* 292 * On older versions of the flash the xSPI Profile 1.0 table has the 293 * 8D-8D-8D Fast Read opcode as 0x00. But it actually should be 0xEE. 294 */ 295 if (nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode == 0) 296 nor->params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode = 297 SPINOR_OP_CYPRESS_RD_FAST; 298 299 /* This flash is also missing the 4-byte Page Program opcode bit. */ 300 spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP], 301 SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1); 302 /* 303 * Since xSPI Page Program opcode is backward compatible with 304 * Legacy SPI, use Legacy SPI opcode there as well. 305 */ 306 spi_nor_set_pp_settings(&nor->params->page_programs[SNOR_CMD_PP_8_8_8_DTR], 307 SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR); 308 309 /* 310 * The xSPI Profile 1.0 table advertises the number of additional 311 * address bytes needed for Read Status Register command as 0 but the 312 * actual value for that is 4. 313 */ 314 nor->params->rdsr_addr_nbytes = 4; 315 } 316 317 static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor, 318 const struct sfdp_parameter_header *bfpt_header, 319 const struct sfdp_bfpt *bfpt) 320 { 321 return cypress_nor_set_page_size(nor); 322 } 323 324 static void s28hx_t_late_init(struct spi_nor *nor) 325 { 326 nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable; 327 nor->params->writesize = 16; 328 } 329 330 static const struct spi_nor_fixups s28hx_t_fixups = { 331 .post_sfdp = s28hx_t_post_sfdp_fixup, 332 .post_bfpt = s28hx_t_post_bfpt_fixup, 333 .late_init = s28hx_t_late_init, 334 }; 335 336 static int 337 s25fs_s_nor_post_bfpt_fixups(struct spi_nor *nor, 338 const struct sfdp_parameter_header *bfpt_header, 339 const struct sfdp_bfpt *bfpt) 340 { 341 /* 342 * The S25FS-S chip family reports 512-byte pages in BFPT but 343 * in reality the write buffer still wraps at the safe default 344 * of 256 bytes. Overwrite the page size advertised by BFPT 345 * to get the writes working. 346 */ 347 nor->params->page_size = 256; 348 349 return 0; 350 } 351 352 static const struct spi_nor_fixups s25fs_s_nor_fixups = { 353 .post_bfpt = s25fs_s_nor_post_bfpt_fixups, 354 }; 355 356 static const struct flash_info spansion_nor_parts[] = { 357 /* Spansion/Cypress -- single (large) sector size only, at least 358 * for the chips listed here (without boot sectors). 359 */ 360 { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64) 361 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, 362 { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128) 363 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, 364 { "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64) 365 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 366 MFR_FLAGS(USE_CLSR) 367 }, 368 { "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256) 369 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 370 MFR_FLAGS(USE_CLSR) 371 }, 372 { "s25fl256s0", INFO6(0x010219, 0x4d0080, 256 * 1024, 128) 373 NO_SFDP_FLAGS(SPI_NOR_SKIP_SFDP | SPI_NOR_DUAL_READ | 374 SPI_NOR_QUAD_READ) 375 MFR_FLAGS(USE_CLSR) 376 }, 377 { "s25fl256s1", INFO6(0x010219, 0x4d0180, 64 * 1024, 512) 378 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 379 MFR_FLAGS(USE_CLSR) 380 }, 381 { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256) 382 FLAGS(SPI_NOR_HAS_LOCK) 383 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 384 MFR_FLAGS(USE_CLSR) 385 }, 386 { "s25fs128s1", INFO6(0x012018, 0x4d0181, 64 * 1024, 256) 387 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 388 MFR_FLAGS(USE_CLSR) 389 .fixups = &s25fs_s_nor_fixups, }, 390 { "s25fs256s0", INFO6(0x010219, 0x4d0081, 256 * 1024, 128) 391 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 392 MFR_FLAGS(USE_CLSR) 393 }, 394 { "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512) 395 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 396 MFR_FLAGS(USE_CLSR) 397 }, 398 { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256) 399 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 400 MFR_FLAGS(USE_CLSR) 401 .fixups = &s25fs_s_nor_fixups, }, 402 { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64) }, 403 { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256) }, 404 { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64) 405 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 406 MFR_FLAGS(USE_CLSR) 407 }, 408 { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256) 409 NO_SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 410 MFR_FLAGS(USE_CLSR) 411 }, 412 { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8) }, 413 { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16) }, 414 { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32) }, 415 { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64) }, 416 { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128) }, 417 { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8) 418 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | 419 SPI_NOR_QUAD_READ) }, 420 { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16) 421 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | 422 SPI_NOR_QUAD_READ) }, 423 { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32) 424 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | 425 SPI_NOR_QUAD_READ) }, 426 { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128) 427 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | 428 SPI_NOR_QUAD_READ) }, 429 { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32) 430 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | 431 SPI_NOR_QUAD_READ) }, 432 { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64) 433 NO_SFDP_FLAGS(SECT_4K) }, 434 { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128) 435 NO_SFDP_FLAGS(SECT_4K) }, 436 { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8) 437 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) }, 438 { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16) 439 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) }, 440 { "s25fl064l", INFO(0x016017, 0, 64 * 1024, 128) 441 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 442 FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, 443 { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256) 444 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 445 FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, 446 { "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512) 447 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) 448 FIXUP_FLAGS(SPI_NOR_4B_OPCODES) }, 449 { "s25hl512t", INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256) 450 PARSE_SFDP 451 MFR_FLAGS(USE_CLSR) 452 .fixups = &s25hx_t_fixups }, 453 { "s25hl01gt", INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512) 454 PARSE_SFDP 455 MFR_FLAGS(USE_CLSR) 456 .fixups = &s25hx_t_fixups }, 457 { "s25hs512t", INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256) 458 PARSE_SFDP 459 MFR_FLAGS(USE_CLSR) 460 .fixups = &s25hx_t_fixups }, 461 { "s25hs01gt", INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512) 462 PARSE_SFDP 463 MFR_FLAGS(USE_CLSR) 464 .fixups = &s25hx_t_fixups }, 465 { "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1) 466 FLAGS(SPI_NOR_NO_ERASE) }, 467 { "s28hl512t", INFO(0x345a1a, 0, 256 * 1024, 256) 468 PARSE_SFDP 469 .fixups = &s28hx_t_fixups, 470 }, 471 { "s28hl01gt", INFO(0x345a1b, 0, 256 * 1024, 512) 472 PARSE_SFDP 473 .fixups = &s28hx_t_fixups, 474 }, 475 { "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256) 476 PARSE_SFDP 477 .fixups = &s28hx_t_fixups, 478 }, 479 { "s28hs01gt", INFO(0x345b1b, 0, 256 * 1024, 512) 480 PARSE_SFDP 481 .fixups = &s28hx_t_fixups, 482 }, 483 }; 484 485 /** 486 * spansion_nor_clear_sr() - Clear the Status Register. 487 * @nor: pointer to 'struct spi_nor'. 488 */ 489 static void spansion_nor_clear_sr(struct spi_nor *nor) 490 { 491 int ret; 492 493 if (nor->spimem) { 494 struct spi_mem_op op = SPANSION_CLSR_OP; 495 496 spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); 497 498 ret = spi_mem_exec_op(nor->spimem, &op); 499 } else { 500 ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLSR, 501 NULL, 0); 502 } 503 504 if (ret) 505 dev_dbg(nor->dev, "error %d clearing SR\n", ret); 506 } 507 508 /** 509 * spansion_nor_sr_ready_and_clear() - Query the Status Register to see if the 510 * flash is ready for new commands and clear it if there are any errors. 511 * @nor: pointer to 'struct spi_nor'. 512 * 513 * Return: 1 if ready, 0 if not ready, -errno on errors. 514 */ 515 static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor) 516 { 517 int ret; 518 519 ret = spi_nor_read_sr(nor, nor->bouncebuf); 520 if (ret) 521 return ret; 522 523 if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) { 524 if (nor->bouncebuf[0] & SR_E_ERR) 525 dev_err(nor->dev, "Erase Error occurred\n"); 526 else 527 dev_err(nor->dev, "Programming Error occurred\n"); 528 529 spansion_nor_clear_sr(nor); 530 531 /* 532 * WEL bit remains set to one when an erase or page program 533 * error occurs. Issue a Write Disable command to protect 534 * against inadvertent writes that can possibly corrupt the 535 * contents of the memory. 536 */ 537 ret = spi_nor_write_disable(nor); 538 if (ret) 539 return ret; 540 541 return -EIO; 542 } 543 544 return !(nor->bouncebuf[0] & SR_WIP); 545 } 546 547 static void spansion_nor_late_init(struct spi_nor *nor) 548 { 549 if (nor->params->size > SZ_16M) { 550 nor->flags |= SNOR_F_4B_OPCODES; 551 /* No small sector erase for 4-byte command set */ 552 nor->erase_opcode = SPINOR_OP_SE; 553 nor->mtd.erasesize = nor->info->sector_size; 554 } 555 556 if (nor->info->mfr_flags & USE_CLSR) 557 nor->params->ready = spansion_nor_sr_ready_and_clear; 558 } 559 560 static const struct spi_nor_fixups spansion_nor_fixups = { 561 .late_init = spansion_nor_late_init, 562 }; 563 564 const struct spi_nor_manufacturer spi_nor_spansion = { 565 .name = "spansion", 566 .parts = spansion_nor_parts, 567 .nparts = ARRAY_SIZE(spansion_nor_parts), 568 .fixups = &spansion_nor_fixups, 569 }; 570