/* Use 20 dummy cycles for memory array reads. */
*buf = 20;
op = (struct spi_mem_op)
MICRON_ST_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
SPINOR_REG_MT_CFR1V, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); if (ret) return ret;
buf[0] = SPINOR_MT_OCT_DTR;
op = (struct spi_mem_op)
MICRON_ST_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
SPINOR_REG_MT_CFR0V, 1, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto); if (ret) return ret;
/* Read flash ID to make sure the switch was successful. */
ret = spi_nor_read_id(nor, 0, 8, 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. The next register is the dummy cycle configuration * register. Since the transaction needs to be at least 2 bytes wide, * set the next register to its default value. This also makes sense * because the value was changed when enabling 8D-8D-8D mode, it should * be reset when disabling.
*/
buf[0] = SPINOR_MT_EXSPI;
buf[1] = SPINOR_REG_MT_CFR1V_DEF;
op = (struct spi_mem_op)
MICRON_ST_NOR_WR_ANY_REG_OP(nor->addr_nbytes,
SPINOR_REG_MT_CFR0V, 2, buf);
ret = spi_nor_write_any_volatile_reg(nor, &op, SNOR_PROTO_8_8_8_DTR); 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;
/* * The BFPT quad enable field is set to a reserved value so the quad * enable function is ignored by spi_nor_parse_bfpt(). Make sure we * disable it.
*/
nor->params->quad_enable = NULL;
/* * Unfortunately the die erase opcode does not have a 4-byte opcode * correspondent for these flashes. The SFDP 4BAIT table fails to * consider the die erase too. We're forced to enter in the 4 byte * address mode in order to benefit of the die erase.
*/ return spi_nor_set_4byte_addr_mode(nor, true);
}
/* * Unfortunately the die erase opcode does not have a 4-byte opcode * correspondent for these flashes. The SFDP 4BAIT table fails to * consider the die erase too. We're forced to enter in the 4 byte * address mode in order to benefit of the die erase.
*/ return spi_nor_set_4byte_addr_mode(nor, true);
}
/** * micron_st_nor_read_fsr() - Read the Flag Status Register. * @nor: pointer to 'struct spi_nor' * @fsr: pointer to a DMA-able buffer where the value of the * Flag Status Register will be written. Should be at least 2 * bytes. * * Return: 0 on success, -errno otherwise.
*/ staticint micron_st_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
{ int ret;
if (nor->spimem) { struct spi_mem_op op = MICRON_ST_RDFSR_OP(fsr);
if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
op.addr.nbytes = nor->params->rdsr_addr_nbytes;
op.dummy.nbytes = nor->params->rdsr_dummy; /* * We don't want to read only one byte in DTR mode. So, * read 2 and then discard the second byte.
*/
op.data.nbytes = 2;
}
ret = spi_mem_exec_op(nor->spimem, &op);
} else {
ret = spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDFSR, fsr,
1);
}
if (ret)
dev_dbg(nor->dev, "error %d reading FSR\n", ret);
return ret;
}
/** * micron_st_nor_clear_fsr() - Clear the Flag Status Register. * @nor: pointer to 'struct spi_nor'.
*/ staticvoid micron_st_nor_clear_fsr(struct spi_nor *nor)
{ int ret;
if (nor->spimem) { struct spi_mem_op op = MICRON_ST_CLFSR_OP;
ret = spi_mem_exec_op(nor->spimem, &op);
} else {
ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLFSR,
NULL, 0);
}
if (ret)
dev_dbg(nor->dev, "error %d clearing FSR\n", ret);
}
/** * micron_st_nor_ready() - Query the Status Register as well as the Flag Status * Register to see if the flash is ready for new commands. If there are any * errors in the FSR clear them. * @nor: pointer to 'struct spi_nor'. * * Return: 1 if ready, 0 if not ready, -errno on errors.
*/ staticint micron_st_nor_ready(struct spi_nor *nor)
{ int sr_ready, ret;
sr_ready = spi_nor_sr_ready(nor); if (sr_ready < 0) return sr_ready;
ret = micron_st_nor_read_fsr(nor, nor->bouncebuf); if (ret) { /* * Some controllers, such as Intel SPI, do not support low * level operations such as reading the flag status * register. They only expose small amount of high level * operations to the software. If this is the case we use * only the status register value.
*/ return ret == -EOPNOTSUPP ? sr_ready : ret;
}
if (nor->bouncebuf[0] & (FSR_E_ERR | FSR_P_ERR)) { if (nor->bouncebuf[0] & FSR_E_ERR)
dev_err(nor->dev, "Erase operation failed.\n"); else
dev_err(nor->dev, "Program operation failed.\n");
if (nor->bouncebuf[0] & FSR_PT_ERR)
dev_err(nor->dev, "Attempted to modify a protected sector.\n");
micron_st_nor_clear_fsr(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.