1092 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2005, Intec Automation Inc.4 * Copyright (C) 2014, Freescale Semiconductor, Inc.5 */6 7#include <linux/bitfield.h>8#include <linux/device.h>9#include <linux/errno.h>10#include <linux/mtd/spi-nor.h>11 12#include "core.h"13 14/* flash_info mfr_flag. Used to clear sticky prorietary SR bits. */15#define USE_CLSR BIT(0)16#define USE_CLPEF BIT(1)17 18#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */19#define SPINOR_OP_CLPEF 0x82 /* Clear program/erase failure flags */20#define SPINOR_OP_CYPRESS_DIE_ERASE 0x61 /* Chip (die) erase */21#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */22#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */23#define SPINOR_REG_CYPRESS_VREG 0x0080000024#define SPINOR_REG_CYPRESS_STR1 0x025#define SPINOR_REG_CYPRESS_STR1V \26 (SPINOR_REG_CYPRESS_VREG + SPINOR_REG_CYPRESS_STR1)27#define SPINOR_REG_CYPRESS_CFR1 0x228#define SPINOR_REG_CYPRESS_CFR1_QUAD_EN BIT(1) /* Quad Enable */29#define SPINOR_REG_CYPRESS_CFR2 0x330#define SPINOR_REG_CYPRESS_CFR2V \31 (SPINOR_REG_CYPRESS_VREG + SPINOR_REG_CYPRESS_CFR2)32#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK GENMASK(3, 0)33#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb34#define SPINOR_REG_CYPRESS_CFR2_ADRBYT BIT(7)35#define SPINOR_REG_CYPRESS_CFR3 0x436#define SPINOR_REG_CYPRESS_CFR3_PGSZ BIT(4) /* Page size. */37#define SPINOR_REG_CYPRESS_CFR5 0x638#define SPINOR_REG_CYPRESS_CFR5_BIT6 BIT(6)39#define SPINOR_REG_CYPRESS_CFR5_DDR BIT(1)40#define SPINOR_REG_CYPRESS_CFR5_OPI BIT(0)41#define SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN \42 (SPINOR_REG_CYPRESS_CFR5_BIT6 | SPINOR_REG_CYPRESS_CFR5_DDR | \43 SPINOR_REG_CYPRESS_CFR5_OPI)44#define SPINOR_REG_CYPRESS_CFR5_OCT_DTR_DS SPINOR_REG_CYPRESS_CFR5_BIT645#define SPINOR_OP_CYPRESS_RD_FAST 0xee46#define SPINOR_REG_CYPRESS_ARCFN 0x0000000647 48/* Cypress SPI NOR flash operations. */49#define CYPRESS_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf) \50 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0), \51 SPI_MEM_OP_ADDR(naddr, addr, 0), \52 SPI_MEM_OP_NO_DUMMY, \53 SPI_MEM_OP_DATA_OUT(ndata, buf, 0))54 55#define CYPRESS_NOR_RD_ANY_REG_OP(naddr, addr, ndummy, buf) \56 SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0), \57 SPI_MEM_OP_ADDR(naddr, addr, 0), \58 SPI_MEM_OP_DUMMY(ndummy, 0), \59 SPI_MEM_OP_DATA_IN(1, buf, 0))60 61#define SPANSION_OP(opcode) \62 SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \63 SPI_MEM_OP_NO_ADDR, \64 SPI_MEM_OP_NO_DUMMY, \65 SPI_MEM_OP_NO_DATA)66 67/**68 * struct spansion_nor_params - Spansion private parameters.69 * @clsr: Clear Status Register or Clear Program and Erase Failure Flag70 * opcode.71 */72struct spansion_nor_params {73 u8 clsr;74};75 76/**77 * spansion_nor_clear_sr() - Clear the Status Register.78 * @nor: pointer to 'struct spi_nor'.79 */80static void spansion_nor_clear_sr(struct spi_nor *nor)81{82 const struct spansion_nor_params *priv_params = nor->params->priv;83 int ret;84 85 if (nor->spimem) {86 struct spi_mem_op op = SPANSION_OP(priv_params->clsr);87 88 spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);89 90 ret = spi_mem_exec_op(nor->spimem, &op);91 } else {92 ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLSR,93 NULL, 0);94 }95 96 if (ret)97 dev_dbg(nor->dev, "error %d clearing SR\n", ret);98}99 100static int cypress_nor_sr_ready_and_clear_reg(struct spi_nor *nor, u64 addr)101{102 struct spi_nor_flash_parameter *params = nor->params;103 struct spi_mem_op op =104 CYPRESS_NOR_RD_ANY_REG_OP(params->addr_mode_nbytes, addr,105 0, nor->bouncebuf);106 int ret;107 108 if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {109 op.dummy.nbytes = params->rdsr_dummy;110 op.data.nbytes = 2;111 }112 113 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);114 if (ret)115 return ret;116 117 if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) {118 if (nor->bouncebuf[0] & SR_E_ERR)119 dev_err(nor->dev, "Erase Error occurred\n");120 else121 dev_err(nor->dev, "Programming Error occurred\n");122 123 spansion_nor_clear_sr(nor);124 125 ret = spi_nor_write_disable(nor);126 if (ret)127 return ret;128 129 return -EIO;130 }131 132 return !(nor->bouncebuf[0] & SR_WIP);133}134/**135 * cypress_nor_sr_ready_and_clear() - Query the Status Register of each die by136 * using Read Any Register command to see if the whole flash is ready for new137 * commands and clear it if there are any errors.138 * @nor: pointer to 'struct spi_nor'.139 *140 * Return: 1 if ready, 0 if not ready, -errno on errors.141 */142static int cypress_nor_sr_ready_and_clear(struct spi_nor *nor)143{144 struct spi_nor_flash_parameter *params = nor->params;145 u64 addr;146 int ret;147 u8 i;148 149 for (i = 0; i < params->n_dice; i++) {150 addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_STR1;151 ret = cypress_nor_sr_ready_and_clear_reg(nor, addr);152 if (ret < 0)153 return ret;154 else if (ret == 0)155 return 0;156 }157 158 return 1;159}160 161static int cypress_nor_set_memlat(struct spi_nor *nor, u64 addr)162{163 struct spi_mem_op op;164 u8 *buf = nor->bouncebuf;165 int ret;166 u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;167 168 op = (struct spi_mem_op)169 CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, addr, 0, buf);170 171 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);172 if (ret)173 return ret;174 175 /* Use 24 dummy cycles for memory array reads. */176 *buf &= ~SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK;177 *buf |= FIELD_PREP(SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK,178 SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24);179 op = (struct spi_mem_op)180 CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes, addr, 1, buf);181 182 ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);183 if (ret)184 return ret;185 186 nor->read_dummy = 24;187 188 return 0;189}190 191static int cypress_nor_set_octal_dtr_bits(struct spi_nor *nor, u64 addr)192{193 struct spi_mem_op op;194 u8 *buf = nor->bouncebuf;195 196 /* Set the octal and DTR enable bits. */197 buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN;198 op = (struct spi_mem_op)199 CYPRESS_NOR_WR_ANY_REG_OP(nor->params->addr_mode_nbytes,200 addr, 1, buf);201 202 return spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);203}204 205static int cypress_nor_octal_dtr_en(struct spi_nor *nor)206{207 const struct spi_nor_flash_parameter *params = nor->params;208 u8 *buf = nor->bouncebuf;209 u64 addr;210 int i, ret;211 212 for (i = 0; i < params->n_dice; i++) {213 addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR2;214 ret = cypress_nor_set_memlat(nor, addr);215 if (ret)216 return ret;217 218 addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR5;219 ret = cypress_nor_set_octal_dtr_bits(nor, addr);220 if (ret)221 return ret;222 }223 224 /* Read flash ID to make sure the switch was successful. */225 ret = spi_nor_read_id(nor, nor->addr_nbytes, 3, buf,226 SNOR_PROTO_8_8_8_DTR);227 if (ret) {228 dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);229 return ret;230 }231 232 if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))233 return -EINVAL;234 235 return 0;236}237 238static int cypress_nor_set_single_spi_bits(struct spi_nor *nor, u64 addr)239{240 struct spi_mem_op op;241 u8 *buf = nor->bouncebuf;242 243 /*244 * The register is 1-byte wide, but 1-byte transactions are not allowed245 * in 8D-8D-8D mode. Since there is no register at the next location,246 * just initialize the value to 0 and let the transaction go on.247 */248 buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_DS;249 buf[1] = 0;250 op = (struct spi_mem_op)251 CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes, addr, 2, buf);252 return spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);253}254 255static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)256{257 const struct spi_nor_flash_parameter *params = nor->params;258 u8 *buf = nor->bouncebuf;259 u64 addr;260 int i, ret;261 262 for (i = 0; i < params->n_dice; i++) {263 addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR5;264 ret = cypress_nor_set_single_spi_bits(nor, addr);265 if (ret)266 return ret;267 }268 269 /* Read flash ID to make sure the switch was successful. */270 ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);271 if (ret) {272 dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);273 return ret;274 }275 276 if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))277 return -EINVAL;278 279 return 0;280}281 282static int cypress_nor_quad_enable_volatile_reg(struct spi_nor *nor, u64 addr)283{284 struct spi_mem_op op;285 u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;286 u8 cfr1v_written;287 int ret;288 289 op = (struct spi_mem_op)290 CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, addr, 0,291 nor->bouncebuf);292 293 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);294 if (ret)295 return ret;296 297 if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1_QUAD_EN)298 return 0;299 300 /* Update the Quad Enable bit. */301 nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1_QUAD_EN;302 op = (struct spi_mem_op)303 CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes, addr, 1,304 nor->bouncebuf);305 ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);306 if (ret)307 return ret;308 309 cfr1v_written = nor->bouncebuf[0];310 311 /* Read back and check it. */312 op = (struct spi_mem_op)313 CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, addr, 0,314 nor->bouncebuf);315 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);316 if (ret)317 return ret;318 319 if (nor->bouncebuf[0] != cfr1v_written) {320 dev_err(nor->dev, "CFR1: Read back test failed\n");321 return -EIO;322 }323 324 return 0;325}326 327/**328 * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile329 * register.330 * @nor: pointer to a 'struct spi_nor'331 *332 * It is recommended to update volatile registers in the field application due333 * to a risk of the non-volatile registers corruption by power interrupt. This334 * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable335 * bit in the CFR1 non-volatile in advance (typically by a Flash programmer336 * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is337 * also set during Flash power-up.338 *339 * Return: 0 on success, -errno otherwise.340 */341static int cypress_nor_quad_enable_volatile(struct spi_nor *nor)342{343 struct spi_nor_flash_parameter *params = nor->params;344 u64 addr;345 u8 i;346 int ret;347 348 for (i = 0; i < params->n_dice; i++) {349 addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR1;350 ret = cypress_nor_quad_enable_volatile_reg(nor, addr);351 if (ret)352 return ret;353 }354 355 return 0;356}357 358/**359 * cypress_nor_determine_addr_mode_by_sr1() - Determine current address mode360 * (3 or 4-byte) by querying status361 * register 1 (SR1).362 * @nor: pointer to a 'struct spi_nor'363 * @addr_mode: ponter to a buffer where we return the determined364 * address mode.365 *366 * This function tries to determine current address mode by comparing SR1 value367 * from RDSR1(no address), RDAR(3-byte address), and RDAR(4-byte address).368 *369 * Return: 0 on success, -errno otherwise.370 */371static int cypress_nor_determine_addr_mode_by_sr1(struct spi_nor *nor,372 u8 *addr_mode)373{374 struct spi_mem_op op =375 CYPRESS_NOR_RD_ANY_REG_OP(3, SPINOR_REG_CYPRESS_STR1V, 0,376 nor->bouncebuf);377 bool is3byte, is4byte;378 int ret;379 380 ret = spi_nor_read_sr(nor, &nor->bouncebuf[1]);381 if (ret)382 return ret;383 384 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);385 if (ret)386 return ret;387 388 is3byte = (nor->bouncebuf[0] == nor->bouncebuf[1]);389 390 op = (struct spi_mem_op)391 CYPRESS_NOR_RD_ANY_REG_OP(4, SPINOR_REG_CYPRESS_STR1V, 0,392 nor->bouncebuf);393 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);394 if (ret)395 return ret;396 397 is4byte = (nor->bouncebuf[0] == nor->bouncebuf[1]);398 399 if (is3byte == is4byte)400 return -EIO;401 if (is3byte)402 *addr_mode = 3;403 else404 *addr_mode = 4;405 406 return 0;407}408 409/**410 * cypress_nor_set_addr_mode_nbytes() - Set the number of address bytes mode of411 * current address mode.412 * @nor: pointer to a 'struct spi_nor'413 *414 * Determine current address mode by reading SR1 with different methods, then415 * query CFR2V[7] to confirm. If determination is failed, force enter to 4-byte416 * address mode.417 *418 * Return: 0 on success, -errno otherwise.419 */420static int cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor)421{422 struct spi_mem_op op;423 u8 addr_mode;424 int ret;425 426 /*427 * Read SR1 by RDSR1 and RDAR(3- AND 4-byte addr). Use write enable428 * that sets bit-1 in SR1.429 */430 ret = spi_nor_write_enable(nor);431 if (ret)432 return ret;433 ret = cypress_nor_determine_addr_mode_by_sr1(nor, &addr_mode);434 if (ret) {435 ret = spi_nor_set_4byte_addr_mode(nor, true);436 if (ret)437 return ret;438 return spi_nor_write_disable(nor);439 }440 ret = spi_nor_write_disable(nor);441 if (ret)442 return ret;443 444 /*445 * Query CFR2V and make sure no contradiction between determined address446 * mode and CFR2V[7].447 */448 op = (struct spi_mem_op)449 CYPRESS_NOR_RD_ANY_REG_OP(addr_mode, SPINOR_REG_CYPRESS_CFR2V,450 0, nor->bouncebuf);451 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);452 if (ret)453 return ret;454 455 if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR2_ADRBYT) {456 if (addr_mode != 4)457 return spi_nor_set_4byte_addr_mode(nor, true);458 } else {459 if (addr_mode != 3)460 return spi_nor_set_4byte_addr_mode(nor, true);461 }462 463 nor->params->addr_nbytes = addr_mode;464 nor->params->addr_mode_nbytes = addr_mode;465 466 return 0;467}468 469/**470 * cypress_nor_get_page_size() - Get flash page size configuration.471 * @nor: pointer to a 'struct spi_nor'472 *473 * The BFPT table advertises a 512B or 256B page size depending on part but the474 * page size is actually configurable (with the default being 256B). Read from475 * CFR3V[4] and set the correct size.476 *477 * Return: 0 on success, -errno otherwise.478 */479static int cypress_nor_get_page_size(struct spi_nor *nor)480{481 struct spi_mem_op op =482 CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes,483 0, 0, nor->bouncebuf);484 struct spi_nor_flash_parameter *params = nor->params;485 int ret;486 u8 i;487 488 /*489 * Use the minimum common page size configuration. Programming 256-byte490 * under 512-byte page size configuration is safe.491 */492 params->page_size = 256;493 for (i = 0; i < params->n_dice; i++) {494 op.addr.val = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR3;495 496 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);497 if (ret)498 return ret;499 500 if (!(nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR3_PGSZ))501 return 0;502 }503 504 params->page_size = 512;505 506 return 0;507}508 509static void cypress_nor_ecc_init(struct spi_nor *nor)510{511 /*512 * Programming is supported only in 16-byte ECC data unit granularity.513 * Byte-programming, bit-walking, or multiple program operations to the514 * same ECC data unit without an erase are not allowed.515 */516 nor->params->writesize = 16;517 nor->flags |= SNOR_F_ECC;518}519 520static int521s25fs256t_post_bfpt_fixup(struct spi_nor *nor,522 const struct sfdp_parameter_header *bfpt_header,523 const struct sfdp_bfpt *bfpt)524{525 struct spi_mem_op op;526 int ret;527 528 ret = cypress_nor_set_addr_mode_nbytes(nor);529 if (ret)530 return ret;531 532 /* Read Architecture Configuration Register (ARCFN) */533 op = (struct spi_mem_op)534 CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes,535 SPINOR_REG_CYPRESS_ARCFN, 1,536 nor->bouncebuf);537 ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);538 if (ret)539 return ret;540 541 /* ARCFN value must be 0 if uniform sector is selected */542 if (nor->bouncebuf[0])543 return -ENODEV;544 545 return 0;546}547 548static int s25fs256t_post_sfdp_fixup(struct spi_nor *nor)549{550 struct spi_nor_flash_parameter *params = nor->params;551 552 /*553 * S25FS256T does not define the SCCR map, but we would like to use the554 * same code base for both single and multi chip package devices, thus555 * set the vreg_offset and n_dice to be able to do so.556 */557 params->vreg_offset = devm_kmalloc(nor->dev, sizeof(u32), GFP_KERNEL);558 if (!params->vreg_offset)559 return -ENOMEM;560 561 params->vreg_offset[0] = SPINOR_REG_CYPRESS_VREG;562 params->n_dice = 1;563 564 /* PP_1_1_4_4B is supported but missing in 4BAIT. */565 params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;566 spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_1_1_4],567 SPINOR_OP_PP_1_1_4_4B,568 SNOR_PROTO_1_1_4);569 570 return cypress_nor_get_page_size(nor);571}572 573static int s25fs256t_late_init(struct spi_nor *nor)574{575 cypress_nor_ecc_init(nor);576 577 return 0;578}579 580static struct spi_nor_fixups s25fs256t_fixups = {581 .post_bfpt = s25fs256t_post_bfpt_fixup,582 .post_sfdp = s25fs256t_post_sfdp_fixup,583 .late_init = s25fs256t_late_init,584};585 586static int587s25hx_t_post_bfpt_fixup(struct spi_nor *nor,588 const struct sfdp_parameter_header *bfpt_header,589 const struct sfdp_bfpt *bfpt)590{591 int ret;592 593 ret = cypress_nor_set_addr_mode_nbytes(nor);594 if (ret)595 return ret;596 597 /* Replace Quad Enable with volatile version */598 nor->params->quad_enable = cypress_nor_quad_enable_volatile;599 600 return 0;601}602 603static int s25hx_t_post_sfdp_fixup(struct spi_nor *nor)604{605 struct spi_nor_flash_parameter *params = nor->params;606 struct spi_nor_erase_type *erase_type = params->erase_map.erase_type;607 unsigned int i;608 609 if (!params->n_dice || !params->vreg_offset) {610 dev_err(nor->dev, "%s failed. The volatile register offset could not be retrieved from SFDP.\n",611 __func__);612 return -EOPNOTSUPP;613 }614 615 /* The 2 Gb parts duplicate info and advertise 4 dice instead of 2. */616 if (params->size == SZ_256M)617 params->n_dice = 2;618 619 /*620 * In some parts, 3byte erase opcodes are advertised by 4BAIT.621 * Convert them to 4byte erase opcodes.622 */623 for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {624 switch (erase_type[i].opcode) {625 case SPINOR_OP_SE:626 erase_type[i].opcode = SPINOR_OP_SE_4B;627 break;628 case SPINOR_OP_BE_4K:629 erase_type[i].opcode = SPINOR_OP_BE_4K_4B;630 break;631 default:632 break;633 }634 }635 636 return cypress_nor_get_page_size(nor);637}638 639static int s25hx_t_late_init(struct spi_nor *nor)640{641 struct spi_nor_flash_parameter *params = nor->params;642 643 /* Fast Read 4B requires mode cycles */644 params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8;645 params->ready = cypress_nor_sr_ready_and_clear;646 cypress_nor_ecc_init(nor);647 648 params->die_erase_opcode = SPINOR_OP_CYPRESS_DIE_ERASE;649 return 0;650}651 652static struct spi_nor_fixups s25hx_t_fixups = {653 .post_bfpt = s25hx_t_post_bfpt_fixup,654 .post_sfdp = s25hx_t_post_sfdp_fixup,655 .late_init = s25hx_t_late_init,656};657 658/**659 * cypress_nor_set_octal_dtr() - Enable or disable octal DTR on Cypress flashes.660 * @nor: pointer to a 'struct spi_nor'661 * @enable: whether to enable or disable Octal DTR662 *663 * This also sets the memory access latency cycles to 24 to allow the flash to664 * run at up to 200MHz.665 *666 * Return: 0 on success, -errno otherwise.667 */668static int cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)669{670 return enable ? cypress_nor_octal_dtr_en(nor) :671 cypress_nor_octal_dtr_dis(nor);672}673 674static int s28hx_t_post_sfdp_fixup(struct spi_nor *nor)675{676 struct spi_nor_flash_parameter *params = nor->params;677 678 if (!params->n_dice || !params->vreg_offset) {679 dev_err(nor->dev, "%s failed. The volatile register offset could not be retrieved from SFDP.\n",680 __func__);681 return -EOPNOTSUPP;682 }683 684 /* The 2 Gb parts duplicate info and advertise 4 dice instead of 2. */685 if (params->size == SZ_256M)686 params->n_dice = 2;687 688 /*689 * On older versions of the flash the xSPI Profile 1.0 table has the690 * 8D-8D-8D Fast Read opcode as 0x00. But it actually should be 0xEE.691 */692 if (params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode == 0)693 params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode =694 SPINOR_OP_CYPRESS_RD_FAST;695 696 /* This flash is also missing the 4-byte Page Program opcode bit. */697 spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP],698 SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1);699 /*700 * Since xSPI Page Program opcode is backward compatible with701 * Legacy SPI, use Legacy SPI opcode there as well.702 */703 spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8_8_8_DTR],704 SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR);705 706 /*707 * The xSPI Profile 1.0 table advertises the number of additional708 * address bytes needed for Read Status Register command as 0 but the709 * actual value for that is 4.710 */711 params->rdsr_addr_nbytes = 4;712 713 return cypress_nor_get_page_size(nor);714}715 716static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,717 const struct sfdp_parameter_header *bfpt_header,718 const struct sfdp_bfpt *bfpt)719{720 return cypress_nor_set_addr_mode_nbytes(nor);721}722 723static int s28hx_t_late_init(struct spi_nor *nor)724{725 struct spi_nor_flash_parameter *params = nor->params;726 727 params->set_octal_dtr = cypress_nor_set_octal_dtr;728 params->ready = cypress_nor_sr_ready_and_clear;729 cypress_nor_ecc_init(nor);730 731 return 0;732}733 734static const struct spi_nor_fixups s28hx_t_fixups = {735 .post_sfdp = s28hx_t_post_sfdp_fixup,736 .post_bfpt = s28hx_t_post_bfpt_fixup,737 .late_init = s28hx_t_late_init,738};739 740static int741s25fs_s_nor_post_bfpt_fixups(struct spi_nor *nor,742 const struct sfdp_parameter_header *bfpt_header,743 const struct sfdp_bfpt *bfpt)744{745 /*746 * The S25FS-S chip family reports 512-byte pages in BFPT but747 * in reality the write buffer still wraps at the safe default748 * of 256 bytes. Overwrite the page size advertised by BFPT749 * to get the writes working.750 */751 nor->params->page_size = 256;752 753 return 0;754}755 756static const struct spi_nor_fixups s25fs_s_nor_fixups = {757 .post_bfpt = s25fs_s_nor_post_bfpt_fixups,758};759 760static const struct flash_info spansion_nor_parts[] = {761 {762 .id = SNOR_ID(0x01, 0x02, 0x12),763 .name = "s25sl004a",764 .size = SZ_512K,765 }, {766 .id = SNOR_ID(0x01, 0x02, 0x13),767 .name = "s25sl008a",768 .size = SZ_1M,769 }, {770 .id = SNOR_ID(0x01, 0x02, 0x14),771 .name = "s25sl016a",772 .size = SZ_2M,773 }, {774 .id = SNOR_ID(0x01, 0x02, 0x15, 0x4d, 0x00),775 .name = "s25sl032p",776 .size = SZ_4M,777 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,778 }, {779 .id = SNOR_ID(0x01, 0x02, 0x15),780 .name = "s25sl032a",781 .size = SZ_4M,782 }, {783 .id = SNOR_ID(0x01, 0x02, 0x16, 0x4d, 0x00),784 .name = "s25sl064p",785 .size = SZ_8M,786 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,787 }, {788 .id = SNOR_ID(0x01, 0x02, 0x16),789 .name = "s25sl064a",790 .size = SZ_8M,791 }, {792 .id = SNOR_ID(0x01, 0x02, 0x19, 0x4d, 0x00, 0x80),793 .name = "s25fl256s0",794 .size = SZ_32M,795 .sector_size = SZ_256K,796 .no_sfdp_flags = SPI_NOR_SKIP_SFDP | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,797 .mfr_flags = USE_CLSR,798 }, {799 .id = SNOR_ID(0x01, 0x02, 0x19, 0x4d, 0x00, 0x81),800 .name = "s25fs256s0",801 .size = SZ_32M,802 .sector_size = SZ_256K,803 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,804 .mfr_flags = USE_CLSR,805 }, {806 .id = SNOR_ID(0x01, 0x02, 0x19, 0x4d, 0x01, 0x80),807 .name = "s25fl256s1",808 .size = SZ_32M,809 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,810 .mfr_flags = USE_CLSR,811 }, {812 .id = SNOR_ID(0x01, 0x02, 0x19, 0x4d, 0x01, 0x81),813 .name = "s25fs256s1",814 .size = SZ_32M,815 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,816 .mfr_flags = USE_CLSR,817 }, {818 .id = SNOR_ID(0x01, 0x02, 0x20, 0x4d, 0x00, 0x80),819 .name = "s25fl512s",820 .size = SZ_64M,821 .sector_size = SZ_256K,822 .flags = SPI_NOR_HAS_LOCK,823 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,824 .mfr_flags = USE_CLSR,825 }, {826 .id = SNOR_ID(0x01, 0x02, 0x20, 0x4d, 0x00, 0x81),827 .name = "s25fs512s",828 .size = SZ_64M,829 .sector_size = SZ_256K,830 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,831 .mfr_flags = USE_CLSR,832 .fixups = &s25fs_s_nor_fixups,833 }, {834 .id = SNOR_ID(0x01, 0x20, 0x18, 0x03, 0x00),835 .name = "s25sl12800",836 .size = SZ_16M,837 .sector_size = SZ_256K,838 }, {839 .id = SNOR_ID(0x01, 0x20, 0x18, 0x03, 0x01),840 .name = "s25sl12801",841 .size = SZ_16M,842 }, {843 .id = SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x00, 0x80),844 .name = "s25fl128s0",845 .size = SZ_16M,846 .sector_size = SZ_256K,847 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,848 .mfr_flags = USE_CLSR,849 }, {850 .id = SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x00),851 .name = "s25fl129p0",852 .size = SZ_16M,853 .sector_size = SZ_256K,854 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,855 .mfr_flags = USE_CLSR,856 }, {857 .id = SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01, 0x80),858 .name = "s25fl128s1",859 .size = SZ_16M,860 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,861 .mfr_flags = USE_CLSR,862 }, {863 .id = SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01, 0x81),864 .name = "s25fs128s1",865 .size = SZ_16M,866 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,867 .mfr_flags = USE_CLSR,868 .fixups = &s25fs_s_nor_fixups,869 }, {870 .id = SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01),871 .name = "s25fl129p1",872 .size = SZ_16M,873 .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,874 .mfr_flags = USE_CLSR,875 }, {876 .id = SNOR_ID(0x01, 0x40, 0x13),877 .name = "s25fl204k",878 .size = SZ_512K,879 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ,880 }, {881 .id = SNOR_ID(0x01, 0x40, 0x14),882 .name = "s25fl208k",883 .size = SZ_1M,884 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ,885 }, {886 .id = SNOR_ID(0x01, 0x40, 0x15),887 .name = "s25fl116k",888 .size = SZ_2M,889 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,890 }, {891 .id = SNOR_ID(0x01, 0x40, 0x16),892 .name = "s25fl132k",893 .size = SZ_4M,894 .no_sfdp_flags = SECT_4K,895 }, {896 .id = SNOR_ID(0x01, 0x40, 0x17),897 .name = "s25fl164k",898 .size = SZ_8M,899 .no_sfdp_flags = SECT_4K,900 }, {901 .id = SNOR_ID(0x01, 0x60, 0x17),902 .name = "s25fl064l",903 .size = SZ_8M,904 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,905 .fixup_flags = SPI_NOR_4B_OPCODES,906 }, {907 .id = SNOR_ID(0x01, 0x60, 0x18),908 .name = "s25fl128l",909 .size = SZ_16M,910 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,911 .fixup_flags = SPI_NOR_4B_OPCODES,912 }, {913 .id = SNOR_ID(0x01, 0x60, 0x19),914 .name = "s25fl256l",915 .size = SZ_32M,916 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,917 .fixup_flags = SPI_NOR_4B_OPCODES,918 }, {919 .id = SNOR_ID(0x04, 0x2c, 0xc2, 0x7f, 0x7f, 0x7f),920 .name = "cy15x104q",921 .size = SZ_512K,922 .sector_size = SZ_512K,923 .flags = SPI_NOR_NO_ERASE,924 }, {925 .id = SNOR_ID(0x34, 0x2a, 0x1a, 0x0f, 0x03, 0x90),926 .name = "s25hl512t",927 .mfr_flags = USE_CLPEF,928 .fixups = &s25hx_t_fixups929 }, {930 .id = SNOR_ID(0x34, 0x2a, 0x1b, 0x0f, 0x03, 0x90),931 .name = "s25hl01gt",932 .mfr_flags = USE_CLPEF,933 .fixups = &s25hx_t_fixups934 }, {935 .id = SNOR_ID(0x34, 0x2a, 0x1c, 0x0f, 0x00, 0x90),936 .name = "s25hl02gt",937 .mfr_flags = USE_CLPEF,938 .fixups = &s25hx_t_fixups939 }, {940 .id = SNOR_ID(0x34, 0x2b, 0x19, 0x0f, 0x08, 0x90),941 .name = "s25fs256t",942 .mfr_flags = USE_CLPEF,943 .fixups = &s25fs256t_fixups944 }, {945 .id = SNOR_ID(0x34, 0x2b, 0x1a, 0x0f, 0x03, 0x90),946 .name = "s25hs512t",947 .mfr_flags = USE_CLPEF,948 .fixups = &s25hx_t_fixups949 }, {950 .id = SNOR_ID(0x34, 0x2b, 0x1b, 0x0f, 0x03, 0x90),951 .name = "s25hs01gt",952 .mfr_flags = USE_CLPEF,953 .fixups = &s25hx_t_fixups954 }, {955 .id = SNOR_ID(0x34, 0x2b, 0x1c, 0x0f, 0x00, 0x90),956 .name = "s25hs02gt",957 .mfr_flags = USE_CLPEF,958 .fixups = &s25hx_t_fixups959 }, {960 .id = SNOR_ID(0x34, 0x5a, 0x1a),961 .name = "s28hl512t",962 .mfr_flags = USE_CLPEF,963 .fixups = &s28hx_t_fixups,964 }, {965 .id = SNOR_ID(0x34, 0x5a, 0x1b),966 .name = "s28hl01gt",967 .mfr_flags = USE_CLPEF,968 .fixups = &s28hx_t_fixups,969 }, {970 .id = SNOR_ID(0x34, 0x5b, 0x19),971 .mfr_flags = USE_CLPEF,972 .fixups = &s28hx_t_fixups,973 }, {974 .id = SNOR_ID(0x34, 0x5b, 0x1a),975 .name = "s28hs512t",976 .mfr_flags = USE_CLPEF,977 .fixups = &s28hx_t_fixups,978 }, {979 .id = SNOR_ID(0x34, 0x5b, 0x1b),980 .name = "s28hs01gt",981 .mfr_flags = USE_CLPEF,982 .fixups = &s28hx_t_fixups,983 }, {984 .id = SNOR_ID(0x34, 0x5b, 0x1c),985 .name = "s28hs02gt",986 .mfr_flags = USE_CLPEF,987 .fixups = &s28hx_t_fixups,988 }, {989 .id = SNOR_ID(0xef, 0x40, 0x13),990 .name = "s25fl004k",991 .size = SZ_512K,992 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,993 }, {994 .id = SNOR_ID(0xef, 0x40, 0x14),995 .name = "s25fl008k",996 .size = SZ_1M,997 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,998 }, {999 .id = SNOR_ID(0xef, 0x40, 0x15),1000 .name = "s25fl016k",1001 .size = SZ_2M,1002 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,1003 }, {1004 .id = SNOR_ID(0xef, 0x40, 0x17),1005 .name = "s25fl064k",1006 .size = SZ_8M,1007 .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,1008 }1009};1010 1011/**1012 * spansion_nor_sr_ready_and_clear() - Query the Status Register to see if the1013 * flash is ready for new commands and clear it if there are any errors.1014 * @nor: pointer to 'struct spi_nor'.1015 *1016 * Return: 1 if ready, 0 if not ready, -errno on errors.1017 */1018static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor)1019{1020 int ret;1021 1022 ret = spi_nor_read_sr(nor, nor->bouncebuf);1023 if (ret)1024 return ret;1025 1026 if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) {1027 if (nor->bouncebuf[0] & SR_E_ERR)1028 dev_err(nor->dev, "Erase Error occurred\n");1029 else1030 dev_err(nor->dev, "Programming Error occurred\n");1031 1032 spansion_nor_clear_sr(nor);1033 1034 /*1035 * WEL bit remains set to one when an erase or page program1036 * error occurs. Issue a Write Disable command to protect1037 * against inadvertent writes that can possibly corrupt the1038 * contents of the memory.1039 */1040 ret = spi_nor_write_disable(nor);1041 if (ret)1042 return ret;1043 1044 return -EIO;1045 }1046 1047 return !(nor->bouncebuf[0] & SR_WIP);1048}1049 1050static int spansion_nor_late_init(struct spi_nor *nor)1051{1052 struct spi_nor_flash_parameter *params = nor->params;1053 struct spansion_nor_params *priv_params;1054 u8 mfr_flags = nor->info->mfr_flags;1055 1056 if (params->size > SZ_16M) {1057 nor->flags |= SNOR_F_4B_OPCODES;1058 /* No small sector erase for 4-byte command set */1059 nor->erase_opcode = SPINOR_OP_SE;1060 nor->mtd.erasesize = nor->info->sector_size ?:1061 SPI_NOR_DEFAULT_SECTOR_SIZE;1062 }1063 1064 if (mfr_flags & (USE_CLSR | USE_CLPEF)) {1065 priv_params = devm_kmalloc(nor->dev, sizeof(*priv_params),1066 GFP_KERNEL);1067 if (!priv_params)1068 return -ENOMEM;1069 1070 if (mfr_flags & USE_CLSR)1071 priv_params->clsr = SPINOR_OP_CLSR;1072 else if (mfr_flags & USE_CLPEF)1073 priv_params->clsr = SPINOR_OP_CLPEF;1074 1075 params->priv = priv_params;1076 params->ready = spansion_nor_sr_ready_and_clear;1077 }1078 1079 return 0;1080}1081 1082static const struct spi_nor_fixups spansion_nor_fixups = {1083 .late_init = spansion_nor_late_init,1084};1085 1086const struct spi_nor_manufacturer spi_nor_spansion = {1087 .name = "spansion",1088 .parts = spansion_nor_parts,1089 .nparts = ARRAY_SIZE(spansion_nor_parts),1090 .fixups = &spansion_nor_fixups,1091};1092