ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); if (ret) return ret;
if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) { if (nor->bouncebuf[0] & SR_E_ERR)
dev_err(nor->dev, "Erase Error occurred\n"); else
dev_err(nor->dev, "Programming Error occurred\n");
spansion_nor_clear_sr(nor);
ret = spi_nor_write_disable(nor); if (ret) return ret;
return -EIO;
}
return !(nor->bouncebuf[0] & SR_WIP);
} /** * cypress_nor_sr_ready_and_clear() - Query the Status Register of each die by * using Read Any Register command to see if the whole flash is ready for new * commands and clear it if there are any errors. * @nor: pointer to 'struct spi_nor'. * * Return: 1 if ready, 0 if not ready, -errno on errors.
*/ staticint cypress_nor_sr_ready_and_clear(struct spi_nor *nor)
{ struct spi_nor_flash_parameter *params = nor->params;
u64 addr; int ret;
u8 i;
for (i = 0; i < params->n_dice; i++) {
addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_STR1;
ret = cypress_nor_sr_ready_and_clear_reg(nor, addr); if (ret < 0) return ret; elseif (ret == 0) return 0;
}
/* Set the octal and DTR enable bits. */
buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN;
op = (struct spi_mem_op)
CYPRESS_NOR_WR_ANY_REG_OP(nor->params->addr_mode_nbytes,
addr, 1, buf);
staticint cypress_nor_octal_dtr_en(struct spi_nor *nor)
{ conststruct spi_nor_flash_parameter *params = nor->params;
u8 *buf = nor->bouncebuf;
u64 addr; int i, ret;
for (i = 0; i < params->n_dice; i++) {
addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR2;
ret = cypress_nor_set_memlat(nor, addr); if (ret) return ret;
addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR5;
ret = cypress_nor_set_octal_dtr_bits(nor, addr); if (ret) return ret;
}
/* Read flash ID to make sure the switch was successful. */
ret = spi_nor_read_id(nor, nor->addr_nbytes, 3, buf,
SNOR_PROTO_8_8_8_DTR); if (ret) {
dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret); return ret;
}
if (memcmp(buf, nor->info->id->bytes, nor->info->id->len)) return -EINVAL;
/* * The register is 1-byte wide, but 1-byte transactions are not allowed * in 8D-8D-8D mode. Since there is no register at the next location, * just initialize the value to 0 and let the transaction go on.
*/
buf[0] = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_DS;
buf[1] = 0;
op = (struct spi_mem_op)
CYPRESS_NOR_WR_ANY_REG_OP(nor->addr_nbytes, addr, 2, buf); return spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
}
staticint cypress_nor_octal_dtr_dis(struct spi_nor *nor)
{ conststruct spi_nor_flash_parameter *params = nor->params;
u8 *buf = nor->bouncebuf;
u64 addr; int i, ret;
for (i = 0; i < params->n_dice; i++) {
addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR5;
ret = cypress_nor_set_single_spi_bits(nor, addr); if (ret) return ret;
}
/* Read flash ID to make sure the switch was successful. */
ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1); if (ret) {
dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret); return ret;
}
if (memcmp(buf, nor->info->id->bytes, nor->info->id->len)) return -EINVAL;
op = (struct spi_mem_op)
CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, addr, 0,
nor->bouncebuf);
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); if (ret) return ret;
if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1_QUAD_EN) return 0;
/* Update the Quad Enable bit. */
nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1_QUAD_EN;
op = (struct spi_mem_op)
CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes, addr, 1,
nor->bouncebuf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); if (ret) return ret;
cfr1v_written = nor->bouncebuf[0];
/* Read back and check it. */
op = (struct spi_mem_op)
CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes, addr, 0,
nor->bouncebuf);
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); if (ret) return ret;
if (nor->bouncebuf[0] != cfr1v_written) {
dev_err(nor->dev, "CFR1: Read back test failed\n"); return -EIO;
}
return 0;
}
/** * cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile * register. * @nor: pointer to a 'struct spi_nor' * * It is recommended to update volatile registers in the field application due * to a risk of the non-volatile registers corruption by power interrupt. This * function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable * bit in the CFR1 non-volatile in advance (typically by a Flash programmer * before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is * also set during Flash power-up. * * Return: 0 on success, -errno otherwise.
*/ staticint cypress_nor_quad_enable_volatile(struct spi_nor *nor)
{ struct spi_nor_flash_parameter *params = nor->params;
u64 addr;
u8 i; int ret;
for (i = 0; i < params->n_dice; i++) {
addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR1;
ret = cypress_nor_quad_enable_volatile_reg(nor, addr); if (ret) return ret;
}
return 0;
}
staticint cypress_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
{ int ret; struct spi_mem_op op = CYPRESS_NOR_EN4B_EX4B_OP(enable);
ret = spi_mem_exec_op(nor->spimem, &op); if (ret)
dev_dbg(nor->dev, "error %d setting 4-byte mode\n", ret);
return ret;
}
/** * cypress_nor_determine_addr_mode_by_sr1() - Determine current address mode * (3 or 4-byte) by querying status * register 1 (SR1). * @nor: pointer to a 'struct spi_nor' * @addr_mode: ponter to a buffer where we return the determined * address mode. * * This function tries to determine current address mode by comparing SR1 value * from RDSR1(no address), RDAR(3-byte address), and RDAR(4-byte address). * * Return: 0 on success, -errno otherwise.
*/ staticint cypress_nor_determine_addr_mode_by_sr1(struct spi_nor *nor,
u8 *addr_mode)
{ struct spi_mem_op op =
CYPRESS_NOR_RD_ANY_REG_OP(3, SPINOR_REG_CYPRESS_STR1V, 0,
nor->bouncebuf); bool is3byte, is4byte; int ret;
ret = spi_nor_read_sr(nor, &nor->bouncebuf[1]); if (ret) return ret;
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); if (ret) return ret;
if (is3byte == is4byte) return -EIO; if (is3byte)
*addr_mode = 3; else
*addr_mode = 4;
return 0;
}
/** * cypress_nor_set_addr_mode_nbytes() - Set the number of address bytes mode of * current address mode. * @nor: pointer to a 'struct spi_nor' * * Determine current address mode by reading SR1 with different methods, then * query CFR2V[7] to confirm. If determination is failed, force enter to 4-byte * address mode. * * Return: 0 on success, -errno otherwise.
*/ staticint cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor)
{ struct spi_mem_op op;
u8 addr_mode; int ret;
/* * Read SR1 by RDSR1 and RDAR(3- AND 4-byte addr). Use write enable * that sets bit-1 in SR1.
*/
ret = spi_nor_write_enable(nor); if (ret) return ret;
ret = cypress_nor_determine_addr_mode_by_sr1(nor, &addr_mode); if (ret) {
ret = spi_nor_set_4byte_addr_mode(nor, true); if (ret) return ret; return spi_nor_write_disable(nor);
}
ret = spi_nor_write_disable(nor); if (ret) return ret;
/* * Query CFR2V and make sure no contradiction between determined address * mode and CFR2V[7].
*/
op = (struct spi_mem_op)
CYPRESS_NOR_RD_ANY_REG_OP(addr_mode, SPINOR_REG_CYPRESS_CFR2V,
0, nor->bouncebuf);
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); if (ret) return ret;
if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR2_ADRBYT) { if (addr_mode != 4) return spi_nor_set_4byte_addr_mode(nor, true);
} else { if (addr_mode != 3) return spi_nor_set_4byte_addr_mode(nor, true);
}
/** * cypress_nor_get_page_size() - Get flash page size configuration. * @nor: pointer to a 'struct spi_nor' * * The BFPT table advertises a 512B or 256B page size depending on part but the * page size is actually configurable (with the default being 256B). Read from * CFR3V[4] and set the correct size. * * Return: 0 on success, -errno otherwise.
*/ staticint cypress_nor_get_page_size(struct spi_nor *nor)
{ struct spi_mem_op op =
CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes,
0, 0, nor->bouncebuf); struct spi_nor_flash_parameter *params = nor->params; int ret;
u8 i;
/* * Use the minimum common page size configuration. Programming 256-byte * under 512-byte page size configuration is safe.
*/
params->page_size = 256; for (i = 0; i < params->n_dice; i++) {
op.addr.val = params->vreg_offset[i] + SPINOR_REG_CYPRESS_CFR3;
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); if (ret) return ret;
if (!(nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR3_PGSZ)) return 0;
}
params->page_size = 512;
return 0;
}
staticvoid cypress_nor_ecc_init(struct spi_nor *nor)
{ /* * Programming is supported only in 16-byte ECC data unit granularity. * Byte-programming, bit-walking, or multiple program operations to the * same ECC data unit without an erase are not allowed.
*/
nor->params->writesize = 16;
nor->flags |= SNOR_F_ECC;
}
/* * S25FS256T does not define the SCCR map, but we would like to use the * same code base for both single and multi chip package devices, thus * set the vreg_offset and n_dice to be able to do so.
*/
params->vreg_offset = devm_kmalloc(nor->dev, sizeof(u32), GFP_KERNEL); if (!params->vreg_offset) return -ENOMEM;
/* PP_1_1_4_4B is supported but missing in 4BAIT. */
params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_1_1_4],
SPINOR_OP_PP_1_1_4_4B,
SNOR_PROTO_1_1_4);
if (!params->n_dice || !params->vreg_offset) {
dev_err(nor->dev, "%s failed. The volatile register offset could not be retrieved from SFDP.\n",
__func__); return -EOPNOTSUPP;
}
/* The 2 Gb parts duplicate info and advertise 4 dice instead of 2. */ if (params->size == SZ_256M)
params->n_dice = 2;
/* * In some parts, 3byte erase opcodes are advertised by 4BAIT. * Convert them to 4byte erase opcodes.
*/ for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { switch (erase_type[i].opcode) { case SPINOR_OP_SE:
erase_type[i].opcode = SPINOR_OP_SE_4B; break; case SPINOR_OP_BE_4K:
erase_type[i].opcode = SPINOR_OP_BE_4K_4B; break; default: break;
}
}
/** * cypress_nor_set_octal_dtr() - Enable or disable octal DTR on Cypress flashes. * @nor: pointer to a 'struct spi_nor' * @enable: whether to enable or disable Octal DTR * * This also sets the memory access latency cycles to 24 to allow the flash to * run at up to 200MHz. * * Return: 0 on success, -errno otherwise.
*/ staticint cypress_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
{ return enable ? cypress_nor_octal_dtr_en(nor) :
cypress_nor_octal_dtr_dis(nor);
}
if (!params->n_dice || !params->vreg_offset) {
dev_err(nor->dev, "%s failed. The volatile register offset could not be retrieved from SFDP.\n",
__func__); return -EOPNOTSUPP;
}
/* The 2 Gb parts duplicate info and advertise 4 dice instead of 2. */ if (params->size == SZ_256M)
params->n_dice = 2;
/* * On older versions of the flash the xSPI Profile 1.0 table has the * 8D-8D-8D Fast Read opcode as 0x00. But it actually should be 0xEE.
*/ if (params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode == 0)
params->reads[SNOR_CMD_READ_8_8_8_DTR].opcode =
SPINOR_OP_CYPRESS_RD_FAST;
/* This flash is also missing the 4-byte Page Program opcode bit. */
spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP],
SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1); /* * Since xSPI Page Program opcode is backward compatible with * Legacy SPI, use Legacy SPI opcode there as well.
*/
spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8_8_8_DTR],
SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR);
/* * The xSPI Profile 1.0 table advertises the number of additional * address bytes needed for Read Status Register command as 0 but the * actual value for that is 4.
*/
params->rdsr_addr_nbytes = 4;
return cypress_nor_get_page_size(nor);
}
staticint s28hx_t_post_bfpt_fixup(struct spi_nor *nor, conststruct sfdp_parameter_header *bfpt_header, conststruct sfdp_bfpt *bfpt)
{ /* Assign 4-byte address mode method that is not determined in BFPT */
nor->params->set_4byte_addr_mode = cypress_nor_set_4byte_addr_mode;
staticint
s25fs_s_nor_post_bfpt_fixups(struct spi_nor *nor, conststruct sfdp_parameter_header *bfpt_header, conststruct sfdp_bfpt *bfpt)
{ /* * The S25FS-S chip family reports 512-byte pages in BFPT but * in reality the write buffer still wraps at the safe default * of 256 bytes. Overwrite the page size advertised by BFPT * to get the writes working.
*/
nor->params->page_size = 256;
/** * spansion_nor_sr_ready_and_clear() - Query the Status Register to see if the * flash is ready for new commands and clear it if there are any errors. * @nor: pointer to 'struct spi_nor'. * * Return: 1 if ready, 0 if not ready, -errno on errors.
*/ staticint spansion_nor_sr_ready_and_clear(struct spi_nor *nor)
{ int ret;
ret = spi_nor_read_sr(nor, nor->bouncebuf); if (ret) return ret;
if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) { if (nor->bouncebuf[0] & SR_E_ERR)
dev_err(nor->dev, "Erase Error occurred\n"); else
dev_err(nor->dev, "Programming Error occurred\n");
spansion_nor_clear_sr(nor);
/* * WEL bit remains set to one when an erase or page program * error occurs. Issue a Write Disable command to protect * against inadvertent writes that can possibly corrupt the * contents of the memory.
*/
ret = spi_nor_write_disable(nor); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.